@classytic/arc 2.11.1 → 2.11.3
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/LICENSE +21 -21
- package/README.md +143 -673
- package/bin/arc.js +2 -2
- package/dist/{BaseController-JNV08qOT.mjs → BaseController-swXruJ2_.mjs} +2 -2
- package/dist/{actionPermissions-C8YYU92K.mjs → actionPermissions-sUUKDhtP.mjs} +4 -2
- package/dist/adapters/index.d.mts +2 -2
- package/dist/audit/index.d.mts +1 -1
- package/dist/auth/index.d.mts +1 -1
- package/dist/auth/index.mjs +1 -1
- package/dist/cli/commands/docs.mjs +1 -1
- package/dist/cli/commands/generate.d.mts +0 -2
- package/dist/cli/commands/generate.mjs +15 -15
- package/dist/cli/commands/init.mjs +24 -22
- package/dist/context/index.mjs +1 -1
- package/dist/core/index.d.mts +2 -2
- package/dist/core/index.mjs +3 -3
- package/dist/{core-DXdSSFW-.mjs → core-DnUsRpuX.mjs} +20 -8
- package/dist/{createActionRouter-BwaSM0No.mjs → createActionRouter-u3ql2EDo.mjs} +73 -13
- package/dist/{createApp-P1d6rjPy.mjs → createApp-BFxtdKy6.mjs} +1 -1
- package/dist/docs/index.d.mts +1 -1
- package/dist/docs/index.mjs +1 -1
- package/dist/{eventPlugin--5HIkdPU.mjs → eventPlugin-KrFIQ097.mjs} +1 -1
- package/dist/events/index.d.mts +1 -1
- package/dist/events/index.mjs +11 -3
- package/dist/factory/index.d.mts +1 -1
- package/dist/factory/index.mjs +1 -1
- package/dist/hooks/index.d.mts +1 -1
- package/dist/idempotency/index.d.mts +1 -1
- package/dist/{index-C_bgx9o4.d.mts → index-6u4_Gg6G.d.mts} +34 -0
- package/dist/{index-CvM1e09j.d.mts → index-BbMrcvGp.d.mts} +1 -1
- package/dist/{index-pUczGjO0.d.mts → index-BdXnTPRj.d.mts} +1 -1
- package/dist/{index-smCAoA5W.d.mts → index-DdQ3O9Pg.d.mts} +1 -1
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +6 -6
- package/dist/integrations/index.d.mts +1 -1
- package/dist/integrations/mcp/index.d.mts +2 -2
- package/dist/integrations/mcp/index.mjs +1 -1
- package/dist/integrations/mcp/testing.d.mts +1 -1
- package/dist/integrations/mcp/testing.mjs +1 -1
- package/dist/middleware/index.d.mts +1 -1
- package/dist/{openapi-C0L9ar7m.mjs → openapi-BGUn7Ki1.mjs} +2 -2
- package/dist/org/index.d.mts +1 -1
- package/dist/permissions/index.mjs +1 -1
- package/dist/{permissions-B4vU9L0Q.mjs → permissions-gd_aUWrR.mjs} +42 -0
- package/dist/pipeline/index.d.mts +1 -1
- package/dist/plugins/index.d.mts +1 -1
- package/dist/plugins/index.mjs +1 -1
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/presets/filesUpload.d.mts +1 -1
- package/dist/presets/filesUpload.mjs +1 -1
- 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/search.d.mts +1 -1
- package/dist/presets/search.mjs +1 -1
- package/dist/{presets-k604Lj99.mjs → presets-Z7P5w4gF.mjs} +1 -1
- package/dist/registry/index.d.mts +1 -1
- package/dist/{requestContext-CfRkaxwf.mjs → requestContext-C5XeK3VA.mjs} +15 -0
- package/dist/{resourceToTools--okX6QBr.mjs → resourceToTools-ByZpgjeH.mjs} +5 -4
- package/dist/{routerShared-DeESFp4a.mjs → routerShared-BqLRb5l7.mjs} +60 -3
- package/dist/testing/index.d.mts +2 -2
- package/dist/testing/index.mjs +1 -1
- package/dist/types/index.d.mts +1 -1
- package/dist/{types-Bh_gEJBi.d.mts → types-9beEMe25.d.mts} +1 -1
- package/dist/{types-BdA4uMBV.d.mts → types-BH7dEGvU.d.mts} +1 -1
- package/dist/utils/index.d.mts +1 -1
- package/dist/utils/index.mjs +1 -1
- package/dist/{utils-D3Yxnrwr.mjs → utils-CcYTj09l.mjs} +1 -1
- package/package.json +5 -1
- package/skills/arc/references/events.md +489 -489
package/bin/arc.js
CHANGED
|
@@ -334,7 +334,7 @@ GLOBAL OPTIONS
|
|
|
334
334
|
|
|
335
335
|
INIT OPTIONS
|
|
336
336
|
--mongokit Use MongoKit adapter (default, recommended)
|
|
337
|
-
--custom Use custom adapter
|
|
337
|
+
--custom Use custom / Drizzle-ready adapter template
|
|
338
338
|
--better-auth Use Better Auth (default, recommended)
|
|
339
339
|
--jwt Use Arc built-in JWT auth
|
|
340
340
|
--multi-tenant, --multi Multi-tenant mode (adds org scoping)
|
|
@@ -346,7 +346,7 @@ INIT OPTIONS
|
|
|
346
346
|
--skip-install Skip npm install after scaffolding
|
|
347
347
|
|
|
348
348
|
GENERATE SUBCOMMANDS
|
|
349
|
-
resource, r Generate
|
|
349
|
+
resource, r Generate resource-first scaffold (model, repo, resource, test)
|
|
350
350
|
controller, c Generate controller only
|
|
351
351
|
model, m Generate model only
|
|
352
352
|
repository, repo Generate repository only
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { h as SYSTEM_FIELDS, o as DEFAULT_TENANT_FIELD } from "./constants-BhY1OHoH.mjs";
|
|
2
2
|
import { arcLog } from "./logger/index.mjs";
|
|
3
3
|
import { _ as isElevated, n as PUBLIC_SCOPE, o as getOrgId, v as isMember } from "./types-AOD8fxIw.mjs";
|
|
4
|
-
import { M as simpleEqualityMatcher, j as getUserId, k as ArcQueryParser } from "./utils-
|
|
4
|
+
import { M as simpleEqualityMatcher, j as getUserId, k as ArcQueryParser } from "./utils-CcYTj09l.mjs";
|
|
5
5
|
import { t as buildQueryKey } from "./keys-CARyUjiR.mjs";
|
|
6
|
-
import { M as applyFieldWritePermissions, P as resolveEffectiveRoles } from "./permissions-
|
|
6
|
+
import { M as applyFieldWritePermissions, P as resolveEffectiveRoles } from "./permissions-gd_aUWrR.mjs";
|
|
7
7
|
import { t as getUserRoles } from "./types-DV9WDfeg.mjs";
|
|
8
8
|
import { r as ForbiddenError } from "./errors-D5c-5BJL.mjs";
|
|
9
9
|
//#region src/core/AccessControl.ts
|
|
@@ -5,8 +5,10 @@
|
|
|
5
5
|
*
|
|
6
6
|
* Callers decide what "no gate" means:
|
|
7
7
|
* - HTTP: boot-time throw in `normalizeActionsToRouterConfig`.
|
|
8
|
-
* - MCP:
|
|
9
|
-
*
|
|
8
|
+
* - MCP: tool-generation throw in `resourceToTools` (mirrors HTTP — the
|
|
9
|
+
* two surfaces fail closed identically so MCP can't expose an
|
|
10
|
+
* unauthenticated mutating tool when the HTTP plugin lifecycle hasn't
|
|
11
|
+
* run).
|
|
10
12
|
* - OpenAPI: docs advertise the endpoint as unauthenticated.
|
|
11
13
|
*/
|
|
12
14
|
function resolveActionPermission(input) {
|
|
@@ -1,3 +1,3 @@
|
|
|
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-
|
|
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-6u4_Gg6G.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-BbMrcvGp.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/audit/index.d.mts
CHANGED
package/dist/auth/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Ot as AuthHelpers, kt as AuthPluginOptions } from "../index-
|
|
1
|
+
import { Ot as AuthHelpers, kt as AuthPluginOptions } from "../index-6u4_Gg6G.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,4 +1,4 @@
|
|
|
1
|
-
import { _ as requireTeamMembership, m as requireOrgRole, p as requireOrgMembership } from "../permissions-
|
|
1
|
+
import { _ as requireTeamMembership, m as requireOrgRole, p as requireOrgMembership } from "../permissions-gd_aUWrR.mjs";
|
|
2
2
|
import { n as normalizeRoles, t as getUserRoles } from "../types-DV9WDfeg.mjs";
|
|
3
3
|
import { t as ArcError } from "../errors-D5c-5BJL.mjs";
|
|
4
4
|
import { n as extractBetterAuthOpenApi } from "../betterAuthOpenApi-DwxtK3uG.mjs";
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as ResourceRegistry } from "../../ResourceRegistry-DkAeAuTX.mjs";
|
|
2
|
-
import { t as buildOpenApiSpec } from "../../openapi-
|
|
2
|
+
import { t as buildOpenApiSpec } from "../../openapi-BGUn7Ki1.mjs";
|
|
3
3
|
import { dirname, resolve } from "node:path";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
5
|
import { mkdirSync, writeFileSync } from "node:fs";
|
|
@@ -6,8 +6,6 @@
|
|
|
6
6
|
* - src/resources/product/product.model.ts
|
|
7
7
|
* - src/resources/product/product.repository.ts
|
|
8
8
|
* - src/resources/product/product.resource.ts
|
|
9
|
-
* - src/resources/product/product.controller.ts
|
|
10
|
-
* - src/resources/product/product.schemas.ts
|
|
11
9
|
*
|
|
12
10
|
* Handles kebab-case names: `arc g r org-profile` generates:
|
|
13
11
|
* - Class names: OrgProfile, OrgProfileRepository
|
|
@@ -9,8 +9,6 @@ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
|
9
9
|
* - src/resources/product/product.model.ts
|
|
10
10
|
* - src/resources/product/product.repository.ts
|
|
11
11
|
* - src/resources/product/product.resource.ts
|
|
12
|
-
* - src/resources/product/product.controller.ts
|
|
13
|
-
* - src/resources/product/product.schemas.ts
|
|
14
12
|
*
|
|
15
13
|
* Handles kebab-case names: `arc g r org-profile` generates:
|
|
16
14
|
* - Class names: OrgProfile, OrgProfileRepository
|
|
@@ -58,7 +56,7 @@ ${ts ? `
|
|
|
58
56
|
export interface I${name} {
|
|
59
57
|
name: string;
|
|
60
58
|
description?: string;
|
|
61
|
-
isActive: boolean;
|
|
59
|
+
${isMultiTenant ? "organizationId: string;\n " : ""}isActive: boolean;
|
|
62
60
|
}
|
|
63
61
|
|
|
64
62
|
export type ${name}Document = HydratedDocument<I${name}>;
|
|
@@ -67,14 +65,14 @@ const ${camel}Schema = new Schema${ts ? `<I${name}>` : ""}(
|
|
|
67
65
|
{
|
|
68
66
|
name: { type: String, required: true, trim: true },
|
|
69
67
|
description: { type: String, trim: true },
|
|
70
|
-
isActive: { type: Boolean, default: true },
|
|
68
|
+
${isMultiTenant ? "organizationId: { type: String, required: true, index: true },\n " : ""}isActive: { type: Boolean, default: true },
|
|
71
69
|
},
|
|
72
70
|
{ timestamps: true }
|
|
73
71
|
);
|
|
74
72
|
|
|
75
73
|
// Indexes
|
|
76
74
|
${camel}Schema.index({ name: 1 });
|
|
77
|
-
${camel}Schema.index({ isActive: 1 });
|
|
75
|
+
${isMultiTenant ? `${camel}Schema.index({ organizationId: 1, isActive: 1 });\n` : ""}${camel}Schema.index({ isActive: 1 });
|
|
78
76
|
|
|
79
77
|
const ${name} = mongoose.models.${name} || mongoose.model('${name}', ${camel}Schema);
|
|
80
78
|
export default ${name};
|
|
@@ -193,20 +191,21 @@ export default crudSchemas;
|
|
|
193
191
|
*/
|
|
194
192
|
|
|
195
193
|
import { defineResource, createMongooseAdapter } from '@classytic/arc';
|
|
196
|
-
import {
|
|
194
|
+
import { allOf, requireOrgMembership, requireRoles } from '@classytic/arc/permissions';
|
|
195
|
+
import { multiTenantPreset } from '@classytic/arc/presets';
|
|
197
196
|
import ${name}${ts ? `, { type I${name} }` : ""} from './${fileName}.model.js';
|
|
198
197
|
import ${camel}Repository from './${fileName}.repository.js';${queryParserImport}
|
|
199
198
|
|
|
200
199
|
const ${camel}Resource = defineResource${ts ? `<I${name}>` : ""}({
|
|
201
200
|
name: '${fileName}',
|
|
202
201
|
adapter: createMongooseAdapter({ model: ${name}, repository: ${camel}Repository }),${queryParserConfig}
|
|
203
|
-
presets: ['softDelete'],
|
|
202
|
+
presets: ['softDelete', multiTenantPreset({ tenantField: 'organizationId' })],
|
|
204
203
|
permissions: {
|
|
205
|
-
list:
|
|
206
|
-
get:
|
|
207
|
-
create: requireRoles(['admin']),
|
|
208
|
-
update: requireRoles(['admin']),
|
|
209
|
-
delete: requireRoles(['admin']),
|
|
204
|
+
list: requireOrgMembership(),
|
|
205
|
+
get: requireOrgMembership(),
|
|
206
|
+
create: allOf(requireOrgMembership(), requireRoles(['admin'])),
|
|
207
|
+
update: allOf(requireOrgMembership(), requireRoles(['admin'])),
|
|
208
|
+
delete: allOf(requireOrgMembership(), requireRoles(['admin'])),
|
|
210
209
|
},
|
|
211
210
|
});
|
|
212
211
|
|
|
@@ -367,7 +366,7 @@ async function generate(type, args) {
|
|
|
367
366
|
}
|
|
368
367
|
}
|
|
369
368
|
/**
|
|
370
|
-
* Generate a
|
|
369
|
+
* Generate a resource-first scaffold
|
|
371
370
|
*/
|
|
372
371
|
async function generateResource(name, lowerName, resourcePath, templates, ext, includeMcp = false) {
|
|
373
372
|
console.log(`\nGenerating resource: ${name}...\n`);
|
|
@@ -417,8 +416,9 @@ Next steps:
|
|
|
417
416
|
src/resources/${lowerName}/${lowerName}.model.${ext}
|
|
418
417
|
|
|
419
418
|
3. Adjust permissions in ${lowerName}.resource.${ext}:
|
|
420
|
-
${isMultiTenant ? ` -
|
|
421
|
-
-
|
|
419
|
+
${isMultiTenant ? ` - requireOrgMembership() → member of the current organization
|
|
420
|
+
- multiTenantPreset() → injects and filters organizationId
|
|
421
|
+
- requireRoles(['admin']) → admin writes inside the org scope` : ` - requireAuth() → any authenticated user
|
|
422
422
|
- requireRoles(['admin']) → specific platform roles`}
|
|
423
423
|
|
|
424
424
|
4. Run tests:
|
|
@@ -26,7 +26,7 @@ async function init(options = {}) {
|
|
|
26
26
|
`);
|
|
27
27
|
const config = await gatherConfig(options);
|
|
28
28
|
console.log(`\nCreating project: ${config.name}`);
|
|
29
|
-
console.log(` Adapter: ${config.adapter === "mongokit" ? "MongoKit (MongoDB)" : "Custom"}`);
|
|
29
|
+
console.log(` Adapter: ${config.adapter === "mongokit" ? "MongoKit (MongoDB)" : "Custom / Drizzle-ready"}`);
|
|
30
30
|
console.log(` Auth: ${config.auth === "better-auth" ? "Better Auth (recommended)" : "Arc JWT"}`);
|
|
31
31
|
console.log(` Tenant: ${config.tenant === "multi" ? "Multi-tenant" : "Single-tenant"}`);
|
|
32
32
|
console.log(` Language: ${config.typescript ? "TypeScript" : "JavaScript"}`);
|
|
@@ -156,7 +156,7 @@ async function gatherConfig(options) {
|
|
|
156
156
|
try {
|
|
157
157
|
const name = options.name || await question("Project name: ") || "my-arc-app";
|
|
158
158
|
let adapter = options.adapter || "mongokit";
|
|
159
|
-
if (!options.adapter && !nonInteractive) adapter = await question("Database adapter [1=MongoKit (recommended), 2=Custom]: ") === "2" ? "custom" : "mongokit";
|
|
159
|
+
if (!options.adapter && !nonInteractive) adapter = await question("Database adapter [1=MongoKit (recommended), 2=Custom / Drizzle-ready]: ") === "2" ? "custom" : "mongokit";
|
|
160
160
|
let auth = options.auth || "better-auth";
|
|
161
161
|
if (!options.auth && !nonInteractive) auth = await question("Auth strategy [1=Better Auth (recommended), 2=Arc JWT]: ") === "2" ? "jwt" : "better-auth";
|
|
162
162
|
let tenant = options.tenant || "single";
|
|
@@ -171,12 +171,12 @@ async function gatherConfig(options) {
|
|
|
171
171
|
console.log(" MongoDB Atlas works with the raw driver (mongodb 6.15+ with nodejs_compat_v2),");
|
|
172
172
|
console.log(" but MongoKit depends on Mongoose. Options:");
|
|
173
173
|
console.log(" 1. Use AWS Lambda / Vercel Serverless (Node.js) — Mongoose works normally");
|
|
174
|
-
console.log(" 2. Use Cloudflare Hyperdrive + PostgreSQL (
|
|
174
|
+
console.log(" 2. Use Cloudflare Hyperdrive + PostgreSQL (wire sqlitekit/Drizzle via custom adapter)");
|
|
175
175
|
console.log(" 3. Continue with MongoKit — works on Lambda/Vercel, NOT on Cloudflare Workers");
|
|
176
176
|
console.log("");
|
|
177
177
|
if ((await question("Continue with MongoKit? [y/N]: ")).toLowerCase() !== "y") {
|
|
178
178
|
adapter = "custom";
|
|
179
|
-
console.log(" Switched to custom adapter.
|
|
179
|
+
console.log(" Switched to custom adapter. Wire sqlitekit/Drizzle here; Prisma remains experimental.");
|
|
180
180
|
}
|
|
181
181
|
}
|
|
182
182
|
return {
|
|
@@ -465,7 +465,7 @@ src/
|
|
|
465
465
|
│ ├── env.${ext} # Env loader (import first!)
|
|
466
466
|
│ └── index.${ext} # App config
|
|
467
467
|
├── shared/ # Shared utilities
|
|
468
|
-
│ ├── adapter.${ext} # ${config.adapter === "mongokit" ? "MongoKit adapter factory" : "Custom adapter"}
|
|
468
|
+
│ ├── adapter.${ext} # ${config.adapter === "mongokit" ? "MongoKit adapter factory" : "Custom / Drizzle-ready adapter"}
|
|
469
469
|
│ ├── permissions.${ext} # Permission helpers
|
|
470
470
|
│ └── presets/ # ${config.tenant === "multi" ? "Multi-tenant presets" : "Standard presets"}
|
|
471
471
|
├── plugins/ # App-specific plugins
|
|
@@ -995,29 +995,31 @@ function customAdapterTemplate(config) {
|
|
|
995
995
|
return `/**
|
|
996
996
|
* Custom Adapter Factory
|
|
997
997
|
*
|
|
998
|
-
*
|
|
998
|
+
* Use this for sqlitekit/Drizzle, Prisma experiments, or any repository
|
|
999
|
+
* that satisfies Arc's RepositoryLike contract.
|
|
999
1000
|
*/
|
|
1000
1001
|
|
|
1001
|
-
import {
|
|
1002
|
-
${ts ? "import type { Model } from 'mongoose';" : ""}
|
|
1002
|
+
${ts ? "import type { DataAdapter, RepositoryLike } from '@classytic/arc/adapters';" : ""}
|
|
1003
1003
|
|
|
1004
1004
|
/**
|
|
1005
|
-
* Create a custom adapter for a resource
|
|
1005
|
+
* Create a custom adapter for a resource.
|
|
1006
1006
|
*
|
|
1007
|
-
*
|
|
1008
|
-
* -
|
|
1009
|
-
*
|
|
1010
|
-
*
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1007
|
+
* Recommended SQL path:
|
|
1008
|
+
* - sqlitekit repository + Arc's createDrizzleAdapter for Drizzle tables
|
|
1009
|
+
*
|
|
1010
|
+
* Experimental path:
|
|
1011
|
+
* - Prisma can be wired with createPrismaAdapter, but keep it opt-in until
|
|
1012
|
+
* your app has integration coverage.
|
|
1013
|
+
*/
|
|
1014
|
+
export function createAdapter${ts ? "<TDoc = unknown>" : ""}(
|
|
1015
|
+
_source${ts ? ": unknown" : ""},
|
|
1016
|
+
repository${ts ? ": RepositoryLike<TDoc>" : ""}
|
|
1017
|
+
)${ts ? ": DataAdapter<TDoc>" : ""} {
|
|
1018
|
+
return {
|
|
1019
|
+
type: 'custom',
|
|
1020
|
+
name: 'custom-repository',
|
|
1019
1021
|
repository,
|
|
1020
|
-
}
|
|
1022
|
+
};
|
|
1021
1023
|
}
|
|
1022
1024
|
`;
|
|
1023
1025
|
}
|
package/dist/context/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as requestContext } from "../requestContext-
|
|
1
|
+
import { t as requestContext } from "../requestContext-C5XeK3VA.mjs";
|
|
2
2
|
export { requestContext };
|
package/dist/core/index.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
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-
|
|
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-
|
|
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-6u4_Gg6G.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-BdXnTPRj.mjs";
|
|
3
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,5 +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 { 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-
|
|
3
|
-
import { _ as
|
|
4
|
-
import { a as createPermissionMiddleware, i as createCrudRouter, n as ResourceDefinition, r as defineResource, t as defineResourceVariants } from "../core-
|
|
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-swXruJ2_.mjs";
|
|
3
|
+
import { _ as getControllerContext, g as createRequestContext, h as createFastifyHandler, m as createCrudHandlers, v as getControllerScope, y as sendControllerResponse } from "../routerShared-BqLRb5l7.mjs";
|
|
4
|
+
import { a as createPermissionMiddleware, i as createCrudRouter, n as ResourceDefinition, r as defineResource, t as defineResourceVariants } from "../core-DnUsRpuX.mjs";
|
|
5
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 };
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS } from "./constants-BhY1OHoH.mjs";
|
|
2
2
|
import { arcLog } from "./logger/index.mjs";
|
|
3
|
-
import { m as assertValidConfig, y as getDefaultCrudSchemas } from "./utils-
|
|
4
|
-
import { t as BaseController } from "./BaseController-
|
|
3
|
+
import { m as assertValidConfig, y as getDefaultCrudSchemas } from "./utils-CcYTj09l.mjs";
|
|
4
|
+
import { t as BaseController } from "./BaseController-swXruJ2_.mjs";
|
|
5
5
|
import { n as convertRouteSchema, t as convertOpenApiSchemas } from "./schemaConverter-B0oKLuqI.mjs";
|
|
6
|
-
import { c as buildPreHandlerChain, d as
|
|
7
|
-
import { t as applyPresets } from "./presets-
|
|
6
|
+
import { b as buildRequestScopeProjection, c as buildPreHandlerChain, d as resolveRoutePreHandlers, f as resolveRouterPluginMw, h as createFastifyHandler, i as buildAuthMiddleware, l as buildRateLimitConfig, m as createCrudHandlers, o as buildCrudPermissionMw, p as selectPluginMw, r as buildArcDecorator, s as buildPipelineHandler, u as resolvePipelineSteps } from "./routerShared-BqLRb5l7.mjs";
|
|
7
|
+
import { t as applyPresets } from "./presets-Z7P5w4gF.mjs";
|
|
8
8
|
import { t as hasEvents } from "./typeGuards-CcFZXgU7.mjs";
|
|
9
|
-
import { t as resolveActionPermission } from "./actionPermissions-
|
|
9
|
+
import { t as resolveActionPermission } from "./actionPermissions-sUUKDhtP.mjs";
|
|
10
10
|
//#region src/core/createCrudRouter.ts
|
|
11
11
|
/**
|
|
12
12
|
* Mount custom routes (from presets or user-defined `routes`) on Fastify.
|
|
@@ -39,7 +39,7 @@ function createCustomRoutes(fastify, routes, controller, options) {
|
|
|
39
39
|
...route.description ? { description: route.description } : {},
|
|
40
40
|
...convertedSchema ?? {}
|
|
41
41
|
};
|
|
42
|
-
const customPreHandlers =
|
|
42
|
+
const customPreHandlers = resolveRoutePreHandlers(route.preHandler, fastify, `${route.method} ${route.path}`);
|
|
43
43
|
const preHandler = buildPreHandlerChain({
|
|
44
44
|
preAuth: route.preAuth ?? [],
|
|
45
45
|
arcDecorator,
|
|
@@ -469,7 +469,19 @@ function resolveOrAutoCreateController(resolvedConfig, adapter, repository, hasC
|
|
|
469
469
|
if (typeof ctrl.setQueryParser === "function") ctrl.setQueryParser(resolvedConfig.queryParser);
|
|
470
470
|
else arcLog("defineResource").warn(`Resource "${resolvedConfig.name}" declares a custom \`queryParser\` but its controller does not expose \`setQueryParser(qp)\`. The parser will NOT be threaded into the controller's query resolution — operator filters (\`[contains]\`, \`[like]\`, etc.) may fall back to the controller's internal default. Extend \`BaseController\` / \`BaseCrudController\` (both implement \`setQueryParser\`) OR add the method to your custom controller to honor the resource-level parser.`);
|
|
471
471
|
}
|
|
472
|
-
if (controller
|
|
472
|
+
if (controller) {
|
|
473
|
+
const droppedOptions = [];
|
|
474
|
+
if (resolvedConfig.tenantField !== void 0) droppedOptions.push("tenantField");
|
|
475
|
+
if (resolvedConfig.schemaOptions !== void 0 && Object.keys(resolvedConfig.schemaOptions).length > 0) droppedOptions.push("schemaOptions");
|
|
476
|
+
if (resolvedConfig.idField !== void 0) droppedOptions.push("idField");
|
|
477
|
+
if (resolvedConfig.defaultSort !== void 0) droppedOptions.push("defaultSort");
|
|
478
|
+
if (resolvedConfig.cache !== void 0) droppedOptions.push("cache");
|
|
479
|
+
if (resolvedConfig.onFieldWriteDenied !== void 0) droppedOptions.push("onFieldWriteDenied");
|
|
480
|
+
if (resolvedConfig._controllerOptions !== void 0) droppedOptions.push("preset-injected fields (slug/softDelete/parent)");
|
|
481
|
+
if (droppedOptions.length > 0) arcLog("defineResource").warn(`Resource "${resolvedConfig.name}" declares a custom controller AND resource-level option(s) [${droppedOptions.join(", ")}]. Arc only threads these when it auto-builds the controller — when you pass your own, they are dropped silently and the controller falls back to its own defaults (e.g. tenantField → 'organizationId'). Forward them to your controller's \`super(repo, { ... })\` call. Same root cause as the \`queryParser\` warn above.`);
|
|
482
|
+
return controller;
|
|
483
|
+
}
|
|
484
|
+
if (!hasCrudRoutes || !repository) return controller;
|
|
473
485
|
const qp = resolvedConfig.queryParser;
|
|
474
486
|
let maxLimitFromParser;
|
|
475
487
|
if (qp?.getQuerySchema) {
|
|
@@ -869,7 +881,7 @@ var ResourceDefinition = class {
|
|
|
869
881
|
fields: self.fields
|
|
870
882
|
});
|
|
871
883
|
if (self.actions && Object.keys(self.actions).length > 0) {
|
|
872
|
-
const { createActionRouter } = await import("./createActionRouter-
|
|
884
|
+
const { createActionRouter } = await import("./createActionRouter-u3ql2EDo.mjs").then((n) => n.n);
|
|
873
885
|
createActionRouter(typedInstance, {
|
|
874
886
|
...normalizeActionsToRouterConfig(self.actions, self.actionPermissions, self.tag, self.permissions, self.name, typedInstance.log),
|
|
875
887
|
resourceName: self.name,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
|
|
2
|
-
import { a as buildAuthMiddlewareForPermissions, c as buildPreHandlerChain,
|
|
2
|
+
import { a as buildAuthMiddlewareForPermissions, c as buildPreHandlerChain, f as resolveRouterPluginMw, l as buildRateLimitConfig, n as buildActionPipelineHandler, p as selectPluginMw, r as buildArcDecorator, t as buildActionPermissionMw, u as resolvePipelineSteps, y as sendControllerResponse } from "./routerShared-BqLRb5l7.mjs";
|
|
3
3
|
import { n as schemaIRToJsonSchemaBranch, t as normalizeSchemaIR } from "./schemaIR-BlG9bY7v.mjs";
|
|
4
4
|
//#region src/core/createActionRouter.ts
|
|
5
5
|
var createActionRouter_exports = /* @__PURE__ */ __exportAll({
|
|
@@ -118,34 +118,94 @@ function createActionRouter(fastify, config) {
|
|
|
118
118
|
* {
|
|
119
119
|
* "type": "object",
|
|
120
120
|
* "required": ["action"],
|
|
121
|
+
* "properties": {
|
|
122
|
+
* "action": { "type": "string", "enum": ["dispatch", "approve"] },
|
|
123
|
+
* "carrier": { "type": "string" }
|
|
124
|
+
* },
|
|
121
125
|
* "oneOf": [
|
|
122
|
-
* {
|
|
123
|
-
*
|
|
126
|
+
* {
|
|
127
|
+
* "properties": {
|
|
128
|
+
* "action": { "const": "dispatch" },
|
|
129
|
+
* "carrier": { "type": "string" } // ← every branch lists the union
|
|
130
|
+
* },
|
|
131
|
+
* "required": ["action", "carrier"]
|
|
132
|
+
* },
|
|
133
|
+
* {
|
|
134
|
+
* "properties": {
|
|
135
|
+
* "action": { "const": "approve" },
|
|
136
|
+
* "carrier": { "type": "string" } // ← even though approve doesn't use it
|
|
137
|
+
* },
|
|
138
|
+
* "required": ["action"]
|
|
139
|
+
* }
|
|
124
140
|
* ]
|
|
125
141
|
* }
|
|
126
142
|
* ```
|
|
127
143
|
*
|
|
128
|
-
*
|
|
129
|
-
*
|
|
144
|
+
* **Why every branch carries the full property union.** AJV's
|
|
145
|
+
* `removeAdditional: 'all'` (Fastify's framework default) interacts badly
|
|
146
|
+
* with `oneOf`: when a branch's `properties` lacks a field, AJV strips it
|
|
147
|
+
* from the body during that branch's evaluation — *even if a different
|
|
148
|
+
* branch would have allowed it*. The strip mutates the body before
|
|
149
|
+
* `oneOf` finishes discriminating, so by the time the matching branch
|
|
150
|
+
* wins, the body has already lost fields. Concretely: `actions: { verify:
|
|
151
|
+
* {}, hold: { schema: z.object({ amount, reason }.optional()) } }` +
|
|
152
|
+
* `POST { action: 'hold', amount: 1, reason }` lands at the handler as
|
|
153
|
+
* `{ action: 'hold' }`. Empirically reproduced and locked at
|
|
154
|
+
* [tests/core/action-discriminator-strip.test.ts](../../tests/core/action-discriminator-strip.test.ts).
|
|
155
|
+
*
|
|
156
|
+
* Listing every action's properties on every branch makes per-branch
|
|
157
|
+
* removeAdditional walks see every caller field as "in this branch's
|
|
158
|
+
* properties," so nothing gets stripped during oneOf evaluation. The
|
|
159
|
+
* `required` array stays per-action, so the handler still gets called
|
|
160
|
+
* only when the matching branch's required-field contract is satisfied.
|
|
161
|
+
* Per-branch `additionalProperties: false` (Zod v4 default) carries
|
|
162
|
+
* through but, under host removeAdditional: 'all', it can no longer
|
|
163
|
+
* reject sibling-action fields — those become silently stripped at top
|
|
164
|
+
* level instead. That's the host's opt-in to stripping; arc's job is to
|
|
165
|
+
* stop accidentally losing the action's *own* declared fields.
|
|
166
|
+
*
|
|
167
|
+
* Under arc's own `createApp` (`removeAdditional: false`), strict-mode
|
|
168
|
+
* rejection still functions normally — see
|
|
169
|
+
* [tests/core/action-strict-schema-parity.test.ts](../../tests/core/action-strict-schema-parity.test.ts).
|
|
130
170
|
*
|
|
131
171
|
* Exported so OpenAPI generation and MCP tool generation can reuse the same
|
|
132
172
|
* schema shape (single source of truth).
|
|
133
173
|
*/
|
|
134
174
|
function buildActionBodySchema(actionEnum, actionSchemas = {}) {
|
|
135
|
-
const
|
|
175
|
+
const unionProperties = {};
|
|
176
|
+
const irs = [];
|
|
136
177
|
for (const actionName of actionEnum) {
|
|
137
178
|
const ir = normalizeSchemaIR(actionSchemas[actionName]);
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
required: ["action"]
|
|
144
|
-
}));
|
|
179
|
+
irs.push({
|
|
180
|
+
name: actionName,
|
|
181
|
+
ir
|
|
182
|
+
});
|
|
183
|
+
for (const [key, val] of Object.entries(ir.properties)) unionProperties[key] = val;
|
|
145
184
|
}
|
|
185
|
+
const branches = [];
|
|
186
|
+
for (const { name, ir } of irs) branches.push(schemaIRToJsonSchemaBranch({
|
|
187
|
+
...ir,
|
|
188
|
+
properties: {
|
|
189
|
+
...unionProperties,
|
|
190
|
+
...ir.properties
|
|
191
|
+
}
|
|
192
|
+
}, {
|
|
193
|
+
properties: { action: {
|
|
194
|
+
type: "string",
|
|
195
|
+
const: name
|
|
196
|
+
} },
|
|
197
|
+
required: ["action"]
|
|
198
|
+
}));
|
|
146
199
|
return {
|
|
147
200
|
type: "object",
|
|
148
201
|
required: ["action"],
|
|
202
|
+
properties: {
|
|
203
|
+
action: {
|
|
204
|
+
type: "string",
|
|
205
|
+
enum: [...actionEnum]
|
|
206
|
+
},
|
|
207
|
+
...unionProperties
|
|
208
|
+
},
|
|
149
209
|
oneOf: branches
|
|
150
210
|
};
|
|
151
211
|
}
|
|
@@ -204,7 +204,7 @@ async function registerArcCore(fastify, config, trackPlugin) {
|
|
|
204
204
|
await fastify.register(arcCorePlugin, { emitEvents: config.arcPlugins?.emitEvents !== false });
|
|
205
205
|
trackPlugin("arc-core");
|
|
206
206
|
if (config.arcPlugins?.events !== false) {
|
|
207
|
-
const { default: eventPlugin } = await import("./eventPlugin
|
|
207
|
+
const { default: eventPlugin } = await import("./eventPlugin-KrFIQ097.mjs").then((n) => n.n);
|
|
208
208
|
const eventOpts = typeof config.arcPlugins?.events === "object" ? config.arcPlugins.events : {};
|
|
209
209
|
await fastify.register(eventPlugin, {
|
|
210
210
|
...eventOpts,
|
package/dist/docs/index.d.mts
CHANGED
package/dist/docs/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as getUserRoles } from "../types-DV9WDfeg.mjs";
|
|
2
|
-
import { n as openApiPlugin, r as openapi_default, t as buildOpenApiSpec } from "../openapi-
|
|
2
|
+
import { n as openApiPlugin, r as openapi_default, t as buildOpenApiSpec } from "../openapi-BGUn7Ki1.mjs";
|
|
3
3
|
import fp from "fastify-plugin";
|
|
4
4
|
//#region src/docs/scalar.ts
|
|
5
5
|
const scalarPlugin = async (fastify, opts = {}) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
|
|
2
|
-
import { t as requestContext } from "./requestContext-
|
|
2
|
+
import { t as requestContext } from "./requestContext-C5XeK3VA.mjs";
|
|
3
3
|
import fp from "fastify-plugin";
|
|
4
4
|
//#region src/events/EventTransport.ts
|
|
5
5
|
/**
|
package/dist/events/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jn as RepositoryLike } from "../index-
|
|
1
|
+
import { jn as RepositoryLike } from "../index-6u4_Gg6G.mjs";
|
|
2
2
|
import { a as EventMeta, c as MemoryEventTransportOptions, d as createEvent, i as EventLogger, l as PublishManyResult, n as DomainEvent, o as EventTransport, r as EventHandler, s as MemoryEventTransport, t as DeadLetteredEvent, u as createChildEvent } from "../EventTransport-CfVEGaEl.mjs";
|
|
3
3
|
import { a as withRetry, c as EventDefinitionOutput, d as EventSchema, f as ValidationResult, i as createDeadLetterPublisher, l as EventRegistry, m as defineEvent, n as eventPlugin, o as CustomValidator, p as createEventRegistry, r as RetryOptions, s as EventDefinitionInput, t as EventPluginOptions, u as EventRegistryOptions } from "../eventPlugin-CUNjYYRY.mjs";
|
|
4
4
|
import { RedisEventTransportOptions, RedisLike } from "./transports/redis.mjs";
|
package/dist/events/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as MemoryEventTransport, i as withRetry, o as createChildEvent, r as createDeadLetterPublisher, s as createEvent, t as eventPlugin } from "../eventPlugin
|
|
1
|
+
import { a as MemoryEventTransport, i as withRetry, o as createChildEvent, r as createDeadLetterPublisher, s as createEvent, t as eventPlugin } from "../eventPlugin-KrFIQ097.mjs";
|
|
2
2
|
import { n as createSafeGetOne, t as createIsDuplicateKeyError } from "../store-helpers-BhrzxvyQ.mjs";
|
|
3
3
|
import { and, anyOf, eq, lte, ne, or } from "@classytic/repo-core/filter";
|
|
4
4
|
import { update } from "@classytic/repo-core/update";
|
|
@@ -217,12 +217,16 @@ function crudEventType(resource, suffix) {
|
|
|
217
217
|
}
|
|
218
218
|
/** Arc framework lifecycle events — emitted automatically by the framework */
|
|
219
219
|
const ARC_LIFECYCLE_EVENTS = Object.freeze({
|
|
220
|
+
/** Emitted when a resource plugin is registered */
|
|
220
221
|
RESOURCE_REGISTERED: "arc.resource.registered",
|
|
222
|
+
/** Emitted when Arc is fully ready (all resources registered, onReady fired) */
|
|
221
223
|
READY: "arc.ready"
|
|
222
224
|
});
|
|
223
225
|
/** Cache-specific event types for observability and external triggers */
|
|
224
226
|
const CACHE_EVENTS = Object.freeze({
|
|
227
|
+
/** Emitted when a resource's cache version is bumped */
|
|
225
228
|
VERSION_BUMPED: "arc.cache.version.bumped",
|
|
229
|
+
/** Emitted when a tag version is bumped */
|
|
226
230
|
TAG_VERSION_BUMPED: "arc.cache.tag.bumped"
|
|
227
231
|
});
|
|
228
232
|
//#endregion
|
|
@@ -489,7 +493,7 @@ function repositoryAsOutboxStore(repository) {
|
|
|
489
493
|
code: error.code
|
|
490
494
|
} : { message: error.message };
|
|
491
495
|
const firstFailedAt = current.firstFailedAt ?? now;
|
|
492
|
-
await r.findOneAndUpdate(filter, update({ set: {
|
|
496
|
+
if (await r.findOneAndUpdate(filter, update({ set: {
|
|
493
497
|
status: targetStatus,
|
|
494
498
|
visibleAt,
|
|
495
499
|
leaseOwner: null,
|
|
@@ -497,7 +501,11 @@ function repositoryAsOutboxStore(repository) {
|
|
|
497
501
|
lastFailedAt: now,
|
|
498
502
|
lastError: errorInfo,
|
|
499
503
|
firstFailedAt
|
|
500
|
-
} }), { returnDocument: "after" });
|
|
504
|
+
} }), { returnDocument: "after" })) return;
|
|
505
|
+
if (options?.consumerId) {
|
|
506
|
+
const after = await safeGetOne(baseFilter);
|
|
507
|
+
if (after && after.leaseOwner !== options.consumerId) throw new OutboxOwnershipError(eventId, options.consumerId, after.leaseOwner);
|
|
508
|
+
}
|
|
501
509
|
},
|
|
502
510
|
async getDeadLettered(limit) {
|
|
503
511
|
return unwrapDocs(await r.getAll({
|
package/dist/factory/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as CustomPluginAuthOption, c as RawBodyOptions, d as ResourceLike, f as ResourceModule, i as CustomAuthenticatorOption, l as UnderPressureOptions, n as BetterAuthOption, o as JwtAuthOption, p as loadResources, r as CreateAppOptions, s as MultipartOptions, t as AuthOption, u as LoadResourcesOptions } from "../types-
|
|
1
|
+
import { a as CustomPluginAuthOption, c as RawBodyOptions, d as ResourceLike, f as ResourceModule, i as CustomAuthenticatorOption, l as UnderPressureOptions, n as BetterAuthOption, o as JwtAuthOption, p as loadResources, r as CreateAppOptions, s as MultipartOptions, t as AuthOption, u as LoadResourcesOptions } from "../types-BH7dEGvU.mjs";
|
|
2
2
|
import { FastifyInstance } from "fastify";
|
|
3
3
|
|
|
4
4
|
//#region src/factory/createApp.d.ts
|
package/dist/factory/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as edgePreset, c as testingPreset, i as developmentPreset, n as createApp, o as getPreset, s as productionPreset, t as ArcFactory } from "../createApp-
|
|
1
|
+
import { a as edgePreset, c as testingPreset, i as developmentPreset, n as createApp, o as getPreset, s as productionPreset, t as ArcFactory } from "../createApp-BFxtdKy6.mjs";
|
|
2
2
|
import { t as loadResources } from "../loadResources-CPpkyKfM.mjs";
|
|
3
3
|
//#region src/factory/edge.ts
|
|
4
4
|
/**
|
package/dist/hooks/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { Cn as beforeUpdate, Sn as beforeDelete, Tn as defineHook, _n as HookSystemOptions, bn as afterUpdate, dn as HookContext, fn as HookHandler, gn as HookSystem, hn as HookRegistration, mn as HookPhase, pn as HookOperation, un as DefineHookOptions, vn as afterCreate, wn as createHookSystem, xn as beforeCreate, yn as afterDelete } from "../index-
|
|
1
|
+
import { Cn as beforeUpdate, Sn as beforeDelete, Tn as defineHook, _n as HookSystemOptions, bn as afterUpdate, dn as HookContext, fn as HookHandler, gn as HookSystem, hn as HookRegistration, mn as HookPhase, pn as HookOperation, un as DefineHookOptions, vn as afterCreate, wn as createHookSystem, xn as beforeCreate, yn as afterDelete } from "../index-6u4_Gg6G.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,4 +1,4 @@
|
|
|
1
|
-
import { jn as RepositoryLike } from "../index-
|
|
1
|
+
import { jn as RepositoryLike } from "../index-6u4_Gg6G.mjs";
|
|
2
2
|
import { i as createIdempotencyResult, n as IdempotencyResult, r as IdempotencyStore, t as IdempotencyLock } from "../interface-CkkWm5uR.mjs";
|
|
3
3
|
import { i as RedisIdempotencyStoreOptions, n as RedisClient } from "../redis-Cm1gnRDf.mjs";
|
|
4
4
|
import { FastifyPluginAsync } from "fastify";
|