@classytic/arc 2.8.0 → 2.8.1
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 +10 -1
- package/dist/{BaseController-CpMfCXdn.mjs → BaseController-DAGGc5Xn.mjs} +76 -25
- package/dist/{EventTransport-n1KBxC_N.d.mts → EventTransport-CLXJUzyT.d.mts} +37 -1
- package/dist/{ResourceRegistry-BOtJuRCs.mjs → ResourceRegistry-Dtcojmu8.mjs} +14 -2
- package/dist/adapters/index.d.mts +2 -2
- package/dist/adapters/index.mjs +1 -1
- package/dist/{adapters-BxGgSHjj.mjs → adapters-BBqAVvPK.mjs} +11 -0
- package/dist/auth/index.d.mts +1 -1
- package/dist/auth/index.mjs +3 -3
- package/dist/{betterAuthOpenApi-CHCIuA-p.mjs → betterAuthOpenApi-C5lDyRH2.mjs} +1 -1
- package/dist/cli/commands/docs.mjs +2 -2
- package/dist/cli/commands/introspect.mjs +1 -1
- package/dist/core/index.d.mts +2 -2
- package/dist/core/index.mjs +4 -4
- package/dist/{core-BfrfxNqO.mjs → core-CrLDuqoT.mjs} +1 -1
- package/dist/{createActionRouter-CbkIAaGh.mjs → createActionRouter-Df1BuawX.mjs} +87 -21
- package/dist/{createApp-Cy8eUNKQ.mjs → createApp-p2OThysU.mjs} +2 -2
- package/dist/{defineResource-CovBXvTB.mjs → defineResource-CqeUltrW.mjs} +19 -7
- package/dist/docs/index.d.mts +1 -1
- package/dist/docs/index.mjs +1 -1
- package/dist/dynamic/index.d.mts +1 -1
- package/dist/dynamic/index.mjs +1 -1
- package/dist/{errorHandler-BW08lEiy.mjs → errorHandler-Cw34h_om.mjs} +1 -1
- package/dist/{errorHandler-BeN-ERN7.d.mts → errorHandler-DJ7OAB2V.d.mts} +1 -1
- package/dist/{eventPlugin-CAOWMQS8.d.mts → eventPlugin-Cdjwo0Gv.d.mts} +1 -1
- package/dist/{eventPlugin-x4jo3sG0.mjs → eventPlugin-XijlQmlL.mjs} +19 -1
- package/dist/events/index.d.mts +399 -28
- package/dist/events/index.mjs +345 -29
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis.d.mts +1 -1
- 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/{index-BpMhrFgn.d.mts → index-0zj73o2U.d.mts} +1 -1
- package/dist/{index-qct60lnl.d.mts → index-DadoLP51.d.mts} +35 -3
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +7 -7
- package/dist/integrations/event-gateway.d.mts +1 -1
- 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/{interface-IJqN3pXK.d.mts → interface-CS6d7HiB.d.mts} +549 -107
- package/dist/{openapi-AYLVjqVe.mjs → openapi-q6rNKfZy.mjs} +49 -2
- package/dist/org/index.d.mts +1 -1
- package/dist/plugins/index.d.mts +2 -2
- package/dist/plugins/index.mjs +3 -3
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/presets/index.d.mts +3 -3
- package/dist/presets/multiTenant.d.mts +1 -1
- package/dist/{redis-stream-CF1lrKVk.d.mts → redis-stream-BgrYzpeq.d.mts} +1 -1
- package/dist/registry/index.d.mts +1 -1
- package/dist/registry/index.mjs +1 -1
- package/dist/{resourceToTools-C_1SMiCz.mjs → resourceToTools-DNNWnZtx.mjs} +193 -63
- package/dist/rpc/index.mjs +1 -1
- package/dist/testing/index.d.mts +2 -2
- package/dist/testing/index.mjs +1 -1
- package/dist/types/index.d.mts +2 -2
- package/dist/{types-gUxAIZHp.d.mts → types-BlOuKTPw.d.mts} +4 -4
- package/dist/{types-Ct0PUUSp.d.mts → types-D3b7hA00.d.mts} +1 -1
- package/dist/utils/index.d.mts +2 -14
- package/dist/utils/index.mjs +5 -5
- package/dist/{utils-B-l6410F.mjs → utils-7sJ8X83I.mjs} +1 -13
- package/package.json +4 -3
- /package/dist/{circuitBreaker-l18oRgL5.mjs → circuitBreaker-cmi5XDv5.mjs} +0 -0
- /package/dist/{errors-Cg58SLNi.mjs → errors-BF2bIOIS.mjs} +0 -0
- /package/dist/{requestContext-xHIKedG6.mjs → requestContext-DYvHl113.mjs} +0 -0
- /package/dist/{schemaConverter-Y5EejTnJ.mjs → schemaConverter-OxfCshus.mjs} +0 -0
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Database-agnostic resource framework for Fastify. Define resources, get CRUD routes, permissions, presets, caching, events, OpenAPI, and MCP tools — without boilerplate.
|
|
4
4
|
|
|
5
|
-
**v2.8.
|
|
5
|
+
**v2.8.1** | Fastify 5+ | Node.js 22+ | ESM only | 260+ test files, 3600+ tests
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -694,6 +694,15 @@ npx @classytic/arc doctor # Health check
|
|
|
694
694
|
| `@classytic/arc/docs` | OpenAPI generation |
|
|
695
695
|
| `@classytic/arc/cli` | CLI commands (programmatic) |
|
|
696
696
|
|
|
697
|
+
## v2.8.1 Highlights
|
|
698
|
+
|
|
699
|
+
- **Per-action discriminated validation** — `actions` schemas now enforce required fields via a `oneOf` body schema; missing inputs are rejected at the HTTP layer by AJV (no more silent bypass)
|
|
700
|
+
- **Actions in OpenAPI** — `POST /:id/action` endpoint auto-generated from `ResourceDefinition.actions`, with per-action descriptions and the same discriminated body schema as the runtime router
|
|
701
|
+
- **Route/action metadata preserved** — `mcp: false`, `description`, `annotations` no longer dropped during `routes → additionalRoutes` normalization
|
|
702
|
+
- **Canonical source retained** — `ResourceDefinition.routes` and `ResourceDefinition.actions` now kept as declared, so OpenAPI/MCP/registry can read the original shape
|
|
703
|
+
- **Outbox hardening** — expanded `OutboxStore` contract (`claimPending`, `fail`, write options, dedupe, visibleAt), ownership-mismatch throws, onError reporting, safe multi-worker relay
|
|
704
|
+
- **`slugLookup` fallback** — works with MongoKit's default Repository (no custom `getBySlug` needed)
|
|
705
|
+
|
|
697
706
|
## v2.8.0 Highlights
|
|
698
707
|
|
|
699
708
|
- **MCP Integration** — expose resources as AI agent tools (stateless by default, service scope, multi-tenancy)
|
|
@@ -843,9 +843,11 @@ var BaseController = class {
|
|
|
843
843
|
status: 400
|
|
844
844
|
};
|
|
845
845
|
}
|
|
846
|
+
const deleteMode = req.query?.hard === "true" || req.query?.hard === true || req.body?.mode === "hard" ? "hard" : void 0;
|
|
846
847
|
const repoDelete = async () => this.repository.delete(repoId, {
|
|
847
848
|
user,
|
|
848
|
-
context: arcContext
|
|
849
|
+
context: arcContext,
|
|
850
|
+
...deleteMode ? { mode: deleteMode } : {}
|
|
849
851
|
});
|
|
850
852
|
let result;
|
|
851
853
|
if (hooks && this.resourceName) result = await hooks.executeAround(this.resourceName, "delete", existing, repoDelete, {
|
|
@@ -854,7 +856,13 @@ var BaseController = class {
|
|
|
854
856
|
meta: { id }
|
|
855
857
|
});
|
|
856
858
|
else result = await repoDelete();
|
|
857
|
-
if (!(
|
|
859
|
+
if (!(() => {
|
|
860
|
+
if (typeof result !== "object" || result === null) return !!result;
|
|
861
|
+
const r = result;
|
|
862
|
+
if (typeof r.success === "boolean") return r.success;
|
|
863
|
+
if (typeof r.deletedCount === "number") return r.deletedCount > 0;
|
|
864
|
+
return true;
|
|
865
|
+
})()) return {
|
|
858
866
|
success: false,
|
|
859
867
|
error: "Resource not found",
|
|
860
868
|
status: 404
|
|
@@ -876,16 +884,23 @@ var BaseController = class {
|
|
|
876
884
|
};
|
|
877
885
|
}
|
|
878
886
|
async getBySlug(req) {
|
|
887
|
+
const slugField = this._presetFields.slugField ?? "slug";
|
|
888
|
+
const slug = req.params[slugField] ?? req.params.slug;
|
|
889
|
+
const options = this.queryResolver.resolve(req, this.meta(req));
|
|
879
890
|
const repo = this.repository;
|
|
880
|
-
|
|
891
|
+
let item = null;
|
|
892
|
+
if (repo.getBySlug) item = await repo.getBySlug(slug, options);
|
|
893
|
+
else if (repo.getOne) {
|
|
894
|
+
const filter = {
|
|
895
|
+
[slugField]: slug,
|
|
896
|
+
...options?.filter ?? {}
|
|
897
|
+
};
|
|
898
|
+
item = await repo.getOne(filter, options);
|
|
899
|
+
} else return {
|
|
881
900
|
success: false,
|
|
882
|
-
error: "Slug lookup not implemented",
|
|
901
|
+
error: "Slug lookup not implemented — repository needs getBySlug() or getOne()",
|
|
883
902
|
status: 501
|
|
884
903
|
};
|
|
885
|
-
const slugField = this._presetFields.slugField ?? "slug";
|
|
886
|
-
const slug = req.params[slugField] ?? req.params.slug;
|
|
887
|
-
const options = this.queryResolver.resolve(req, this.meta(req));
|
|
888
|
-
const item = await repo.getBySlug(slug, options);
|
|
889
904
|
if (!this.accessControl.validateItemAccess(item, req)) return {
|
|
890
905
|
success: false,
|
|
891
906
|
error: "Resource not found",
|
|
@@ -904,21 +919,25 @@ var BaseController = class {
|
|
|
904
919
|
error: "Soft delete not implemented",
|
|
905
920
|
status: 501
|
|
906
921
|
};
|
|
907
|
-
const
|
|
908
|
-
const result = await repo.getDeleted(
|
|
909
|
-
if (Array.isArray(result))
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
+
const parsed = this.queryResolver.resolve(req, this.meta(req));
|
|
923
|
+
const result = await repo.getDeleted(parsed, parsed);
|
|
924
|
+
if (Array.isArray(result)) {
|
|
925
|
+
const docs = result;
|
|
926
|
+
return {
|
|
927
|
+
success: true,
|
|
928
|
+
data: {
|
|
929
|
+
method: "offset",
|
|
930
|
+
docs,
|
|
931
|
+
page: 1,
|
|
932
|
+
limit: docs.length,
|
|
933
|
+
total: docs.length,
|
|
934
|
+
pages: 1,
|
|
935
|
+
hasNext: false,
|
|
936
|
+
hasPrev: false
|
|
937
|
+
},
|
|
938
|
+
status: 200
|
|
939
|
+
};
|
|
940
|
+
}
|
|
922
941
|
return {
|
|
923
942
|
success: true,
|
|
924
943
|
data: result,
|
|
@@ -950,13 +969,45 @@ var BaseController = class {
|
|
|
950
969
|
details: { code: "OWNERSHIP_DENIED" },
|
|
951
970
|
status: 403
|
|
952
971
|
};
|
|
972
|
+
const arcContext = this.meta(req);
|
|
973
|
+
const user = req.user;
|
|
953
974
|
const repoId = this.resolveRepoId(id, existing);
|
|
954
|
-
const
|
|
975
|
+
const hooks = this.getHooks(req);
|
|
976
|
+
if (hooks && this.resourceName) try {
|
|
977
|
+
await hooks.executeBefore(this.resourceName, "restore", existing, {
|
|
978
|
+
user,
|
|
979
|
+
context: arcContext,
|
|
980
|
+
meta: { id }
|
|
981
|
+
});
|
|
982
|
+
} catch (err) {
|
|
983
|
+
return {
|
|
984
|
+
success: false,
|
|
985
|
+
error: "Hook execution failed",
|
|
986
|
+
details: {
|
|
987
|
+
code: "BEFORE_RESTORE_HOOK_ERROR",
|
|
988
|
+
message: err.message
|
|
989
|
+
},
|
|
990
|
+
status: 400
|
|
991
|
+
};
|
|
992
|
+
}
|
|
993
|
+
const repoRestore = () => repo.restore(repoId);
|
|
994
|
+
let item;
|
|
995
|
+
if (hooks && this.resourceName) item = await hooks.executeAround(this.resourceName, "restore", existing, repoRestore, {
|
|
996
|
+
user,
|
|
997
|
+
context: arcContext,
|
|
998
|
+
meta: { id }
|
|
999
|
+
});
|
|
1000
|
+
else item = await repoRestore();
|
|
955
1001
|
if (!item) return {
|
|
956
1002
|
success: false,
|
|
957
1003
|
error: "Resource not found",
|
|
958
1004
|
status: 404
|
|
959
1005
|
};
|
|
1006
|
+
if (hooks && this.resourceName) await hooks.executeAfter(this.resourceName, "restore", item, {
|
|
1007
|
+
user,
|
|
1008
|
+
context: arcContext,
|
|
1009
|
+
meta: { id }
|
|
1010
|
+
});
|
|
960
1011
|
return {
|
|
961
1012
|
success: true,
|
|
962
1013
|
data: item,
|
|
@@ -1223,7 +1274,7 @@ var BaseController = class {
|
|
|
1223
1274
|
};
|
|
1224
1275
|
return {
|
|
1225
1276
|
success: true,
|
|
1226
|
-
data: await repo.deleteMany(scopedFilter),
|
|
1277
|
+
data: req.query?.hard === "true" || req.query?.hard === true || body.mode === "hard" ? await repo.deleteMany(scopedFilter, { mode: "hard" }) : await repo.deleteMany(scopedFilter),
|
|
1227
1278
|
status: 200
|
|
1228
1279
|
};
|
|
1229
1280
|
}
|
|
@@ -61,6 +61,25 @@ interface EventTransport {
|
|
|
61
61
|
* Publish an event to the transport
|
|
62
62
|
*/
|
|
63
63
|
publish(event: DomainEvent): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Publish a batch of events to the transport (optional, v2.8.1+).
|
|
66
|
+
*
|
|
67
|
+
* Transports that can efficiently batch (Kafka producer, Redis pipeline,
|
|
68
|
+
* RabbitMQ publisher confirms, SQS send-message-batch) should implement
|
|
69
|
+
* this. {@link import('./outbox.js').EventOutbox.relay} auto-detects and
|
|
70
|
+
* uses it for much higher throughput than per-event publishing.
|
|
71
|
+
*
|
|
72
|
+
* **Contract**: the returned `PublishManyResult` must describe the
|
|
73
|
+
* per-event outcome so the caller can acknowledge successes and fail the
|
|
74
|
+
* rest. Partial success is allowed — the transport reports it per event.
|
|
75
|
+
*
|
|
76
|
+
* If not implemented, `EventOutbox.relay` falls back to calling
|
|
77
|
+
* {@link publish} once per event.
|
|
78
|
+
*
|
|
79
|
+
* @param events - Events to publish (in order)
|
|
80
|
+
* @returns Per-event outcome map keyed by `event.meta.id`
|
|
81
|
+
*/
|
|
82
|
+
publishMany?(events: readonly DomainEvent[]): Promise<PublishManyResult>;
|
|
64
83
|
/**
|
|
65
84
|
* Subscribe to events matching a pattern
|
|
66
85
|
* @param pattern - Event type pattern (e.g., 'product.*', '*')
|
|
@@ -73,6 +92,14 @@ interface EventTransport {
|
|
|
73
92
|
*/
|
|
74
93
|
close?(): Promise<void>;
|
|
75
94
|
}
|
|
95
|
+
/**
|
|
96
|
+
* Per-event outcome returned by {@link EventTransport.publishMany}.
|
|
97
|
+
*
|
|
98
|
+
* The key is `event.meta.id`; the value is `null` for success or an `Error`
|
|
99
|
+
* for per-event failure. Transports MUST include an entry for every event
|
|
100
|
+
* in the input batch.
|
|
101
|
+
*/
|
|
102
|
+
type PublishManyResult = ReadonlyMap<string, Error | null>;
|
|
76
103
|
interface MemoryEventTransportOptions {
|
|
77
104
|
/** Logger for error/warning messages (default: console) */
|
|
78
105
|
logger?: EventLogger;
|
|
@@ -88,6 +115,15 @@ declare class MemoryEventTransport implements EventTransport {
|
|
|
88
115
|
private logger;
|
|
89
116
|
constructor(options?: MemoryEventTransportOptions);
|
|
90
117
|
publish(event: DomainEvent): Promise<void>;
|
|
118
|
+
/**
|
|
119
|
+
* Reference `publishMany` implementation — delegates to `publish()` in order.
|
|
120
|
+
*
|
|
121
|
+
* Production transports (Kafka, Redis pipeline, SQS batch) should override
|
|
122
|
+
* this with a single batched network call. Memory transport has nothing to
|
|
123
|
+
* batch, so we just loop — the loop still returns a proper result map so
|
|
124
|
+
* `EventOutbox.relay` can exercise the batched code path in tests.
|
|
125
|
+
*/
|
|
126
|
+
publishMany(events: readonly DomainEvent[]): Promise<PublishManyResult>;
|
|
91
127
|
subscribe(pattern: string, handler: EventHandler): Promise<() => void>;
|
|
92
128
|
close(): Promise<void>;
|
|
93
129
|
}
|
|
@@ -96,4 +132,4 @@ declare class MemoryEventTransport implements EventTransport {
|
|
|
96
132
|
*/
|
|
97
133
|
declare function createEvent<T>(type: string, payload: T, meta?: Partial<DomainEvent["meta"]>): DomainEvent<T>;
|
|
98
134
|
//#endregion
|
|
99
|
-
export { MemoryEventTransport as a, EventTransport as i, EventHandler as n, MemoryEventTransportOptions as o, EventLogger as r,
|
|
135
|
+
export { MemoryEventTransport as a, createEvent as c, EventTransport as i, EventHandler as n, MemoryEventTransportOptions as o, EventLogger as r, PublishManyResult as s, DomainEvent as t };
|
|
@@ -52,6 +52,17 @@ var ResourceRegistry = class {
|
|
|
52
52
|
pipelineSteps: extractPipelineSteps(resource.pipe),
|
|
53
53
|
rateLimit: resource.rateLimit,
|
|
54
54
|
audit: resource.audit,
|
|
55
|
+
actionPermissions: resource.actionPermissions,
|
|
56
|
+
actions: resource.actions ? Object.entries(resource.actions).map(([name, entry]) => {
|
|
57
|
+
if (typeof entry === "function") return { name };
|
|
58
|
+
return {
|
|
59
|
+
name,
|
|
60
|
+
description: entry.description,
|
|
61
|
+
schema: entry.schema,
|
|
62
|
+
permissions: entry.permissions,
|
|
63
|
+
mcp: entry.mcp
|
|
64
|
+
};
|
|
65
|
+
}) : void 0,
|
|
55
66
|
plugin: resource.toPlugin()
|
|
56
67
|
};
|
|
57
68
|
this._resources.set(resource.name, entry);
|
|
@@ -99,11 +110,12 @@ var ResourceRegistry = class {
|
|
|
99
110
|
byModule: this._groupBy(resources, "module"),
|
|
100
111
|
presetUsage: presetCounts,
|
|
101
112
|
totalRoutes: resources.reduce((sum, r) => {
|
|
102
|
-
|
|
113
|
+
const actionsCount = (r.actions?.length ?? 0) > 0 ? 1 : 0;
|
|
114
|
+
if (r.disableDefaultRoutes) return sum + (r.additionalRoutes?.length ?? 0) + actionsCount;
|
|
103
115
|
const disabledSet = new Set(r.disabledRoutes ?? []);
|
|
104
116
|
let defaultCount = CRUD_OPERATIONS.filter((route) => !disabledSet.has(route)).length;
|
|
105
117
|
if (!disabledSet.has("update") && r.updateMethod === "both") defaultCount += 1;
|
|
106
|
-
return sum + defaultCount + (r.additionalRoutes?.length ?? 0);
|
|
118
|
+
return sum + defaultCount + (r.additionalRoutes?.length ?? 0) + actionsCount;
|
|
107
119
|
}, 0),
|
|
108
120
|
totalEvents: resources.reduce((sum, r) => sum + (r.events?.length ?? 0), 0)
|
|
109
121
|
};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { a as RelationMetadata, c as ValidationResult, i as FieldMetadata, o as RepositoryLike, r as DataAdapter, s as SchemaMetadata, t as AdapterFactory } from "../interface-
|
|
2
|
-
import { a as PrismaQueryParserOptions, c as MongooseAdapterOptions, i as PrismaQueryParser, l as createMongooseAdapter, n as PrismaAdapterOptions, o as createPrismaAdapter, r as PrismaQueryOptions, s as MongooseAdapter, t as PrismaAdapter } from "../index-
|
|
1
|
+
import { a as RelationMetadata, c as ValidationResult, i as FieldMetadata, o as RepositoryLike, r as DataAdapter, s as SchemaMetadata, t as AdapterFactory } from "../interface-CS6d7HiB.mjs";
|
|
2
|
+
import { a as PrismaQueryParserOptions, c as MongooseAdapterOptions, i as PrismaQueryParser, l as createMongooseAdapter, n as PrismaAdapterOptions, o as createPrismaAdapter, r as PrismaQueryOptions, s as MongooseAdapter, t as PrismaAdapter } from "../index-0zj73o2U.mjs";
|
|
3
3
|
export { AdapterFactory, DataAdapter, FieldMetadata, MongooseAdapter, MongooseAdapterOptions, PrismaAdapter, PrismaAdapterOptions, PrismaQueryOptions, PrismaQueryParser, PrismaQueryParserOptions, RelationMetadata, RepositoryLike, SchemaMetadata, ValidationResult, createMongooseAdapter, createPrismaAdapter };
|
package/dist/adapters/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as createMongooseAdapter, i as MongooseAdapter, n as PrismaQueryParser, r as createPrismaAdapter, t as PrismaAdapter } from "../adapters-
|
|
1
|
+
import { a as createMongooseAdapter, i as MongooseAdapter, n as PrismaQueryParser, r as createPrismaAdapter, t as PrismaAdapter } from "../adapters-BBqAVvPK.mjs";
|
|
2
2
|
export { MongooseAdapter, PrismaAdapter, PrismaQueryParser, createMongooseAdapter, createPrismaAdapter };
|
|
@@ -90,6 +90,17 @@ var MongooseAdapter = class {
|
|
|
90
90
|
if (blockedFields.has(fieldName)) continue;
|
|
91
91
|
const typeInfo = schemaType;
|
|
92
92
|
properties[fieldName] = this.mongooseTypeToOpenApi(typeInfo);
|
|
93
|
+
const rule = fieldRules[fieldName];
|
|
94
|
+
if (rule) {
|
|
95
|
+
const prop = properties[fieldName];
|
|
96
|
+
if (rule.minLength != null && prop.minLength == null) prop.minLength = rule.minLength;
|
|
97
|
+
if (rule.maxLength != null && prop.maxLength == null) prop.maxLength = rule.maxLength;
|
|
98
|
+
if (rule.min != null && prop.minimum == null) prop.minimum = rule.min;
|
|
99
|
+
if (rule.max != null && prop.maximum == null) prop.maximum = rule.max;
|
|
100
|
+
if (rule.pattern != null && prop.pattern == null) prop.pattern = rule.pattern;
|
|
101
|
+
if (rule.enum != null && prop.enum == null) prop.enum = rule.enum;
|
|
102
|
+
if (rule.description != null && prop.description == null) prop.description = rule.description;
|
|
103
|
+
}
|
|
93
104
|
if (typeInfo.isRequired && !optionalSet.has(fieldName) && !fieldRules[fieldName]?.optional) required.push(fieldName);
|
|
94
105
|
}
|
|
95
106
|
const readonlyForInput = new Set([...readonlySet]);
|
package/dist/auth/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { b as AuthPluginOptions, y as AuthHelpers } from "../interface-
|
|
1
|
+
import { b as AuthPluginOptions, y as AuthHelpers } from "../interface-CS6d7HiB.mjs";
|
|
2
2
|
import { t as PermissionCheck } from "../types-BoaZHr-2.mjs";
|
|
3
3
|
import { t as ExternalOpenApiPaths } from "../externalPaths-BQ8QijNH.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-BkzVU8h2.mjs";
|
package/dist/auth/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { n as normalizeRoles, t as getUserRoles } from "../types-ZUu_h0jp.mjs";
|
|
2
|
-
import { t as ArcError } from "../errors-
|
|
2
|
+
import { t as ArcError } from "../errors-BF2bIOIS.mjs";
|
|
3
3
|
import { h as requireTeamMembership, l as requireOrgMembership, u as requireOrgRole } from "../permissions-CH4cNwJi.mjs";
|
|
4
|
-
import { n as extractBetterAuthOpenApi } from "../betterAuthOpenApi-
|
|
4
|
+
import { n as extractBetterAuthOpenApi } from "../betterAuthOpenApi-C5lDyRH2.mjs";
|
|
5
5
|
import { createHmac, randomUUID, timingSafeEqual } from "node:crypto";
|
|
6
6
|
import fp from "fastify-plugin";
|
|
7
7
|
//#region src/auth/authPlugin.ts
|
|
@@ -677,7 +677,7 @@ function createBetterAuthAdapter(options) {
|
|
|
677
677
|
if (!fastify.hasDecorator("authenticate")) fastify.decorate("authenticate", authenticate);
|
|
678
678
|
if (!fastify.hasDecorator("optionalAuthenticate")) fastify.decorate("optionalAuthenticate", optionalAuthenticate);
|
|
679
679
|
if (!extractedOpenApi && openapiOpt !== false && auth.api && typeof auth.api === "object") {
|
|
680
|
-
const { extractBetterAuthOpenApi } = await import("../betterAuthOpenApi-
|
|
680
|
+
const { extractBetterAuthOpenApi } = await import("../betterAuthOpenApi-C5lDyRH2.mjs").then((n) => n.t);
|
|
681
681
|
extractedOpenApi = extractBetterAuthOpenApi(auth.api, {
|
|
682
682
|
basePath,
|
|
683
683
|
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-OxfCshus.mjs";
|
|
3
3
|
//#region src/auth/betterAuthOpenApi.ts
|
|
4
4
|
var betterAuthOpenApi_exports = /* @__PURE__ */ __exportAll({ extractBetterAuthOpenApi: () => extractBetterAuthOpenApi });
|
|
5
5
|
/**
|
|
@@ -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-Dtcojmu8.mjs";
|
|
2
|
+
import { t as buildOpenApiSpec } from "../../openapi-q6rNKfZy.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 ResourceRegistry } from "../../ResourceRegistry-
|
|
1
|
+
import { t as ResourceRegistry } from "../../ResourceRegistry-Dtcojmu8.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/core/index.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { At as BaseController, Ft as BodySanitizerConfig, It as AccessControl, Jt as defineResource, Lt as AccessControlConfig, Mt as QueryResolver, Nt as QueryResolverConfig, Pt as BodySanitizer, jt as BaseControllerOptions, qt as ResourceDefinition } from "../interface-
|
|
2
|
-
import { A as MutationOperation, C as HOOK_PHASES, D as MAX_REGEX_LENGTH, E as MAX_FILTER_DEPTH, M as SYSTEM_FIELDS, O as MAX_SEARCH_LENGTH, S as HOOK_OPERATIONS, T as HookPhase, _ as DEFAULT_LIMIT, a as getControllerScope, b as DEFAULT_TENANT_FIELD, c as createCrudRouter, d as ActionRouterConfig, f as IdempotencyService, g as DEFAULT_ID_FIELD, h as CrudOperation, i as getControllerContext, j as RESERVED_QUERY_PARAMS, k as MUTATION_OPERATIONS, l as createPermissionMiddleware, m as CRUD_OPERATIONS, n as createFastifyHandler, o as sendControllerResponse, p as createActionRouter, r as createRequestContext, s as defineResourceVariants, t as createCrudHandlers, u as ActionHandler, v as DEFAULT_MAX_LIMIT, w as HookOperation, x as DEFAULT_UPDATE_METHOD, y as DEFAULT_SORT } from "../index-
|
|
1
|
+
import { At as BaseController, Ft as BodySanitizerConfig, It as AccessControl, Jt as defineResource, Lt as AccessControlConfig, Mt as QueryResolver, Nt as QueryResolverConfig, Pt as BodySanitizer, jt as BaseControllerOptions, qt as ResourceDefinition } from "../interface-CS6d7HiB.mjs";
|
|
2
|
+
import { A as MutationOperation, C as HOOK_PHASES, D as MAX_REGEX_LENGTH, E as MAX_FILTER_DEPTH, M as SYSTEM_FIELDS, O as MAX_SEARCH_LENGTH, S as HOOK_OPERATIONS, T as HookPhase, _ as DEFAULT_LIMIT, a as getControllerScope, b as DEFAULT_TENANT_FIELD, c as createCrudRouter, d as ActionRouterConfig, f as IdempotencyService, g as DEFAULT_ID_FIELD, h as CrudOperation, i as getControllerContext, j as RESERVED_QUERY_PARAMS, k as MUTATION_OPERATIONS, l as createPermissionMiddleware, m as CRUD_OPERATIONS, n as createFastifyHandler, o as sendControllerResponse, p as createActionRouter, r as createRequestContext, s as defineResourceVariants, t as createCrudHandlers, u as ActionHandler, v as DEFAULT_MAX_LIMIT, w as HookOperation, x as DEFAULT_UPDATE_METHOD, y as DEFAULT_SORT } from "../index-DadoLP51.mjs";
|
|
3
3
|
export { AccessControl, AccessControlConfig, ActionHandler, ActionRouterConfig, 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, IdempotencyService, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, MutationOperation, QueryResolver, QueryResolverConfig, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, createActionRouter, createCrudHandlers, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineResource, defineResourceVariants, getControllerContext, getControllerScope, sendControllerResponse };
|
package/dist/core/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
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-Cxde4rpC.mjs";
|
|
2
|
-
import { i as AccessControl, n as QueryResolver, r as BodySanitizer, t as BaseController } from "../BaseController-
|
|
3
|
-
import {
|
|
4
|
-
import { c as createCrudHandlers, d as getControllerContext, f as getControllerScope, l as createFastifyHandler, n as defineResource, o as createCrudRouter, p as sendControllerResponse, s as createPermissionMiddleware, t as ResourceDefinition, u as createRequestContext } from "../defineResource-
|
|
5
|
-
import { t as defineResourceVariants } from "../core-
|
|
2
|
+
import { i as AccessControl, n as QueryResolver, r as BodySanitizer, t as BaseController } from "../BaseController-DAGGc5Xn.mjs";
|
|
3
|
+
import { n as createActionRouter } from "../createActionRouter-Df1BuawX.mjs";
|
|
4
|
+
import { c as createCrudHandlers, d as getControllerContext, f as getControllerScope, l as createFastifyHandler, n as defineResource, o as createCrudRouter, p as sendControllerResponse, s as createPermissionMiddleware, t as ResourceDefinition, u as createRequestContext } from "../defineResource-CqeUltrW.mjs";
|
|
5
|
+
import { t as defineResourceVariants } from "../core-CrLDuqoT.mjs";
|
|
6
6
|
export { AccessControl, BaseController, BodySanitizer, 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, createActionRouter, createCrudHandlers, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineResource, defineResourceVariants, getControllerContext, getControllerScope, sendControllerResponse };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as defineResource } from "./defineResource-
|
|
1
|
+
import { n as defineResource } from "./defineResource-CqeUltrW.mjs";
|
|
2
2
|
//#region src/core/defineResourceVariants.ts
|
|
3
3
|
/**
|
|
4
4
|
* Define multiple resources from a shared base config and per-variant overrides.
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { t as __exportAll } from "./chunk-BpYLSNr0.mjs";
|
|
2
2
|
import { n as normalizePermissionResult, t as applyPermissionResult } from "./applyPermissionResult-D6GPMsvh.mjs";
|
|
3
|
+
import { a as toJsonSchema } from "./schemaConverter-OxfCshus.mjs";
|
|
3
4
|
//#region src/core/createActionRouter.ts
|
|
4
|
-
var createActionRouter_exports = /* @__PURE__ */ __exportAll({
|
|
5
|
+
var createActionRouter_exports = /* @__PURE__ */ __exportAll({
|
|
6
|
+
buildActionBodySchema: () => buildActionBodySchema,
|
|
7
|
+
createActionRouter: () => createActionRouter
|
|
8
|
+
});
|
|
5
9
|
/**
|
|
6
10
|
* Create action-based state transition endpoint
|
|
7
11
|
*
|
|
@@ -18,20 +22,7 @@ function createActionRouter(fastify, config) {
|
|
|
18
22
|
fastify.log.warn("[createActionRouter] No actions defined, skipping route creation");
|
|
19
23
|
return;
|
|
20
24
|
}
|
|
21
|
-
const
|
|
22
|
-
type: "string",
|
|
23
|
-
enum: actionEnum,
|
|
24
|
-
description: `Action to perform: ${actionEnum.join(" | ")}`
|
|
25
|
-
} };
|
|
26
|
-
Object.entries(actionSchemas).forEach(([actionName, schema]) => {
|
|
27
|
-
if (schema && typeof schema === "object") Object.entries(schema).forEach(([propName, propSchema]) => {
|
|
28
|
-
const schemaObj = propSchema;
|
|
29
|
-
bodyProperties[propName] = {
|
|
30
|
-
...schemaObj,
|
|
31
|
-
description: `${schemaObj.description || ""} (for ${actionName} action)`.trim()
|
|
32
|
-
};
|
|
33
|
-
});
|
|
34
|
-
});
|
|
25
|
+
const bodySchema = buildActionBodySchema(actionEnum, actionSchemas);
|
|
35
26
|
const routeSchema = {
|
|
36
27
|
tags: tag ? [tag] : void 0,
|
|
37
28
|
summary: `Perform action (${actionEnum.join("/")})`,
|
|
@@ -44,11 +35,7 @@ function createActionRouter(fastify, config) {
|
|
|
44
35
|
} },
|
|
45
36
|
required: ["id"]
|
|
46
37
|
},
|
|
47
|
-
body:
|
|
48
|
-
type: "object",
|
|
49
|
-
properties: bodyProperties,
|
|
50
|
-
required: ["action"]
|
|
51
|
-
}
|
|
38
|
+
body: bodySchema
|
|
52
39
|
};
|
|
53
40
|
const preHandler = [];
|
|
54
41
|
const hasPublicActions = Object.entries(actionPermissions).some(([, p]) => p?._isPublic) || globalAuth && globalAuth?._isPublic;
|
|
@@ -167,6 +154,85 @@ function createActionRouter(fastify, config) {
|
|
|
167
154
|
}, "[createActionRouter] Registered action endpoint: POST /:id/action");
|
|
168
155
|
}
|
|
169
156
|
/**
|
|
157
|
+
* Build a discriminated body schema for the unified action endpoint.
|
|
158
|
+
*
|
|
159
|
+
* Produces a schema of the form:
|
|
160
|
+
* ```json
|
|
161
|
+
* {
|
|
162
|
+
* "type": "object",
|
|
163
|
+
* "required": ["action"],
|
|
164
|
+
* "oneOf": [
|
|
165
|
+
* { "properties": { "action": { "const": "dispatch" }, "carrier": {...} }, "required": ["action", "carrier"] },
|
|
166
|
+
* { "properties": { "action": { "const": "approve" } }, "required": ["action"] }
|
|
167
|
+
* ]
|
|
168
|
+
* }
|
|
169
|
+
* ```
|
|
170
|
+
*
|
|
171
|
+
* AJV validates this natively, so an action call missing required fields is
|
|
172
|
+
* rejected with HTTP 400 before the handler ever runs.
|
|
173
|
+
*
|
|
174
|
+
* Exported so OpenAPI generation and MCP tool generation can reuse the same
|
|
175
|
+
* schema shape (single source of truth).
|
|
176
|
+
*/
|
|
177
|
+
function buildActionBodySchema(actionEnum, actionSchemas = {}) {
|
|
178
|
+
const branches = [];
|
|
179
|
+
for (const actionName of actionEnum) {
|
|
180
|
+
const raw = actionSchemas[actionName];
|
|
181
|
+
const { properties, required } = normalizeActionSchema(raw);
|
|
182
|
+
const branchProperties = {
|
|
183
|
+
action: {
|
|
184
|
+
type: "string",
|
|
185
|
+
const: actionName
|
|
186
|
+
},
|
|
187
|
+
...properties
|
|
188
|
+
};
|
|
189
|
+
const branchRequired = ["action", ...required.filter((r) => r !== "action")];
|
|
190
|
+
branches.push({
|
|
191
|
+
type: "object",
|
|
192
|
+
properties: branchProperties,
|
|
193
|
+
required: branchRequired
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
type: "object",
|
|
198
|
+
required: ["action"],
|
|
199
|
+
oneOf: branches
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Normalize the accepted schema shapes into `{ properties, required }`.
|
|
204
|
+
*
|
|
205
|
+
* Handles:
|
|
206
|
+
* 1. Full JSON Schema object (has `type: 'object'` + `properties`)
|
|
207
|
+
* 2. Zod v4 schema (has `_zod` marker) — converted via `toJsonSchema`
|
|
208
|
+
* 3. Legacy field map (`{ fieldName: { type: 'string' } }`) — every field required
|
|
209
|
+
* unless its schema has `nullable: true` or sentinel `required: false`
|
|
210
|
+
*/
|
|
211
|
+
function normalizeActionSchema(raw) {
|
|
212
|
+
if (!raw || typeof raw !== "object") return {
|
|
213
|
+
properties: {},
|
|
214
|
+
required: []
|
|
215
|
+
};
|
|
216
|
+
const converted = toJsonSchema(raw);
|
|
217
|
+
if (converted && typeof converted === "object" && (converted.type === "object" || "properties" in converted)) return {
|
|
218
|
+
properties: converted.properties ?? {},
|
|
219
|
+
required: Array.isArray(converted.required) ? converted.required : []
|
|
220
|
+
};
|
|
221
|
+
const properties = {};
|
|
222
|
+
const required = [];
|
|
223
|
+
for (const [fieldName, fieldSchema] of Object.entries(raw)) {
|
|
224
|
+
if (fieldName === "type" || fieldName === "properties" || fieldName === "required") continue;
|
|
225
|
+
if (!fieldSchema || typeof fieldSchema !== "object") continue;
|
|
226
|
+
const fs = fieldSchema;
|
|
227
|
+
properties[fieldName] = fs;
|
|
228
|
+
if (fs.required !== false) required.push(fieldName);
|
|
229
|
+
}
|
|
230
|
+
return {
|
|
231
|
+
properties,
|
|
232
|
+
required
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
170
236
|
* Build description with action details
|
|
171
237
|
* Uses _roles metadata from PermissionCheck functions for OpenAPI docs
|
|
172
238
|
*/
|
|
@@ -180,4 +246,4 @@ function buildActionDescription(actions, actionPermissions) {
|
|
|
180
246
|
return lines.join("\n");
|
|
181
247
|
}
|
|
182
248
|
//#endregion
|
|
183
|
-
export {
|
|
249
|
+
export { createActionRouter as n, createActionRouter_exports as r, buildActionBodySchema as t };
|
|
@@ -207,7 +207,7 @@ async function registerArcCore(fastify, config, trackPlugin) {
|
|
|
207
207
|
await fastify.register(arcCorePlugin, { emitEvents: config.arcPlugins?.emitEvents !== false });
|
|
208
208
|
trackPlugin("arc-core");
|
|
209
209
|
if (config.arcPlugins?.events !== false) {
|
|
210
|
-
const { default: eventPlugin } = await import("./eventPlugin-
|
|
210
|
+
const { default: eventPlugin } = await import("./eventPlugin-XijlQmlL.mjs").then((n) => n.n);
|
|
211
211
|
const eventOpts = typeof config.arcPlugins?.events === "object" ? config.arcPlugins.events : {};
|
|
212
212
|
await fastify.register(eventPlugin, {
|
|
213
213
|
...eventOpts,
|
|
@@ -350,7 +350,7 @@ async function registerElevation(fastify, config, trackPlugin) {
|
|
|
350
350
|
*/
|
|
351
351
|
async function registerErrorHandler(fastify, config, trackPlugin) {
|
|
352
352
|
if (config.errorHandler === false) return;
|
|
353
|
-
const { errorHandlerPlugin } = await import("./errorHandler-
|
|
353
|
+
const { errorHandlerPlugin } = await import("./errorHandler-Cw34h_om.mjs").then((n) => n.n);
|
|
354
354
|
const errorOpts = typeof config.errorHandler === "object" ? config.errorHandler : { includeStack: config.preset !== "production" };
|
|
355
355
|
await fastify.register(errorHandlerPlugin, errorOpts);
|
|
356
356
|
trackPlugin("arc-error-handler", errorOpts);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS } from "./constants-Cxde4rpC.mjs";
|
|
2
2
|
import { _ as isElevated, n as PUBLIC_SCOPE, v as isMember } from "./types-AOD8fxIw.mjs";
|
|
3
|
-
import { t as BaseController } from "./BaseController-
|
|
3
|
+
import { t as BaseController } from "./BaseController-DAGGc5Xn.mjs";
|
|
4
4
|
import { i as resolveEffectiveRoles, t as applyFieldReadPermissions } from "./fields-ipsbIRPK.mjs";
|
|
5
5
|
import { t as getUserRoles } from "./types-ZUu_h0jp.mjs";
|
|
6
6
|
import { n as normalizePermissionResult, t as applyPermissionResult } from "./applyPermissionResult-D6GPMsvh.mjs";
|
|
7
|
-
import { t as
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
7
|
+
import { n as convertRouteSchema, t as convertOpenApiSchemas } from "./schemaConverter-OxfCshus.mjs";
|
|
8
|
+
import { t as requestContext } from "./requestContext-DYvHl113.mjs";
|
|
9
|
+
import { i as getDefaultCrudSchemas } from "./utils-7sJ8X83I.mjs";
|
|
10
|
+
import { r as ForbiddenError } from "./errors-BF2bIOIS.mjs";
|
|
11
11
|
import { t as hasEvents } from "./typeGuards-CcFZXgU7.mjs";
|
|
12
12
|
import { r as getAvailablePresets, t as applyPresets } from "./presets-BFrGvvjL.mjs";
|
|
13
13
|
//#region src/pipeline/pipe.ts
|
|
@@ -1087,6 +1087,16 @@ var ResourceDefinition = class {
|
|
|
1087
1087
|
customSchemas;
|
|
1088
1088
|
permissions;
|
|
1089
1089
|
additionalRoutes;
|
|
1090
|
+
/**
|
|
1091
|
+
* Original v2.8 `routes` declaration — retained for downstream consumers
|
|
1092
|
+
* (OpenAPI, MCP, registry, CLI introspect). Preserves fields dropped during
|
|
1093
|
+
* normalization to `additionalRoutes` (notably `mcp`, `description`,
|
|
1094
|
+
* `annotations`). Undefined when the resource was defined with the legacy
|
|
1095
|
+
* `additionalRoutes` shape.
|
|
1096
|
+
*
|
|
1097
|
+
* Added in 2.8.1 — the source-of-truth fix for "canonical resource manifest".
|
|
1098
|
+
*/
|
|
1099
|
+
routes;
|
|
1090
1100
|
middlewares;
|
|
1091
1101
|
disableDefaultRoutes;
|
|
1092
1102
|
disabledRoutes;
|
|
@@ -1117,6 +1127,7 @@ var ResourceDefinition = class {
|
|
|
1117
1127
|
this.schemaOptions = config.schemaOptions ?? {};
|
|
1118
1128
|
this.customSchemas = config.customSchemas ?? {};
|
|
1119
1129
|
this.permissions = config.permissions ?? {};
|
|
1130
|
+
this.routes = config.routes;
|
|
1120
1131
|
this.additionalRoutes = config.routes ? convertRoutesToAdditionalRoutes(config.routes) : config.additionalRoutes ?? [];
|
|
1121
1132
|
this.middlewares = config.middlewares ?? {};
|
|
1122
1133
|
this.disableDefaultRoutes = config.disableDefaultRoutes ?? false;
|
|
@@ -1283,7 +1294,7 @@ var ResourceDefinition = class {
|
|
|
1283
1294
|
fields: self.fields
|
|
1284
1295
|
});
|
|
1285
1296
|
if (self.actions && Object.keys(self.actions).length > 0) {
|
|
1286
|
-
const { createActionRouter } = await import("./createActionRouter-
|
|
1297
|
+
const { createActionRouter } = await import("./createActionRouter-Df1BuawX.mjs").then((n) => n.r);
|
|
1287
1298
|
createActionRouter(instance, normalizeActionsToRouterConfig(self.actions, self.actionPermissions, self.tag));
|
|
1288
1299
|
}
|
|
1289
1300
|
if (self.events && Object.keys(self.events).length > 0) typedInstance.log?.debug?.(`Resource '${self.name}' defined ${Object.keys(self.events).length} events`);
|
|
@@ -1358,7 +1369,8 @@ function convertRoutesToAdditionalRoutes(routes) {
|
|
|
1358
1369
|
preAuth: route.preAuth,
|
|
1359
1370
|
streamResponse: route.streamResponse,
|
|
1360
1371
|
schema: route.schema,
|
|
1361
|
-
mcpHandler: route.mcpHandler
|
|
1372
|
+
mcpHandler: route.mcpHandler,
|
|
1373
|
+
mcp: route.mcp
|
|
1362
1374
|
}));
|
|
1363
1375
|
}
|
|
1364
1376
|
/**
|
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-ZUu_h0jp.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-q6rNKfZy.mjs";
|
|
3
3
|
import fp from "fastify-plugin";
|
|
4
4
|
//#region src/docs/scalar.ts
|
|
5
5
|
const scalarPlugin = async (fastify, opts = {}) => {
|
package/dist/dynamic/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { qt as ResourceDefinition, r as DataAdapter } from "../interface-
|
|
1
|
+
import { qt as ResourceDefinition, r as DataAdapter } from "../interface-CS6d7HiB.mjs";
|
|
2
2
|
import { t as PermissionCheck } from "../types-BoaZHr-2.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/dynamic/ArcDynamicLoader.d.ts
|
package/dist/dynamic/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { t as ArcQueryParser } from "../queryParser-CgCtsjti.mjs";
|
|
2
|
-
import { n as defineResource } from "../defineResource-
|
|
2
|
+
import { n as defineResource } from "../defineResource-CqeUltrW.mjs";
|
|
3
3
|
import { C as publicRead, T as readOnly, b as fullPublic, v as adminOnly, w as publicReadAdminWrite, x as ownerWithAdminBypass, y as authenticated } from "../permissions-CH4cNwJi.mjs";
|
|
4
4
|
//#region src/dynamic/ArcDynamicLoader.ts
|
|
5
5
|
const VALID_FIELD_TYPES = new Set([
|