@classytic/arc 2.8.1 → 2.8.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/README.md +1 -1
- package/dist/{ResourceRegistry-Dtcojmu8.mjs → ResourceRegistry-Dq3_zBQP.mjs} +5 -5
- package/dist/adapters/index.d.mts +2 -2
- package/dist/audit/index.d.mts +1 -1
- package/dist/audit/index.mjs +1 -1
- package/dist/audit/mongodb.d.mts +1 -1
- package/dist/audit/mongodb.mjs +1 -1
- package/dist/auth/index.d.mts +4 -4
- package/dist/auth/redis-session.d.mts +1 -1
- package/dist/cache/index.d.mts +2 -2
- package/dist/cli/commands/describe.mjs +1 -1
- package/dist/cli/commands/docs.mjs +2 -2
- package/dist/cli/commands/generate.mjs +1 -1
- package/dist/cli/commands/init.mjs +10 -10
- package/dist/cli/commands/introspect.mjs +3 -3
- package/dist/core/index.d.mts +3 -3
- package/dist/core/index.mjs +4 -4
- package/dist/{core-CrLDuqoT.mjs → core-DKSwNSXf.mjs} +1 -1
- package/dist/{createApp-p2OThysU.mjs → createApp-BOYjBgdI.mjs} +16 -7
- package/dist/{defineResource-CqeUltrW.mjs → defineResource-Bb_Bdhtw.mjs} +42 -27
- package/dist/docs/index.d.mts +2 -2
- package/dist/docs/index.mjs +1 -1
- package/dist/dynamic/index.d.mts +2 -2
- package/dist/dynamic/index.mjs +1 -1
- package/dist/{errorHandler-DJ7OAB2V.d.mts → errorHandler-CdZDavNH.d.mts} +2 -2
- package/dist/{eventPlugin-Cdjwo0Gv.d.mts → eventPlugin-CVxlE6De.d.mts} +1 -1
- package/dist/events/index.d.mts +3 -3
- package/dist/events/index.mjs +1 -1
- package/dist/events/transports/redis-stream-entry.d.mts +1 -1
- package/dist/events/transports/redis-stream-entry.mjs +3 -1
- package/dist/events/transports/redis.d.mts +1 -1
- package/dist/factory/index.d.mts +1 -1
- package/dist/factory/index.mjs +2 -152
- package/dist/hooks/index.d.mts +1 -1
- package/dist/idempotency/index.d.mts +3 -3
- package/dist/idempotency/mongodb.d.mts +1 -1
- package/dist/idempotency/mongodb.mjs +18 -6
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/idempotency/redis.mjs +10 -1
- package/dist/{index-0zj73o2U.d.mts → index-BgmMdpm8.d.mts} +1 -1
- package/dist/{index-CBru2y5Y.d.mts → index-CSkeivBx.d.mts} +3 -3
- package/dist/{index-DadoLP51.d.mts → index-CpTSDqmD.d.mts} +26 -4
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +3 -3
- package/dist/integrations/event-gateway.d.mts +1 -1
- package/dist/integrations/event-gateway.mjs +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-CS6d7HiB.d.mts → interface-BVuMfeVv.d.mts} +47 -18
- package/dist/loadResources-Bksk8ydA.mjs +154 -0
- package/dist/{mongodb-B1eVtFhw.d.mts → mongodb-B8U2xaLj.d.mts} +1 -1
- package/dist/{mongodb-NShVZDMr.d.mts → mongodb-X7LbEjTN.d.mts} +10 -1
- package/dist/{openapi-q6rNKfZy.mjs → openapi-CYCuekCn.mjs} +2 -2
- package/dist/org/index.d.mts +2 -2
- package/dist/permissions/index.d.mts +3 -3
- package/dist/plugins/index.d.mts +5 -5
- package/dist/plugins/index.mjs +7 -7
- package/dist/plugins/tracing-entry.d.mts +1 -1
- package/dist/plugins/tracing-entry.mjs +1 -1
- package/dist/policies/index.d.mts +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-BFrGvvjL.mjs → presets-C2xgzW6x.mjs} +10 -18
- package/dist/{queryCachePlugin-BCFVXnxK.d.mts → queryCachePlugin-CnTZZTC5.d.mts} +1 -1
- package/dist/{redis-stream-BgrYzpeq.d.mts → redis-stream-D54N5oXs.d.mts} +1 -1
- package/dist/{redis-Bunu3qWg.d.mts → redis-z3sFr1UP.d.mts} +1 -1
- package/dist/registry/index.d.mts +1 -1
- package/dist/registry/index.mjs +1 -1
- package/dist/{resourceToTools-DNNWnZtx.mjs → resourceToTools-O_HwWXFa.mjs} +1 -1
- package/dist/rpc/index.d.mts +1 -1
- package/dist/scope/index.d.mts +2 -2
- package/dist/testing/index.d.mts +2 -2
- package/dist/testing/index.mjs +1 -1
- package/dist/types/index.d.mts +4 -4
- package/dist/{types-BlOuKTPw.d.mts → types-Bg2X42_m.d.mts} +30 -9
- package/dist/{types-BoaZHr-2.d.mts → types-CVC4HOKi.d.mts} +1 -1
- package/dist/{types-D3b7hA00.d.mts → types-CcG4avic.d.mts} +1 -1
- package/dist/utils/index.d.mts +43 -5
- package/dist/utils/index.mjs +3 -3
- package/dist/{utils-7sJ8X83I.mjs → utils-yYT3HDXt.mjs} +65 -1
- package/package.json +8 -8
- package/skills/arc/SKILL.md +79 -6
- /package/dist/{EventTransport-CLXJUzyT.d.mts → EventTransport-CinyO7zQ.d.mts} +0 -0
- /package/dist/{caching-CHH-iHs3.mjs → caching-CjybdRwx.mjs} +0 -0
- /package/dist/{circuitBreaker-BGVoB1hD.d.mts → circuitBreaker-CvXkjfrW.d.mts} +0 -0
- /package/dist/{elevation-UJO3-NvX.d.mts → elevation-s5ykdNHr.d.mts} +0 -0
- /package/dist/{errorHandler-Cw34h_om.mjs → errorHandler-mzqk4cGl.mjs} +0 -0
- /package/dist/{errors-BI8kEKsO.d.mts → errors-Bmn3eZT6.d.mts} +0 -0
- /package/dist/{eventPlugin-XijlQmlL.mjs → eventPlugin-D91S2YF4.mjs} +0 -0
- /package/dist/{externalPaths-BQ8QijNH.d.mts → externalPaths-Bapitwvd.d.mts} +0 -0
- /package/dist/{fields-DoeDgh2b.d.mts → fields-DC4So2M2.d.mts} +0 -0
- /package/dist/{interface-CkkWm5uR.d.mts → interface-B-pe8fhj.d.mts} +0 -0
- /package/dist/{interface-bpoLKKqx.d.mts → interface-DplgQO2e.d.mts} +0 -0
- /package/dist/{metrics-DuhiSEZI.mjs → metrics-TuOmguhi.mjs} +0 -0
- /package/dist/{mongodb-5Ff3w8jy.mjs → mongodb-B5O6xaW1.mjs} +0 -0
- /package/dist/{pluralize-BneOJkpi.mjs → pluralize-A0tWEl1K.mjs} +0 -0
- /package/dist/{replyHelpers-CXtJDAZ0.mjs → replyHelpers-BLojtuvR.mjs} +0 -0
- /package/dist/{sessionManager-BkzVU8h2.d.mts → sessionManager-D-oNWHz3.d.mts} +0 -0
- /package/dist/{sse-CD5Hghpu.mjs → sse-CJpt7LGI.mjs} +0 -0
- /package/dist/{tracing-xqXzWeaf.d.mts → tracing-DxjKk7eW.d.mts} +0 -0
- /package/dist/{types-CN6JvmYz.d.mts → types-C72d3NDn.d.mts} +0 -0
- /package/dist/{versioning-CPU_5Xfs.mjs → versioning-Cm8qoFDg.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.3** | Fastify 5+ | Node.js 22+ | ESM only | 278+ test files, 3844+ tests
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -31,7 +31,7 @@ var ResourceRegistry = class {
|
|
|
31
31
|
permissions: resource.permissions,
|
|
32
32
|
presets: resource._appliedPresets ?? [],
|
|
33
33
|
routes: [],
|
|
34
|
-
|
|
34
|
+
customRoutes: (resource.routes ?? []).map((r) => ({
|
|
35
35
|
method: r.method,
|
|
36
36
|
path: r.path,
|
|
37
37
|
handler: typeof r.handler === "string" ? r.handler : r.handler.name || "anonymous",
|
|
@@ -39,7 +39,7 @@ var ResourceRegistry = class {
|
|
|
39
39
|
summary: r.summary,
|
|
40
40
|
description: r.description,
|
|
41
41
|
permissions: r.permissions,
|
|
42
|
-
|
|
42
|
+
raw: r.raw,
|
|
43
43
|
schema: r.schema
|
|
44
44
|
})),
|
|
45
45
|
events: Object.keys(resource.events ?? {}),
|
|
@@ -111,11 +111,11 @@ var ResourceRegistry = class {
|
|
|
111
111
|
presetUsage: presetCounts,
|
|
112
112
|
totalRoutes: resources.reduce((sum, r) => {
|
|
113
113
|
const actionsCount = (r.actions?.length ?? 0) > 0 ? 1 : 0;
|
|
114
|
-
if (r.disableDefaultRoutes) return sum + (r.
|
|
114
|
+
if (r.disableDefaultRoutes) return sum + (r.customRoutes?.length ?? 0) + actionsCount;
|
|
115
115
|
const disabledSet = new Set(r.disabledRoutes ?? []);
|
|
116
116
|
let defaultCount = CRUD_OPERATIONS.filter((route) => !disabledSet.has(route)).length;
|
|
117
117
|
if (!disabledSet.has("update") && r.updateMethod === "both") defaultCount += 1;
|
|
118
|
-
return sum + defaultCount + (r.
|
|
118
|
+
return sum + defaultCount + (r.customRoutes?.length ?? 0) + actionsCount;
|
|
119
119
|
}, 0),
|
|
120
120
|
totalEvents: resources.reduce((sum, r) => sum + (r.events?.length ?? 0), 0)
|
|
121
121
|
};
|
|
@@ -170,7 +170,7 @@ var ResourceRegistry = class {
|
|
|
170
170
|
module: r.module,
|
|
171
171
|
presets: r.presets,
|
|
172
172
|
permissions: r.permissions,
|
|
173
|
-
routes: [...defaultRoutes, ...r.
|
|
173
|
+
routes: [...defaultRoutes, ...r.customRoutes?.map((ar) => ({
|
|
174
174
|
method: ar.method,
|
|
175
175
|
path: `${r.prefix}${ar.path}`,
|
|
176
176
|
operation: ar.operation ?? (typeof ar.handler === "string" ? ar.handler : "custom"),
|
|
@@ -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-BVuMfeVv.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-BgmMdpm8.mjs";
|
|
3
3
|
export { AdapterFactory, DataAdapter, FieldMetadata, MongooseAdapter, MongooseAdapterOptions, PrismaAdapter, PrismaAdapterOptions, PrismaQueryOptions, PrismaQueryParser, PrismaQueryParserOptions, RelationMetadata, RepositoryLike, SchemaMetadata, ValidationResult, createMongooseAdapter, createPrismaAdapter };
|
package/dist/audit/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as AuditContext, c as AuditStore, i as AuditAction, l as AuditStoreOptions, n as MongoAuditStoreOptions, o as AuditEntry, r as MongoConnection, s as AuditQueryOptions, u as createAuditEntry } from "../mongodb-
|
|
1
|
+
import { a as AuditContext, c as AuditStore, i as AuditAction, l as AuditStoreOptions, n as MongoAuditStoreOptions, o as AuditEntry, r as MongoConnection, s as AuditQueryOptions, u as createAuditEntry } from "../mongodb-B8U2xaLj.mjs";
|
|
2
2
|
import { FastifyPluginAsync } from "fastify";
|
|
3
3
|
|
|
4
4
|
//#region src/audit/auditPlugin.d.ts
|
package/dist/audit/index.mjs
CHANGED
package/dist/audit/mongodb.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as MongoAuditStoreOptions, t as MongoAuditStore } from "../mongodb-
|
|
1
|
+
import { n as MongoAuditStoreOptions, t as MongoAuditStore } from "../mongodb-B8U2xaLj.mjs";
|
|
2
2
|
export { MongoAuditStore, type MongoAuditStoreOptions };
|
package/dist/audit/mongodb.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as MongoAuditStore } from "../mongodb-
|
|
1
|
+
import { t as MongoAuditStore } from "../mongodb-B5O6xaW1.mjs";
|
|
2
2
|
export { MongoAuditStore };
|
package/dist/auth/index.d.mts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { b as AuthPluginOptions, y as AuthHelpers } from "../interface-
|
|
2
|
-
import { t as PermissionCheck } from "../types-
|
|
3
|
-
import { t as ExternalOpenApiPaths } from "../externalPaths-
|
|
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-
|
|
1
|
+
import { b as AuthPluginOptions, y as AuthHelpers } from "../interface-BVuMfeVv.mjs";
|
|
2
|
+
import { t as PermissionCheck } from "../types-CVC4HOKi.mjs";
|
|
3
|
+
import { t as ExternalOpenApiPaths } from "../externalPaths-Bapitwvd.mjs";
|
|
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";
|
|
5
5
|
import { FastifyPluginAsync, FastifyReply as FastifyReply$1, FastifyRequest as FastifyRequest$1 } from "fastify";
|
|
6
6
|
|
|
7
7
|
//#region src/auth/authPlugin.d.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as SessionData, s as SessionStore } from "../sessionManager-
|
|
1
|
+
import { i as SessionData, s as SessionStore } from "../sessionManager-D-oNWHz3.mjs";
|
|
2
2
|
|
|
3
3
|
//#region src/auth/redis-session.d.ts
|
|
4
4
|
/** Minimal Redis client interface — compatible with ioredis */
|
package/dist/cache/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { i as CacheStore, n as CacheSetOptions, r as CacheStats, t as CacheLogger } from "../interface-
|
|
2
|
-
import { a as CacheEnvelope, c as QueryCache, i as queryCachePlugin, l as QueryCacheConfig, n as QueryCacheDefaults, o as CacheResult, r as QueryCachePluginOptions, s as CacheStatus, t as CrossResourceRule } from "../queryCachePlugin-
|
|
1
|
+
import { i as CacheStore, n as CacheSetOptions, r as CacheStats, t as CacheLogger } from "../interface-DplgQO2e.mjs";
|
|
2
|
+
import { a as CacheEnvelope, c as QueryCache, i as queryCachePlugin, l as QueryCacheConfig, n as QueryCacheDefaults, o as CacheResult, r as QueryCachePluginOptions, s as CacheStatus, t as CrossResourceRule } from "../queryCachePlugin-CnTZZTC5.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/cache/keys.d.ts
|
|
5
5
|
/**
|
|
@@ -128,7 +128,7 @@ function describeRoutes(resource) {
|
|
|
128
128
|
routes.push(route);
|
|
129
129
|
}
|
|
130
130
|
}
|
|
131
|
-
for (const ar of resource.
|
|
131
|
+
for (const ar of resource.routes ?? []) routes.push({
|
|
132
132
|
method: ar.method,
|
|
133
133
|
path: `${resource.prefix}${ar.path}`,
|
|
134
134
|
operation: typeof ar.handler === "string" ? ar.handler : "custom",
|
|
@@ -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-Dq3_zBQP.mjs";
|
|
2
|
+
import { t as buildOpenApiSpec } from "../../openapi-CYCuekCn.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-A0tWEl1K.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
|
|
@@ -1678,7 +1678,7 @@ const exampleResource = defineResource${ts ? "<ExampleDocument>" : ""}({
|
|
|
1678
1678
|
permissions: ${config.tenant === "multi" ? "orgStaffPermissions" : "publicReadPermissions"},
|
|
1679
1679
|
|
|
1680
1680
|
// Add custom routes here:
|
|
1681
|
-
//
|
|
1681
|
+
// routes: [
|
|
1682
1682
|
// {
|
|
1683
1683
|
// method: 'GET',
|
|
1684
1684
|
// path: '/custom',
|
|
@@ -2134,14 +2134,14 @@ export const authResource = defineResource({
|
|
|
2134
2134
|
adapter: createAdapter(User${ts ? " as any" : ""}, userRepository${ts ? " as any" : ""}),
|
|
2135
2135
|
disableDefaultRoutes: true,
|
|
2136
2136
|
|
|
2137
|
-
|
|
2137
|
+
routes: [
|
|
2138
2138
|
{
|
|
2139
2139
|
method: 'POST',
|
|
2140
2140
|
path: '/register',
|
|
2141
2141
|
summary: 'Register new user',
|
|
2142
2142
|
permissions: allowPublic(),
|
|
2143
2143
|
handler: handlers.register,
|
|
2144
|
-
|
|
2144
|
+
raw: true,
|
|
2145
2145
|
schema: { body: schemas.registerBody, response: { 201: schemas.successResponse } },
|
|
2146
2146
|
},
|
|
2147
2147
|
{
|
|
@@ -2150,7 +2150,7 @@ export const authResource = defineResource({
|
|
|
2150
2150
|
summary: 'User login',
|
|
2151
2151
|
permissions: allowPublic(),
|
|
2152
2152
|
handler: handlers.login,
|
|
2153
|
-
|
|
2153
|
+
raw: true,
|
|
2154
2154
|
schema: { body: schemas.loginBody, response: { 200: schemas.loginResponse } },
|
|
2155
2155
|
},
|
|
2156
2156
|
{
|
|
@@ -2159,7 +2159,7 @@ export const authResource = defineResource({
|
|
|
2159
2159
|
summary: 'Refresh access token',
|
|
2160
2160
|
permissions: allowPublic(),
|
|
2161
2161
|
handler: handlers.refreshToken,
|
|
2162
|
-
|
|
2162
|
+
raw: true,
|
|
2163
2163
|
schema: { body: schemas.refreshBody, response: { 200: schemas.tokenResponse } },
|
|
2164
2164
|
},
|
|
2165
2165
|
{
|
|
@@ -2168,7 +2168,7 @@ export const authResource = defineResource({
|
|
|
2168
2168
|
summary: 'Request password reset',
|
|
2169
2169
|
permissions: allowPublic(),
|
|
2170
2170
|
handler: handlers.forgotPassword,
|
|
2171
|
-
|
|
2171
|
+
raw: true,
|
|
2172
2172
|
schema: { body: schemas.forgotBody, response: { 200: schemas.successResponse } },
|
|
2173
2173
|
},
|
|
2174
2174
|
{
|
|
@@ -2177,7 +2177,7 @@ export const authResource = defineResource({
|
|
|
2177
2177
|
summary: 'Reset password with token',
|
|
2178
2178
|
permissions: allowPublic(),
|
|
2179
2179
|
handler: handlers.resetPassword,
|
|
2180
|
-
|
|
2180
|
+
raw: true,
|
|
2181
2181
|
schema: { body: schemas.resetBody, response: { 200: schemas.successResponse } },
|
|
2182
2182
|
},
|
|
2183
2183
|
],
|
|
@@ -2195,14 +2195,14 @@ export const userProfileResource = defineResource({
|
|
|
2195
2195
|
adapter: createAdapter(User${ts ? " as any" : ""}, userRepository${ts ? " as any" : ""}),
|
|
2196
2196
|
disableDefaultRoutes: true,
|
|
2197
2197
|
|
|
2198
|
-
|
|
2198
|
+
routes: [
|
|
2199
2199
|
{
|
|
2200
2200
|
method: 'GET',
|
|
2201
2201
|
path: '/me',
|
|
2202
2202
|
summary: 'Get current user profile',
|
|
2203
2203
|
permissions: requireAuth(),
|
|
2204
2204
|
handler: handlers.getUserProfile,
|
|
2205
|
-
|
|
2205
|
+
raw: true,
|
|
2206
2206
|
schema: { response: { 200: schemas.userProfileResponse } },
|
|
2207
2207
|
},
|
|
2208
2208
|
{
|
|
@@ -2211,7 +2211,7 @@ export const userProfileResource = defineResource({
|
|
|
2211
2211
|
summary: 'Update current user profile',
|
|
2212
2212
|
permissions: requireAuth(),
|
|
2213
2213
|
handler: handlers.updateUserProfile,
|
|
2214
|
-
|
|
2214
|
+
raw: true,
|
|
2215
2215
|
schema: { body: schemas.updateUserBody, response: { 200: schemas.userProfileResponse } },
|
|
2216
2216
|
},
|
|
2217
2217
|
],
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as ResourceRegistry } from "../../ResourceRegistry-
|
|
1
|
+
import { t as ResourceRegistry } from "../../ResourceRegistry-Dq3_zBQP.mjs";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
3
|
import { pathToFileURL } from "node:url";
|
|
4
4
|
//#region src/cli/commands/introspect.ts
|
|
@@ -56,14 +56,14 @@ async function introspect(args) {
|
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
if (resource.presets && resource.presets.length > 0) console.log(` Presets: ${resource.presets.join(", ")}`);
|
|
59
|
-
if (resource.
|
|
59
|
+
if (resource.customRoutes && resource.customRoutes.length > 0) console.log(` Additional Routes: ${resource.customRoutes.length}`);
|
|
60
60
|
console.log("");
|
|
61
61
|
});
|
|
62
62
|
const stats = registry.getStats();
|
|
63
63
|
console.log("Summary:");
|
|
64
64
|
console.log(` Total Resources: ${stats.totalResources}`);
|
|
65
65
|
console.log(` With Presets: ${resources.filter((r) => r.presets?.length > 0).length}`);
|
|
66
|
-
console.log(` With Custom Routes: ${resources.filter((r) => r.
|
|
66
|
+
console.log(` With Custom Routes: ${resources.filter((r) => r.customRoutes && r.customRoutes.length > 0).length}`);
|
|
67
67
|
} catch (error) {
|
|
68
68
|
if (error instanceof Error) throw error;
|
|
69
69
|
throw new Error(String(error));
|
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
|
|
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 };
|
|
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-BVuMfeVv.mjs";
|
|
2
|
+
import { A as MUTATION_OPERATIONS, C as HOOK_OPERATIONS, D as MAX_FILTER_DEPTH, E as HookPhase, M as RESERVED_QUERY_PARAMS, N as SYSTEM_FIELDS, O as MAX_REGEX_LENGTH, S as DEFAULT_UPDATE_METHOD, T as HookOperation, _ as DEFAULT_ID_FIELD, a as getControllerScope, b as DEFAULT_SORT, c as createCrudRouter, d as ActionRouterConfig, f as IdempotencyService, g as CrudOperation, h as CRUD_OPERATIONS, i as getControllerContext, j as MutationOperation, k as MAX_SEARCH_LENGTH, l as createPermissionMiddleware, m as createActionRouter, n as createFastifyHandler, o as sendControllerResponse, p as buildActionBodySchema, r as createRequestContext, s as defineResourceVariants, t as createCrudHandlers, u as ActionHandler, v as DEFAULT_LIMIT, w as HOOK_PHASES, x as DEFAULT_TENANT_FIELD, y as DEFAULT_MAX_LIMIT } from "../index-CpTSDqmD.mjs";
|
|
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, buildActionBodySchema, 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
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-
|
|
5
|
-
import { t as defineResourceVariants } from "../core-
|
|
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 };
|
|
3
|
+
import { n as createActionRouter, t as buildActionBodySchema } 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-Bb_Bdhtw.mjs";
|
|
5
|
+
import { t as defineResourceVariants } from "../core-DKSwNSXf.mjs";
|
|
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, buildActionBodySchema, 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-Bb_Bdhtw.mjs";
|
|
2
2
|
//#region src/core/defineResourceVariants.ts
|
|
3
3
|
/**
|
|
4
4
|
* Define multiple resources from a shared base config and per-variant overrides.
|
|
@@ -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-D91S2YF4.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,
|
|
@@ -243,7 +243,7 @@ async function registerArcPlugins(fastify, config, trackPlugin, modules) {
|
|
|
243
243
|
trackPlugin("arc-graceful-shutdown");
|
|
244
244
|
}
|
|
245
245
|
if (config.arcPlugins?.caching) {
|
|
246
|
-
const { default: cachingPlugin } = await import("./caching-
|
|
246
|
+
const { default: cachingPlugin } = await import("./caching-CjybdRwx.mjs").then((n) => n.r);
|
|
247
247
|
const opts = config.arcPlugins.caching === true ? {} : config.arcPlugins.caching;
|
|
248
248
|
await fastify.register(cachingPlugin, opts);
|
|
249
249
|
trackPlugin("arc-caching", opts);
|
|
@@ -260,19 +260,19 @@ async function registerArcPlugins(fastify, config, trackPlugin, modules) {
|
|
|
260
260
|
}
|
|
261
261
|
if (config.arcPlugins?.sse) if (config.arcPlugins?.events === false) fastify.log.warn("SSE plugin requires events plugin (arcPlugins.events). SSE disabled.");
|
|
262
262
|
else {
|
|
263
|
-
const { default: ssePlugin } = await import("./sse-
|
|
263
|
+
const { default: ssePlugin } = await import("./sse-CJpt7LGI.mjs").then((n) => n.r);
|
|
264
264
|
const opts = config.arcPlugins.sse === true ? {} : config.arcPlugins.sse;
|
|
265
265
|
await fastify.register(ssePlugin, opts);
|
|
266
266
|
trackPlugin("arc-sse", opts);
|
|
267
267
|
}
|
|
268
268
|
if (config.arcPlugins?.metrics) {
|
|
269
|
-
const { default: metricsPlugin } = await import("./metrics-
|
|
269
|
+
const { default: metricsPlugin } = await import("./metrics-TuOmguhi.mjs").then((n) => n.r);
|
|
270
270
|
const opts = config.arcPlugins.metrics === true ? {} : config.arcPlugins.metrics;
|
|
271
271
|
await fastify.register(metricsPlugin, opts);
|
|
272
272
|
trackPlugin("arc-metrics", opts);
|
|
273
273
|
}
|
|
274
274
|
if (config.arcPlugins?.versioning) {
|
|
275
|
-
const { default: versioningPlugin } = await import("./versioning-
|
|
275
|
+
const { default: versioningPlugin } = await import("./versioning-Cm8qoFDg.mjs").then((n) => n.r);
|
|
276
276
|
await fastify.register(versioningPlugin, config.arcPlugins.versioning);
|
|
277
277
|
trackPlugin("arc-versioning", config.arcPlugins.versioning);
|
|
278
278
|
}
|
|
@@ -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-mzqk4cGl.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);
|
|
@@ -416,6 +416,15 @@ async function registerResources(fastify, config) {
|
|
|
416
416
|
for (const init of config.bootstrap) await init(fastify);
|
|
417
417
|
fastify.log.debug(`${config.bootstrap.length} bootstrap function(s) executed`);
|
|
418
418
|
}
|
|
419
|
+
if (!config.resources?.length && config.resourceDir) {
|
|
420
|
+
const { loadResources } = await import("./loadResources-Bksk8ydA.mjs").then((n) => n.n);
|
|
421
|
+
const { resolve } = await import("node:path");
|
|
422
|
+
const dir = resolve(config.resourceDir);
|
|
423
|
+
config = {
|
|
424
|
+
...config,
|
|
425
|
+
resources: await loadResources(dir, { logger: fastify.log })
|
|
426
|
+
};
|
|
427
|
+
}
|
|
419
428
|
if (config.resources?.length) {
|
|
420
429
|
const seen = /* @__PURE__ */ new Set();
|
|
421
430
|
for (const resource of config.resources) if (resource.name) {
|
|
@@ -720,7 +729,7 @@ async function createApp(options) {
|
|
|
720
729
|
await registerErrorHandler(fastify, config, trackPlugin);
|
|
721
730
|
await registerResources(fastify, config);
|
|
722
731
|
if (config.replyHelpers) {
|
|
723
|
-
const { replyHelpersPlugin } = await import("./replyHelpers-
|
|
732
|
+
const { replyHelpersPlugin } = await import("./replyHelpers-BLojtuvR.mjs").then((n) => n.n);
|
|
724
733
|
await fastify.register(replyHelpersPlugin);
|
|
725
734
|
}
|
|
726
735
|
if (config.serializeBigInt) fastify.addHook("preSerialization", async (_request, _reply, payload) => {
|
|
@@ -6,10 +6,10 @@ import { t as getUserRoles } from "./types-ZUu_h0jp.mjs";
|
|
|
6
6
|
import { n as normalizePermissionResult, t as applyPermissionResult } from "./applyPermissionResult-D6GPMsvh.mjs";
|
|
7
7
|
import { n as convertRouteSchema, t as convertOpenApiSchemas } from "./schemaConverter-OxfCshus.mjs";
|
|
8
8
|
import { t as requestContext } from "./requestContext-DYvHl113.mjs";
|
|
9
|
-
import { i as getDefaultCrudSchemas } from "./utils-
|
|
9
|
+
import { i as getDefaultCrudSchemas } from "./utils-yYT3HDXt.mjs";
|
|
10
10
|
import { r as ForbiddenError } from "./errors-BF2bIOIS.mjs";
|
|
11
11
|
import { t as hasEvents } from "./typeGuards-CcFZXgU7.mjs";
|
|
12
|
-
import { r as getAvailablePresets, t as applyPresets } from "./presets-
|
|
12
|
+
import { r as getAvailablePresets, t as applyPresets } from "./presets-C2xgzW6x.mjs";
|
|
13
13
|
//#region src/pipeline/pipe.ts
|
|
14
14
|
/**
|
|
15
15
|
* Compose pipeline steps into an ordered array.
|
|
@@ -390,7 +390,7 @@ function buildPermissionMiddleware(permissionCheck, resourceName, action) {
|
|
|
390
390
|
* Create additional routes from preset/custom definitions
|
|
391
391
|
*/
|
|
392
392
|
function createAdditionalRoutes(fastify, routes, controller, options) {
|
|
393
|
-
const { tag, resourceName, arcDecorator, rateLimitConfig, cacheMw, idempotencyMw, pipeline } = options;
|
|
393
|
+
const { tag, resourceName, arcDecorator, rateLimitConfig, cacheMw, idempotencyMw, pipeline, routeGuards } = options;
|
|
394
394
|
for (const route of routes) {
|
|
395
395
|
const opName = route.operation ?? (typeof route.handler === "string" ? route.handler : `${route.method.toLowerCase()}${route.path.replace(/[/:]/g, "_")}`);
|
|
396
396
|
let handler;
|
|
@@ -431,6 +431,7 @@ function createAdditionalRoutes(fastify, routes, controller, options) {
|
|
|
431
431
|
authMw,
|
|
432
432
|
permissionMw,
|
|
433
433
|
pluginMw,
|
|
434
|
+
...routeGuards,
|
|
434
435
|
...customPreHandlers
|
|
435
436
|
].filter(Boolean);
|
|
436
437
|
const isStream = route.streamResponse === true;
|
|
@@ -479,7 +480,7 @@ function createPipelineHandler(controllerMethod, steps, operation, resourceName)
|
|
|
479
480
|
* @param options - Router configuration
|
|
480
481
|
*/
|
|
481
482
|
function createCrudRouter(fastify, controller, options = {}) {
|
|
482
|
-
const { tag = "Resource", schemas = {}, permissions = {}, middlewares = {}, additionalRoutes = [], disableDefaultRoutes = false, disabledRoutes = [], resourceName = "unknown", schemaOptions, rateLimit, pipe: pipeline, fields: fieldPermissions, updateMethod = DEFAULT_UPDATE_METHOD } = options;
|
|
483
|
+
const { tag = "Resource", schemas = {}, permissions = {}, middlewares = {}, routeGuards = [], additionalRoutes = [], disableDefaultRoutes = false, disabledRoutes = [], resourceName = "unknown", schemaOptions, rateLimit, pipe: pipeline, fields: fieldPermissions, updateMethod = DEFAULT_UPDATE_METHOD } = options;
|
|
483
484
|
const rateLimitConfig = buildRateLimitConfig(rateLimit);
|
|
484
485
|
const cacheMw = !(fastify.hasDecorator("queryCache") && controller && typeof controller._cacheConfig !== "undefined" && controller._cacheConfig !== void 0) && fastify.hasDecorator("responseCache") ? fastify.responseCache.middleware : null;
|
|
485
486
|
const idempotencyMw = fastify.hasDecorator("idempotency") ? fastify.idempotency.middleware : null;
|
|
@@ -542,6 +543,7 @@ function createCrudRouter(fastify, controller, options = {}) {
|
|
|
542
543
|
buildAuthMiddleware(fastify, permissions.list),
|
|
543
544
|
buildPermissionMiddleware(permissions.list, resourceName, "list"),
|
|
544
545
|
cacheMw,
|
|
546
|
+
...routeGuards,
|
|
545
547
|
...mw.list
|
|
546
548
|
].filter(Boolean);
|
|
547
549
|
fastify.route({
|
|
@@ -562,6 +564,7 @@ function createCrudRouter(fastify, controller, options = {}) {
|
|
|
562
564
|
buildAuthMiddleware(fastify, permissions.get),
|
|
563
565
|
buildPermissionMiddleware(permissions.get, resourceName, "get"),
|
|
564
566
|
cacheMw,
|
|
567
|
+
...routeGuards,
|
|
565
568
|
...mw.get
|
|
566
569
|
].filter(Boolean);
|
|
567
570
|
fastify.route({
|
|
@@ -583,6 +586,7 @@ function createCrudRouter(fastify, controller, options = {}) {
|
|
|
583
586
|
buildAuthMiddleware(fastify, permissions.create),
|
|
584
587
|
buildPermissionMiddleware(permissions.create, resourceName, "create"),
|
|
585
588
|
idempotencyMw,
|
|
589
|
+
...routeGuards,
|
|
586
590
|
...mw.create
|
|
587
591
|
].filter(Boolean);
|
|
588
592
|
fastify.route({
|
|
@@ -604,6 +608,7 @@ function createCrudRouter(fastify, controller, options = {}) {
|
|
|
604
608
|
buildAuthMiddleware(fastify, permissions.update),
|
|
605
609
|
buildPermissionMiddleware(permissions.update, resourceName, "update"),
|
|
606
610
|
idempotencyMw,
|
|
611
|
+
...routeGuards,
|
|
607
612
|
...mw.update
|
|
608
613
|
].filter(Boolean);
|
|
609
614
|
for (const method of updateMethods) fastify.route({
|
|
@@ -624,6 +629,7 @@ function createCrudRouter(fastify, controller, options = {}) {
|
|
|
624
629
|
arcDecorator,
|
|
625
630
|
buildAuthMiddleware(fastify, permissions.delete),
|
|
626
631
|
buildPermissionMiddleware(permissions.delete, resourceName, "delete"),
|
|
632
|
+
...routeGuards,
|
|
627
633
|
...mw.delete
|
|
628
634
|
].filter(Boolean);
|
|
629
635
|
fastify.route({
|
|
@@ -647,7 +653,8 @@ function createCrudRouter(fastify, controller, options = {}) {
|
|
|
647
653
|
rateLimitConfig,
|
|
648
654
|
cacheMw,
|
|
649
655
|
idempotencyMw,
|
|
650
|
-
pipeline
|
|
656
|
+
pipeline,
|
|
657
|
+
routeGuards
|
|
651
658
|
});
|
|
652
659
|
}
|
|
653
660
|
/**
|
|
@@ -701,10 +708,10 @@ function validateResourceConfig(config, options = {}) {
|
|
|
701
708
|
message: "Adapter must provide a repository",
|
|
702
709
|
suggestion: "Ensure your adapter returns a valid CrudRepository"
|
|
703
710
|
});
|
|
704
|
-
} else if (!config.adapter && !config.
|
|
711
|
+
} else if (!config.adapter && !config.routes?.length) warnings.push({
|
|
705
712
|
field: "config",
|
|
706
|
-
message: "Resource has no adapter and no
|
|
707
|
-
suggestion: "Provide either adapter for CRUD or
|
|
713
|
+
message: "Resource has no adapter and no routes",
|
|
714
|
+
suggestion: "Provide either adapter for CRUD or routes for custom logic"
|
|
708
715
|
});
|
|
709
716
|
if (config.controller && !options.skipControllerCheck && !config.disableDefaultRoutes) {
|
|
710
717
|
const ctrl = config.controller;
|
|
@@ -715,7 +722,7 @@ function validateResourceConfig(config, options = {}) {
|
|
|
715
722
|
suggestion: "Extend BaseController which implements IController interface"
|
|
716
723
|
});
|
|
717
724
|
}
|
|
718
|
-
if (config.controller && config.
|
|
725
|
+
if (config.controller && config.routes) validateRouteHandlers(config.controller, config.routes, errors);
|
|
719
726
|
if (config.permissions) validatePermissionKeys(config, options, errors, warnings);
|
|
720
727
|
if (config.presets && !options.allowUnknownPresets) validatePresets(config.presets, errors, warnings);
|
|
721
728
|
if (config.prefix) {
|
|
@@ -730,18 +737,18 @@ function validateResourceConfig(config, options = {}) {
|
|
|
730
737
|
suggestion: `Change to "${config.prefix.slice(0, -1)}"`
|
|
731
738
|
});
|
|
732
739
|
}
|
|
733
|
-
if (config.
|
|
740
|
+
if (config.routes) validateRoutes(config.routes, errors);
|
|
734
741
|
return {
|
|
735
742
|
valid: errors.length === 0,
|
|
736
743
|
errors,
|
|
737
744
|
warnings
|
|
738
745
|
};
|
|
739
746
|
}
|
|
740
|
-
function
|
|
747
|
+
function validateRouteHandlers(controller, routes, errors) {
|
|
741
748
|
const ctrl = controller;
|
|
742
749
|
for (const route of routes) if (typeof route.handler === "string") {
|
|
743
750
|
if (typeof ctrl[route.handler] !== "function") errors.push({
|
|
744
|
-
field: `
|
|
751
|
+
field: `routes[${route.method} ${route.path}]`,
|
|
745
752
|
message: `Handler "${route.handler}" not found on controller`,
|
|
746
753
|
suggestion: `Add method "${route.handler}" to controller or use a function handler`
|
|
747
754
|
});
|
|
@@ -749,7 +756,7 @@ function validateAdditionalRouteHandlers(controller, routes, errors) {
|
|
|
749
756
|
}
|
|
750
757
|
function validatePermissionKeys(config, options, _errors, warnings) {
|
|
751
758
|
const validKeys = new Set([...CRUD_OPERATIONS, ...options.additionalPermissionKeys ?? []]);
|
|
752
|
-
for (const route of config.
|
|
759
|
+
for (const route of config.routes ?? []) if (typeof route.handler === "string") validKeys.add(route.handler);
|
|
753
760
|
for (const preset of config.presets ?? []) {
|
|
754
761
|
const presetName = typeof preset === "string" ? preset : preset.name;
|
|
755
762
|
if (presetName === "softDelete") {
|
|
@@ -773,7 +780,7 @@ function validatePermissionKeys(config, options, _errors, warnings) {
|
|
|
773
780
|
function validatePresets(presets, errors, warnings) {
|
|
774
781
|
const availablePresets = getAvailablePresets();
|
|
775
782
|
for (const preset of presets) {
|
|
776
|
-
if (typeof preset === "object" && ("middlewares" in preset || "
|
|
783
|
+
if (typeof preset === "object" && ("middlewares" in preset || "routes" in preset)) continue;
|
|
777
784
|
const presetName = typeof preset === "string" ? preset : preset.name;
|
|
778
785
|
if (!availablePresets.includes(presetName)) errors.push({
|
|
779
786
|
field: "presets",
|
|
@@ -798,7 +805,7 @@ function validatePresetOptions(preset, warnings) {
|
|
|
798
805
|
suggestion: validOptions.length > 0 ? `Valid options: ${validOptions.join(", ")}` : `Preset "${preset.name}" has no configurable options`
|
|
799
806
|
});
|
|
800
807
|
}
|
|
801
|
-
function
|
|
808
|
+
function validateRoutes(routes, errors) {
|
|
802
809
|
const validMethods = [
|
|
803
810
|
"GET",
|
|
804
811
|
"POST",
|
|
@@ -811,26 +818,26 @@ function validateAdditionalRoutes(routes, errors) {
|
|
|
811
818
|
const seenRoutes = /* @__PURE__ */ new Set();
|
|
812
819
|
for (const [i, route] of routes.entries()) {
|
|
813
820
|
if (!validMethods.includes(route.method)) errors.push({
|
|
814
|
-
field: `
|
|
821
|
+
field: `routes[${i}].method`,
|
|
815
822
|
message: `Invalid HTTP method "${route.method}"`,
|
|
816
823
|
suggestion: `Valid methods: ${validMethods.join(", ")}`
|
|
817
824
|
});
|
|
818
825
|
if (!route.path) errors.push({
|
|
819
|
-
field: `
|
|
826
|
+
field: `routes[${i}].path`,
|
|
820
827
|
message: "Route path is required"
|
|
821
828
|
});
|
|
822
829
|
else if (!route.path.startsWith("/")) errors.push({
|
|
823
|
-
field: `
|
|
830
|
+
field: `routes[${i}].path`,
|
|
824
831
|
message: `Route path must start with "/" (got "${route.path}")`,
|
|
825
832
|
suggestion: `Change to "/${route.path}"`
|
|
826
833
|
});
|
|
827
834
|
if (!route.handler) errors.push({
|
|
828
|
-
field: `
|
|
835
|
+
field: `routes[${i}].handler`,
|
|
829
836
|
message: "Route handler is required"
|
|
830
837
|
});
|
|
831
838
|
const routeKey = `${route.method} ${route.path}`;
|
|
832
839
|
if (seenRoutes.has(routeKey)) errors.push({
|
|
833
|
-
field: `
|
|
840
|
+
field: `routes[${i}]`,
|
|
834
841
|
message: `Duplicate route "${routeKey}"`
|
|
835
842
|
});
|
|
836
843
|
seenRoutes.add(routeKey);
|
|
@@ -884,11 +891,6 @@ function defineResource(config) {
|
|
|
884
891
|
if (config.permissions) {
|
|
885
892
|
for (const [key, value] of Object.entries(config.permissions)) if (value !== void 0 && typeof value !== "function") throw new Error(`[Arc] Resource '${config.name}': permissions.${key} must be a PermissionCheck function.\nUse allowPublic(), requireAuth(), or requireRoles(['role']) from @classytic/arc/permissions.`);
|
|
886
893
|
}
|
|
887
|
-
for (const route of config.additionalRoutes ?? []) {
|
|
888
|
-
if (typeof route.permissions !== "function") throw new Error(`[Arc] Resource '${config.name}' route ${route.method} ${route.path}: permissions is required and must be a PermissionCheck function.\nUse allowPublic() or requireAuth() from @classytic/arc/permissions.`);
|
|
889
|
-
if (typeof route.wrapHandler !== "boolean") throw new Error(`[Arc] Resource '${config.name}' route ${route.method} ${route.path}: wrapHandler is required.\nSet true for ControllerHandler (context object) or false for FastifyHandler (req, reply).`);
|
|
890
|
-
}
|
|
891
|
-
if (config.routes && config.additionalRoutes) throw new Error(`[Arc] Resource '${config.name}': Cannot use both 'routes' and 'additionalRoutes'.\nUse 'routes' (v2.8) — it replaces 'additionalRoutes'.`);
|
|
892
894
|
for (const route of config.routes ?? []) if (typeof route.permissions !== "function") throw new Error(`[Arc] Resource '${config.name}' route ${route.method} ${route.path}: permissions is required and must be a PermissionCheck function.`);
|
|
893
895
|
if (config.actions) {
|
|
894
896
|
const CRUD_OPS = new Set([
|
|
@@ -1098,6 +1100,7 @@ var ResourceDefinition = class {
|
|
|
1098
1100
|
*/
|
|
1099
1101
|
routes;
|
|
1100
1102
|
middlewares;
|
|
1103
|
+
routeGuards;
|
|
1101
1104
|
disableDefaultRoutes;
|
|
1102
1105
|
disabledRoutes;
|
|
1103
1106
|
actions;
|
|
@@ -1128,8 +1131,9 @@ var ResourceDefinition = class {
|
|
|
1128
1131
|
this.customSchemas = config.customSchemas ?? {};
|
|
1129
1132
|
this.permissions = config.permissions ?? {};
|
|
1130
1133
|
this.routes = config.routes;
|
|
1131
|
-
this.additionalRoutes = config.routes ? convertRoutesToAdditionalRoutes(config.routes) :
|
|
1134
|
+
this.additionalRoutes = config.routes ? convertRoutesToAdditionalRoutes(config.routes) : [];
|
|
1132
1135
|
this.middlewares = config.middlewares ?? {};
|
|
1136
|
+
this.routeGuards = config.routeGuards;
|
|
1133
1137
|
this.disableDefaultRoutes = config.disableDefaultRoutes ?? false;
|
|
1134
1138
|
this.disabledRoutes = config.disabledRoutes ?? [];
|
|
1135
1139
|
this.actions = config.actions;
|
|
@@ -1283,6 +1287,7 @@ var ResourceDefinition = class {
|
|
|
1283
1287
|
schemas: schemas ?? void 0,
|
|
1284
1288
|
permissions: self.permissions,
|
|
1285
1289
|
middlewares: self.middlewares,
|
|
1290
|
+
routeGuards: self.routeGuards,
|
|
1286
1291
|
additionalRoutes: resolvedRoutes,
|
|
1287
1292
|
disableDefaultRoutes: self.disableDefaultRoutes,
|
|
1288
1293
|
disabledRoutes: self.disabledRoutes,
|
|
@@ -1331,7 +1336,17 @@ var ResourceDefinition = class {
|
|
|
1331
1336
|
prefix: this.prefix,
|
|
1332
1337
|
presets: this._appliedPresets,
|
|
1333
1338
|
permissions: this.permissions,
|
|
1334
|
-
|
|
1339
|
+
customRoutes: (this.routes ?? []).map((r) => ({
|
|
1340
|
+
method: r.method,
|
|
1341
|
+
path: r.path,
|
|
1342
|
+
handler: typeof r.handler === "string" ? r.handler : r.handler.name || "anonymous",
|
|
1343
|
+
operation: r.operation,
|
|
1344
|
+
summary: r.summary,
|
|
1345
|
+
description: r.description,
|
|
1346
|
+
permissions: r.permissions,
|
|
1347
|
+
raw: r.raw,
|
|
1348
|
+
schema: r.schema
|
|
1349
|
+
})),
|
|
1335
1350
|
routes: [],
|
|
1336
1351
|
events: Object.keys(this.events)
|
|
1337
1352
|
};
|
package/dist/docs/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { it as RegistryEntry } from "../interface-
|
|
2
|
-
import { t as ExternalOpenApiPaths } from "../externalPaths-
|
|
1
|
+
import { it as RegistryEntry } from "../interface-BVuMfeVv.mjs";
|
|
2
|
+
import { t as ExternalOpenApiPaths } from "../externalPaths-Bapitwvd.mjs";
|
|
3
3
|
import { FastifyPluginAsync } from "fastify";
|
|
4
4
|
|
|
5
5
|
//#region src/docs/openapi.d.ts
|
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-CYCuekCn.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,5 +1,5 @@
|
|
|
1
|
-
import { qt as ResourceDefinition, r as DataAdapter } from "../interface-
|
|
2
|
-
import { t as PermissionCheck } from "../types-
|
|
1
|
+
import { qt as ResourceDefinition, r as DataAdapter } from "../interface-BVuMfeVv.mjs";
|
|
2
|
+
import { t as PermissionCheck } from "../types-CVC4HOKi.mjs";
|
|
3
3
|
|
|
4
4
|
//#region src/dynamic/ArcDynamicLoader.d.ts
|
|
5
5
|
interface ArcArchitectureSchema {
|