@classytic/arc 2.10.8 → 2.11.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-DVNKvoX4.mjs → BaseController-JNV08qOT.mjs} +480 -442
- package/dist/{queryCachePlugin-Dumka73q.d.mts → QueryCache-DOBNHBE0.d.mts} +2 -32
- package/dist/adapters/index.d.mts +2 -2
- package/dist/adapters/index.mjs +1 -1
- package/dist/{adapters-BXY4i-hw.mjs → adapters-D0tT2Tyo.mjs} +54 -0
- package/dist/audit/index.d.mts +1 -1
- package/dist/auth/index.d.mts +1 -1
- package/dist/auth/index.mjs +5 -5
- package/dist/{betterAuthOpenApi--rdY15Ld.mjs → betterAuthOpenApi-DwxtK3uG.mjs} +1 -1
- package/dist/cache/index.d.mts +3 -2
- package/dist/cache/index.mjs +3 -3
- package/dist/cli/commands/docs.mjs +2 -2
- package/dist/cli/commands/generate.mjs +37 -27
- package/dist/cli/commands/init.mjs +46 -33
- package/dist/cli/commands/introspect.mjs +1 -1
- package/dist/context/index.mjs +1 -1
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +4 -3
- package/dist/core-DXdSSFW-.mjs +1037 -0
- package/dist/createActionRouter-BwaSM0No.mjs +166 -0
- package/dist/{createApp-BwnEAO2h.mjs → createApp-DvNYEhpb.mjs} +75 -27
- package/dist/docs/index.d.mts +1 -1
- package/dist/docs/index.mjs +2 -2
- package/dist/{elevation-Dci0AYLT.mjs → elevation-DOFoxoDs.mjs} +1 -1
- package/dist/{errorHandler-CSxe7KIM.mjs → errorHandler-BQm8ZxTK.mjs} +1 -1
- package/dist/{eventPlugin-ByU4Cv0e.mjs → eventPlugin--5HIkdPU.mjs} +1 -1
- package/dist/events/index.d.mts +3 -3
- package/dist/events/index.mjs +2 -2
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/factory/index.d.mts +1 -1
- package/dist/factory/index.mjs +2 -2
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.mjs +1 -1
- package/dist/idempotency/index.d.mts +3 -3
- package/dist/idempotency/index.mjs +1 -1
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/{index-C_Noptz-.d.mts → index-BYCqHCVu.d.mts} +2 -2
- package/dist/{index-BGbpGVyM.d.mts → index-Cm0vUrr_.d.mts} +699 -494
- package/dist/{index-BziRPS4H.d.mts → index-DAushRTt.d.mts} +29 -10
- package/dist/index-DsJ1MNfC.d.mts +1179 -0
- package/dist/{index-EqQN6p0W.d.mts → index-t8pLpPFW.d.mts} +11 -8
- package/dist/index.d.mts +6 -38
- package/dist/index.mjs +9 -9
- package/dist/integrations/event-gateway.d.mts +1 -1
- package/dist/integrations/event-gateway.mjs +1 -1
- package/dist/integrations/index.d.mts +2 -2
- 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 +46 -5
- package/dist/integrations/streamline.mjs +50 -21
- package/dist/integrations/websocket-redis.d.mts +1 -1
- package/dist/integrations/websocket.d.mts +2 -154
- package/dist/integrations/websocket.mjs +292 -224
- package/dist/{keys-nWQGUTu1.mjs → keys-CARyUjiR.mjs} +2 -0
- package/dist/{loadResources-Bksk8ydA.mjs → loadResources-YNwKHvRA.mjs} +3 -1
- package/dist/middleware/index.d.mts +1 -1
- package/dist/middleware/index.mjs +1 -1
- package/dist/{openapi-DpNpqBmo.mjs → openapi-C0L9ar7m.mjs} +4 -4
- package/dist/org/index.d.mts +1 -1
- package/dist/permissions/index.d.mts +1 -1
- package/dist/permissions/index.mjs +2 -4
- package/dist/{permissions-wkqRwicB.mjs → permissions-B4vU9L0Q.mjs} +221 -3
- package/dist/{pipe-CGJxqDGx.mjs → pipe-DVoIheVC.mjs} +1 -1
- package/dist/pipeline/index.d.mts +1 -1
- package/dist/pipeline/index.mjs +1 -1
- package/dist/plugins/index.d.mts +4 -4
- package/dist/plugins/index.mjs +10 -10
- package/dist/plugins/response-cache.mjs +1 -1
- package/dist/plugins/tracing-entry.d.mts +1 -1
- package/dist/plugins/tracing-entry.mjs +42 -24
- package/dist/presets/filesUpload.d.mts +1 -1
- package/dist/presets/filesUpload.mjs +3 -3
- package/dist/presets/index.d.mts +1 -1
- package/dist/presets/index.mjs +1 -1
- package/dist/presets/multiTenant.d.mts +1 -1
- package/dist/presets/multiTenant.mjs +6 -0
- package/dist/presets/search.d.mts +1 -1
- package/dist/presets/search.mjs +1 -1
- package/dist/{presets-CrwOvuXI.mjs → presets-k604Lj99.mjs} +1 -1
- package/dist/queryCachePlugin-BUXBSm4F.d.mts +34 -0
- package/dist/{queryCachePlugin-ChLNZvFT.mjs → queryCachePlugin-Bq6bO6vc.mjs} +3 -3
- package/dist/{redis-MXLp1oOf.d.mts → redis-Cm1gnRDf.d.mts} +1 -1
- package/dist/registry/index.d.mts +1 -1
- package/dist/registry/index.mjs +2 -2
- package/dist/{resourceToTools-BhF3JV5p.mjs → resourceToTools--okX6QBr.mjs} +534 -420
- package/dist/routerShared-DeESFp4a.mjs +515 -0
- package/dist/schemaIR-BlG9bY7v.mjs +137 -0
- package/dist/scope/index.mjs +2 -2
- package/dist/testing/index.d.mts +367 -711
- package/dist/testing/index.mjs +637 -1434
- package/dist/{tracing-xqXzWeaf.d.mts → tracing-DokiEsuz.d.mts} +9 -4
- package/dist/types/index.d.mts +3 -3
- package/dist/types/index.mjs +1 -3
- package/dist/{types-CVdgPXBW.d.mts → types-CgikqKAj.d.mts} +118 -19
- package/dist/{types-CVKBssX5.d.mts → types-D9NqiYIw.d.mts} +1 -1
- package/dist/utils/index.d.mts +2 -968
- package/dist/utils/index.mjs +5 -6
- package/dist/utils-D3Yxnrwr.mjs +1639 -0
- package/dist/websocket-CyJ1VIFI.d.mts +186 -0
- package/package.json +7 -5
- package/skills/arc/SKILL.md +123 -38
- package/skills/arc/references/testing.md +212 -183
- package/dist/applyPermissionResult-QhV1Pa-g.mjs +0 -37
- package/dist/core-3MWJosCH.mjs +0 -1459
- package/dist/createActionRouter-C8UUB3Px.mjs +0 -249
- package/dist/errors-BI8kEKsO.d.mts +0 -140
- package/dist/fields-CTMWOUDt.mjs +0 -126
- package/dist/queryParser-NR__Qiju.mjs +0 -419
- package/dist/types-CDnTEpga.mjs +0 -27
- package/dist/utils-LMwVidKy.mjs +0 -947
- /package/dist/{HookSystem-BjFu7zf1.mjs → HookSystem-CGsMd6oK.mjs} +0 -0
- /package/dist/{ResourceRegistry-CcN2LVrc.mjs → ResourceRegistry-DkAeAuTX.mjs} +0 -0
- /package/dist/{actionPermissions-TUVR3uiZ.mjs → actionPermissions-C8YYU92K.mjs} +0 -0
- /package/dist/{caching-3h93rkJM.mjs → caching-CheW3m-S.mjs} +0 -0
- /package/dist/{errorHandler-2ii4RIYr.d.mts → errorHandler-Co3lnVmJ.d.mts} +0 -0
- /package/dist/{errors-BqdUDja_.mjs → errors-D5c-5BJL.mjs} +0 -0
- /package/dist/{eventPlugin-D1ThQ1Pp.d.mts → eventPlugin-CUNjYYRY.d.mts} +0 -0
- /package/dist/{interface-B-pe8fhj.d.mts → interface-CkkWm5uR.d.mts} +0 -0
- /package/dist/{interface-yhyb_pLY.d.mts → interface-Da0r7Lna.d.mts} +0 -0
- /package/dist/{memory-DqI-449b.mjs → memory-DikHSvWa.mjs} +0 -0
- /package/dist/{metrics-TuOmguhi.mjs → metrics-Csh4nsvv.mjs} +0 -0
- /package/dist/{multipartBody-CUQGVlM_.mjs → multipartBody-CvTR1Un6.mjs} +0 -0
- /package/dist/{pluralize-CWP6MB39.mjs → pluralize-BneOJkpi.mjs} +0 -0
- /package/dist/{redis-stream-bkO88VHx.d.mts → redis-stream-CM8TXTix.d.mts} +0 -0
- /package/dist/{registry-B0Wl7uVV.mjs → registry-D63ee7fl.mjs} +0 -0
- /package/dist/{replyHelpers-BLojtuvR.mjs → replyHelpers-ByllIXXV.mjs} +0 -0
- /package/dist/{requestContext-C38GskNt.mjs → requestContext-CfRkaxwf.mjs} +0 -0
- /package/dist/{schemaConverter-BxFDdtXu.mjs → schemaConverter-B0oKLuqI.mjs} +0 -0
- /package/dist/{sse-D8UeDwis.mjs → sse-V7aXc3bW.mjs} +0 -0
- /package/dist/{store-helpers-DYYUQbQN.mjs → store-helpers-BhrzxvyQ.mjs} +0 -0
- /package/dist/{typeGuards-Cj5Rgvlg.mjs → typeGuards-CcFZXgU7.mjs} +0 -0
- /package/dist/{types-D57iXYb8.mjs → types-DV9WDfeg.mjs} +0 -0
- /package/dist/{versioning-B6mimogM.mjs → versioning-CGPjkqAg.mjs} +0 -0
- /package/dist/{versioning-CeUXHfjw.d.mts → versioning-M9lNLhO8.d.mts} +0 -0
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { r as CacheStore } from "./interface-
|
|
2
|
-
import { FastifyPluginAsync } from "fastify";
|
|
1
|
+
import { r as CacheStore } from "./interface-Da0r7Lna.mjs";
|
|
3
2
|
|
|
4
3
|
//#region src/cache/QueryCache.d.ts
|
|
5
4
|
/** Metadata wrapper stored in CacheStore */
|
|
@@ -39,33 +38,4 @@ declare class QueryCache {
|
|
|
39
38
|
bumpTagVersion(tag: string): Promise<void>;
|
|
40
39
|
}
|
|
41
40
|
//#endregion
|
|
42
|
-
|
|
43
|
-
interface QueryCachePluginOptions {
|
|
44
|
-
/** CacheStore instance. Default: MemoryCacheStore with default options. */
|
|
45
|
-
store?: CacheStore;
|
|
46
|
-
/** Global defaults for staleTime/gcTime (seconds) */
|
|
47
|
-
defaults?: {
|
|
48
|
-
staleTime?: number;
|
|
49
|
-
gcTime?: number;
|
|
50
|
-
};
|
|
51
|
-
}
|
|
52
|
-
interface QueryCacheDefaults {
|
|
53
|
-
staleTime: number;
|
|
54
|
-
gcTime: number;
|
|
55
|
-
}
|
|
56
|
-
/** Cross-resource invalidation rules collected from resource configs */
|
|
57
|
-
interface CrossResourceRule {
|
|
58
|
-
pattern: string;
|
|
59
|
-
tags: string[];
|
|
60
|
-
}
|
|
61
|
-
declare module "fastify" {
|
|
62
|
-
interface FastifyInstance {
|
|
63
|
-
queryCache: QueryCache;
|
|
64
|
-
queryCacheConfig: QueryCacheDefaults;
|
|
65
|
-
/** Register cross-resource invalidation rules (called by defineResource) */
|
|
66
|
-
registerCacheInvalidationRule?(rule: CrossResourceRule): void;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
declare const queryCachePlugin: FastifyPluginAsync<QueryCachePluginOptions>;
|
|
70
|
-
//#endregion
|
|
71
|
-
export { CacheEnvelope as a, QueryCache as c, queryCachePlugin as i, QueryCacheConfig as l, QueryCacheDefaults as n, CacheResult as o, QueryCachePluginOptions as r, CacheStatus as s, CrossResourceRule as t };
|
|
41
|
+
export { QueryCacheConfig as a, QueryCache as i, CacheResult as n, CacheStatus as r, CacheEnvelope as t };
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as PrismaQueryParserOptions, c as MongooseAdapterOptions, d as DrizzleAdapterOptions, f as createDrizzleAdapter, i as PrismaQueryParser, l as createMongooseAdapter, n as PrismaAdapterOptions, o as createPrismaAdapter, r as PrismaQueryOptions, s as MongooseAdapter, t as PrismaAdapter, u as DrizzleAdapter } from "../index-
|
|
1
|
+
import { An as RelationMetadata, En as AdapterFactory, Mn as SchemaMetadata, Nn as ValidationResult, On as DataAdapter, jn as RepositoryLike, kn as FieldMetadata } from "../index-Cm0vUrr_.mjs";
|
|
2
|
+
import { a as PrismaQueryParserOptions, c as MongooseAdapterOptions, d as DrizzleAdapterOptions, f as createDrizzleAdapter, i as PrismaQueryParser, l as createMongooseAdapter, n as PrismaAdapterOptions, o as createPrismaAdapter, r as PrismaQueryOptions, s as MongooseAdapter, t as PrismaAdapter, u as DrizzleAdapter } from "../index-DAushRTt.mjs";
|
|
3
3
|
export { AdapterFactory, DataAdapter, DrizzleAdapter, DrizzleAdapterOptions, FieldMetadata, MongooseAdapter, MongooseAdapterOptions, PrismaAdapter, PrismaAdapterOptions, PrismaQueryOptions, PrismaQueryParser, PrismaQueryParserOptions, RelationMetadata, RepositoryLike, SchemaMetadata, ValidationResult, createDrizzleAdapter, createMongooseAdapter, createPrismaAdapter };
|
package/dist/adapters/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as createMongooseAdapter, i as MongooseAdapter, n as PrismaQueryParser, o as DrizzleAdapter, r as createPrismaAdapter, s as createDrizzleAdapter, t as PrismaAdapter } from "../adapters-
|
|
1
|
+
import { a as createMongooseAdapter, i as MongooseAdapter, n as PrismaQueryParser, o as DrizzleAdapter, r as createPrismaAdapter, s as createDrizzleAdapter, t as PrismaAdapter } from "../adapters-D0tT2Tyo.mjs";
|
|
2
2
|
export { DrizzleAdapter, MongooseAdapter, PrismaAdapter, PrismaQueryParser, createDrizzleAdapter, createMongooseAdapter, createPrismaAdapter };
|
|
@@ -35,9 +35,58 @@ function mergeFieldRuleConstraints(schemas, schemaOptions) {
|
|
|
35
35
|
if (rule.pattern != null && prop.pattern == null) prop.pattern = rule.pattern;
|
|
36
36
|
if (rule.enum != null && prop.enum == null) prop.enum = rule.enum;
|
|
37
37
|
if (rule.description != null && prop.description == null) prop.description = rule.description;
|
|
38
|
+
if (rule.nullable === true) applyNullable(prop);
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
41
|
}
|
|
42
|
+
/**
|
|
43
|
+
* Widen a JSON Schema property to also accept `null`.
|
|
44
|
+
*
|
|
45
|
+
* Handles the three ways a property can be typed:
|
|
46
|
+
* - `type: 'string'` → `type: ['string', 'null']`
|
|
47
|
+
* - `type: [...]` → append `'null'` if missing
|
|
48
|
+
* - `anyOf: [...]` → append `{ type: 'null' }` branch if missing
|
|
49
|
+
*
|
|
50
|
+
* **Enum interaction:** when the widened prop also carries `enum: [...]`,
|
|
51
|
+
* `null` is appended to the enum list too. AJV's `enum` keyword rejects
|
|
52
|
+
* values not in the list regardless of the widened `type`, so
|
|
53
|
+
* `{ type: ['string','null'], enum: ['a','b'] }` alone would still reject
|
|
54
|
+
* `null`. The fix is `enum: ['a','b', null]`. (The `anyOf` branch dodges
|
|
55
|
+
* this entirely — each branch scopes its own enum.)
|
|
56
|
+
*
|
|
57
|
+
* No-op when the schema already admits null (don't double-wrap) or has
|
|
58
|
+
* no `type` / `anyOf` anchor to widen (e.g. Mixed — already accepts null).
|
|
59
|
+
*
|
|
60
|
+
* Mutates in place — callers already treat the slot schema as owned.
|
|
61
|
+
* Exported so adapters that walk `fieldRules` inline (mongoose fallback,
|
|
62
|
+
* drizzle post-process) can reuse the same widening logic.
|
|
63
|
+
*/
|
|
64
|
+
function applyNullable(prop) {
|
|
65
|
+
if (Array.isArray(prop.anyOf)) {
|
|
66
|
+
if (!prop.anyOf.some((b) => b && typeof b === "object" && (b.type === "null" || b.const === null))) prop.anyOf.push({ type: "null" });
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
if (Array.isArray(prop.type)) {
|
|
70
|
+
if (!prop.type.includes("null")) prop.type.push("null");
|
|
71
|
+
widenEnumToIncludeNull(prop);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
if (typeof prop.type === "string") {
|
|
75
|
+
prop.type = [prop.type, "null"];
|
|
76
|
+
widenEnumToIncludeNull(prop);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Append `null` to `enum` when present. Required because AJV's `enum`
|
|
82
|
+
* keyword is independent of `type` — a value must appear in the enum
|
|
83
|
+
* array verbatim even if the widened type says null is allowed.
|
|
84
|
+
*/
|
|
85
|
+
function widenEnumToIncludeNull(prop) {
|
|
86
|
+
if (!Array.isArray(prop.enum)) return;
|
|
87
|
+
if (prop.enum.includes(null)) return;
|
|
88
|
+
prop.enum = [...prop.enum, null];
|
|
89
|
+
}
|
|
41
90
|
//#endregion
|
|
42
91
|
//#region src/adapters/types.ts
|
|
43
92
|
/**
|
|
@@ -306,6 +355,7 @@ var MongooseAdapter = class {
|
|
|
306
355
|
if (rule.pattern != null && prop.pattern == null) prop.pattern = rule.pattern;
|
|
307
356
|
if (rule.enum != null && prop.enum == null) prop.enum = rule.enum;
|
|
308
357
|
if (rule.description != null && prop.description == null) prop.description = rule.description;
|
|
358
|
+
if (rule.nullable === true) applyNullable(prop);
|
|
309
359
|
}
|
|
310
360
|
if (typeInfo.isRequired && !optionalSet.has(fieldName) && !fieldRules[fieldName]?.optional) required.push(fieldName);
|
|
311
361
|
}
|
|
@@ -432,6 +482,10 @@ var MongooseAdapter = class {
|
|
|
432
482
|
baseType.type = "object";
|
|
433
483
|
baseType.additionalProperties = true;
|
|
434
484
|
}
|
|
485
|
+
if (options.default === null) {
|
|
486
|
+
applyNullable(baseType);
|
|
487
|
+
baseType.default = null;
|
|
488
|
+
}
|
|
435
489
|
return baseType;
|
|
436
490
|
}
|
|
437
491
|
};
|
package/dist/audit/index.d.mts
CHANGED
package/dist/auth/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Ot as AuthHelpers, kt as AuthPluginOptions } from "../index-Cm0vUrr_.mjs";
|
|
2
2
|
import { c as PermissionCheck } from "../fields-C8Y0XLAu.mjs";
|
|
3
3
|
import { t as ExternalOpenApiPaths } from "../externalPaths-Bapitwvd.mjs";
|
|
4
4
|
import { a as SessionManagerOptions, c as createSessionManager, i as SessionData, n as MemorySessionStoreOptions, o as SessionManagerResult, r as SessionCookieOptions, s as SessionStore, t as MemorySessionStore } from "../sessionManager-D-oNWHz3.mjs";
|
package/dist/auth/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as
|
|
3
|
-
import {
|
|
4
|
-
import { n as extractBetterAuthOpenApi } from "../betterAuthOpenApi
|
|
1
|
+
import { _ as requireTeamMembership, m as requireOrgRole, p as requireOrgMembership } from "../permissions-B4vU9L0Q.mjs";
|
|
2
|
+
import { n as normalizeRoles, t as getUserRoles } from "../types-DV9WDfeg.mjs";
|
|
3
|
+
import { t as ArcError } from "../errors-D5c-5BJL.mjs";
|
|
4
|
+
import { n as extractBetterAuthOpenApi } from "../betterAuthOpenApi-DwxtK3uG.mjs";
|
|
5
5
|
import { createHmac, randomUUID, timingSafeEqual } from "node:crypto";
|
|
6
6
|
import fp from "fastify-plugin";
|
|
7
7
|
//#region src/auth/authPlugin.ts
|
|
@@ -684,7 +684,7 @@ function createBetterAuthAdapter(options) {
|
|
|
684
684
|
if (!fastify.hasDecorator("authenticate")) fastify.decorate("authenticate", authenticate);
|
|
685
685
|
if (!fastify.hasDecorator("optionalAuthenticate")) fastify.decorate("optionalAuthenticate", optionalAuthenticate);
|
|
686
686
|
if (!extractedOpenApi && openapiOpt !== false && auth.api && typeof auth.api === "object") {
|
|
687
|
-
const { extractBetterAuthOpenApi } = await import("../betterAuthOpenApi
|
|
687
|
+
const { extractBetterAuthOpenApi } = await import("../betterAuthOpenApi-DwxtK3uG.mjs").then((n) => n.t);
|
|
688
688
|
extractedOpenApi = extractBetterAuthOpenApi(auth.api, {
|
|
689
689
|
basePath,
|
|
690
690
|
userFields
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
|
|
2
|
-
import { a as toJsonSchema } from "./schemaConverter-
|
|
2
|
+
import { a as toJsonSchema } from "./schemaConverter-B0oKLuqI.mjs";
|
|
3
3
|
//#region src/auth/betterAuthOpenApi.ts
|
|
4
4
|
var betterAuthOpenApi_exports = /* @__PURE__ */ __exportAll({ extractBetterAuthOpenApi: () => extractBetterAuthOpenApi });
|
|
5
5
|
/**
|
package/dist/cache/index.d.mts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import { n as CacheStats, r as CacheStore, t as CacheLogger } from "../interface-
|
|
2
|
-
import { a as
|
|
1
|
+
import { n as CacheStats, r as CacheStore, t as CacheLogger } from "../interface-Da0r7Lna.mjs";
|
|
2
|
+
import { a as QueryCacheConfig, i as QueryCache, n as CacheResult, r as CacheStatus, t as CacheEnvelope } from "../QueryCache-DOBNHBE0.mjs";
|
|
3
|
+
import { i as queryCachePlugin, n as QueryCacheDefaults, r as QueryCachePluginOptions, t as CrossResourceRule } from "../queryCachePlugin-BUXBSm4F.mjs";
|
|
3
4
|
|
|
4
5
|
//#region src/cache/keys.d.ts
|
|
5
6
|
/**
|
package/dist/cache/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { i as versionKey, n as hashParams, r as tagVersionKey, t as buildQueryKey } from "../keys-
|
|
2
|
-
import { t as MemoryCacheStore } from "../memory-
|
|
3
|
-
import { r as QueryCache, t as queryCachePlugin } from "../queryCachePlugin-
|
|
1
|
+
import { i as versionKey, n as hashParams, r as tagVersionKey, t as buildQueryKey } from "../keys-CARyUjiR.mjs";
|
|
2
|
+
import { t as MemoryCacheStore } from "../memory-DikHSvWa.mjs";
|
|
3
|
+
import { r as QueryCache, t as queryCachePlugin } from "../queryCachePlugin-Bq6bO6vc.mjs";
|
|
4
4
|
//#region src/cache/redis.ts
|
|
5
5
|
/**
|
|
6
6
|
* Redis-backed cache store.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { t as ResourceRegistry } from "../../ResourceRegistry-
|
|
2
|
-
import { t as buildOpenApiSpec } from "../../openapi-
|
|
1
|
+
import { t as ResourceRegistry } from "../../ResourceRegistry-DkAeAuTX.mjs";
|
|
2
|
+
import { t as buildOpenApiSpec } from "../../openapi-C0L9ar7m.mjs";
|
|
3
3
|
import { dirname, resolve } from "node:path";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
5
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as pluralize } from "../../pluralize-
|
|
1
|
+
import { t as pluralize } from "../../pluralize-BneOJkpi.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.ts
|
|
@@ -159,14 +159,18 @@ import { buildCrudSchemasFromModel } from '@classytic/mongokit/utils';
|
|
|
159
159
|
const crudSchemas = buildCrudSchemasFromModel(${name}, {
|
|
160
160
|
strictAdditionalProperties: true,
|
|
161
161
|
fieldRules: {
|
|
162
|
-
// systemManaged:
|
|
162
|
+
// systemManaged: framework stamps it — strip from body + required[]
|
|
163
163
|
// deletedAt: { systemManaged: true },
|
|
164
164
|
// immutable: cannot be updated after creation
|
|
165
165
|
// slug: { immutable: true },
|
|
166
|
-
// immutableAfterCreate:
|
|
166
|
+
// immutableAfterCreate: alias for immutable
|
|
167
167
|
// organizationId: { immutableAfterCreate: true },
|
|
168
|
-
// optional: removed from required
|
|
168
|
+
// optional: removed from required[] (properties kept)
|
|
169
169
|
// description: { optional: true },
|
|
170
|
+
// nullable: widen JSON-Schema type to accept null (Zod .nullable() rescue)
|
|
171
|
+
// priceMode: { nullable: true },
|
|
172
|
+
// preserveForElevated: elevated admins keep the field on ingest (cross-tenant writes)
|
|
173
|
+
// organizationId: { systemManaged: true, preserveForElevated: true },
|
|
170
174
|
},
|
|
171
175
|
query: {
|
|
172
176
|
filterableFields: {
|
|
@@ -274,42 +278,48 @@ ${ts ? "import { z } from 'zod';\n" : "const { z } = require('zod');\n"}
|
|
|
274
278
|
return `/**
|
|
275
279
|
* ${name} Tests
|
|
276
280
|
* Generated by Arc CLI
|
|
281
|
+
*
|
|
282
|
+
* 2.11 testing surface:
|
|
283
|
+
* - createTestApp turnkey Fastify + in-memory Mongo + auth + fixtures
|
|
284
|
+
* - expectArc fluent envelope matchers (.ok, .unauthorized, .forbidden, ...)
|
|
285
|
+
* - ctx.auth unified TestAuthProvider — register a role, reuse .headers
|
|
277
286
|
*/
|
|
278
287
|
|
|
279
|
-
import { describe, it,
|
|
280
|
-
import
|
|
281
|
-
import {
|
|
282
|
-
|
|
288
|
+
import { describe, it, beforeAll, afterAll } from 'vitest';
|
|
289
|
+
import { createTestApp, expectArc } from '@classytic/arc/testing';
|
|
290
|
+
import type { TestAppContext } from '@classytic/arc/testing';
|
|
291
|
+
import ${camel}Resource from '../src/resources/${fileName}/${fileName}.resource.js';
|
|
283
292
|
|
|
284
293
|
describe('${name} Resource', () => {
|
|
285
|
-
let
|
|
294
|
+
let ctx${ts ? ": TestAppContext" : ""};
|
|
286
295
|
|
|
287
296
|
beforeAll(async () => {
|
|
288
|
-
|
|
289
|
-
|
|
297
|
+
ctx = await createTestApp({
|
|
298
|
+
resources: [${camel}Resource],
|
|
299
|
+
authMode: 'jwt',
|
|
300
|
+
connectMongoose: true,
|
|
301
|
+
});
|
|
290
302
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
303
|
+
ctx.auth${ts ? "!" : ""}.register('admin', {
|
|
304
|
+
user: { id: '1', roles: ['admin'] },
|
|
305
|
+
orgId: 'org-1',
|
|
306
|
+
});
|
|
294
307
|
});
|
|
295
308
|
|
|
296
|
-
afterAll(
|
|
297
|
-
await app.close();
|
|
298
|
-
await mongoose.connection.close();
|
|
299
|
-
});
|
|
309
|
+
afterAll(() => ctx.close());
|
|
300
310
|
|
|
301
311
|
describe('GET /${pluralize(fileName)}', () => {
|
|
302
|
-
it('should return a list', async () => {
|
|
303
|
-
const
|
|
304
|
-
|
|
305
|
-
url: '/${pluralize(fileName)}',
|
|
306
|
-
});
|
|
307
|
-
|
|
308
|
-
expect(response.statusCode).toBe(200);
|
|
309
|
-
const body = JSON.parse(response.body);
|
|
310
|
-
expect(body).toHaveProperty('docs');
|
|
312
|
+
it('should return a paginated list', async () => {
|
|
313
|
+
const res = await ctx.app.inject({ method: 'GET', url: '/${pluralize(fileName)}' });
|
|
314
|
+
expectArc(res).ok().paginated();
|
|
311
315
|
});
|
|
312
316
|
});
|
|
317
|
+
|
|
318
|
+
// More coverage patterns:
|
|
319
|
+
// - expectArc(res).unauthorized() for missing auth
|
|
320
|
+
// - expectArc(res).forbidden() for wrong role
|
|
321
|
+
// - ctx.auth.as('admin').headers for authenticated requests
|
|
322
|
+
// - ctx.fixtures.create('${fileName}', {...}) for seeded data
|
|
313
323
|
});
|
|
314
324
|
`;
|
|
315
325
|
}
|
|
@@ -309,7 +309,7 @@ function packageJsonTemplate(config) {
|
|
|
309
309
|
"#utils/*": "./src/utils/*"
|
|
310
310
|
},
|
|
311
311
|
scripts,
|
|
312
|
-
engines: { node: ">=
|
|
312
|
+
engines: { node: ">=22" }
|
|
313
313
|
}, null, 2);
|
|
314
314
|
}
|
|
315
315
|
function tsconfigTemplate() {
|
|
@@ -1746,8 +1746,12 @@ import { buildCrudSchemasFromModel } from '@classytic/mongokit/utils';
|
|
|
1746
1746
|
const crudSchemas = buildCrudSchemasFromModel(Example, {
|
|
1747
1747
|
strictAdditionalProperties: true,
|
|
1748
1748
|
fieldRules: {
|
|
1749
|
-
//
|
|
1749
|
+
// Framework-injected fields — strip from body + required[]
|
|
1750
1750
|
// deletedAt: { systemManaged: true },
|
|
1751
|
+
// Legitimate null values (Zod .nullable() patterns) — widen JSON-Schema type
|
|
1752
|
+
// priceMode: { nullable: true },
|
|
1753
|
+
// Elevated-admin override for systemManaged fields (cross-tenant writes)
|
|
1754
|
+
// organizationId: { systemManaged: true, preserveForElevated: true },
|
|
1751
1755
|
},
|
|
1752
1756
|
query: {
|
|
1753
1757
|
filterableFields: {
|
|
@@ -1781,61 +1785,70 @@ function exampleTestTemplate(config) {
|
|
|
1781
1785
|
*
|
|
1782
1786
|
* Run tests: npm test
|
|
1783
1787
|
* Watch mode: npm run test:watch
|
|
1788
|
+
*
|
|
1789
|
+
* Uses arc's 2.11 testing surface:
|
|
1790
|
+
* - createTestApp — turnkey Fastify + in-memory Mongo + auth + fixtures
|
|
1791
|
+
* - expectArc — fluent envelope matchers (.ok, .unauthorized, .forbidden, ...)
|
|
1792
|
+
* - ctx.auth — unified TestAuthProvider, register a role once then reuse .headers
|
|
1784
1793
|
*/
|
|
1785
1794
|
|
|
1786
|
-
import { describe, it,
|
|
1787
|
-
|
|
1788
|
-
|
|
1795
|
+
import { describe, it, beforeAll, afterAll } from 'vitest';
|
|
1796
|
+
import { createTestApp, expectArc } from '@classytic/arc/testing';
|
|
1797
|
+
import type { TestAppContext } from '@classytic/arc/testing';
|
|
1798
|
+
import { exampleResource } from '../src/resources/example/example.js';
|
|
1799
|
+
|
|
1789
1800
|
describe('Example Resource', () => {
|
|
1790
|
-
let
|
|
1801
|
+
let ctx${ts ? ": TestAppContext" : ""};
|
|
1791
1802
|
|
|
1792
1803
|
beforeAll(async () => {
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1804
|
+
ctx = await createTestApp({
|
|
1805
|
+
resources: [exampleResource],
|
|
1806
|
+
authMode: 'jwt',
|
|
1807
|
+
${config.adapter === "mongokit" ? " connectMongoose: true,\n" : ""} });
|
|
1808
|
+
|
|
1809
|
+
ctx.auth${ts ? "!" : ""}.register('admin', {
|
|
1810
|
+
user: { id: '1', roles: ['admin'] },
|
|
1811
|
+
orgId: 'org-1',
|
|
1812
|
+
});
|
|
1800
1813
|
});
|
|
1801
1814
|
|
|
1802
|
-
afterAll(
|
|
1803
|
-
await app.close();
|
|
1804
|
-
${config.adapter === "mongokit" ? " await mongoose.connection.close();" : ""}
|
|
1805
|
-
});
|
|
1815
|
+
afterAll(() => ctx.close());
|
|
1806
1816
|
|
|
1807
1817
|
describe('GET /examples', () => {
|
|
1808
|
-
it('should return a list of examples', async () => {
|
|
1809
|
-
const
|
|
1810
|
-
|
|
1811
|
-
url: '/examples',
|
|
1812
|
-
});
|
|
1813
|
-
|
|
1814
|
-
expect(response.statusCode).toBe(200);
|
|
1815
|
-
const body = JSON.parse(response.body);
|
|
1816
|
-
expect(body).toHaveProperty('docs');
|
|
1817
|
-
expect(Array.isArray(body.docs)).toBe(true);
|
|
1818
|
+
it('should return a list of examples (public)', async () => {
|
|
1819
|
+
const res = await ctx.app.inject({ method: 'GET', url: '/examples' });
|
|
1820
|
+
expectArc(res).ok().paginated();
|
|
1818
1821
|
});
|
|
1819
1822
|
});
|
|
1820
1823
|
|
|
1821
1824
|
describe('POST /examples', () => {
|
|
1822
1825
|
it('should require authentication', async () => {
|
|
1823
|
-
const
|
|
1826
|
+
const res = await ctx.app.inject({
|
|
1824
1827
|
method: 'POST',
|
|
1825
1828
|
url: '/examples',
|
|
1826
1829
|
payload: { name: 'Test Example' },
|
|
1827
1830
|
});
|
|
1831
|
+
expectArc(res).unauthorized();
|
|
1832
|
+
});
|
|
1828
1833
|
|
|
1829
|
-
|
|
1830
|
-
|
|
1834
|
+
it('should create when admin is authenticated', async () => {
|
|
1835
|
+
const res = await ctx.app.inject({
|
|
1836
|
+
method: 'POST',
|
|
1837
|
+
url: '/examples',
|
|
1838
|
+
headers: ctx.auth${ts ? "!" : ""}.as('admin').headers,
|
|
1839
|
+
payload: { name: 'Test Example' },
|
|
1840
|
+
});
|
|
1841
|
+
expectArc(res).ok();
|
|
1831
1842
|
});
|
|
1832
1843
|
});
|
|
1833
1844
|
|
|
1834
1845
|
// Add more tests as needed:
|
|
1835
|
-
// - GET /examples/:id
|
|
1836
|
-
// - PATCH /examples/:id
|
|
1837
|
-
// - DELETE /examples/:id
|
|
1846
|
+
// - GET /examples/:id (expectArc(res).ok().hasData({ name: '...' }))
|
|
1847
|
+
// - PATCH /examples/:id (expectArc(res).ok())
|
|
1848
|
+
// - DELETE /examples/:id (expectArc(res).ok())
|
|
1838
1849
|
// - Custom endpoints
|
|
1850
|
+
// - Permission denials (expectArc(res).forbidden().hasError(/reason/))
|
|
1851
|
+
// - Field hiding (expectArc(res).hidesField('password'))
|
|
1839
1852
|
});
|
|
1840
1853
|
`;
|
|
1841
1854
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as ResourceRegistry } from "../../ResourceRegistry-
|
|
1
|
+
import { t as ResourceRegistry } from "../../ResourceRegistry-DkAeAuTX.mjs";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { pathToFileURL } from "node:url";
|
|
4
4
|
//#region src/cli/commands/introspect.ts
|
package/dist/context/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as requestContext } from "../requestContext-
|
|
1
|
+
import { t as requestContext } from "../requestContext-CfRkaxwf.mjs";
|
|
2
2
|
export { requestContext };
|
package/dist/core/index.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { B as ResourceDefinition, V as defineResource,
|
|
2
|
-
import { C as MAX_REGEX_LENGTH, D as RESERVED_QUERY_PARAMS, E as MutationOperation, O as SYSTEM_FIELDS, S as MAX_FILTER_DEPTH, T as MUTATION_OPERATIONS, _ as DEFAULT_UPDATE_METHOD, a as getControllerScope, b as HookOperation, c as createCrudRouter, d as CrudOperation, f as DEFAULT_ID_FIELD, g as DEFAULT_TENANT_FIELD, h as DEFAULT_SORT, i as getControllerContext, l as createPermissionMiddleware, m as DEFAULT_MAX_LIMIT, n as createFastifyHandler, o as sendControllerResponse, p as DEFAULT_LIMIT, r as createRequestContext, s as defineResourceVariants, t as createCrudHandlers, u as CRUD_OPERATIONS, v as HOOK_OPERATIONS, w as MAX_SEARCH_LENGTH, x as HookPhase, y as HOOK_PHASES } from "../index-
|
|
3
|
-
export { AccessControl, AccessControlConfig, BaseController, BaseControllerOptions, BodySanitizer, BodySanitizerConfig, CRUD_OPERATIONS, CrudOperation, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, HOOK_OPERATIONS, HOOK_PHASES, HookOperation, HookPhase, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, MutationOperation, QueryResolver, QueryResolverConfig, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, createCrudHandlers, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineResource, defineResourceVariants, getControllerContext, getControllerScope, sendControllerResponse };
|
|
1
|
+
import { B as ResourceDefinition, Gt as TreeMixin, Ht as SoftDeleteExt, Jt as BulkExt, Kt as SlugExt, Ut as SoftDeleteMixin, V as defineResource, Vt as BaseController, Wt as TreeExt, Yt as BulkMixin, an as QueryResolverConfig, cn as AccessControl, in as QueryResolver, ln as AccessControlConfig, nn as BaseCrudController, on as BodySanitizer, qt as SlugMixin, rn as ListResult, sn as BodySanitizerConfig, tn as BaseControllerOptions } from "../index-Cm0vUrr_.mjs";
|
|
2
|
+
import { C as MAX_REGEX_LENGTH, D as RESERVED_QUERY_PARAMS, E as MutationOperation, O as SYSTEM_FIELDS, S as MAX_FILTER_DEPTH, T as MUTATION_OPERATIONS, _ as DEFAULT_UPDATE_METHOD, a as getControllerScope, b as HookOperation, c as createCrudRouter, d as CrudOperation, f as DEFAULT_ID_FIELD, g as DEFAULT_TENANT_FIELD, h as DEFAULT_SORT, i as getControllerContext, l as createPermissionMiddleware, m as DEFAULT_MAX_LIMIT, n as createFastifyHandler, o as sendControllerResponse, p as DEFAULT_LIMIT, r as createRequestContext, s as defineResourceVariants, t as createCrudHandlers, u as CRUD_OPERATIONS, v as HOOK_OPERATIONS, w as MAX_SEARCH_LENGTH, x as HookPhase, y as HOOK_PHASES } from "../index-t8pLpPFW.mjs";
|
|
3
|
+
export { AccessControl, AccessControlConfig, BaseController, BaseControllerOptions, BaseCrudController, BodySanitizer, BodySanitizerConfig, BulkExt, BulkMixin, CRUD_OPERATIONS, CrudOperation, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, HOOK_OPERATIONS, HOOK_PHASES, HookOperation, HookPhase, ListResult, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, MutationOperation, QueryResolver, QueryResolverConfig, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, SlugExt, SlugMixin, SoftDeleteExt, SoftDeleteMixin, TreeExt, TreeMixin, createCrudHandlers, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineResource, defineResourceVariants, getControllerContext, getControllerScope, sendControllerResponse };
|
package/dist/core/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { a as DEFAULT_SORT, c as HOOK_OPERATIONS, d as MAX_REGEX_LENGTH, f as MAX_SEARCH_LENGTH, h as SYSTEM_FIELDS, i as DEFAULT_MAX_LIMIT, l as HOOK_PHASES, m as RESERVED_QUERY_PARAMS, n as DEFAULT_ID_FIELD, o as DEFAULT_TENANT_FIELD, p as MUTATION_OPERATIONS, r as DEFAULT_LIMIT, s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS, u as MAX_FILTER_DEPTH } from "../constants-BhY1OHoH.mjs";
|
|
2
|
-
import { i as AccessControl, n as
|
|
3
|
-
import {
|
|
4
|
-
|
|
2
|
+
import { a as BulkMixin, c as BodySanitizer, i as SlugMixin, l as AccessControl, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, s as QueryResolver, t as BaseController } from "../BaseController-JNV08qOT.mjs";
|
|
3
|
+
import { _ as getControllerScope, g as getControllerContext, h as createRequestContext, m as createFastifyHandler, p as createCrudHandlers, v as sendControllerResponse } from "../routerShared-DeESFp4a.mjs";
|
|
4
|
+
import { a as createPermissionMiddleware, i as createCrudRouter, n as ResourceDefinition, r as defineResource, t as defineResourceVariants } from "../core-DXdSSFW-.mjs";
|
|
5
|
+
export { AccessControl, BaseController, BaseCrudController, BodySanitizer, BulkMixin, CRUD_OPERATIONS, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, HOOK_OPERATIONS, HOOK_PHASES, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, QueryResolver, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, SlugMixin, SoftDeleteMixin, TreeMixin, createCrudHandlers, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineResource, defineResourceVariants, getControllerContext, getControllerScope, sendControllerResponse };
|