@classytic/arc 2.19.0 → 2.21.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-BnLYgE9A.mjs} +4 -4
- package/dist/{EventTransport-IEn7Tn-Q.d.mts → EventTransport-QmY7A258.d.mts} +0 -1
- package/dist/{QueryCache-TRfXau3W.d.mts → QueryCache-Z1B38koh.d.mts} +0 -1
- package/dist/{ResourceRegistry-5fKZwhK_.mjs → ResourceRegistry-7RnrEWNP.mjs} +1 -1
- package/dist/{actionPermissions-D7NGwcAR.mjs → actionPermissions-ze70xXJi.mjs} +1 -1
- package/dist/audit/index.d.mts +9 -5
- package/dist/audit/index.mjs +1 -1
- package/dist/auth/audit.d.mts +7 -4
- package/dist/auth/audit.mjs +5 -0
- package/dist/auth/index.d.mts +7 -14
- package/dist/auth/index.mjs +7 -5
- package/dist/auth/redis-session.d.mts +1 -2
- package/dist/{buildHandler-B0qvAguf.mjs → buildHandler-D_2ULWxZ.mjs} +3 -3
- package/dist/cache/index.d.mts +2 -3
- package/dist/cache/index.mjs +2 -2
- package/dist/cli/commands/describe.d.mts +1 -2
- 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/context/index.d.mts +2 -2
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +5 -5
- package/dist/{core-Ba-6Sue6.mjs → core-DZ6Xe1jR.mjs} +182 -55
- package/dist/{createActionRouter-B_WzBFyf.mjs → createActionRouter-BWMDW-dL.mjs} +4 -4
- package/dist/{createAggregationRouter-B_G_nIjm.mjs → createAggregationRouter-l5mNdYrZ.mjs} +5 -4
- package/dist/{createApp--703hQE1.mjs → createApp-Bi61XxqU.mjs} +229 -24
- package/dist/discovery/index.d.mts +0 -1
- package/dist/docs/index.d.mts +1 -2
- package/dist/docs/index.mjs +1 -1
- package/dist/{elevation-xGUBq6p_.d.mts → elevation-C9s5hFP_.d.mts} +0 -1
- package/dist/encryption/index.d.mts +2 -144
- package/dist/{errorHandler-BtUUDPEa.d.mts → errorHandler-B0e-bq-O.d.mts} +0 -1
- package/dist/{errors-DOHkjQlD.d.mts → errors-DHcHVAgk.d.mts} +0 -1
- package/dist/{eventPlugin-DbBFd3x_.d.mts → eventPlugin-A6EbthXR.d.mts} +10 -6
- package/dist/events/index.d.mts +9 -6
- package/dist/events/index.mjs +9 -6
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis.d.mts +1 -2
- package/dist/factory/index.d.mts +5 -4
- package/dist/factory/index.mjs +3 -3
- package/dist/{fastify-augmentation-D-5_yQJi.d.mts → fastify-augmentation-DafigGQp.d.mts} +12 -2
- package/dist/{fields-C7ahdGYf.d.mts → fields-BGqrAa_u.d.mts} +1 -2
- package/dist/{generate-Brans3fW.mjs → generate-usRSdQmP.mjs} +4 -3
- package/dist/hooks/index.d.mts +1 -1
- package/dist/idempotency/index.d.mts +4 -3
- package/dist/idempotency/index.mjs +1 -1
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/{index-CP6A1Ffj.d.mts → index-B5N-NaHs.d.mts} +88 -7
- package/dist/{index-CRKiiP5o.d.mts → index-B5PoNbfu.d.mts} +41 -7
- package/dist/{index-CUTG2Cuo.d.mts → index-Dtrj6XZk.d.mts} +90 -29
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +7 -7
- package/dist/{init-Bqpt1Hxf.mjs → init-0YhHkXGk.mjs} +239 -140
- package/dist/integrations/event-gateway.d.mts +2 -3
- package/dist/integrations/index.d.mts +2 -2
- package/dist/integrations/jobs.d.mts +0 -1
- package/dist/integrations/mcp/index.d.mts +6 -7
- package/dist/integrations/mcp/index.mjs +1 -1
- package/dist/integrations/mcp/testing.d.mts +1 -2
- package/dist/integrations/mcp/testing.mjs +1 -1
- package/dist/integrations/streamline.d.mts +19 -7
- package/dist/integrations/streamline.mjs +9 -5
- package/dist/integrations/webhooks.d.mts +0 -1
- package/dist/integrations/websocket-pushref-redis.d.mts +1 -2
- package/dist/integrations/websocket-redis.d.mts +1 -2
- package/dist/integrations/websocket.d.mts +2 -2
- package/dist/{loadResources-B8UmpITt.mjs → loadResources-DpU8pfjV.mjs} +4 -3
- package/dist/{loadResourcesFromEntry-BTlFEx05.mjs → loadResourcesFromEntry-OMCvIEE7.mjs} +1 -1
- package/dist/{mcpPlugin-C088Nd-G.mjs → mcpPlugin-B9XjjNVG.mjs} +148 -49
- package/dist/middleware/index.d.mts +1 -2
- package/dist/middleware/index.mjs +1 -1
- package/dist/module-WeuU5jfd.d.mts +429 -0
- package/dist/{openapi-DZ-5a5Op.mjs → openapi-Kyod_di6.mjs} +3 -3
- package/dist/permissions/index.d.mts +3 -3
- package/dist/permissions/index.mjs +2 -2
- package/dist/{permissions-BPB1xqGf.mjs → permissions-BJMuKMl7.mjs} +43 -3
- package/dist/pipeline/index.d.mts +1 -2
- package/dist/plugins/index.d.mts +87 -10
- package/dist/plugins/index.mjs +91 -4
- package/dist/plugins/response-cache.d.mts +5 -3
- package/dist/plugins/tracing-entry.d.mts +1 -1
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/{pluralize-DccFV9R7.mjs → pluralize-BhrgwZb9.mjs} +3 -3
- package/dist/presets/filesUpload.d.mts +4 -5
- package/dist/presets/filesUpload.mjs +1 -1
- package/dist/presets/index.d.mts +16 -3
- package/dist/presets/index.mjs +1 -1
- package/dist/presets/multiTenant.d.mts +1 -2
- package/dist/presets/multiTenant.mjs +1 -1
- package/dist/presets/search.d.mts +2 -3
- package/dist/presets/search.mjs +3 -2
- package/dist/{presets-BtyFwTO4.mjs → presets-gw0ciIUD.mjs} +1 -1
- package/dist/{pushref-registry-DnCqL3aa.d.mts → pushref-registry-BbcnpNTm.d.mts} +4 -2
- package/dist/{queryCachePlugin-xzFyKAjT.d.mts → queryCachePlugin-CfYWq-Ak.d.mts} +1 -2
- package/dist/{queryCachePlugin-emHb0CuX.mjs → queryCachePlugin-DzqLN904.mjs} +2 -2
- package/dist/{redis-C3W0qbz8.d.mts → redis-UDtLaNj6.d.mts} +0 -1
- package/dist/{redis-stream-DsP1vqZB.d.mts → redis-stream-iVR2l7aS.d.mts} +1 -2
- package/dist/{registerRoute-BdV8DDwU.mjs → registerRoute-oGAl0oA8.mjs} +1 -1
- package/dist/registry/index.d.mts +2 -2
- 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/schemas/index.d.mts +0 -1
- package/dist/scim/index.d.mts +0 -1
- package/dist/scim/index.mjs +2 -2
- package/dist/scope/index.d.mts +2 -3
- package/dist/{sessionManager-BXG-HGwG.d.mts → sessionManager-BHOM3N_0.d.mts} +10 -6
- package/dist/{storage-Co_PQpeQ.d.mts → storage-DLUZ04kK.d.mts} +8 -4
- package/dist/sync/changelog.d.mts +2 -0
- package/dist/sync/changelog.mjs +2 -0
- package/dist/testing/index.d.mts +2 -3
- package/dist/testing/index.mjs +6 -3
- package/dist/testing/storageContract.d.mts +1 -2
- package/dist/{tracing-D8jlGXP7.d.mts → tracing-CsGKQJGg.d.mts} +0 -1
- package/dist/types/index.d.mts +4 -4
- package/dist/types/storage.d.mts +1 -1
- package/dist/types-Cc91nXuA.d.mts +132 -0
- package/dist/{types-LNebCoJx.d.mts → types-DH0GupI7.d.mts} +8 -4
- package/dist/{types-DpvSF5Hh.d.mts → types-DRj-Ut4n.d.mts} +1 -2
- package/dist/{types-9_wtNPsI.d.mts → types-DpxoNX5v.d.mts} +112 -214
- package/dist/utils/index.d.mts +182 -128
- package/dist/utils/index.mjs +2 -2
- package/dist/{utils-C6QQ9-hd.mjs → utils-CO8a3B_1.mjs} +1435 -1391
- package/dist/{validate-CRcaWzp2.mjs → validate-C2mGgSXg.mjs} +3 -3
- package/dist/{versioning-D_eBCfNr.d.mts → versioning-DQ4mCvg0.d.mts} +1 -2
- package/dist/{websocket-MlYlrYq0.d.mts → websocket-uuWqM6UY.d.mts} +5 -4
- package/package.json +18 -13
- package/skills/arc/SKILL.md +10 -0
- package/skills/arc/references/mcp.md +2 -0
- package/skills/arc-module-publishing/SKILL.md +242 -0
- package/skills/arc-module-publishing/references/authoring-modules.md +272 -0
- package/skills/arc-module-publishing/references/package-manifest.md +155 -0
- package/skills/arc-module-publishing/references/publishing-workflow.md +182 -0
package/dist/events/index.mjs
CHANGED
|
@@ -417,12 +417,13 @@ function repositoryAsOutboxStore(repository) {
|
|
|
417
417
|
},
|
|
418
418
|
async getPending(limit) {
|
|
419
419
|
const now = /* @__PURE__ */ new Date();
|
|
420
|
-
|
|
420
|
+
const result = await r.getAll({
|
|
421
421
|
filters: claimableFilter(now),
|
|
422
422
|
sort: { createdAt: 1 },
|
|
423
423
|
page: 1,
|
|
424
424
|
limit
|
|
425
|
-
})
|
|
425
|
+
});
|
|
426
|
+
return unwrapDocs(result).map((d) => d.event).filter(isWellFormed);
|
|
426
427
|
},
|
|
427
428
|
async claimPending(options) {
|
|
428
429
|
const limit = options?.limit ?? DEFAULT_CLAIM_LIMIT;
|
|
@@ -493,12 +494,13 @@ function repositoryAsOutboxStore(repository) {
|
|
|
493
494
|
}
|
|
494
495
|
},
|
|
495
496
|
async getDeadLettered(limit) {
|
|
496
|
-
|
|
497
|
+
const result = await r.getAll({
|
|
497
498
|
filters: eq("status", "dead_letter"),
|
|
498
499
|
sort: { [idField]: 1 },
|
|
499
500
|
page: 1,
|
|
500
501
|
limit
|
|
501
|
-
})
|
|
502
|
+
});
|
|
503
|
+
return unwrapDocs(result).filter((d) => isWellFormed(d.event)).map((d) => ({
|
|
502
504
|
event: d.event,
|
|
503
505
|
error: {
|
|
504
506
|
message: d.lastError?.message ?? "unknown",
|
|
@@ -513,13 +515,14 @@ function repositoryAsOutboxStore(repository) {
|
|
|
513
515
|
const cutoff = new Date(Date.now() - olderThanMs);
|
|
514
516
|
let totalDeleted = 0;
|
|
515
517
|
for (;;) {
|
|
516
|
-
const
|
|
518
|
+
const result = await r.getAll({
|
|
517
519
|
filters: and(eq("status", "delivered"), lte("deliveredAt", cutoff)),
|
|
518
520
|
sort: { deliveredAt: 1 },
|
|
519
521
|
page: 1,
|
|
520
522
|
limit: DEFAULT_PURGE_BATCH,
|
|
521
523
|
select: idField
|
|
522
|
-
})
|
|
524
|
+
});
|
|
525
|
+
const batch = unwrapDocs(result);
|
|
523
526
|
if (batch.length === 0) break;
|
|
524
527
|
const ids = batch.map((d) => d[idField]);
|
|
525
528
|
const res = await r.deleteMany(anyOf(idField, ids));
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as RedisStreamTransport, r as RedisStreamTransportOptions, t as RedisStreamLike } from "../../redis-stream-
|
|
1
|
+
import { n as RedisStreamTransport, r as RedisStreamTransportOptions, t as RedisStreamLike } from "../../redis-stream-iVR2l7aS.mjs";
|
|
2
2
|
export { type RedisStreamLike, RedisStreamTransport, type RedisStreamTransportOptions };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { a as EventTransport, i as EventLogger, n as DomainEvent, r as EventHandler } from "../../EventTransport-
|
|
2
|
-
|
|
1
|
+
import { a as EventTransport, i as EventLogger, n as DomainEvent, r as EventHandler } from "../../EventTransport-QmY7A258.mjs";
|
|
3
2
|
//#region src/events/transports/redis.d.ts
|
|
4
3
|
interface RedisLike {
|
|
5
4
|
publish(channel: string, message: string): Promise<number>;
|
package/dist/factory/index.d.mts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as getModuleExports, c as LoadResourcesOptions, d as loadResources, i as defineModule, l as ResourceLike, n as ArcModuleInput, o as orderModules, r as ArcModuleRegistry, s as resolveModule, t as ArcModule, u as ResourceModule } from "../module-WeuU5jfd.mjs";
|
|
2
|
+
import "../fastify-augmentation-DafigGQp.mjs";
|
|
3
|
+
import { a as CustomPluginAuthOption, c as RawBodyOptions, d as preloadResourcesAsync, i as CustomAuthenticatorOption, l as UnderPressureOptions, n as BetterAuthOption, o as JwtAuthOption, r as CreateAppOptions, s as MultipartOptions, t as AuthOption, u as preloadResources } from "../types-DpxoNX5v.mjs";
|
|
2
4
|
import { FastifyInstance, FastifyServerOptions } from "fastify";
|
|
3
|
-
|
|
4
5
|
//#region src/factory/createApp.d.ts
|
|
5
6
|
/**
|
|
6
7
|
* Create a production-ready Fastify application with Arc framework.
|
|
7
8
|
*
|
|
8
9
|
* Boot order:
|
|
9
10
|
* ```
|
|
10
|
-
* 0. Logger, validation, preset merge
|
|
11
|
+
* 0. Logger, validation → beforeBoot() (DB connect etc.), preset merge
|
|
11
12
|
* 1. Create Fastify instance
|
|
12
13
|
* 2. Security plugins (Helmet, CORS, Rate Limit) — opt-out
|
|
13
14
|
* 3. Utility plugins (Under Pressure, Sensible, Multipart, Raw Body)
|
|
@@ -95,4 +96,4 @@ declare const edgePreset: Partial<CreateAppOptions>;
|
|
|
95
96
|
*/
|
|
96
97
|
declare function getPreset(name: "production" | "development" | "testing" | "edge"): Partial<CreateAppOptions>;
|
|
97
98
|
//#endregion
|
|
98
|
-
export { ArcFactory, type AuthOption, type BetterAuthOption, type CreateAppOptions, type CustomAuthenticatorOption, type CustomPluginAuthOption, type FetchHandlerOptions, type JwtAuthOption, type LoadResourcesOptions, type MultipartOptions, type RawBodyOptions, type ResourceLike, type ResourceModule, type UnderPressureOptions, createApp, developmentPreset, edgePreset, getPreset, loadResources, preloadResources, preloadResourcesAsync, productionPreset, testingPreset, toFetchHandler };
|
|
99
|
+
export { ArcFactory, type ArcModule, type ArcModuleInput, type ArcModuleRegistry, type AuthOption, type BetterAuthOption, type CreateAppOptions, type CustomAuthenticatorOption, type CustomPluginAuthOption, type FetchHandlerOptions, type JwtAuthOption, type LoadResourcesOptions, type MultipartOptions, type RawBodyOptions, type ResourceLike, type ResourceModule, type UnderPressureOptions, createApp, defineModule, developmentPreset, edgePreset, getModuleExports, getPreset, loadResources, orderModules, preloadResources, preloadResourcesAsync, productionPreset, resolveModule, testingPreset, toFetchHandler };
|
package/dist/factory/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { n as preloadResourcesAsync, t as preloadResources } from "../preloadResources-CHw3_oA_.mjs";
|
|
2
|
-
import { a as edgePreset, c as testingPreset, i as developmentPreset, n as createApp, o as getPreset, s as productionPreset, t as ArcFactory } from "../createApp
|
|
3
|
-
import { t as loadResources } from "../loadResources-
|
|
2
|
+
import { a as edgePreset, c as testingPreset, d as orderModules, f as resolveModule, i as developmentPreset, l as defineModule, n as createApp, o as getPreset, s as productionPreset, t as ArcFactory, u as getModuleExports } from "../createApp-Bi61XxqU.mjs";
|
|
3
|
+
import { t as loadResources } from "../loadResources-DpU8pfjV.mjs";
|
|
4
4
|
//#region src/factory/edge.ts
|
|
5
5
|
/**
|
|
6
6
|
* Convert a Fastify app into a Web Standards fetch handler.
|
|
@@ -47,4 +47,4 @@ function toFetchHandler(app, options = {}) {
|
|
|
47
47
|
};
|
|
48
48
|
}
|
|
49
49
|
//#endregion
|
|
50
|
-
export { ArcFactory, createApp, developmentPreset, edgePreset, getPreset, loadResources, preloadResources, preloadResourcesAsync, productionPreset, testingPreset, toFetchHandler };
|
|
50
|
+
export { ArcFactory, createApp, defineModule, developmentPreset, edgePreset, getModuleExports, getPreset, loadResources, orderModules, preloadResources, preloadResourcesAsync, productionPreset, resolveModule, testingPreset, toFetchHandler };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { bn as HookSystem, z as ResourceRegistry } from "./index-
|
|
1
|
+
import { bn as HookSystem, z as ResourceRegistry } from "./index-Dtrj6XZk.mjs";
|
|
2
2
|
import { t as ExternalOpenApiPaths } from "./externalPaths-BE6wFpYv.mjs";
|
|
3
|
+
import { r as ArcModuleRegistry } from "./module-WeuU5jfd.mjs";
|
|
3
4
|
import { FastifyPluginAsync } from "fastify";
|
|
4
|
-
|
|
5
5
|
//#region src/core/arcCorePlugin.d.ts
|
|
6
6
|
interface ArcCorePluginOptions {
|
|
7
7
|
/** Enable event emission for CRUD operations (requires eventPlugin) */
|
|
@@ -28,6 +28,16 @@ interface ArcCore {
|
|
|
28
28
|
externalOpenApiPaths: ExternalOpenApiPaths[];
|
|
29
29
|
/** Registered plugins for introspection */
|
|
30
30
|
plugins: Map<string, PluginMeta>;
|
|
31
|
+
/**
|
|
32
|
+
* Module public exports — `bootstrap()` return values keyed by module name
|
|
33
|
+
* (see `src/factory/module.ts`). Read via `getModuleExports(fastify, name)`:
|
|
34
|
+
* augment `ArcModuleRegistry` once and the name infers the export type;
|
|
35
|
+
* otherwise pass it inline. `Partial<ArcModuleRegistry>` gives augmented
|
|
36
|
+
* apps typed direct access (`fastify.arc.modules.order`), while the
|
|
37
|
+
* `Record<string, unknown>` intersection keeps un-augmented reads open.
|
|
38
|
+
* Populated lazily by `registerResources` — absent until a module exports.
|
|
39
|
+
*/
|
|
40
|
+
modules?: Partial<ArcModuleRegistry> & Record<string, unknown>;
|
|
31
41
|
}
|
|
32
42
|
declare const arcCorePlugin: FastifyPluginAsync<ArcCorePluginOptions>;
|
|
33
43
|
declare const _default: FastifyPluginAsync<ArcCorePluginOptions>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as pluralize } from "./pluralize-
|
|
1
|
+
import { t as pluralize } from "./pluralize-BhrgwZb9.mjs";
|
|
2
2
|
import { join } from "node:path";
|
|
3
3
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
4
4
|
//#region src/cli/commands/generate/name-helpers.ts
|
|
@@ -601,9 +601,10 @@ async function generate(type, args) {
|
|
|
601
601
|
if (!type) throw new Error("Missing type argument\nUsage: arc generate <resource|controller|model|repository|schemas> <name>");
|
|
602
602
|
const [name, ...restArgs] = args;
|
|
603
603
|
if (!name) throw new Error("Missing name argument\nUsage: arc generate <type> <name>\nExample: arc generate resource product");
|
|
604
|
+
if (!/^[A-Za-z][A-Za-z0-9-]*$/.test(name)) throw new Error(`Invalid name "${name}". Use kebab-case: a letter followed by letters, digits, or hyphens (e.g. 'product', 'order-line'). No slashes, dots, spaces, or path segments.`);
|
|
604
605
|
const capitalizedName = toPascalCase(name);
|
|
605
606
|
const lowerName = name.toLowerCase();
|
|
606
|
-
if ((type === "resource" || type === "r" || type === "model" || type === "m") && new Set([
|
|
607
|
+
if ((type === "resource" || type === "r" || type === "model" || type === "m") && (/* @__PURE__ */ new Set([
|
|
607
608
|
"user",
|
|
608
609
|
"session",
|
|
609
610
|
"account",
|
|
@@ -614,7 +615,7 @@ async function generate(type, args) {
|
|
|
614
615
|
"team",
|
|
615
616
|
"team-member",
|
|
616
617
|
"apikey"
|
|
617
|
-
]).has(lowerName)) {
|
|
618
|
+
])).has(lowerName)) {
|
|
618
619
|
console.warn(`\n[arc generate] "${lowerName}" is a Better Auth-owned collection.\nBetter Auth's organization/admin/bearer plugins write this collection directly,\nso generating a parallel arc model would create a duplicate registration.\n\nRecommended pattern:\n import { createBetterAuthOverlay } from '@classytic/mongokit/better-auth';\n const adapter = await createBetterAuthOverlay({\n auth, mongoose, collection: '${lowerName}',\n });\n // ...then \`defineResource({ name: '${lowerName}', adapter, ... })\` reads\n // BA's collection through arc with full pagination/filters/permissions.\n\nAborting. Re-run with a different name if you need a separate domain model.\n`);
|
|
619
620
|
return;
|
|
620
621
|
}
|
package/dist/hooks/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Cn as afterDelete, Dn as beforeUpdate, En as beforeDelete, On as createHookSystem, Sn as afterCreate, Tn as beforeCreate, _n as HookOperation, bn as HookSystem, gn as HookHandler, hn as HookContext, kn as defineHook, mn as DefineHookOptions, vn as HookPhase, wn as afterUpdate, xn as HookSystemOptions, yn as HookRegistration } from "../index-
|
|
1
|
+
import { Cn as afterDelete, Dn as beforeUpdate, En as beforeDelete, On as createHookSystem, Sn as afterCreate, Tn as beforeCreate, _n as HookOperation, bn as HookSystem, gn as HookHandler, hn as HookContext, kn as defineHook, mn as DefineHookOptions, vn as HookPhase, wn as afterUpdate, xn as HookSystemOptions, yn as HookRegistration } from "../index-Dtrj6XZk.mjs";
|
|
2
2
|
export { type DefineHookOptions, type HookContext, type HookHandler, type HookOperation, type HookPhase, type HookRegistration, HookSystem, type HookSystemOptions, afterCreate, afterDelete, afterUpdate, beforeCreate, beforeDelete, beforeUpdate, createHookSystem, defineHook };
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { i as createIdempotencyResult, n as IdempotencyResult, r as IdempotencyStore, t as IdempotencyLock } from "../interface-Uk8ONJv7.mjs";
|
|
2
|
-
import { i as RedisIdempotencyStoreOptions, n as RedisClient } from "../redis-
|
|
2
|
+
import { i as RedisIdempotencyStoreOptions, n as RedisClient } from "../redis-UDtLaNj6.mjs";
|
|
3
3
|
import { FastifyPluginAsync } from "fastify";
|
|
4
4
|
import { RepositoryLike } from "@classytic/repo-core/adapter";
|
|
5
|
-
|
|
6
5
|
//#region src/idempotency/idempotencyPlugin.d.ts
|
|
7
6
|
interface IdempotencyPluginOptions {
|
|
8
7
|
/** Enable idempotency (default: false) */
|
|
@@ -60,7 +59,9 @@ declare module "fastify" {
|
|
|
60
59
|
interface FastifyInstance {
|
|
61
60
|
/** Idempotency utilities */
|
|
62
61
|
idempotency: {
|
|
63
|
-
/** Manually invalidate an idempotency key */
|
|
62
|
+
/** Manually invalidate an idempotency key */
|
|
63
|
+
invalidate: (key: string) => Promise<void>;
|
|
64
|
+
/** Check if a key has a cached response */
|
|
64
65
|
has: (key: string) => Promise<boolean>;
|
|
65
66
|
/**
|
|
66
67
|
* Route-level preHandler for idempotency check + lock.
|
|
@@ -387,7 +387,7 @@ const idempotencyPlugin = async (fastify, opts = {}) => {
|
|
|
387
387
|
const statusCode = reply.statusCode;
|
|
388
388
|
if (statusCode < 200 || statusCode >= 300) return payload;
|
|
389
389
|
const headersToCache = {};
|
|
390
|
-
const excludeHeaders = new Set([
|
|
390
|
+
const excludeHeaders = /* @__PURE__ */ new Set([
|
|
391
391
|
"content-length",
|
|
392
392
|
"transfer-encoding",
|
|
393
393
|
"connection",
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as UpstashRedisLike, i as RedisIdempotencyStoreOptions, n as RedisClient, o as ioredisAsIdempotencyClient, r as RedisIdempotencyStore, s as upstashAsIdempotencyClient, t as IoredisLike } from "../redis-
|
|
1
|
+
import { a as UpstashRedisLike, i as RedisIdempotencyStoreOptions, n as RedisClient, o as ioredisAsIdempotencyClient, r as RedisIdempotencyStore, s as upstashAsIdempotencyClient, t as IoredisLike } from "../redis-UDtLaNj6.mjs";
|
|
2
2
|
export { type IoredisLike, type RedisClient, RedisIdempotencyStore, type RedisIdempotencyStoreOptions, type UpstashRedisLike, ioredisAsIdempotencyClient, upstashAsIdempotencyClient };
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import { C as RequestContext, Et as AggregationConfig, F as FastifyWithDecorators, H as ActionDefinition, K as ArcFieldRule, L as RequestWithExtras, T as CrudRouterOptions, V as ResourceDefinition, bt as IControllerResponse, ht as RouteSchemaOptions, pt as RouteMcpConfig, q as CrudController, qt as AnyRecord, st as ResourceConfig, xt as IRequestContext, yt as IController } from "./index-
|
|
2
|
-
import { i as RequestScope } from "./types-
|
|
3
|
-
import { c as PermissionCheck } from "./fields-
|
|
1
|
+
import { C as RequestContext, Et as AggregationConfig, F as FastifyWithDecorators, H as ActionDefinition, K as ArcFieldRule, L as RequestWithExtras, T as CrudRouterOptions, V as ResourceDefinition, bt as IControllerResponse, ht as RouteSchemaOptions, pt as RouteMcpConfig, q as CrudController, qt as AnyRecord, st as ResourceConfig, xt as IRequestContext, yt as IController } from "./index-Dtrj6XZk.mjs";
|
|
2
|
+
import { i as RequestScope } from "./types-DH0GupI7.mjs";
|
|
3
|
+
import { c as PermissionCheck } from "./fields-BGqrAa_u.mjs";
|
|
4
|
+
import "./fastify-augmentation-DafigGQp.mjs";
|
|
4
5
|
import { FastifyReply, FastifyRequest, RouteHandlerMethod } from "fastify";
|
|
5
6
|
import { z } from "zod";
|
|
7
|
+
import { DataAdapter } from "@classytic/repo-core/adapter";
|
|
6
8
|
import { AggDateBucket, AggMeasure, AggTopN } from "@classytic/repo-core/repository";
|
|
7
9
|
import { LookupSpec } from "@classytic/repo-core/lookup";
|
|
8
|
-
|
|
9
10
|
//#region src/constants.d.ts
|
|
10
11
|
/**
|
|
11
12
|
* Arc Framework Constants — Single Source of Truth
|
|
@@ -130,7 +131,7 @@ declare function createPermissionMiddleware(permission: PermissionCheck, resourc
|
|
|
130
131
|
* Plain JSON-Schema entries skip the inference path entirely (they go
|
|
131
132
|
* through the untyped `ActionDefinition` form).
|
|
132
133
|
*/
|
|
133
|
-
interface DefineActionConfig<TSchema extends z.ZodTypeAny | undefined = undefined, TData =
|
|
134
|
+
interface DefineActionConfig<TSchema extends z.ZodTypeAny | undefined = undefined, TData = TSchema extends z.ZodTypeAny ? z.infer<TSchema> : Record<string, unknown>> {
|
|
134
135
|
/** Per-action body schema (Zod v4). Drives both AJV validation and the typed `data` param. */
|
|
135
136
|
schema?: TSchema;
|
|
136
137
|
/** Per-action permission gate. Falls back to resource-level if omitted. */
|
|
@@ -167,6 +168,86 @@ interface DefineActionConfig<TSchema extends z.ZodTypeAny | undefined = undefine
|
|
|
167
168
|
*/
|
|
168
169
|
declare function defineAction<TSchema extends z.ZodTypeAny | undefined = undefined>(config: DefineActionConfig<TSchema>): ActionDefinition;
|
|
169
170
|
//#endregion
|
|
171
|
+
//#region src/core/defineResource/seams.d.ts
|
|
172
|
+
/**
|
|
173
|
+
* Structural adapter boundary — the `ControllerLike` pattern (v2.10.6)
|
|
174
|
+
* applied to adapters. `DataAdapter<T>` is invariant in `T`, so a
|
|
175
|
+
* `DataAdapter<HydratedDocument<IProduct>>` built by the HOST does not
|
|
176
|
+
* assign to a module's `DataAdapter<AnyRecord>` slot; before this type,
|
|
177
|
+
* module authors erased the slot to `unknown` and cast at every use.
|
|
178
|
+
*
|
|
179
|
+
* Arc only reaches for these members at runtime — the rest of the adapter's
|
|
180
|
+
* shape is the caller's concern. All slots optional + `unknown` so every
|
|
181
|
+
* kit adapter (mongokit, sqlitekit, prismakit, custom) assigns structurally.
|
|
182
|
+
*
|
|
183
|
+
* Used by {@link ResourceSeams}; `ResourceConfig.adapter` itself stays
|
|
184
|
+
* `DataAdapter<TDoc>` so `defineResource`'s doc-type inference is untouched.
|
|
185
|
+
*/
|
|
186
|
+
interface AdapterLike {
|
|
187
|
+
repository?: unknown;
|
|
188
|
+
generateSchemas?: unknown;
|
|
189
|
+
getSchemaMetadata?: unknown;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Seam-slot type transform, two widenings per property:
|
|
193
|
+
*
|
|
194
|
+
* - admits explicit `undefined` — {@link mergeResourceConfig} skips
|
|
195
|
+
* `undefined` values at runtime, so the type says so. Makes
|
|
196
|
+
* field-mapping seams (`{ permissions: cfg.permissionsMap, ... }`)
|
|
197
|
+
* ergonomic under `exactOptionalPropertyTypes: true` (stricter than
|
|
198
|
+
* arc's own tsconfig — found by a live spine-module smoke).
|
|
199
|
+
* - array slots also accept `readonly` arrays — hosts naturally write
|
|
200
|
+
* route/preset tables `as const` or behind `readonly` exports; the
|
|
201
|
+
* merge copies arrays into fresh mutable ones, so a frozen host table
|
|
202
|
+
* never leaks into arc's internals.
|
|
203
|
+
*/
|
|
204
|
+
type SeamSlot<V> = V | undefined | (V extends (infer E)[] ? readonly E[] : never);
|
|
205
|
+
type SkippableUndefined<T> = { [K in keyof T]: SeamSlot<T[K]>; };
|
|
206
|
+
/**
|
|
207
|
+
* The host-injectable subset of a resource config — everything a module can
|
|
208
|
+
* let its host override, i.e. every `ResourceConfig` slot except the
|
|
209
|
+
* module-owned `name` (and the internal preset-tracking field).
|
|
210
|
+
*
|
|
211
|
+
* Type your module's per-resource override bundles as `ResourceSeams` (or a
|
|
212
|
+
* `Pick<ResourceSeams, ...>` allow-list when you want to constrain what
|
|
213
|
+
* hosts may touch) and pass them through {@link mergeResourceConfig}.
|
|
214
|
+
*/
|
|
215
|
+
type ResourceSeams<TDoc = AnyRecord> = SkippableUndefined<Omit<ResourceConfig<TDoc>, "name" | "_appliedPresets" | "adapter">> & {
|
|
216
|
+
/** Any kit adapter — widened via {@link AdapterLike} at this boundary. */
|
|
217
|
+
adapter?: DataAdapter<TDoc> | AdapterLike | undefined;
|
|
218
|
+
};
|
|
219
|
+
/**
|
|
220
|
+
* Base-config input for {@link mergeResourceConfig} — a required `name`
|
|
221
|
+
* plus every seam slot (which is exactly `ResourceConfig` with the
|
|
222
|
+
* {@link AdapterLike} widening, `undefined`-skipping, and readonly-array
|
|
223
|
+
* acceptance the seams get). Module builders constructing DEFAULT adapters
|
|
224
|
+
* from untyped kernel engine bags hit the identical `DataAdapter<T>`
|
|
225
|
+
* invariance at the base as hosts do at the seam.
|
|
226
|
+
*/
|
|
227
|
+
type SeamedResourceConfig<TDoc = AnyRecord> = {
|
|
228
|
+
name: string;
|
|
229
|
+
} & ResourceSeams<TDoc>;
|
|
230
|
+
/**
|
|
231
|
+
* Canonical slot-aware merge of a base resource config with host seams.
|
|
232
|
+
* Later seams win over earlier ones; `undefined` values never clobber.
|
|
233
|
+
*
|
|
234
|
+
* Merge semantics (value-driven — no per-slot registry to drift):
|
|
235
|
+
*
|
|
236
|
+
* - **Top-level arrays CONCAT** — `routes`, `middlewares`, `presets`,
|
|
237
|
+
* `routeGuards`, `disabledRoutes`: additive collections, base first.
|
|
238
|
+
* - **Plain objects merge recursively** — `permissions`, `actions`,
|
|
239
|
+
* `schemaOptions` (incl. `fieldRules`), `aggregations`, `customSchemas`,
|
|
240
|
+
* `fields`, `cache`, `events`: per-key composition. Arrays NESTED inside
|
|
241
|
+
* them replace (they're value lists — enums, sort specs), not concat.
|
|
242
|
+
* - **Everything else last-wins** — class instances (`adapter`,
|
|
243
|
+
* `controller`, `queryParser`), functions, scalars.
|
|
244
|
+
*
|
|
245
|
+
* The single `as` at the return is the one documented erasure for the
|
|
246
|
+
* {@link AdapterLike}-widened seam slots — inside the helper so no module
|
|
247
|
+
* author ever writes one (mirrors mongokit's one-cast-at-the-boundary rule).
|
|
248
|
+
*/
|
|
249
|
+
declare function mergeResourceConfig<TDoc = AnyRecord>(base: SeamedResourceConfig<TDoc>, ...seams: ReadonlyArray<ResourceSeams<TDoc> | undefined>): ResourceConfig<TDoc>;
|
|
250
|
+
//#endregion
|
|
170
251
|
//#region src/core/defineResourceVariants.d.ts
|
|
171
252
|
/**
|
|
172
253
|
* Required identity fields for each variant. The user MUST provide a unique
|
|
@@ -188,7 +269,7 @@ type VariantsMap<TDoc = AnyRecord> = Record<string, VariantOverride<TDoc>>;
|
|
|
188
269
|
* Result type — preserves the variant keys so destructuring is type-safe:
|
|
189
270
|
* `const { articlePublic, articleAdmin } = defineResourceVariants(...)`.
|
|
190
271
|
*/
|
|
191
|
-
type VariantsResult<TDoc, V extends VariantsMap<TDoc>> = { [K in keyof V]: ResourceDefinition<TDoc
|
|
272
|
+
type VariantsResult<TDoc, V extends VariantsMap<TDoc>> = { [K in keyof V]: ResourceDefinition<TDoc>; };
|
|
192
273
|
/**
|
|
193
274
|
* Define multiple resources from a shared base config and per-variant overrides.
|
|
194
275
|
*
|
|
@@ -344,4 +425,4 @@ declare function isFieldReadable(rule: ArcFieldRule | undefined): boolean;
|
|
|
344
425
|
*/
|
|
345
426
|
declare function collectReadBlockedFields(schemaOptions: RouteSchemaOptions | undefined): Set<string> | null;
|
|
346
427
|
//#endregion
|
|
347
|
-
export {
|
|
428
|
+
export { HOOK_OPERATIONS as A, SYSTEM_FIELDS as B, CrudOperation as C, DEFAULT_SORT as D, DEFAULT_MAX_LIMIT as E, MAX_REGEX_LENGTH as F, MAX_SEARCH_LENGTH as I, MUTATION_OPERATIONS as L, HookOperation as M, HookPhase as N, DEFAULT_TENANT_FIELD as O, MAX_FILTER_DEPTH as P, MutationOperation as R, CRUD_OPERATIONS as S, DEFAULT_LIMIT as T, DefineActionConfig as _, createRequestContext as a, createPermissionMiddleware as b, sendControllerResponse as c, getEntityQuery as d, defineResourceVariants as f, mergeResourceConfig as g, SeamedResourceConfig as h, createFastifyHandler as i, HOOK_PHASES as j, DEFAULT_UPDATE_METHOD as k, getEntityId as l, ResourceSeams as m, isFieldReadable as n, getControllerContext as o, AdapterLike as p, createCrudHandlers as r, getControllerScope as s, collectReadBlockedFields as t, getEntityIdField as u, defineAction as v, DEFAULT_ID_FIELD as w, defineAggregation as x, createCrudRouter as y, RESERVED_QUERY_PARAMS as z };
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { r as CacheStore, t as CacheLogger } from "./interface-C1_WLTMK.mjs";
|
|
2
|
-
import { i as RequestScope, n as Mandate } from "./types-
|
|
3
|
-
import { c as PermissionCheck, l as PermissionContext, u as PermissionResult } from "./fields-
|
|
2
|
+
import { i as RequestScope, n as Mandate } from "./types-DH0GupI7.mjs";
|
|
3
|
+
import { c as PermissionCheck, l as PermissionContext, u as PermissionResult } from "./fields-BGqrAa_u.mjs";
|
|
4
4
|
import { FastifyReply, FastifyRequest } from "fastify";
|
|
5
|
-
|
|
6
5
|
//#region src/permissions/agent.d.ts
|
|
7
6
|
/**
|
|
8
7
|
* Require a sender-constrained credential — the inbound token MUST carry a
|
|
@@ -356,8 +355,11 @@ interface DynamicPermissionMatrixConfig {
|
|
|
356
355
|
* and `ttlSeconds > 0`, Arc creates an internal MemoryCacheStore.
|
|
357
356
|
*/
|
|
358
357
|
cache?: {
|
|
359
|
-
/** Cache TTL in seconds */
|
|
360
|
-
|
|
358
|
+
/** Cache TTL in seconds */
|
|
359
|
+
ttlSeconds: number;
|
|
360
|
+
/** Optional custom cache key builder */
|
|
361
|
+
key?: (ctx: PermissionContext) => string | null | undefined;
|
|
362
|
+
/** Hard entry cap for internal memory store (default: 1000) */
|
|
361
363
|
maxEntries?: number;
|
|
362
364
|
};
|
|
363
365
|
}
|
|
@@ -620,7 +622,7 @@ declare function requireOrgInScope<TDoc = Record<string, unknown>>(target: strin
|
|
|
620
622
|
*/
|
|
621
623
|
declare function requireTeamMembership<TDoc = Record<string, unknown>>(): PermissionCheck<TDoc>;
|
|
622
624
|
declare namespace presets_d_exports {
|
|
623
|
-
export { adminOnly, authenticated, fullPublic, ownerWithAdminBypass, publicRead, publicReadAdminWrite, readOnly };
|
|
625
|
+
export { adminOnly, authenticated, fullPublic, ownerWithAdminBypass, permissionMatrix, publicRead, publicReadAdminWrite, readOnly };
|
|
624
626
|
}
|
|
625
627
|
/**
|
|
626
628
|
* ResourcePermissions shape — matches the type in types/index.ts
|
|
@@ -652,6 +654,33 @@ declare function authenticated<TDoc = Record<string, unknown>>(overrides?: Permi
|
|
|
652
654
|
* @param roles - Required roles (user needs at least one). Default: ['admin']
|
|
653
655
|
*/
|
|
654
656
|
declare function adminOnly<TDoc = Record<string, unknown>>(roles?: readonly string[], overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
|
|
657
|
+
/**
|
|
658
|
+
* Arbitrary-gate CRUD matrix — the generalization every host and arc-*
|
|
659
|
+
* module hand-rolls as `{ list: view, get: view, create: manage, ... }`.
|
|
660
|
+
*
|
|
661
|
+
* Unlike the fixed presets above, the gates are caller-supplied
|
|
662
|
+
* `PermissionCheck`s, so ANY combinator plugs in — org roles, ownership,
|
|
663
|
+
* `anyOf(...)`, service scopes, custom async checks. `delete` defaults to
|
|
664
|
+
* the `write` gate.
|
|
665
|
+
*
|
|
666
|
+
* @example
|
|
667
|
+
* ```typescript
|
|
668
|
+
* // Two-gate (view/manage) — the arc-* module convention:
|
|
669
|
+
* permissionMatrix({ read: requireAuth(), write: requireOrgRole('manager') })
|
|
670
|
+
*
|
|
671
|
+
* // Three-gate with a stricter delete:
|
|
672
|
+
* permissionMatrix({
|
|
673
|
+
* read: allowPublic(),
|
|
674
|
+
* write: requireOrgRole('manager'),
|
|
675
|
+
* delete: requireOrgRole('owner'),
|
|
676
|
+
* })
|
|
677
|
+
* ```
|
|
678
|
+
*/
|
|
679
|
+
declare function permissionMatrix<TDoc = Record<string, unknown>>(gates: {
|
|
680
|
+
read: PermissionCheck<TDoc>;
|
|
681
|
+
write: PermissionCheck<TDoc>;
|
|
682
|
+
delete?: PermissionCheck<TDoc>;
|
|
683
|
+
}, overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
|
|
655
684
|
/**
|
|
656
685
|
* Owner-scoped with admin bypass.
|
|
657
686
|
* list = auth (scoped to owner), get = auth, create = auth,
|
|
@@ -669,7 +698,12 @@ declare function fullPublic<TDoc = Record<string, unknown>>(overrides?: Permissi
|
|
|
669
698
|
/**
|
|
670
699
|
* Read-only: list + get authenticated, write operations denied.
|
|
671
700
|
* Useful for computed/derived resources.
|
|
701
|
+
*
|
|
702
|
+
* Writes carry an explicit `denyAll` check — an omitted CRUD permission
|
|
703
|
+
* mounts the route with NO gate (public-by-omission), so leaving
|
|
704
|
+
* create/update/delete undefined here would expose unauthenticated writes.
|
|
705
|
+
* Hosts that disable write routes entirely (`disabledRoutes`) are unaffected.
|
|
672
706
|
*/
|
|
673
707
|
declare function readOnly<TDoc = Record<string, unknown>>(overrides?: PermissionOverrides<TDoc>): ResourcePermissions<TDoc>;
|
|
674
708
|
//#endregion
|
|
675
|
-
export {
|
|
709
|
+
export { requireOwnership as A, requireMandate as B, createOrgPermissions as C, denyAll as D, anyOf as E, normalizePermissionResult as F, RequireAgentScopeOptions as I, RequireMandateOptions as L, roles as M, when as N, not as O, applyPermissionResult as P, requireAgentScope as R, createDynamicPermissionMatrix as S, allowPublic as T, createRoleHierarchy as _, permissionMatrix as a, DynamicPermissionMatrixConfig as b, publicReadAdminWrite as c, requireOrgMembership as d, requireOrgRole as f, RoleHierarchy as g, requireTeamMembership as h, ownerWithAdminBypass as i, requireRoles as j, requireAuth as k, readOnly as l, requireServiceScope as m, authenticated as n, presets_d_exports as o, requireScopeContext as p, fullPublic as r, publicRead as s, adminOnly as t, requireOrgInScope as u, ConnectEventsOptions as v, allOf as w, PermissionEventBus as x, DynamicPermissionMatrix as y, requireDPoP as z };
|