@classytic/arc 2.19.0 → 2.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/bin/arc.js +37 -0
- package/dist/{BaseController-Dy6EQHjM.mjs → BaseController-D-MHZ27_.mjs} +4 -4
- package/dist/{ResourceRegistry-5fKZwhK_.mjs → ResourceRegistry-7RnrEWNP.mjs} +1 -1
- package/dist/{actionPermissions-D7NGwcAR.mjs → actionPermissions-C9RMiIpc.mjs} +1 -1
- package/dist/audit/index.mjs +1 -1
- package/dist/auth/index.d.mts +1 -1
- package/dist/auth/index.mjs +7 -5
- package/dist/{buildHandler-B0qvAguf.mjs → buildHandler-D_2ULWxZ.mjs} +3 -3
- package/dist/cache/index.mjs +2 -2
- package/dist/cli/commands/describe.d.mts +1 -1
- package/dist/cli/commands/describe.mjs +2 -2
- package/dist/cli/commands/docs.mjs +2 -2
- package/dist/cli/commands/generate.mjs +1 -1
- package/dist/cli/commands/init.mjs +1 -1
- package/dist/cli/commands/introspect.mjs +4 -13
- package/dist/cli/index.mjs +2 -2
- package/dist/{constants-gaEeMlz-.mjs → constants-DNre0wRg.mjs} +1 -1
- package/dist/core/index.d.mts +2 -2
- package/dist/core/index.mjs +4 -4
- package/dist/{core-Ba-6Sue6.mjs → core-CWhyGkiM.mjs} +125 -53
- package/dist/{createActionRouter-B_WzBFyf.mjs → createActionRouter-HlQso0jO.mjs} +4 -4
- package/dist/{createAggregationRouter-B_G_nIjm.mjs → createAggregationRouter-5LzPzgw1.mjs} +5 -4
- package/dist/{createApp--703hQE1.mjs → createApp-D6uwzCKu.mjs} +210 -17
- package/dist/docs/index.d.mts +1 -1
- package/dist/docs/index.mjs +1 -1
- package/dist/events/index.mjs +9 -6
- package/dist/factory/index.d.mts +3 -2
- package/dist/factory/index.mjs +2 -2
- package/dist/{fastify-augmentation-D-5_yQJi.d.mts → fastify-augmentation-CCQJEDgh.d.mts} +12 -1
- package/dist/{generate-Brans3fW.mjs → generate-usRSdQmP.mjs} +4 -3
- package/dist/hooks/index.d.mts +1 -1
- package/dist/idempotency/index.mjs +1 -1
- package/dist/{index-CRKiiP5o.d.mts → index-CdFkIMEd.d.mts} +5 -0
- package/dist/{index-CP6A1Ffj.d.mts → index-DUa8WHz3.d.mts} +1 -1
- package/dist/{index-CUTG2Cuo.d.mts → index-_--GyzcO.d.mts} +28 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.mjs +6 -6
- package/dist/{init-Bqpt1Hxf.mjs → init-YH_nslQR.mjs} +87 -5
- package/dist/integrations/index.d.mts +1 -1
- package/dist/integrations/mcp/index.d.mts +2 -2
- package/dist/integrations/mcp/index.mjs +1 -1
- package/dist/integrations/mcp/testing.d.mts +1 -1
- package/dist/integrations/mcp/testing.mjs +1 -1
- package/dist/integrations/streamline.d.mts +17 -5
- package/dist/integrations/streamline.mjs +9 -5
- package/dist/{loadResourcesFromEntry-BTlFEx05.mjs → loadResourcesFromEntry-OMCvIEE7.mjs} +1 -1
- package/dist/{mcpPlugin-C088Nd-G.mjs → mcpPlugin-CuW6L_uD.mjs} +148 -49
- package/dist/middleware/index.d.mts +1 -1
- package/dist/middleware/index.mjs +1 -1
- package/dist/module-JYH9V0I8.d.mts +384 -0
- package/dist/{openapi-DZ-5a5Op.mjs → openapi-Dq6RbEGK.mjs} +3 -3
- package/dist/permissions/index.d.mts +1 -1
- package/dist/permissions/index.mjs +1 -1
- package/dist/{permissions-BPB1xqGf.mjs → permissions-CgbOLJZG.mjs} +10 -2
- package/dist/pipeline/index.d.mts +1 -1
- package/dist/plugins/index.d.mts +10 -5
- package/dist/plugins/index.mjs +3 -3
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/{pluralize-DccFV9R7.mjs → pluralize-BhrgwZb9.mjs} +3 -3
- package/dist/presets/filesUpload.d.mts +1 -1
- package/dist/presets/filesUpload.mjs +1 -1
- package/dist/presets/index.d.mts +16 -2
- package/dist/presets/index.mjs +1 -1
- package/dist/presets/multiTenant.d.mts +1 -1
- package/dist/presets/multiTenant.mjs +1 -1
- package/dist/presets/search.d.mts +1 -1
- package/dist/presets/search.mjs +3 -2
- package/dist/{presets-BtyFwTO4.mjs → presets-DWsYQdbV.mjs} +1 -1
- package/dist/{queryCachePlugin-emHb0CuX.mjs → queryCachePlugin-DzqLN904.mjs} +2 -2
- package/dist/{registerRoute-BdV8DDwU.mjs → registerRoute-DGSREwPw.mjs} +1 -1
- package/dist/registry/index.d.mts +1 -1
- package/dist/registry/index.mjs +2 -2
- package/dist/{registry-Bm9LjWKs.mjs → registry-vcOCtPij.mjs} +1 -1
- package/dist/{schemaIR-D1MJwqmp.mjs → schemaIR-ajetw3Fv.mjs} +1 -42
- package/dist/scim/index.mjs +2 -2
- package/dist/sync/changelog.d.mts +2 -0
- package/dist/sync/changelog.mjs +2 -0
- package/dist/testing/index.d.mts +2 -2
- package/dist/testing/index.mjs +2 -2
- package/dist/types/index.d.mts +1 -1
- package/dist/{types-9_wtNPsI.d.mts → types-BHMKlMBU.d.mts} +53 -195
- package/dist/{types-DpvSF5Hh.d.mts → types-C9b2HR5W.d.mts} +1 -1
- package/dist/utils/index.d.mts +1 -1
- package/dist/utils/index.mjs +1 -1
- package/dist/{utils-C6QQ9-hd.mjs → utils-ChjYQpjn.mjs} +1400 -1400
- package/dist/{validate-CRcaWzp2.mjs → validate-C2mGgSXg.mjs} +3 -3
- package/package.json +13 -8
- package/skills/arc/SKILL.md +10 -0
- package/skills/arc/references/mcp.md +2 -0
|
@@ -316,14 +316,14 @@ function validateTopNConfig(resource, aggregation, topN, groupBy, measures, buck
|
|
|
316
316
|
if (!topN.sortBy || Object.keys(topN.sortBy).length === 0) throw new ArcAggregationConfigError(`Resource "${resource}" aggregation "${aggregation}" topN.sortBy must declare at least one ranking field.`);
|
|
317
317
|
const partitionList = Array.isArray(topN.partitionBy) ? topN.partitionBy : [topN.partitionBy];
|
|
318
318
|
if (partitionList.length === 0) throw new ArcAggregationConfigError(`Resource "${resource}" aggregation "${aggregation}" topN.partitionBy must declare at least one partition column.`);
|
|
319
|
-
const validKeys = new Set([
|
|
319
|
+
const validKeys = /* @__PURE__ */ new Set([
|
|
320
320
|
...groupBy,
|
|
321
321
|
...bucketAliases,
|
|
322
322
|
...Object.keys(measures)
|
|
323
323
|
]);
|
|
324
324
|
for (const key of partitionList) if (!validKeys.has(key)) throw new ArcAggregationConfigError(`Resource "${resource}" aggregation "${aggregation}" topN.partitionBy "${key}" is not a groupBy field, dateBucket alias, or measure alias. Available: ${[...validKeys].join(", ") || "(none — declare groupBy, dateBuckets, or measures)"}.`);
|
|
325
325
|
}
|
|
326
|
-
const VALID_BUCKET_UNITS = new Set([
|
|
326
|
+
const VALID_BUCKET_UNITS = /* @__PURE__ */ new Set([
|
|
327
327
|
"minute",
|
|
328
328
|
"hour",
|
|
329
329
|
"day",
|
|
@@ -332,7 +332,7 @@ const VALID_BUCKET_UNITS = new Set([
|
|
|
332
332
|
"quarter",
|
|
333
333
|
"year"
|
|
334
334
|
]);
|
|
335
|
-
const CUSTOM_BIN_UNIT_BLOCKLIST = new Set(["quarter", "year"]);
|
|
335
|
+
const CUSTOM_BIN_UNIT_BLOCKLIST = /* @__PURE__ */ new Set(["quarter", "year"]);
|
|
336
336
|
/**
|
|
337
337
|
* Validate `dateBuckets`. Catches the two classes of misconfig kits
|
|
338
338
|
* already throw on at runtime — alias collisions and field-rule
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@classytic/arc",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.20.0",
|
|
4
4
|
"description": "Resource-oriented backend framework for Fastify - clean, minimal, powerful, tree-shakable",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -203,6 +203,10 @@
|
|
|
203
203
|
"./auth/audit": {
|
|
204
204
|
"types": "./dist/auth/audit.d.mts",
|
|
205
205
|
"default": "./dist/auth/audit.mjs"
|
|
206
|
+
},
|
|
207
|
+
"./sync": {
|
|
208
|
+
"types": "./dist/sync/changelog.d.mts",
|
|
209
|
+
"default": "./dist/sync/changelog.mjs"
|
|
206
210
|
}
|
|
207
211
|
},
|
|
208
212
|
"main": "./dist/index.mjs",
|
|
@@ -242,15 +246,16 @@
|
|
|
242
246
|
"push": "classytic-push",
|
|
243
247
|
"release:tag": "node -e \"require('child_process').execSync('npm run push -- v'+require('./package.json').version,{stdio:'inherit'})\"",
|
|
244
248
|
"release": "npm run push -- main && npm run release:tag && npm publish",
|
|
245
|
-
"
|
|
249
|
+
"check:peer-skew": "node scripts/check-peer-skew.mjs",
|
|
250
|
+
"prepublishOnly": "npm run check:peer-skew && npm run typecheck && npm run lint && npm run build && npm run test:ci && npm run smoke"
|
|
246
251
|
},
|
|
247
252
|
"engines": {
|
|
248
253
|
"node": ">=22"
|
|
249
254
|
},
|
|
250
255
|
"peerDependencies": {
|
|
251
|
-
"@classytic/primitives": ">=0.
|
|
252
|
-
"@classytic/repo-core": ">=0.
|
|
253
|
-
"@classytic/streamline": ">=2.
|
|
256
|
+
"@classytic/primitives": ">=0.9.0",
|
|
257
|
+
"@classytic/repo-core": ">=0.7.0",
|
|
258
|
+
"@classytic/streamline": ">=2.7.0",
|
|
254
259
|
"@fastify/cors": ">=11.0.0",
|
|
255
260
|
"@fastify/helmet": ">=13.0.0",
|
|
256
261
|
"@fastify/jwt": ">=10.0.0",
|
|
@@ -369,10 +374,10 @@
|
|
|
369
374
|
"@biomejs/biome": "^2.5.0",
|
|
370
375
|
"@classytic/dev-tools": "^0.2.0",
|
|
371
376
|
"@classytic/mongokit": "^3.16.1",
|
|
372
|
-
"@classytic/primitives": "^0.
|
|
373
|
-
"@classytic/repo-core": "^0.
|
|
377
|
+
"@classytic/primitives": "^0.9.1",
|
|
378
|
+
"@classytic/repo-core": "^0.7.0",
|
|
374
379
|
"@classytic/sqlitekit": "^0.6.0",
|
|
375
|
-
"@classytic/streamline": "^2.
|
|
380
|
+
"@classytic/streamline": "^2.7.0",
|
|
376
381
|
"@fastify/cors": "^11.2.0",
|
|
377
382
|
"@fastify/helmet": "^13.0.2",
|
|
378
383
|
"@fastify/jwt": "^10.1.0",
|
package/skills/arc/SKILL.md
CHANGED
|
@@ -706,6 +706,16 @@ routes: [
|
|
|
706
706
|
{ method: 'GET', path: '/stream', raw: true, handler: async (req, reply) => reply.send(stream) },
|
|
707
707
|
]
|
|
708
708
|
|
|
709
|
+
// Per-route rate limit (2.20) — overrides the resource/app default for ONE endpoint.
|
|
710
|
+
// `false` = never throttle, object = tighten, omit = inherit. Custom routes only;
|
|
711
|
+
// actions share one POST /:id/action mount, so throttle an action by making it a route.
|
|
712
|
+
routes: [
|
|
713
|
+
{ method: 'POST', path: '/export', handler: 'export', permissions: requireAuth(),
|
|
714
|
+
rateLimit: { max: 5, timeWindow: '1 minute' } },
|
|
715
|
+
{ method: 'GET', path: '/health', handler: 'health', permissions: allowPublic(),
|
|
716
|
+
rateLimit: false },
|
|
717
|
+
]
|
|
718
|
+
|
|
709
719
|
// Per-resource opt-out of resourcePrefix (webhooks / admin routes)
|
|
710
720
|
defineResource({ name: 'webhook', prefix: '/hooks', skipGlobalPrefix: true });
|
|
711
721
|
|
|
@@ -50,6 +50,8 @@ Resource `actions` (v2.8) also auto-generate MCP tools — each action becomes a
|
|
|
50
50
|
|
|
51
51
|
Tool handlers call `BaseController` — same pipeline as REST (auth, org-scoping, hooks, field permissions, cache).
|
|
52
52
|
|
|
53
|
+
**Query params on generated tools (2.20):** `list_*` accepts `page`/`limit` (offset) **and** `cursor` (keyset, stable under concurrent inserts — when set, `page` is ignored), plus `sort`/`search`/`select`/`populate`. `get_*` accepts `select` for field projection alongside `id`. Both mirror REST exactly (same `QueryResolver`).
|
|
54
|
+
|
|
53
55
|
### McpPluginOptions
|
|
54
56
|
|
|
55
57
|
| Option | Type | Default | Description |
|