@classytic/arc 2.34.0 → 2.36.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/dist/{BaseController-CbkuhNI2.mjs → BaseController-CTJKm6Cb.mjs} +95 -14
- package/dist/{EventTransport-tq4CEB-q.mjs → EventTransport-D23Uvhg4.mjs} +1 -1
- package/dist/{HookSystem-DqXkMXkB.mjs → HookSystem-DgwxNZTx.mjs} +6 -4
- package/dist/{ResourceRegistry-DoALUlOO.mjs → ResourceRegistry-DNuYVbmv.mjs} +2 -2
- package/dist/{pipeline-q69DZzgG.mjs → actionPermissions-D97DniUQ.mjs} +30 -7
- package/dist/audit/index.d.mts +2 -2
- package/dist/audit/index.mjs +2 -2
- package/dist/auth/audit.mjs +1 -1
- package/dist/auth/index.d.mts +2 -2
- package/dist/auth/index.mjs +6 -6
- package/dist/auth/redis-session.mjs +1 -1
- package/dist/{authorizationDecision-CMMLWmuZ.mjs → authorizationDecision-EsiY3nUu.mjs} +2 -2
- package/dist/{base-Csjc2oF-.d.mts → base-C-NL2fTi.d.mts} +16 -1
- package/dist/{buildHandler-BrdYrG_1.mjs → buildHandler-Dohd2JuY.mjs} +4 -4
- package/dist/cache/index.mjs +4 -4
- package/dist/{caching-BcGmvnHh.mjs → caching-CP3GLJ7U.mjs} +2 -2
- package/dist/cleanup/index.d.mts +2 -2
- package/dist/cleanup/index.mjs +4 -4
- package/dist/cli/commands/describe.d.mts +1 -1
- package/dist/cli/commands/describe.mjs +3 -3
- package/dist/cli/commands/docs.mjs +3 -3
- package/dist/cli/commands/doctor.mjs +1 -1
- package/dist/cli/commands/generate.mjs +2 -2
- package/dist/cli/commands/init.mjs +2 -2
- package/dist/cli/commands/introspect.mjs +2 -2
- package/dist/cli/index.mjs +3 -3
- package/dist/{constants-BxCoxmiN.mjs → constants-DUoKAGYD.mjs} +1 -1
- package/dist/context/index.d.mts +16 -1
- package/dist/context/index.mjs +64 -4
- package/dist/core/index.d.mts +2 -2
- package/dist/core/index.mjs +7 -8
- package/dist/{core-BYKa8wHu.mjs → core-DTXsiNTJ.mjs} +3 -3
- package/dist/{createActionRouter-D6T0jWhS.mjs → createActionRouter-CZz6JO93.mjs} +27 -64
- package/dist/{createAggregationRouter-QLV2PrWP.mjs → createAggregationRouter-DKrGv_EC.mjs} +7 -7
- package/dist/defineAggregation-CpQfcM8R.mjs +25 -0
- package/dist/{defineResource-ZhuLonLm.mjs → defineResource-DWzjyxb2.mjs} +62 -66
- package/dist/discovery/index.mjs +1 -1
- package/dist/docs/index.d.mts +1 -1
- package/dist/docs/index.mjs +3 -3
- package/dist/{elevation-B0tlY8y1.mjs → elevation-D_cmo80j.mjs} +4 -4
- package/dist/encryption/index.mjs +3 -3
- package/dist/{errorHandler-C7xBqHsI.mjs → errorHandler-2RT0hLSI.mjs} +3 -3
- package/dist/{errors-Cd_yy7aW.mjs → errors-DDKni6Tz.mjs} +1 -1
- package/dist/{eventPlugin-DSNEZWfV.d.mts → eventPlugin-B47sfCJ8.d.mts} +1 -1
- package/dist/{eventPlugin-Dar8qRaj.mjs → eventPlugin-c3YwGzz9.mjs} +5 -5
- package/dist/events/index.d.mts +2 -2
- package/dist/events/index.mjs +5 -5
- package/dist/events/transports/redis-stream-entry.mjs +1 -1
- package/dist/events/transports/redis.mjs +1 -1
- package/dist/factory/index.d.mts +5 -5
- package/dist/factory/index.mjs +5 -6
- package/dist/{fastify-augmentation-DVsTAy6X.d.mts → fastify-augmentation-Bk_9PoiV.d.mts} +3 -3
- package/dist/{fields-CojeUkS4.mjs → fields-DdP225wt.mjs} +1 -1
- package/dist/{generate-DiB0nHPR.mjs → generate-B1bKdcV9.mjs} +2 -2
- package/dist/{headers-CveNO9gR.mjs → headers-DKslnhey.mjs} +2 -2
- package/dist/{health-CasG2A28.mjs → health-k6NODS8f.mjs} +1 -1
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.mjs +2 -2
- package/dist/idempotency/index.mjs +22 -56
- package/dist/idempotency/redis.mjs +1 -1
- package/dist/{index-B-DvUzsr.d.mts → index-BtYoMip1.d.mts} +21 -3
- package/dist/{index-BcR2bFZQ.d.mts → index-C01wWGJt.d.mts} +33 -105
- package/dist/{index-C5NnMEKF.d.mts → index-C50BUxKs.d.mts} +1 -1
- package/dist/{index-CFAJEWCX.d.mts → index-RdpLP71b.d.mts} +7 -30
- package/dist/{index-ugr1tQlW.d.mts → index-eyg5WEcy.d.mts} +1 -1
- package/dist/index.d.mts +5 -5
- package/dist/index.mjs +11 -12
- package/dist/{init-mdJ-v4Xp.mjs → init-LuGxIbQ_.mjs} +1 -1
- package/dist/integrations/event-gateway.mjs +2 -2
- package/dist/integrations/index.d.mts +2 -2
- package/dist/integrations/index.mjs +1 -1
- package/dist/integrations/jobs/index.d.mts +1 -1
- package/dist/integrations/jobs/index.mjs +2 -2
- package/dist/integrations/mcp/index.d.mts +4 -4
- package/dist/integrations/mcp/index.mjs +2 -2
- package/dist/integrations/mcp/testing.d.mts +1 -1
- package/dist/integrations/mcp/testing.mjs +3 -3
- package/dist/integrations/streamline.mjs +3 -3
- package/dist/integrations/webhooks.d.mts +4 -2
- package/dist/integrations/webhooks.mjs +28 -27
- package/dist/integrations/websocket-pushref-redis.mjs +1 -1
- package/dist/integrations/websocket-redis.mjs +1 -1
- package/dist/integrations/websocket.mjs +1 -1
- package/dist/{interface-DznJrm9R.mjs → interface-B7awDx3b.mjs} +1 -1
- package/dist/{jsonBody-CfGH-GxO.mjs → jsonBody-CiHih3ZU.mjs} +2 -2
- package/dist/{keys-WeKvY1dE.mjs → keys-BcNl12HN.mjs} +1 -1
- package/dist/{loadResources-Bj-aSsXi.mjs → loadResources-DGlfRQc9.mjs} +2 -2
- package/dist/{loadResourcesFromEntry-DwaxNcE2.mjs → loadResourcesFromEntry-VYPGSas8.mjs} +2 -2
- package/dist/logger/index.d.mts +23 -4
- package/dist/logger/index.mjs +50 -7
- package/dist/{mcpPlugin-DX3PHD7K.mjs → mcpPlugin-NxSlc-Ks.mjs} +15 -16
- package/dist/{memory-qYSB7rMQ.mjs → memory-BU-C-MV3.mjs} +2 -2
- package/dist/{metrics-D7uchLjN.mjs → metrics-7_1GbJpl.mjs} +2 -2
- package/dist/middleware/index.d.mts +1 -1
- package/dist/middleware/index.mjs +3 -3
- package/dist/migrations/index.mjs +7 -4
- package/dist/{module-CwKsgZXp.mjs → module-CQNHzE7g.mjs} +1 -1
- package/dist/{multipartBody-4w-S3-PU.mjs → multipartBody-Bi5yqW0M.mjs} +1 -1
- package/dist/{openapi-CkV5mQ53.mjs → openapi-RpNbPBL-.mjs} +6 -6
- package/dist/outbox-admin/index.d.mts +2 -2
- package/dist/outbox-admin/index.mjs +4 -4
- package/dist/{outbox-module-D1QfHqO4.mjs → outbox-module-ClcFrq98.mjs} +6 -4
- package/dist/{outbox-module-C1Bs_FXF.d.mts → outbox-module-b1TyDGGi.d.mts} +24 -1
- package/dist/permissions/index.d.mts +2 -2
- package/dist/permissions/index.mjs +5 -5
- package/dist/{permissions-CP47jdi7.mjs → permissions-DgPrZsJh.mjs} +36 -9
- package/dist/{pipe-BzzoEhHj.mjs → pipe-Cjy1UiXX.mjs} +2 -2
- package/dist/pipeline/index.d.mts +1 -1
- package/dist/pipeline/index.mjs +2 -2
- package/dist/plugins/index.d.mts +92 -7
- package/dist/plugins/index.mjs +168 -17
- package/dist/plugins/response-cache.mjs +2 -2
- package/dist/plugins/tracing-entry.mjs +2 -2
- package/dist/{pluralize-B7xf8qZF.mjs → pluralize-B7m0dPm8.mjs} +1 -1
- package/dist/{preloadResources-g07ldtzh.d.mts → preloadResources-BuutdWgr.d.mts} +54 -270
- package/dist/{createApp-zR-DEesr.mjs → preloadResources-CjnW4iIX.mjs} +170 -34
- package/dist/presets/filesUpload.d.mts +3 -3
- package/dist/presets/filesUpload.mjs +5 -5
- package/dist/presets/index.d.mts +2 -2
- package/dist/presets/index.mjs +2 -2
- package/dist/presets/multiTenant.d.mts +1 -1
- package/dist/presets/multiTenant.mjs +3 -3
- package/dist/presets/search.d.mts +9 -47
- package/dist/presets/search.mjs +2 -2
- package/dist/{presets-BAPijK_A.mjs → presets-CsGg8B58.mjs} +4 -4
- package/dist/{projection-BKM0Ui-s.mjs → projection-koISNyQo.mjs} +2 -2
- package/dist/{queryCachePlugin-DhsZ0ZIc.mjs → queryCachePlugin-DHueQT9O.mjs} +5 -5
- package/dist/{rateLimitKey-XngqVNEV.mjs → rateLimitKey-Bma8VXDO.mjs} +1 -1
- package/dist/{realtime-G1TC6Yzc.mjs → realtime-BBoC91Bz.mjs} +9 -9
- package/dist/{rateLimit-D4-ASwsI.mjs → registerRoute-BTgORTlR.mjs} +114 -3
- package/dist/registry/index.d.mts +2 -2
- package/dist/registry/index.mjs +3 -3
- package/dist/{registry-CLxCR5LF.mjs → registry-BzvRCYS6.mjs} +15 -56
- package/dist/{renewingLease-BnWtbA2U.mjs → renewingLease-CgIGh0Ab.mjs} +14 -2
- package/dist/{replyHelpers-BSBVCwL3.mjs → replyHelpers-BN16KPHr.mjs} +2 -2
- package/dist/{requestContext-uYE35JxI.mjs → requestContext-B93dmpf0.mjs} +1 -1
- package/dist/{rolldown-runtime-DNg-KNCk.mjs → rolldown-runtime-JJWfp8rp.mjs} +1 -1
- package/dist/{runtimeCapabilities-Dm88DaTW.mjs → runtimeCapabilities-jK99Ciw_.mjs} +1 -1
- package/dist/{schedules-CAcZgia0.mjs → schedules-CKKEL21P.mjs} +6 -4
- package/dist/{schemaConverter-XH1RZRyu.mjs → schemaConverter-gg0_aUPF.mjs} +19 -32
- package/dist/{schemaIR-CDvclAew.mjs → schemaIR-CngYvpCF.mjs} +2 -2
- package/dist/schemas/index.mjs +1 -1
- package/dist/scim/index.mjs +2 -2
- package/dist/scope/index.d.mts +1 -1
- package/dist/scope/index.mjs +5 -5
- package/dist/{scope-BaWcqBvr.mjs → scope-B1RsHdjF.mjs} +4 -4
- package/dist/simpleEqualityMatcher-_9NAMHUD.mjs +43 -0
- package/dist/{sse-Cf0jUHsh.mjs → sse-Bxt03Hk5.mjs} +5 -5
- package/dist/{sseStream-Bvpi-UXQ.mjs → sseStream-BMHTLlhR.mjs} +2 -2
- package/dist/{store-helpers-B88p99Z2.mjs → store-helpers-Brt8OxWZ.mjs} +1 -1
- package/dist/{streaming-DsT1B5zJ.mjs → streaming-CiTJW8kZ.mjs} +1 -1
- package/dist/{subscribe-helpers-CLIOHsOK.mjs → subscribe-helpers-B4fNHRNc.mjs} +21 -49
- package/dist/sync/changelog.mjs +1 -1
- package/dist/testing/cleanupStoreContract.mjs +1 -1
- package/dist/testing/index.d.mts +6 -6
- package/dist/testing/index.mjs +10 -11
- package/dist/testing/outboxStoreContract.mjs +1 -1
- package/dist/testing/storageContract.mjs +1 -1
- package/dist/{transactionContext-BYtWnwAS.mjs → transactionContext-D2HwJM2z.mjs} +1 -1
- package/dist/{typeGuards-jjKJDN13.mjs → typeGuards-IE1laMDf.mjs} +1 -1
- package/dist/types/index.d.mts +3 -3
- package/dist/types/index.mjs +1 -1
- package/dist/types/storage.mjs +1 -1
- package/dist/{types-CoqIRrkY.mjs → types-B8lwJv9Q.mjs} +10 -53
- package/dist/{types-BfC83KsP.d.mts → types-BXnTOsXP.d.mts} +1 -1
- package/dist/{types-BcTumAz_.d.mts → types-DDD5RKTu.d.mts} +30 -87
- package/dist/{types-ChuShpCP.d.mts → types-Ddl9OjmE.d.mts} +18 -121
- package/dist/usage/index.d.mts +2 -2
- package/dist/usage/index.mjs +0 -0
- package/dist/{userHelpers-CWF5pbZD.mjs → userHelpers-xQAi5bPF.mjs} +1 -1
- package/dist/utils/index.d.mts +16 -42
- package/dist/utils/index.mjs +11 -11
- package/dist/{utils-h1V_sT-t.mjs → utils-DgNFsJ2c.mjs} +3 -3
- package/dist/{validate-CdQlz52F.mjs → validate-DI3L5V9w.mjs} +2 -2
- package/dist/{versioning-rZbyLVD-.mjs → versioning-COpAyfpZ.mjs} +3 -3
- package/package.json +8 -8
- package/dist/actionPermissions-CUeCmpUd.mjs +0 -25
- package/dist/defineAggregation-Nv-DwfOf.mjs +0 -48
- package/dist/preloadResources-BkyqeTDz.mjs +0 -46
- package/dist/registerRoute-Ba8v0PCa.mjs +0 -113
- package/dist/repositoryFilter-BANpz6BX.mjs +0 -78
- package/dist/simpleEqualityMatcher-Se8VrsaP.mjs +0 -69
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { n as
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
|
+
import { n as evaluateAndApplyPermission } from "./authorizationDecision-EsiY3nUu.mjs";
|
|
3
|
+
import { f as createError } from "./errors-DDKni6Tz.mjs";
|
|
4
|
+
import { u as getRequestScope } from "./types-B8lwJv9Q.mjs";
|
|
5
|
+
import { n as requestContext } from "./requestContext-B93dmpf0.mjs";
|
|
3
6
|
//#region src/core/middlewares/arcDecorator.ts
|
|
4
7
|
/**
|
|
5
8
|
* Build the `arcDecorator` preHandler for a resource.
|
|
@@ -178,6 +181,79 @@ function describeValue(v) {
|
|
|
178
181
|
return `${typeof v} (${JSON.stringify(v).slice(0, 80)})`;
|
|
179
182
|
}
|
|
180
183
|
//#endregion
|
|
184
|
+
//#region src/core/middlewares/permissions.ts
|
|
185
|
+
/**
|
|
186
|
+
* Build a PermissionContext from a Fastify request. Extracted so the CRUD
|
|
187
|
+
* permission middleware and the dynamic action-permission check use the same
|
|
188
|
+
* field layout — divergence here silently broke policy filters for actions.
|
|
189
|
+
*/
|
|
190
|
+
function buildPermissionContext(req, opts) {
|
|
191
|
+
const reqWithExtras = req;
|
|
192
|
+
const params = req.params;
|
|
193
|
+
return {
|
|
194
|
+
user: reqWithExtras.user ?? null,
|
|
195
|
+
scope: getRequestScope(req),
|
|
196
|
+
request: req,
|
|
197
|
+
resource: opts.resource,
|
|
198
|
+
action: opts.action,
|
|
199
|
+
resourceId: opts.resourceId ?? params?.id,
|
|
200
|
+
params,
|
|
201
|
+
data: opts.data ?? req.body
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Static per-route CRUD permission gate. The permission and action are known
|
|
206
|
+
* at route-registration time, so the gate is a plain preHandler.
|
|
207
|
+
*
|
|
208
|
+
* Actions use the dynamic counterpart `buildActionPermissionMw` — their
|
|
209
|
+
* permission is resolved from `body.action` at request time.
|
|
210
|
+
*/
|
|
211
|
+
function buildCrudPermissionMw(permissionCheck, resourceName, action) {
|
|
212
|
+
if (!permissionCheck) return null;
|
|
213
|
+
return async (req, reply) => {
|
|
214
|
+
const context = buildPermissionContext(req, {
|
|
215
|
+
resource: resourceName,
|
|
216
|
+
action
|
|
217
|
+
});
|
|
218
|
+
await evaluateAndApplyPermission(permissionCheck, context, req, reply);
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Dynamic per-action permission gate for the action router.
|
|
223
|
+
*
|
|
224
|
+
* Resolves the permission from `body.action` at request time and runs
|
|
225
|
+
* `evaluateAndApplyPermission` from the canonical `permissionMw` slot — so
|
|
226
|
+
* `_policyFilters` and `request.scope` are installed BEFORE `pluginMw`
|
|
227
|
+
* (idempotency) and `routeGuards` run. Previously this check lived inside
|
|
228
|
+
* the main action handler, which meant idempotency recorded unauthorized
|
|
229
|
+
* requests and route guards saw unfiltered scope — the very divergence
|
|
230
|
+
* routerShared exists to prevent.
|
|
231
|
+
*
|
|
232
|
+
* Also acts as a defensive fallback for invalid action names — the
|
|
233
|
+
* `oneOf` body schema normally rejects these at AJV validation, but
|
|
234
|
+
* hosts that disable schema validation still get a 400 here.
|
|
235
|
+
*/
|
|
236
|
+
function buildActionPermissionMw(actionEnum, actionPermissions, globalAuth, resourceName) {
|
|
237
|
+
const enumSet = new Set(actionEnum);
|
|
238
|
+
const validActions = [...actionEnum];
|
|
239
|
+
return async (req, reply) => {
|
|
240
|
+
const body = req.body ?? {};
|
|
241
|
+
const action = body.action;
|
|
242
|
+
if (!action || !enumSet.has(action)) throw createError(400, `Invalid action '${action ?? ""}'. Valid actions: ${validActions.join(", ")}`, { validActions });
|
|
243
|
+
const permissionCheck = actionPermissions[action] ?? globalAuth;
|
|
244
|
+
if (!permissionCheck) return;
|
|
245
|
+
const { action: _discard, ...data } = body;
|
|
246
|
+
const params = req.params;
|
|
247
|
+
const context = buildPermissionContext(req, {
|
|
248
|
+
resource: resourceName,
|
|
249
|
+
action,
|
|
250
|
+
resourceId: params?.id,
|
|
251
|
+
data
|
|
252
|
+
});
|
|
253
|
+
await evaluateAndApplyPermission(permissionCheck, context, req, reply, { defaultDenialMessage: (user) => user ? `Permission denied for '${action}'` : "Authentication required" });
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
//#endregion
|
|
181
257
|
//#region src/core/middlewares/pluginMw.ts
|
|
182
258
|
/**
|
|
183
259
|
* Pick the request-lifecycle plugin middleware for an HTTP method:
|
|
@@ -246,4 +322,39 @@ function buildRateLimitConfig(rateLimit) {
|
|
|
246
322
|
} };
|
|
247
323
|
}
|
|
248
324
|
//#endregion
|
|
249
|
-
|
|
325
|
+
//#region src/core/middlewares/registerRoute.ts
|
|
326
|
+
/**
|
|
327
|
+
* Register a route with friendly handling of `FST_ERR_DUPLICATED_ROUTE`.
|
|
328
|
+
*
|
|
329
|
+
* Boot-time `validateRouteCrudCollisions()` catches custom-route → auto-CRUD
|
|
330
|
+
* overlaps before Fastify ever runs, but a few cases still slip through to
|
|
331
|
+
* Fastify itself: two presets contributing the same `routes` entry, hosts
|
|
332
|
+
* mounting two resources at the same prefix, custom routes that share a
|
|
333
|
+
* URL with another plugin. Fastify's default message ("Method 'GET'
|
|
334
|
+
* already declared for route '/'") gives no hint at the resource-shaped
|
|
335
|
+
* fix — `disabledRoutes: ['list']` — so wrap it with one.
|
|
336
|
+
*/
|
|
337
|
+
function tryRegisterRoute(fastify, opts, context) {
|
|
338
|
+
try {
|
|
339
|
+
fastify.route(opts);
|
|
340
|
+
} catch (err) {
|
|
341
|
+
const fastifyErr = err;
|
|
342
|
+
if (fastifyErr?.code !== "FST_ERR_DUPLICATED_ROUTE") throw err;
|
|
343
|
+
const method = opts.method;
|
|
344
|
+
const url = opts.url;
|
|
345
|
+
const opHint = context.op ? ` (op: ${context.op})` : "";
|
|
346
|
+
const fixHint = context.op && [
|
|
347
|
+
"list",
|
|
348
|
+
"get",
|
|
349
|
+
"create",
|
|
350
|
+
"update",
|
|
351
|
+
"delete"
|
|
352
|
+
].includes(context.op) ? ` Suppress the auto-CRUD route with \`disabledRoutes: ['${context.op}']\`.` : " If a custom route in `routes:` collides with auto-CRUD, add `disabledRoutes: ['list' | 'get' | 'create' | 'update' | 'delete']` to `defineResource()` to suppress the matching auto-CRUD route.";
|
|
353
|
+
const enhanced = /* @__PURE__ */ new Error(`[arc] Duplicate route ${method} ${url} on resource "${context.resourceName}"${opHint}.${fixHint} Original: ${fastifyErr.message ?? "FST_ERR_DUPLICATED_ROUTE"}`);
|
|
354
|
+
enhanced.code = "FST_ERR_DUPLICATED_ROUTE";
|
|
355
|
+
enhanced.cause = err;
|
|
356
|
+
throw enhanced;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
//#endregion
|
|
360
|
+
export { selectPluginMw as a, buildRouteHooks as c, buildAuthMiddleware as d, buildAuthMiddlewareForPermissions as f, resolveRouterPluginMw as i, resolveRoutePreHandlers as l, buildRateLimitConfig as n, buildActionPermissionMw as o, buildArcDecorator as p, buildRouteConfig as r, buildCrudPermissionMw as s, tryRegisterRoute as t, routeHookOptions as u };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
|
|
2
|
-
import { K as ResolvedTenantPurge, R as RegisterOptions, V as ResourceDefinition, X as CrudRouteKey, k as IntrospectionPluginOptions, p as RegistryEntry, z as ResourceRegistry } from "../index-
|
|
3
|
-
import "../fastify-augmentation-
|
|
2
|
+
import { K as ResolvedTenantPurge, R as RegisterOptions, V as ResourceDefinition, X as CrudRouteKey, k as IntrospectionPluginOptions, p as RegistryEntry, z as ResourceRegistry } from "../index-C01wWGJt.mjs";
|
|
3
|
+
import "../fastify-augmentation-Bk_9PoiV.mjs";
|
|
4
4
|
import { TenantPurgeProgress, TenantPurgeStrategy } from "@classytic/repo-core/repository";
|
|
5
5
|
import { FastifyPluginAsync } from "fastify";
|
|
6
6
|
//#region src/registry/assertNoTenantData.d.ts
|
package/dist/registry/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { a as cascadeDeleteForOrganization, c as assertNoTenantData, i as introspectionPlugin_default, n as buildResourceManifestFromRegistry, o as getCascadingResources, r as introspectionPlugin, s as getCascadingResourcesWithMetadata, t as buildResourceManifest } from "../registry-
|
|
3
|
-
import { t as ResourceRegistry } from "../ResourceRegistry-
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
|
+
import { a as cascadeDeleteForOrganization, c as assertNoTenantData, i as introspectionPlugin_default, n as buildResourceManifestFromRegistry, o as getCascadingResources, r as introspectionPlugin, s as getCascadingResourcesWithMetadata, t as buildResourceManifest } from "../registry-BzvRCYS6.mjs";
|
|
3
|
+
import { t as ResourceRegistry } from "../ResourceRegistry-DNuYVbmv.mjs";
|
|
4
4
|
export { ResourceRegistry, assertNoTenantData, buildResourceManifest, buildResourceManifestFromRegistry, cascadeDeleteForOrganization, getCascadingResources, getCascadingResourcesWithMetadata, introspectionPlugin_default as introspectionPlugin, introspectionPlugin as introspectionPluginFn };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { t as CRUD_OPERATIONS } from "./constants-
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as CRUD_OPERATIONS } from "./constants-DUoKAGYD.mjs";
|
|
3
3
|
import fp from "fastify-plugin";
|
|
4
4
|
//#region src/registry/assertNoTenantData.ts
|
|
5
5
|
/**
|
|
@@ -441,64 +441,23 @@ var introspectionPlugin_default = fp(introspectionPlugin, { name: "arc-introspec
|
|
|
441
441
|
//#endregion
|
|
442
442
|
//#region src/registry/manifest.ts
|
|
443
443
|
/**
|
|
444
|
-
* Resource
|
|
444
|
+
* Resource metadata for frontend code generators — `{ name, prefix, idField,
|
|
445
|
+
* crudOps, actions[] }`, where each action carries its `mount` and
|
|
446
|
+
* `requiresId`.
|
|
445
447
|
*
|
|
446
|
-
*
|
|
447
|
-
*
|
|
448
|
-
*
|
|
449
|
-
* on the resource. The OpenAI-team report flagged this in fajr's
|
|
450
|
-
* `invoices.js`, and now matches needs the same.
|
|
448
|
+
* A hand-rolled FE client needs a method per declarative action and drifts the
|
|
449
|
+
* moment a new one is declared. Arc owns the resource definition, so it can
|
|
450
|
+
* emit the list instead of the host maintaining a parallel one.
|
|
451
451
|
*
|
|
452
|
-
*
|
|
453
|
-
*
|
|
452
|
+
* BE-side only — arc ships no FE runtime. The host decides whether this powers
|
|
453
|
+
* a fetch helper, a TanStack Query factory, an RPC client, or `.d.ts` codegen.
|
|
454
454
|
*
|
|
455
|
-
*
|
|
456
|
-
* name: 'invoice',
|
|
457
|
-
* prefix: '/invoices',
|
|
458
|
-
* idField: '_id',
|
|
459
|
-
* crudOps: ['list', 'get', 'create', 'update', 'delete'],
|
|
460
|
-
* actions: [
|
|
461
|
-
* { name: 'recordPayment', mount: '/:id/action', requiresId: true, description: '...' },
|
|
462
|
-
* { name: 'propose', mount: '/action', requiresId: false, description: '...' },
|
|
463
|
-
* ],
|
|
464
|
-
* }
|
|
465
|
-
*
|
|
466
|
-
* Hosts feed this into their FE generator (or a runtime `createActionsApi`
|
|
467
|
-
* shim) and every action is wired automatically. New actions land on the FE
|
|
468
|
-
* the same moment they're declared on the resource — no parallel list to
|
|
469
|
-
* keep in sync.
|
|
470
|
-
*
|
|
471
|
-
* The helper is BE-side only (lives under `@classytic/arc/registry`) — arc
|
|
472
|
-
* stays a backend framework and doesn't ship FE runtime code. The host
|
|
473
|
-
* decides whether the manifest powers a fetch-based helper, a TanStack
|
|
474
|
-
* Query factory, an RPC client, or static `.d.ts` generation.
|
|
475
|
-
*
|
|
476
|
-
* @example BE → emit JSON at build time / on a route
|
|
455
|
+
* @example
|
|
477
456
|
* ```ts
|
|
478
|
-
* //
|
|
479
|
-
*
|
|
480
|
-
*
|
|
481
|
-
*
|
|
482
|
-
* JSON.stringify(buildResourceManifest(invoiceResource)));
|
|
483
|
-
*
|
|
484
|
-
* // Runtime introspection endpoint
|
|
485
|
-
* fastify.get('/manifest/:name', async (req) => {
|
|
486
|
-
* const r = arc.registry.get(req.params.name);
|
|
487
|
-
* return r ? buildResourceManifestFromRegistry(r) : reply.code(404);
|
|
488
|
-
* });
|
|
489
|
-
* ```
|
|
490
|
-
*
|
|
491
|
-
* @example FE → generate fetch methods from the manifest
|
|
492
|
-
* ```ts
|
|
493
|
-
* import manifest from './fe-gen/invoice.manifest.json';
|
|
494
|
-
* import { createActionsApi } from './my-fe-shim.js'; // host-owned
|
|
495
|
-
*
|
|
496
|
-
* export const invoicesApi = {
|
|
497
|
-
* ...createCrudApi(manifest.prefix),
|
|
498
|
-
* ...createActionsApi(manifest.prefix, manifest.actions),
|
|
499
|
-
* // → invoicesApi.recordPayment(id, body)
|
|
500
|
-
* // → invoicesApi.propose(body) // id-less
|
|
501
|
-
* };
|
|
457
|
+
* // build time
|
|
458
|
+
* writeFileSync('invoice.manifest.json', JSON.stringify(buildResourceManifest(r)));
|
|
459
|
+
* // or at runtime, from the live registry
|
|
460
|
+
* buildResourceManifestFromRegistry(arc.registry.get(name));
|
|
502
461
|
* ```
|
|
503
462
|
*/
|
|
504
463
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
2
|
//#region src/lock/renewingLease.ts
|
|
3
3
|
/**
|
|
4
4
|
* Start renewing an ALREADY-ACQUIRED lease. The caller performed the
|
|
@@ -8,14 +8,23 @@
|
|
|
8
8
|
function startRenewingLease(options) {
|
|
9
9
|
const { lock, name, holderId, leaseMs, onLost, onError } = options;
|
|
10
10
|
const renewEveryMs = options.renewEveryMs ?? Math.max(10, Math.floor(leaseMs / 2));
|
|
11
|
+
const fenced = typeof lock.tryAcquireFenced === "function" && options.token !== void 0;
|
|
11
12
|
let stopped = false;
|
|
12
13
|
let lost = false;
|
|
14
|
+
let token = options.token;
|
|
13
15
|
let timer;
|
|
14
16
|
let inFlight;
|
|
15
17
|
const scheduleNext = () => {
|
|
16
18
|
if (stopped) return;
|
|
17
19
|
timer = setTimeout(() => {
|
|
18
|
-
inFlight = Promise.resolve(lock.
|
|
20
|
+
inFlight = (fenced ? Promise.resolve(lock.tryAcquireFenced?.(name, holderId, leaseMs)).then((result) => {
|
|
21
|
+
if (result === null || result === void 0) return false;
|
|
22
|
+
if (result.token !== token) {
|
|
23
|
+
token = result.token;
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
return true;
|
|
27
|
+
}) : Promise.resolve(lock.tryAcquire(name, holderId, leaseMs))).then((renewed) => {
|
|
19
28
|
if (!renewed && !lost) {
|
|
20
29
|
lost = true;
|
|
21
30
|
onLost?.();
|
|
@@ -34,6 +43,9 @@ function startRenewingLease(options) {
|
|
|
34
43
|
get lost() {
|
|
35
44
|
return lost;
|
|
36
45
|
},
|
|
46
|
+
get token() {
|
|
47
|
+
return token;
|
|
48
|
+
},
|
|
37
49
|
async stop() {
|
|
38
50
|
stopped = true;
|
|
39
51
|
if (timer) clearTimeout(timer);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { t as __exportAll } from "./rolldown-runtime-
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as __exportAll } from "./rolldown-runtime-JJWfp8rp.mjs";
|
|
3
3
|
import { toCanonicalList } from "@classytic/repo-core/pagination";
|
|
4
4
|
import fp from "fastify-plugin";
|
|
5
5
|
//#region src/plugins/replyHelpers.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { t as __exportAll } from "./rolldown-runtime-
|
|
3
|
-
import { t as startRenewingLease } from "./renewingLease-
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as __exportAll } from "./rolldown-runtime-JJWfp8rp.mjs";
|
|
3
|
+
import { t as startRenewingLease } from "./renewingLease-CgIGh0Ab.mjs";
|
|
4
4
|
import fp from "fastify-plugin";
|
|
5
5
|
//#region src/plugins/schedules.ts
|
|
6
6
|
var schedules_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -40,7 +40,8 @@ const schedulesPlugin = async (fastify, opts) => {
|
|
|
40
40
|
if (lock) {
|
|
41
41
|
const lockName = `arc:schedule:${s.name}`;
|
|
42
42
|
const leaseMs = s.leaseMs ?? Math.min(Math.floor(s.every * .9), MAX_DEFAULT_LEASE_MS);
|
|
43
|
-
|
|
43
|
+
const fenced = await lock.tryAcquireFenced?.(lockName, holderId, leaseMs);
|
|
44
|
+
if (!(fenced !== void 0 ? fenced !== null : await lock.tryAcquire(lockName, holderId, leaseMs))) {
|
|
44
45
|
stat.skippedByLock++;
|
|
45
46
|
return;
|
|
46
47
|
}
|
|
@@ -49,6 +50,7 @@ const schedulesPlugin = async (fastify, opts) => {
|
|
|
49
50
|
name: lockName,
|
|
50
51
|
holderId,
|
|
51
52
|
leaseMs,
|
|
53
|
+
...fenced ? { token: fenced.token } : {},
|
|
52
54
|
onLost: () => fastify.log.warn({ schedule: s.name }, "[arc-schedules] lease renewal lost — another holder took the lock; this run may now overlap. Handlers should be idempotent."),
|
|
53
55
|
onError: (err) => fastify.log.warn({
|
|
54
56
|
err,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
2
|
import { arcLog } from "./logger/index.mjs";
|
|
3
3
|
//#region src/utils/schemaConverter.ts
|
|
4
4
|
/**
|
|
@@ -14,44 +14,31 @@ import { arcLog } from "./logger/index.mjs";
|
|
|
14
14
|
* boot with an actionable error; DOC paths warn and degrade — see
|
|
15
15
|
* {@link UnconvertibleMode}. Hosts that never pass Zod pay nothing.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
17
|
+
* TARGET — `draft-7` for Fastify route schemas, `openapi-3.0` for docs. Fastify
|
|
18
|
+
* v5's AJV 8 is draft-07 and wants NUMERIC `exclusiveMinimum`; the
|
|
19
|
+
* `openapi-3.0` target emits the draft-04 boolean form, which AJV rejects at
|
|
20
|
+
* registration (`exclusiveMinimum must be number`). Using `draft-7` makes
|
|
21
|
+
* `.positive()` / `.gt()` work unmodified.
|
|
18
22
|
*
|
|
19
|
-
* Zod
|
|
20
|
-
*
|
|
21
|
-
* - **`draft-7`** (default) — for Fastify route schemas. Fastify v5 bundles AJV 8
|
|
22
|
-
* configured for draft-07, which uses **numeric** `exclusiveMinimum`/`exclusiveMaximum`.
|
|
23
|
-
* The `openapi-3.0` target emits the **boolean** form inherited from draft-04
|
|
24
|
-
* (`exclusiveMinimum: true` alongside `minimum`), which AJV rejects at route
|
|
25
|
-
* registration with `schema is invalid: data/properties/X/exclusiveMinimum must be number`.
|
|
26
|
-
* Using `draft-7` fixes `.positive() / .negative() / .gt() / .lt()` out of the box.
|
|
27
|
-
* - **`openapi-3.0`** — for OpenAPI doc generation (arc emits OpenAPI 3.0.3). Keeps
|
|
28
|
-
* the boolean exclusive form that 3.0 tooling expects.
|
|
29
|
-
*
|
|
30
|
-
* ## Input vs output (`io`)
|
|
31
|
-
*
|
|
32
|
-
* A Zod schema has TWO shapes and `z.toJSONSchema()` emits one of them. Getting
|
|
33
|
-
* this wrong is not cosmetic — it rejects legal traffic:
|
|
23
|
+
* IO DIRECTION — a Zod schema has two shapes and getting this wrong REJECTS
|
|
24
|
+
* LEGAL TRAFFIC:
|
|
34
25
|
*
|
|
35
26
|
* ```ts
|
|
36
27
|
* z.object({ title: z.string(), status: z.string().default("draft") })
|
|
37
|
-
* // io: "output" → required: ["title", "status"]
|
|
38
|
-
* // io: "input" → required: ["title"]
|
|
28
|
+
* // io: "output" → required: ["title", "status"] ← omitting `status` is rejected
|
|
29
|
+
* // io: "input" → required: ["title"] ← correct; the default fills it
|
|
39
30
|
* ```
|
|
40
31
|
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* validates what the client SENDS, before defaults/transforms/coercion apply.
|
|
47
|
-
* - **response** (and the `entity` doc shape) → `io: "output"` — describes what
|
|
48
|
-
* the server RETURNS, after they apply.
|
|
32
|
+
* `.transform()` is worse in output mode: unrepresentable, so it degrades to
|
|
33
|
+
* `{}` — no validation at all. Arc therefore converts by direction: REQUESTS
|
|
34
|
+
* (`body`/`querystring`/`params`/`headers`) use `io: "input"`, validating what
|
|
35
|
+
* the client sends before defaults and transforms; RESPONSES (and the `entity`
|
|
36
|
+
* shape) use `io: "output"`, describing what the server returns.
|
|
49
37
|
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* `z.
|
|
53
|
-
*
|
|
54
|
-
* them; it keeps `additionalProperties: false` in both modes.
|
|
38
|
+
* Consequence: plain `z.object()` emits `additionalProperties: false` only in
|
|
39
|
+
* output mode, because it STRIPS unknown keys rather than rejecting them — so
|
|
40
|
+
* extra keys are legal input. Use `z.strictObject()` when the wire contract
|
|
41
|
+
* must reject them; it holds in both modes.
|
|
55
42
|
*/
|
|
56
43
|
const log = arcLog("schema");
|
|
57
44
|
/** Default target for Fastify-consumed schemas (matches Fastify v5's default AJV draft). */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { o as toJsonSchema } from "./schemaConverter-
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
|
+
import { o as toJsonSchema } from "./schemaConverter-gg0_aUPF.mjs";
|
|
3
3
|
//#region src/core/schemaIR.ts
|
|
4
4
|
/**
|
|
5
5
|
* Schema IR — one canonical representation, two adapters.
|
package/dist/schemas/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
2
|
import { errorContractSchema, errorDetailSchema } from "@classytic/repo-core/errors";
|
|
3
3
|
import { Type, Type as Type$1 } from "typebox";
|
|
4
4
|
//#region src/schemas/index.ts
|
package/dist/scim/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { t as parseJsonBody } from "../jsonBody-
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as parseJsonBody } from "../jsonBody-CiHih3ZU.mjs";
|
|
3
3
|
import fp from "fastify-plugin";
|
|
4
4
|
//#region src/scim/errors.ts
|
|
5
5
|
var ScimError = class extends Error {
|
package/dist/scope/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
import { A as requireOrgId, C as hasOrgAccess, D as isOrgInScope, E as isMember, M as requireUserId, N as scopeFirstCtx, O as isService, S as getUserRoles, T as isElevated, _ as getScopeContextMap, a as ScopeFirstCtx, b as getTenantFromRequest, c as getAncestorOrgIds, d as getMandate, f as getOrgContext, g as getScopeContext, h as getRequestScope, i as RequestScope, j as requireTeamId, k as requireClientId, l as getClientId, m as getOrgRoles, n as Mandate, o as ScopeFirstCtxOptions, p as getOrgId, r as PUBLIC_SCOPE, s as ScopeFirstCtxRequest, t as AUTHENTICATED_SCOPE, u as getDPoPJkt, v as getServiceScopes, w as isAuthenticated, x as getUserId, y as getTeamId } from "../types-
|
|
2
|
+
import { A as requireOrgId, C as hasOrgAccess, D as isOrgInScope, E as isMember, M as requireUserId, N as scopeFirstCtx, O as isService, S as getUserRoles, T as isElevated, _ as getScopeContextMap, a as ScopeFirstCtx, b as getTenantFromRequest, c as getAncestorOrgIds, d as getMandate, f as getOrgContext, g as getScopeContext, h as getRequestScope, i as RequestScope, j as requireTeamId, k as requireClientId, l as getClientId, m as getOrgRoles, n as Mandate, o as ScopeFirstCtxOptions, p as getOrgId, r as PUBLIC_SCOPE, s as ScopeFirstCtxRequest, t as AUTHENTICATED_SCOPE, u as getDPoPJkt, v as getServiceScopes, w as isAuthenticated, x as getUserId, y as getTeamId } from "../types-Ddl9OjmE.mjs";
|
|
3
3
|
import { i as elevationPlugin, n as ElevationOptions, r as _default, t as ElevationEvent } from "../elevation-BXCfVcNG.mjs";
|
|
4
4
|
import { FastifyReply, FastifyRequest } from "fastify";
|
|
5
5
|
//#region src/scope/rateLimitKey.d.ts
|
package/dist/scope/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { C as isService, D as requireUserId, E as requireTeamId, O as scopeFirstCtx, S as isOrgInScope, T as requireOrgId, _ as getUserRoles, a as getDPoPJkt, b as isElevated, c as getOrgId, d as getScopeContext, f as getScopeContextMap, g as getUserId, h as getTenantFromRequest, i as getClientId, l as getOrgRoles, m as getTeamId, n as PUBLIC_SCOPE, o as getMandate, p as getServiceScopes, r as getAncestorOrgIds, s as getOrgContext, t as AUTHENTICATED_SCOPE, u as getRequestScope, v as hasOrgAccess, w as requireClientId, x as isMember, y as isAuthenticated } from "../types-
|
|
3
|
-
import { n as elevation_default, t as elevationPlugin } from "../elevation-
|
|
4
|
-
import { t as createTenantKeyGenerator } from "../rateLimitKey-
|
|
5
|
-
import { t as resolveOrgFromHeader } from "../scope-
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
|
+
import { C as isService, D as requireUserId, E as requireTeamId, O as scopeFirstCtx, S as isOrgInScope, T as requireOrgId, _ as getUserRoles, a as getDPoPJkt, b as isElevated, c as getOrgId, d as getScopeContext, f as getScopeContextMap, g as getUserId, h as getTenantFromRequest, i as getClientId, l as getOrgRoles, m as getTeamId, n as PUBLIC_SCOPE, o as getMandate, p as getServiceScopes, r as getAncestorOrgIds, s as getOrgContext, t as AUTHENTICATED_SCOPE, u as getRequestScope, v as hasOrgAccess, w as requireClientId, x as isMember, y as isAuthenticated } from "../types-B8lwJv9Q.mjs";
|
|
3
|
+
import { n as elevation_default, t as elevationPlugin } from "../elevation-D_cmo80j.mjs";
|
|
4
|
+
import { t as createTenantKeyGenerator } from "../rateLimitKey-Bma8VXDO.mjs";
|
|
5
|
+
import { t as resolveOrgFromHeader } from "../scope-B1RsHdjF.mjs";
|
|
6
6
|
export { AUTHENTICATED_SCOPE, PUBLIC_SCOPE, createTenantKeyGenerator, elevation_default as elevationPlugin, elevationPlugin as elevationPluginFn, getAncestorOrgIds, getClientId, getDPoPJkt, getMandate, getOrgContext, getOrgId, getOrgRoles, getRequestScope, getScopeContext, getScopeContextMap, getServiceScopes, getTeamId, getTenantFromRequest, getUserId, getUserRoles, hasOrgAccess, isAuthenticated, isElevated, isMember, isOrgInScope, isService, requireClientId, requireOrgId, requireTeamId, requireUserId, resolveOrgFromHeader, scopeFirstCtx };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { a as OrgAccessDeniedError, l as UnauthorizedError } from "./errors-
|
|
3
|
-
import { n as requireSingleHeaderValue } from "./headers-
|
|
4
|
-
import { n as getUserRoles } from "./userHelpers-
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
|
+
import { a as OrgAccessDeniedError, l as UnauthorizedError } from "./errors-DDKni6Tz.mjs";
|
|
3
|
+
import { n as requireSingleHeaderValue } from "./headers-DKslnhey.mjs";
|
|
4
|
+
import { n as getUserRoles } from "./userHelpers-xQAi5bPF.mjs";
|
|
5
5
|
//#region src/scope/resolveOrgFromHeader.ts
|
|
6
6
|
/**
|
|
7
7
|
* Create a preHandler hook that resolves org scope from a header.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
|
+
//#region src/utils/simpleEqualityMatcher.ts
|
|
3
|
+
/**
|
|
4
|
+
* `simpleEqualityMatcher` — a minimal, dialect-agnostic flat-key equality
|
|
5
|
+
* matcher for `DataAdapter.matchesFilter` / `BaseController({ matchesFilter })`.
|
|
6
|
+
*
|
|
7
|
+
* Compares `item[key]` to each filter value by string coercion, so a Mongo
|
|
8
|
+
* `ObjectId` matches its string form; array values match by contains. ALL
|
|
9
|
+
* entries must match.
|
|
10
|
+
*
|
|
11
|
+
* NOT an operator engine: no `$in`/`$ne`/`$gt`/`$regex`/`$exists`, no
|
|
12
|
+
* `$and`/`$or`, no dot paths, no schema coercion. Most `_policyFilters` from
|
|
13
|
+
* arc's built-in permission helpers are flat equality (`{ ownerId }`,
|
|
14
|
+
* `{ organizationId }`), and this covers exactly that — defense-in-depth for
|
|
15
|
+
* hosts on minimal repos with no `getOne(compoundFilter)` path.
|
|
16
|
+
*
|
|
17
|
+
* Do NOT use it with operator-shaped filters — supply a native matcher instead
|
|
18
|
+
* (a kit's predicate engine). Kit users need neither: the DB-level filter in
|
|
19
|
+
* `getOne(compoundFilter)` already applies.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* const adapter: DataAdapter = { repository, type: 'custom', name: 'in-memory',
|
|
24
|
+
* matchesFilter: simpleEqualityMatcher };
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
function simpleEqualityMatcher(item, filters) {
|
|
28
|
+
if (!item || typeof item !== "object") return false;
|
|
29
|
+
const obj = item;
|
|
30
|
+
for (const [key, expected] of Object.entries(filters)) {
|
|
31
|
+
if (expected && typeof expected === "object" && !Array.isArray(expected) && Object.getPrototypeOf(expected) === Object.prototype && Object.keys(expected).some((k) => k.startsWith("$"))) return false;
|
|
32
|
+
const actual = obj[key];
|
|
33
|
+
if (Array.isArray(actual)) {
|
|
34
|
+
const expectedStr = String(expected);
|
|
35
|
+
if (!actual.some((v) => String(v) === expectedStr)) return false;
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (String(actual) !== String(expected)) return false;
|
|
39
|
+
}
|
|
40
|
+
return true;
|
|
41
|
+
}
|
|
42
|
+
//#endregion
|
|
43
|
+
export { simpleEqualityMatcher as t };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { t as __exportAll } from "./rolldown-runtime-
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
|
+
import { t as __exportAll } from "./rolldown-runtime-JJWfp8rp.mjs";
|
|
3
3
|
import { arcLog } from "./logger/index.mjs";
|
|
4
|
-
import { c as getOrgId, n as PUBLIC_SCOPE } from "./types-
|
|
5
|
-
import { a as promoteStreamTokenToHeader } from "./streaming-
|
|
6
|
-
import { t as openSseStream } from "./sseStream-
|
|
4
|
+
import { c as getOrgId, n as PUBLIC_SCOPE } from "./types-B8lwJv9Q.mjs";
|
|
5
|
+
import { a as promoteStreamTokenToHeader } from "./streaming-CiTJW8kZ.mjs";
|
|
6
|
+
import { t as openSseStream } from "./sseStream-BMHTLlhR.mjs";
|
|
7
7
|
import fp from "fastify-plugin";
|
|
8
8
|
//#region src/plugins/sse.ts
|
|
9
9
|
var sse_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/*! @classytic/arc v2.
|
|
2
|
-
import { n as forwardedStreamHeaders } from "./streaming-
|
|
1
|
+
/*! @classytic/arc v2.36.0 | MIT | https://classytic.com */
|
|
2
|
+
import { n as forwardedStreamHeaders } from "./streaming-CiTJW8kZ.mjs";
|
|
3
3
|
//#region src/utils/sseStream.ts
|
|
4
4
|
/**
|
|
5
5
|
* Take over the reply socket and open an SSE stream. Call ONLY after every
|