|
| 1 | +--- |
| 2 | +"@objectstack/service-analytics": patch |
| 3 | +"@objectstack/service-automation": patch |
| 4 | +"@objectstack/service-cache": patch |
| 5 | +"@objectstack/service-i18n": patch |
| 6 | +"@objectstack/service-job": patch |
| 7 | +--- |
| 8 | + |
| 9 | +docs: five published service READMEs stop documenting an API that does not exist (#9532) |
| 10 | + |
| 11 | +A version bump is the point, not a side effect: these five READMEs are in their |
| 12 | +packages' `files` arrays with `private` unset, so they are the pages npm renders — |
| 13 | +and a docs-only fix with no bump never reaches npm at all. |
| 14 | + |
| 15 | +Each of the five told a reader to an import of a `Service…` class from its own package |
| 16 | +and call a static `.configure({...})` on it. Neither has ever existed: no class in |
| 17 | +this repo exposes a static `configure`, and none of `ServiceAnalytics`, |
| 18 | +`ServiceAutomation`, `ServiceCache`, `ServiceI18n` or `ServiceJob` is exported by |
| 19 | +anything. A reader following any of them wrote code that could not compile. The real |
| 20 | +entry point in every case is a kernel plugin constructed with `new`: |
| 21 | +`AnalyticsServicePlugin`, `AutomationServicePlugin`, `CacheServicePlugin`, |
| 22 | +`I18nServicePlugin`, `JobServicePlugin`. |
| 23 | + |
| 24 | +⛔ A name swap alone would not have been enough, and the gate landed in #9546 is what |
| 25 | +proves it: substituting the genuine class while keeping `.configure(...)` turns the |
| 26 | +import finding into a call-site finding rather than into silence. Each README is |
| 27 | +rewritten against the package's built type surface, and each package's entry is |
| 28 | +deleted from `scripts/published-readme-exports.baseline.json` in the same change |
| 29 | +(the baseline is reconciled in both directions, so a stale entry fails too). |
| 30 | + |
| 31 | +What was removed as fabricated, beyond the entry point: |
| 32 | + |
| 33 | +- **service-analytics** — a nine-endpoint REST surface (`/analytics/count`, `/sum`, |
| 34 | + `/avg`, `/min`, `/max`, `/group-by`, `/time-series`, `/metrics`, `/metrics/:name`) |
| 35 | + of which none exists; the real surface is `POST /analytics/query`, |
| 36 | + `GET /analytics/meta`, `POST /analytics/sql` and `POST /analytics/dataset/query`. |
| 37 | + Also removed: `defineMetric`, `getMetric`, `compare`, `funnel`, |
| 38 | + `executeDashboard`, `invalidateCache`, and an `AnalyticsServiceConfig` block whose |
| 39 | + four keys (`defaultDriver`, `enableCaching`, `cacheTTL`, `maxMemoryResults`) are |
| 40 | + none of the real ones. |
| 41 | +- **service-automation** — `executeFlow`/`getFlow`/`listFlows`/`getFlowHistory`/ |
| 42 | + `registerTrigger` as the contract (the real contract is `execute(flowName, context?)` |
| 43 | + plus `listFlows()` and a set of optional members), and a five-endpoint REST list that |
| 44 | + matches no mounted route. The flow-authoring half of that README was already accurate |
| 45 | + and is kept. |
| 46 | +- **service-cache** — `mget`/`mset`/`del`/`delPattern`/`namespace`/`ttl`/`expire`/ |
| 47 | + `persist`/`incr`/`incrby`/`decr`/`getOrSet`/`invalidateTag`/`resetStats`, none of |
| 48 | + which exist; `ICacheService` has six members. `CacheStats.keys`/`hitRate` corrected to |
| 49 | + `keyCount` (there is no `hitRate`), and `set(key, value, { ttl })` corrected to the |
| 50 | + real positional `set(key, value, ttl?)` in seconds. |
| 51 | +- **service-i18n** — an `await i18n.t('ns:key')` dialect with namespaces, plural |
| 52 | + suffixes, `context`, `returnObjects`, `setLocale`/`getLocale`, `formatDate`/ |
| 53 | + `formatNumber`/`formatRelative`, `addLocale`/`removeLocale`/`reload`, `getCoverage`/ |
| 54 | + `getMissingKeys`, and a `{{lng}}/{{ns}}` file layout. The real `t()` is synchronous |
| 55 | + and takes the locale positionally — `t(key, locale, params?)` — over one |
| 56 | + `{locale}.json` file per locale. The `POST /i18n/translate` endpoint does not exist. |
| 57 | +- **service-job** — `scheduleInterval`/`scheduleOnce`/`getJob`/`stopJob`/`resumeJob`/ |
| 58 | + `deleteJob`/`runNow`/`getJobHistory`/`clearHistory`/`getLastExecution`, and a |
| 59 | + `schedule({ name, schedule, handler })` options-object call. The real `schedule` is |
| 60 | + positional — `schedule(name, schedule, handler, options?)` — and returns `void`. |
| 61 | + Retry defaults corrected to the enforced ones (`maxRetries: 0`, |
| 62 | + `backoffMultiplier: 1`). |
| 63 | + |
| 64 | +Two capability claims are corrected rather than deleted, because the source is what |
| 65 | +decides: |
| 66 | + |
| 67 | +- **service-cache** advertised Redis as production support. `RedisCacheAdapter` throws |
| 68 | + `RedisCacheAdapter not yet implemented` from every method, and |
| 69 | + `new CacheServicePlugin({ adapter: 'redis' })` throws during `init` rather than |
| 70 | + falling back to memory. The README now says so at the top and points at registering |
| 71 | + a custom `ICacheService` under the slot instead. |
| 72 | +- **service-job**'s `adapter: 'interval'` stores cron registrations that never fire. |
| 73 | + That is now stated in the adapter table rather than left for a reader to discover. |
| 74 | + |
| 75 | +No compliance claim (SOC 2 / HIPAA / GDPR or similar) was found in any of the five — |
| 76 | +the shape that raised `plugin-audit`'s severity in #9517 is absent here. |
0 commit comments