@classytic/arc 1.1.0 → 2.1.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 +247 -794
- package/bin/arc.js +91 -52
- package/dist/EventTransport-BkUDYZEb.d.mts +99 -0
- package/dist/HookSystem-BsGV-j2l.mjs +404 -0
- package/dist/ResourceRegistry-7Ic20ZMw.mjs +249 -0
- package/dist/adapters/index.d.mts +5 -0
- package/dist/adapters/index.mjs +3 -0
- package/dist/audit/index.d.mts +81 -0
- package/dist/audit/index.mjs +275 -0
- package/dist/audit/mongodb.d.mts +5 -0
- package/dist/audit/mongodb.mjs +3 -0
- package/dist/audited-CGdLiSlE.mjs +140 -0
- package/dist/auth/index.d.mts +188 -0
- package/dist/auth/index.mjs +1096 -0
- package/dist/auth/redis-session.d.mts +43 -0
- package/dist/auth/redis-session.mjs +75 -0
- package/dist/betterAuthOpenApi-DjWDddNc.mjs +249 -0
- package/dist/cache/index.d.mts +145 -0
- package/dist/cache/index.mjs +91 -0
- package/dist/caching-GSDJcA6-.mjs +93 -0
- package/dist/chunk-C7Uep-_p.mjs +20 -0
- package/dist/circuitBreaker-DYhWBW_D.mjs +1096 -0
- package/dist/cli/commands/describe.d.mts +18 -0
- package/dist/cli/commands/describe.mjs +238 -0
- package/dist/cli/commands/docs.d.mts +13 -0
- package/dist/cli/commands/docs.mjs +52 -0
- package/dist/cli/commands/{generate.d.ts → generate.d.mts} +3 -2
- package/dist/cli/commands/generate.mjs +357 -0
- package/dist/cli/commands/{init.d.ts → init.d.mts} +11 -8
- package/dist/cli/commands/{init.js → init.mjs} +807 -617
- package/dist/cli/commands/introspect.d.mts +10 -0
- package/dist/cli/commands/introspect.mjs +75 -0
- package/dist/cli/index.d.mts +16 -0
- package/dist/cli/index.mjs +156 -0
- package/dist/constants-DdXFXQtN.mjs +84 -0
- package/dist/core/index.d.mts +5 -0
- package/dist/core/index.mjs +4 -0
- package/dist/createApp-D2D5XXaV.mjs +559 -0
- package/dist/defineResource-PXzSJ15_.mjs +2197 -0
- package/dist/discovery/index.d.mts +46 -0
- package/dist/discovery/index.mjs +109 -0
- package/dist/docs/index.d.mts +162 -0
- package/dist/docs/index.mjs +74 -0
- package/dist/elevation-DGo5shaX.d.mts +87 -0
- package/dist/elevation-DSTbVvYj.mjs +113 -0
- package/dist/errorHandler-C3GY3_ow.mjs +108 -0
- package/dist/errorHandler-CW3OOeYq.d.mts +72 -0
- package/dist/errors-DAWRdiYP.d.mts +124 -0
- package/dist/errors-DBANPbGr.mjs +211 -0
- package/dist/eventPlugin-BEOvaDqo.mjs +229 -0
- package/dist/eventPlugin-H6wDDjGO.d.mts +124 -0
- package/dist/events/index.d.mts +53 -0
- package/dist/events/index.mjs +51 -0
- package/dist/events/transports/redis-stream-entry.d.mts +2 -0
- package/dist/events/transports/redis-stream-entry.mjs +177 -0
- package/dist/events/transports/redis.d.mts +76 -0
- package/dist/events/transports/redis.mjs +124 -0
- package/dist/externalPaths-SyPF2tgK.d.mts +50 -0
- package/dist/factory/index.d.mts +63 -0
- package/dist/factory/index.mjs +3 -0
- package/dist/fastifyAdapter-C8DlE0YH.d.mts +216 -0
- package/dist/fields-Bi_AVKSo.d.mts +109 -0
- package/dist/fields-CTd_CrKr.mjs +114 -0
- package/dist/hooks/index.d.mts +4 -0
- package/dist/hooks/index.mjs +3 -0
- package/dist/idempotency/index.d.mts +96 -0
- package/dist/idempotency/index.mjs +319 -0
- package/dist/idempotency/mongodb.d.mts +2 -0
- package/dist/idempotency/mongodb.mjs +114 -0
- package/dist/idempotency/redis.d.mts +2 -0
- package/dist/idempotency/redis.mjs +103 -0
- package/dist/index.d.mts +260 -0
- package/dist/index.mjs +104 -0
- package/dist/integrations/event-gateway.d.mts +46 -0
- package/dist/integrations/event-gateway.mjs +43 -0
- package/dist/integrations/index.d.mts +5 -0
- package/dist/integrations/index.mjs +1 -0
- package/dist/integrations/jobs.d.mts +103 -0
- package/dist/integrations/jobs.mjs +123 -0
- package/dist/integrations/streamline.d.mts +60 -0
- package/dist/integrations/streamline.mjs +125 -0
- package/dist/integrations/websocket.d.mts +82 -0
- package/dist/integrations/websocket.mjs +288 -0
- package/dist/interface-CSNjltAc.d.mts +77 -0
- package/dist/interface-DTbsvIWe.d.mts +54 -0
- package/dist/interface-e9XfSsUV.d.mts +1097 -0
- package/dist/introspectionPlugin-B3JkrjwU.mjs +53 -0
- package/dist/keys-DhqDRxv3.mjs +42 -0
- package/dist/logger-ByrvQWZO.mjs +78 -0
- package/dist/memory-B2v7KrCB.mjs +143 -0
- package/dist/migrations/index.d.mts +156 -0
- package/dist/migrations/index.mjs +260 -0
- package/dist/mongodb-ClykrfGo.d.mts +118 -0
- package/dist/mongodb-DNKEExbf.mjs +93 -0
- package/dist/mongodb-Dg8O_gvd.d.mts +71 -0
- package/dist/openapi-9nB_kiuR.mjs +525 -0
- package/dist/org/index.d.mts +68 -0
- package/dist/org/index.mjs +513 -0
- package/dist/org/types.d.mts +82 -0
- package/dist/org/types.mjs +1 -0
- package/dist/permissions/index.d.mts +278 -0
- package/dist/permissions/index.mjs +579 -0
- package/dist/plugins/index.d.mts +172 -0
- package/dist/plugins/index.mjs +522 -0
- package/dist/plugins/response-cache.d.mts +87 -0
- package/dist/plugins/response-cache.mjs +283 -0
- package/dist/plugins/tracing-entry.d.mts +2 -0
- package/dist/plugins/tracing-entry.mjs +185 -0
- package/dist/pluralize-CM-jZg7p.mjs +86 -0
- package/dist/policies/{index.d.ts → index.d.mts} +204 -170
- package/dist/policies/index.mjs +321 -0
- package/dist/presets/{index.d.ts → index.d.mts} +62 -131
- package/dist/presets/index.mjs +143 -0
- package/dist/presets/multiTenant.d.mts +24 -0
- package/dist/presets/multiTenant.mjs +113 -0
- package/dist/presets-BTeYbw7h.d.mts +57 -0
- package/dist/presets-CeFtfDR8.mjs +119 -0
- package/dist/prisma-C3iornoK.d.mts +274 -0
- package/dist/prisma-DJbMt3yf.mjs +627 -0
- package/dist/queryCachePlugin-B6R0d4av.mjs +138 -0
- package/dist/queryCachePlugin-Q6SYuHZ6.d.mts +71 -0
- package/dist/redis-UwjEp8Ea.d.mts +49 -0
- package/dist/redis-stream-CBg0upHI.d.mts +103 -0
- package/dist/registry/index.d.mts +11 -0
- package/dist/registry/index.mjs +4 -0
- package/dist/requestContext-xi6OKBL-.mjs +55 -0
- package/dist/schemaConverter-Dtg0Kt9T.mjs +98 -0
- package/dist/schemas/index.d.mts +63 -0
- package/dist/schemas/index.mjs +82 -0
- package/dist/scope/index.d.mts +21 -0
- package/dist/scope/index.mjs +65 -0
- package/dist/sessionManager-D_iEHjQl.d.mts +186 -0
- package/dist/sse-DkqQ1uxb.mjs +123 -0
- package/dist/testing/index.d.mts +907 -0
- package/dist/testing/index.mjs +1976 -0
- package/dist/tracing-8CEbhF0w.d.mts +70 -0
- package/dist/typeGuards-DwxA1t_L.mjs +9 -0
- package/dist/types/index.d.mts +946 -0
- package/dist/types/index.mjs +14 -0
- package/dist/types-B0dhNrnd.d.mts +445 -0
- package/dist/types-Beqn1Un7.mjs +38 -0
- package/dist/types-DelU6kln.mjs +25 -0
- package/dist/types-RLkFVgaw.d.mts +101 -0
- package/dist/utils/index.d.mts +747 -0
- package/dist/utils/index.mjs +6 -0
- package/package.json +194 -68
- package/dist/BaseController-DVAiHxEQ.d.ts +0 -233
- package/dist/adapters/index.d.ts +0 -237
- package/dist/adapters/index.js +0 -668
- package/dist/arcCorePlugin-CsShQdyP.d.ts +0 -273
- package/dist/audit/index.d.ts +0 -195
- package/dist/audit/index.js +0 -319
- package/dist/auth/index.d.ts +0 -47
- package/dist/auth/index.js +0 -174
- package/dist/cli/commands/docs.d.ts +0 -11
- package/dist/cli/commands/docs.js +0 -474
- package/dist/cli/commands/generate.js +0 -334
- package/dist/cli/commands/introspect.d.ts +0 -8
- package/dist/cli/commands/introspect.js +0 -338
- package/dist/cli/index.d.ts +0 -4
- package/dist/cli/index.js +0 -3269
- package/dist/core/index.d.ts +0 -220
- package/dist/core/index.js +0 -2786
- package/dist/createApp-Ce9wl8W9.d.ts +0 -77
- package/dist/docs/index.d.ts +0 -166
- package/dist/docs/index.js +0 -658
- package/dist/errors-8WIxGS_6.d.ts +0 -122
- package/dist/events/index.d.ts +0 -117
- package/dist/events/index.js +0 -89
- package/dist/factory/index.d.ts +0 -38
- package/dist/factory/index.js +0 -1652
- package/dist/hooks/index.d.ts +0 -4
- package/dist/hooks/index.js +0 -199
- package/dist/idempotency/index.d.ts +0 -323
- package/dist/idempotency/index.js +0 -500
- package/dist/index-B4t03KQ0.d.ts +0 -1366
- package/dist/index.d.ts +0 -135
- package/dist/index.js +0 -4756
- package/dist/migrations/index.d.ts +0 -185
- package/dist/migrations/index.js +0 -274
- package/dist/org/index.d.ts +0 -129
- package/dist/org/index.js +0 -220
- package/dist/permissions/index.d.ts +0 -144
- package/dist/permissions/index.js +0 -103
- package/dist/plugins/index.d.ts +0 -46
- package/dist/plugins/index.js +0 -1069
- package/dist/policies/index.js +0 -196
- package/dist/presets/index.js +0 -384
- package/dist/presets/multiTenant.d.ts +0 -39
- package/dist/presets/multiTenant.js +0 -112
- package/dist/registry/index.d.ts +0 -16
- package/dist/registry/index.js +0 -253
- package/dist/testing/index.d.ts +0 -618
- package/dist/testing/index.js +0 -48020
- package/dist/types/index.d.ts +0 -4
- package/dist/types/index.js +0 -8
- package/dist/types-B99TBmFV.d.ts +0 -76
- package/dist/types-BvckRbs2.d.ts +0 -143
- package/dist/utils/index.d.ts +0 -679
- package/dist/utils/index.js +0 -931
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
//#region src/idempotency/stores/redis.ts
|
|
2
|
+
var RedisIdempotencyStore = class {
|
|
3
|
+
name = "redis";
|
|
4
|
+
client;
|
|
5
|
+
prefix;
|
|
6
|
+
lockPrefix;
|
|
7
|
+
ttlMs;
|
|
8
|
+
constructor(options) {
|
|
9
|
+
this.client = options.client;
|
|
10
|
+
this.prefix = options.prefix ?? "idem:";
|
|
11
|
+
this.lockPrefix = options.lockPrefix ?? "idem:lock:";
|
|
12
|
+
this.ttlMs = options.ttlMs ?? 864e5;
|
|
13
|
+
}
|
|
14
|
+
resultKey(key) {
|
|
15
|
+
return `${this.prefix}${key}`;
|
|
16
|
+
}
|
|
17
|
+
lockKey(key) {
|
|
18
|
+
return `${this.lockPrefix}${key}`;
|
|
19
|
+
}
|
|
20
|
+
async get(key) {
|
|
21
|
+
const data = await this.client.get(this.resultKey(key));
|
|
22
|
+
if (!data) return void 0;
|
|
23
|
+
try {
|
|
24
|
+
const result = JSON.parse(data);
|
|
25
|
+
if (new Date(result.expiresAt) < /* @__PURE__ */ new Date()) {
|
|
26
|
+
await this.delete(key);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
...result,
|
|
31
|
+
createdAt: new Date(result.createdAt),
|
|
32
|
+
expiresAt: new Date(result.expiresAt)
|
|
33
|
+
};
|
|
34
|
+
} catch {
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async set(key, result) {
|
|
39
|
+
const data = {
|
|
40
|
+
key,
|
|
41
|
+
...result
|
|
42
|
+
};
|
|
43
|
+
const ttlSeconds = Math.ceil((new Date(result.expiresAt).getTime() - Date.now()) / 1e3);
|
|
44
|
+
if (ttlSeconds > 0) await this.client.set(this.resultKey(key), JSON.stringify(data), { EX: ttlSeconds });
|
|
45
|
+
}
|
|
46
|
+
async tryLock(key, requestId, ttlMs) {
|
|
47
|
+
const ttlSeconds = Math.ceil(ttlMs / 1e3);
|
|
48
|
+
return await this.client.set(this.lockKey(key), requestId, {
|
|
49
|
+
EX: ttlSeconds,
|
|
50
|
+
NX: true
|
|
51
|
+
}) === "OK";
|
|
52
|
+
}
|
|
53
|
+
async unlock(key, requestId) {
|
|
54
|
+
if (await this.client.get(this.lockKey(key)) === requestId) await this.client.del(this.lockKey(key));
|
|
55
|
+
}
|
|
56
|
+
async isLocked(key) {
|
|
57
|
+
return await this.client.exists(this.lockKey(key)) > 0;
|
|
58
|
+
}
|
|
59
|
+
async delete(key) {
|
|
60
|
+
await this.client.del([this.resultKey(key), this.lockKey(key)]);
|
|
61
|
+
}
|
|
62
|
+
async deleteByPrefix(prefix) {
|
|
63
|
+
const resultKeys = await this.scanByPrefix(this.resultKey(prefix));
|
|
64
|
+
const lockKeys = await this.scanByPrefix(this.lockKey(prefix));
|
|
65
|
+
const allKeys = [...resultKeys, ...lockKeys];
|
|
66
|
+
if (allKeys.length === 0) return 0;
|
|
67
|
+
return this.client.del(allKeys);
|
|
68
|
+
}
|
|
69
|
+
async findByPrefix(prefix) {
|
|
70
|
+
const keys = await this.scanByPrefix(this.resultKey(prefix));
|
|
71
|
+
for (const key of keys) {
|
|
72
|
+
const data = await this.client.get(key);
|
|
73
|
+
if (!data) continue;
|
|
74
|
+
try {
|
|
75
|
+
const result = JSON.parse(data);
|
|
76
|
+
if (new Date(result.expiresAt) < /* @__PURE__ */ new Date()) continue;
|
|
77
|
+
return {
|
|
78
|
+
...result,
|
|
79
|
+
createdAt: new Date(result.createdAt),
|
|
80
|
+
expiresAt: new Date(result.expiresAt)
|
|
81
|
+
};
|
|
82
|
+
} catch {
|
|
83
|
+
continue;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/** Scan Redis keys matching a prefix pattern. Falls back to empty if SCAN unavailable. */
|
|
88
|
+
async scanByPrefix(prefix) {
|
|
89
|
+
if (!this.client.scan) return [];
|
|
90
|
+
const keys = [];
|
|
91
|
+
let cursor = "0";
|
|
92
|
+
do {
|
|
93
|
+
const [nextCursor, batch] = await this.client.scan(cursor, "MATCH", `${prefix}*`, "COUNT", 100);
|
|
94
|
+
cursor = nextCursor;
|
|
95
|
+
keys.push(...batch);
|
|
96
|
+
} while (String(cursor) !== "0");
|
|
97
|
+
return keys;
|
|
98
|
+
}
|
|
99
|
+
async close() {}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
//#endregion
|
|
103
|
+
export { RedisIdempotencyStore };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import "./elevation-DGo5shaX.mjs";
|
|
2
|
+
import { D as CrudRepository, E as defineResource, F as OperationFilter, I as PipelineConfig, L as PipelineContext, M as Guard, N as Interceptor, P as NextFunction, R as PipelineStep, S as RouteHandler, T as ResourceDefinition, _ as ControllerLike, a as RepositoryLike, b as IControllerResponse, c as BaseController, i as RelationMetadata, j as QueryOptions, k as PaginatedResult, l as BaseControllerOptions, n as DataAdapter, o as SchemaMetadata, r as FieldMetadata, s as ValidationResult, x as IRequestContext, y as IController, z as Transform } from "./interface-e9XfSsUV.mjs";
|
|
3
|
+
import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, t as FieldPermission } from "./fields-Bi_AVKSo.mjs";
|
|
4
|
+
import { i as UserBase, n as PermissionContext, r as PermissionResult, t as PermissionCheck } from "./types-RLkFVgaw.mjs";
|
|
5
|
+
import { AdditionalRoute, AnyRecord, ApiResponse, ArcInternalMetadata, AuthPluginOptions, ConfigError, CrudController, CrudRouteKey, CrudRouterOptions, CrudSchemas, EventDefinition, FastifyRequestExtras, FastifyWithAuth, FastifyWithDecorators, FieldRule, GracefulShutdownOptions, HealthCheck, HealthOptions, InferAdapterDoc, InferDocType, InferResourceDoc, IntrospectionData, IntrospectionPluginOptions, JWTPayload, MiddlewareConfig, MiddlewareHandler, OwnershipCheck, PresetFunction, PresetResult, RateLimitConfig, RegistryEntry, RegistryStats, RequestContext, RequestIdOptions, RequestWithExtras, ResourceConfig, ResourceMetadata, RouteHandlerMethod, RouteSchemaOptions, ServiceContext, TypedController, TypedRepository, TypedResourceConfig, UserOrganization, ValidateOptions, ValidationResult as ValidationResult$1 } from "./types/index.mjs";
|
|
6
|
+
import { c as MongooseAdapterOptions, l as createMongooseAdapter, n as PrismaAdapterOptions, o as createPrismaAdapter, s as MongooseAdapter, t as PrismaAdapter } from "./prisma-C3iornoK.mjs";
|
|
7
|
+
import "./adapters/index.mjs";
|
|
8
|
+
import { C as MutationOperation, S as MUTATION_OPERATIONS, T as SYSTEM_FIELDS, _ as HookOperation, a as getControllerScope, b as MAX_REGEX_LENGTH, c as CrudOperation, d as DEFAULT_MAX_LIMIT, f as DEFAULT_SORT, g as HOOK_PHASES, h as HOOK_OPERATIONS, l as DEFAULT_ID_FIELD, m as DEFAULT_UPDATE_METHOD, p as DEFAULT_TENANT_FIELD, s as CRUD_OPERATIONS, u as DEFAULT_LIMIT, v as HookPhase, w as RESERVED_QUERY_PARAMS, x as MAX_SEARCH_LENGTH, y as MAX_FILTER_DEPTH } from "./fastifyAdapter-C8DlE0YH.mjs";
|
|
9
|
+
import "./core/index.mjs";
|
|
10
|
+
import { a as NotFoundError, d as ValidationError, i as ForbiddenError, t as ArcError, u as UnauthorizedError } from "./errors-DAWRdiYP.mjs";
|
|
11
|
+
import { a as presets_d_exports, c as readOnly, i as ownerWithAdminBypass, n as authenticated, o as publicRead, r as fullPublic, s as publicReadAdminWrite, t as adminOnly } from "./presets-BTeYbw7h.mjs";
|
|
12
|
+
import { DynamicPermissionMatrix, DynamicPermissionMatrixConfig, allOf, allowPublic, anyOf, createDynamicPermissionMatrix, createOrgPermissions, denyAll, requireAuth, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireTeamMembership, when } from "./permissions/index.mjs";
|
|
13
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
14
|
+
|
|
15
|
+
//#region src/core/validateResourceConfig.d.ts
|
|
16
|
+
interface ConfigError$1 {
|
|
17
|
+
field: string;
|
|
18
|
+
message: string;
|
|
19
|
+
suggestion?: string;
|
|
20
|
+
}
|
|
21
|
+
interface ValidationResult$2 {
|
|
22
|
+
valid: boolean;
|
|
23
|
+
errors: ConfigError$1[];
|
|
24
|
+
warnings: ConfigError$1[];
|
|
25
|
+
}
|
|
26
|
+
interface ValidateOptions$1 {
|
|
27
|
+
/** Skip controller method validation (for testing) */
|
|
28
|
+
skipControllerCheck?: boolean;
|
|
29
|
+
/** Allow unknown preset names */
|
|
30
|
+
allowUnknownPresets?: boolean;
|
|
31
|
+
/** Custom valid permission keys beyond CRUD */
|
|
32
|
+
additionalPermissionKeys?: string[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Validate a resource configuration
|
|
36
|
+
*/
|
|
37
|
+
declare function validateResourceConfig(config: ResourceConfig, options?: ValidateOptions$1): ValidationResult$2;
|
|
38
|
+
/**
|
|
39
|
+
* Format validation errors for display
|
|
40
|
+
*/
|
|
41
|
+
declare function formatValidationErrors(resourceName: string, result: ValidationResult$2): string;
|
|
42
|
+
/**
|
|
43
|
+
* Validate and throw if invalid
|
|
44
|
+
*/
|
|
45
|
+
declare function assertValidConfig(config: ResourceConfig, options?: ValidateOptions$1): void;
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region src/pipeline/guard.d.ts
|
|
48
|
+
interface GuardOptions {
|
|
49
|
+
operations?: OperationFilter;
|
|
50
|
+
handler: (ctx: PipelineContext) => boolean | Promise<boolean>;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Create a named guard.
|
|
54
|
+
*
|
|
55
|
+
* @param name - Guard name (for debugging/introspection)
|
|
56
|
+
* @param handlerOrOptions - Handler function or options object
|
|
57
|
+
*/
|
|
58
|
+
declare function guard(name: string, handlerOrOptions: ((ctx: PipelineContext) => boolean | Promise<boolean>) | GuardOptions): Guard;
|
|
59
|
+
//#endregion
|
|
60
|
+
//#region src/pipeline/transform.d.ts
|
|
61
|
+
interface TransformOptions {
|
|
62
|
+
operations?: OperationFilter;
|
|
63
|
+
handler: (ctx: PipelineContext) => PipelineContext | void | Promise<PipelineContext | void>;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Create a named transform.
|
|
67
|
+
*
|
|
68
|
+
* @param name - Transform name (for debugging/introspection)
|
|
69
|
+
* @param handlerOrOptions - Handler function or options object
|
|
70
|
+
*/
|
|
71
|
+
declare function transform(name: string, handlerOrOptions: ((ctx: PipelineContext) => PipelineContext | void | Promise<PipelineContext | void>) | TransformOptions): Transform;
|
|
72
|
+
//#endregion
|
|
73
|
+
//#region src/pipeline/intercept.d.ts
|
|
74
|
+
interface InterceptOptions {
|
|
75
|
+
operations?: OperationFilter;
|
|
76
|
+
handler: (ctx: PipelineContext, next: NextFunction) => Promise<IControllerResponse<unknown>>;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Create a named interceptor.
|
|
80
|
+
*
|
|
81
|
+
* @param name - Interceptor name (for debugging/introspection)
|
|
82
|
+
* @param handlerOrOptions - Handler function or options object
|
|
83
|
+
*/
|
|
84
|
+
declare function intercept(name: string, handlerOrOptions: ((ctx: PipelineContext, next: NextFunction) => Promise<IControllerResponse<unknown>>) | InterceptOptions): Interceptor;
|
|
85
|
+
//#endregion
|
|
86
|
+
//#region src/pipeline/pipe.d.ts
|
|
87
|
+
/**
|
|
88
|
+
* Compose pipeline steps into an ordered array.
|
|
89
|
+
* Accepts guards, transforms, and interceptors in any order.
|
|
90
|
+
*/
|
|
91
|
+
declare function pipe(...steps: PipelineStep[]): PipelineStep[];
|
|
92
|
+
//#endregion
|
|
93
|
+
//#region src/middleware/middleware.d.ts
|
|
94
|
+
interface NamedMiddleware {
|
|
95
|
+
/** Unique name for debugging/introspection */
|
|
96
|
+
readonly name: string;
|
|
97
|
+
/** Operations this middleware applies to (default: all) */
|
|
98
|
+
readonly operations?: Array<'list' | 'get' | 'create' | 'update' | 'delete' | string>;
|
|
99
|
+
/** Priority — lower numbers run first (default: 10) */
|
|
100
|
+
readonly priority: number;
|
|
101
|
+
/** Conditional execution — return true to run, false to skip */
|
|
102
|
+
readonly when?: (request: RequestWithExtras) => boolean | Promise<boolean>;
|
|
103
|
+
/** The middleware handler */
|
|
104
|
+
readonly handler: MiddlewareHandler;
|
|
105
|
+
}
|
|
106
|
+
interface MiddlewareOptions {
|
|
107
|
+
operations?: NamedMiddleware['operations'];
|
|
108
|
+
priority?: number;
|
|
109
|
+
when?: NamedMiddleware['when'];
|
|
110
|
+
handler: MiddlewareHandler;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Create a named middleware with priority and conditions.
|
|
114
|
+
*/
|
|
115
|
+
declare function middleware(name: string, options: MiddlewareOptions): NamedMiddleware;
|
|
116
|
+
/**
|
|
117
|
+
* Sort named middlewares by priority (ascending — lower runs first).
|
|
118
|
+
* Returns a MiddlewareConfig map keyed by operation, ready to pass to `defineResource()`.
|
|
119
|
+
*/
|
|
120
|
+
declare function sortMiddlewares(middlewares: NamedMiddleware[]): MiddlewareConfig;
|
|
121
|
+
//#endregion
|
|
122
|
+
//#region src/context/requestContext.d.ts
|
|
123
|
+
/**
|
|
124
|
+
* Shape of the request-scoped context store.
|
|
125
|
+
* Populated by Arc's onRequest hook in arcCorePlugin.
|
|
126
|
+
*/
|
|
127
|
+
interface RequestStore {
|
|
128
|
+
/** Unique request identifier */
|
|
129
|
+
requestId?: string;
|
|
130
|
+
/** Authenticated user (if any) */
|
|
131
|
+
user?: {
|
|
132
|
+
id?: string;
|
|
133
|
+
_id?: string;
|
|
134
|
+
roles?: string[];
|
|
135
|
+
[key: string]: unknown;
|
|
136
|
+
} | null;
|
|
137
|
+
/** Active organization ID (multi-tenant) */
|
|
138
|
+
organizationId?: string;
|
|
139
|
+
/** Active team ID (team-scoped resources) */
|
|
140
|
+
teamId?: string;
|
|
141
|
+
/** Current resource name (set by arcDecorator in CRUD routes) */
|
|
142
|
+
resourceName?: string;
|
|
143
|
+
/** Request start time (for timing) */
|
|
144
|
+
startTime: number;
|
|
145
|
+
/** Additional context — extensible by app */
|
|
146
|
+
[key: string]: unknown;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Request context API.
|
|
150
|
+
*
|
|
151
|
+
* - `get()` — returns current store or undefined if outside request scope
|
|
152
|
+
* - `run(store, fn)` — run a function with a specific store (used by Arc internals)
|
|
153
|
+
* - `getStore()` — alias for get() (matches Node.js API naming)
|
|
154
|
+
*/
|
|
155
|
+
declare const requestContext: {
|
|
156
|
+
/**
|
|
157
|
+
* Get the current request context.
|
|
158
|
+
* Returns undefined if called outside a request lifecycle.
|
|
159
|
+
*/
|
|
160
|
+
get(): RequestStore | undefined;
|
|
161
|
+
/**
|
|
162
|
+
* Alias for get() — matches Node.js AsyncLocalStorage API naming.
|
|
163
|
+
*/
|
|
164
|
+
getStore(): RequestStore | undefined;
|
|
165
|
+
/**
|
|
166
|
+
* Run a function within a specific request context.
|
|
167
|
+
* Used internally by Arc's onRequest hook.
|
|
168
|
+
*/
|
|
169
|
+
run<T>(store: RequestStore, fn: () => T): T;
|
|
170
|
+
/**
|
|
171
|
+
* The underlying AsyncLocalStorage instance.
|
|
172
|
+
* Exposed for advanced use cases (testing, custom integrations).
|
|
173
|
+
*/
|
|
174
|
+
storage: AsyncLocalStorage<RequestStore>;
|
|
175
|
+
};
|
|
176
|
+
//#endregion
|
|
177
|
+
//#region src/logger/index.d.ts
|
|
178
|
+
/**
|
|
179
|
+
* Arc Logger — Centralized debug & warning system
|
|
180
|
+
*
|
|
181
|
+
* Lightweight, zero-dependency logger for Arc framework internals.
|
|
182
|
+
* Inspired by the `debug` npm package — disabled by default, opt-in via
|
|
183
|
+
* environment variable or `createApp({ debug })` option.
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```typescript
|
|
187
|
+
* // Enable via env var
|
|
188
|
+
* ARC_DEBUG=1 node server.js // all modules
|
|
189
|
+
* ARC_DEBUG=scope,elevation node server.js // specific modules
|
|
190
|
+
*
|
|
191
|
+
* // Enable via createApp
|
|
192
|
+
* const app = await createApp({ debug: true });
|
|
193
|
+
* const app = await createApp({ debug: 'scope,elevation' });
|
|
194
|
+
*
|
|
195
|
+
* // Suppress warnings (not recommended)
|
|
196
|
+
* ARC_SUPPRESS_WARNINGS=1 node server.js
|
|
197
|
+
*
|
|
198
|
+
* // Framework internals use:
|
|
199
|
+
* import { arcLog } from '../logger/index.js';
|
|
200
|
+
* const log = arcLog('elevation');
|
|
201
|
+
* log.debug('Elevation applied', { userId });
|
|
202
|
+
* log.warn('Something unexpected');
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
205
|
+
interface ArcLoggerOptions {
|
|
206
|
+
/**
|
|
207
|
+
* Enable debug output.
|
|
208
|
+
* - `true` or `'*'` — all modules
|
|
209
|
+
* - `string` — comma-separated module names (e.g., `'scope,elevation'`)
|
|
210
|
+
* - `false` — disabled (default)
|
|
211
|
+
*/
|
|
212
|
+
debug?: boolean | string;
|
|
213
|
+
/**
|
|
214
|
+
* Custom log writer. Defaults to `console`.
|
|
215
|
+
* Useful for routing Arc logs into Fastify's pino logger or test fixtures.
|
|
216
|
+
*/
|
|
217
|
+
writer?: ArcLogWriter;
|
|
218
|
+
}
|
|
219
|
+
interface ArcLogWriter {
|
|
220
|
+
debug: (...args: unknown[]) => void;
|
|
221
|
+
info: (...args: unknown[]) => void;
|
|
222
|
+
warn: (...args: unknown[]) => void;
|
|
223
|
+
error: (...args: unknown[]) => void;
|
|
224
|
+
}
|
|
225
|
+
interface ArcLogger {
|
|
226
|
+
debug: (...args: unknown[]) => void;
|
|
227
|
+
info: (...args: unknown[]) => void;
|
|
228
|
+
warn: (...args: unknown[]) => void;
|
|
229
|
+
error: (...args: unknown[]) => void;
|
|
230
|
+
}
|
|
231
|
+
/**
|
|
232
|
+
* Configure the Arc logger globally.
|
|
233
|
+
*
|
|
234
|
+
* Called automatically by `createApp({ debug })`, but can also be
|
|
235
|
+
* called manually for standalone usage outside of `createApp`.
|
|
236
|
+
*/
|
|
237
|
+
declare function configureArcLogger(options: ArcLoggerOptions): void;
|
|
238
|
+
/**
|
|
239
|
+
* Create a module-scoped logger.
|
|
240
|
+
*
|
|
241
|
+
* Debug and info messages are gated by the `ARC_DEBUG` env var or
|
|
242
|
+
* `createApp({ debug })` option. Warnings always show (unless
|
|
243
|
+
* `ARC_SUPPRESS_WARNINGS=1`). Errors always show.
|
|
244
|
+
*
|
|
245
|
+
* @param module - Module name (e.g., 'scope', 'elevation', 'sse', 'preset')
|
|
246
|
+
* @returns Logger instance for that module
|
|
247
|
+
*
|
|
248
|
+
* @example
|
|
249
|
+
* ```typescript
|
|
250
|
+
* const log = arcLog('elevation');
|
|
251
|
+
* log.debug('Checking elevation header');
|
|
252
|
+
* log.warn('No authenticate decorator found');
|
|
253
|
+
* ```
|
|
254
|
+
*/
|
|
255
|
+
declare function arcLog(module: string): ArcLogger;
|
|
256
|
+
//#endregion
|
|
257
|
+
//#region src/index.d.ts
|
|
258
|
+
declare const version: string;
|
|
259
|
+
//#endregion
|
|
260
|
+
export { type ValidationResult as AdapterValidationResult, type AdditionalRoute, type AnyRecord, type ApiResponse, ArcError, type ArcInternalMetadata, type ArcLogWriter, type ArcLogger, type ArcLoggerOptions, type AuthPluginOptions, BaseController, type BaseControllerOptions, CRUD_OPERATIONS, type ConfigError, type ControllerLike, type CrudController, CrudOperation, type CrudRepository, type CrudRouteKey, type CrudRouterOptions, type CrudSchemas, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, type DataAdapter, type DynamicPermissionMatrix, type DynamicPermissionMatrixConfig, type EventDefinition, type FastifyRequestExtras, type FastifyWithAuth, type FastifyWithDecorators, type FieldMetadata, type FieldPermission, type FieldPermissionMap, type FieldRule, ForbiddenError, type GracefulShutdownOptions, type Guard, HOOK_OPERATIONS, HOOK_PHASES, type HealthCheck, type HealthOptions, HookOperation, HookPhase, type IController, type IControllerResponse, type IRequestContext, type InferAdapterDoc, type InferDocType, type InferResourceDoc, type Interceptor, type IntrospectionData, type IntrospectionPluginOptions, type JWTPayload, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, type MiddlewareConfig, MongooseAdapter, type MongooseAdapterOptions, MutationOperation, type NamedMiddleware, NotFoundError, type OwnershipCheck, type PaginatedResult, type PermissionCheck, type PermissionContext, type PermissionResult, type PipelineConfig, type PipelineContext, type PipelineStep, type PresetFunction, type PresetResult, PrismaAdapter, type PrismaAdapterOptions, type QueryOptions, RESERVED_QUERY_PARAMS, type RateLimitConfig, type RegistryEntry, type RegistryStats, type RelationMetadata, type RepositoryLike, type RequestContext, type RequestIdOptions, type RequestStore, type RequestWithExtras, type ResourceConfig, ResourceDefinition, type ResourceMetadata, type RouteHandler, type RouteHandlerMethod, type RouteSchemaOptions, SYSTEM_FIELDS, type SchemaMetadata, type ServiceContext, type Transform, type TypedController, type TypedRepository, type TypedResourceConfig, UnauthorizedError, type UserBase, type UserOrganization, type ValidateOptions, ValidationError, type ValidationResult$1 as ValidationResult, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, arcLog, assertValidConfig, authenticated, configureArcLogger, createDynamicPermissionMatrix, createMongooseAdapter, createOrgPermissions, createPrismaAdapter, defineResource, denyAll, fields, formatValidationErrors, fullPublic, getControllerScope, guard, intercept, middleware, ownerWithAdminBypass, presets_d_exports as permissions, pipe, publicRead, publicReadAdminWrite, readOnly, requestContext, requireAuth, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireTeamMembership, sortMiddlewares, transform, validateResourceConfig, version, when };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
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-DdXFXQtN.mjs";
|
|
2
|
+
import { a as createMongooseAdapter, i as MongooseAdapter, r as createPrismaAdapter, t as PrismaAdapter } from "./prisma-DJbMt3yf.mjs";
|
|
3
|
+
import { a as validateResourceConfig, g as BaseController, i as formatValidationErrors, l as pipe, m as getControllerScope, n as defineResource, r as assertValidConfig, t as ResourceDefinition } from "./defineResource-PXzSJ15_.mjs";
|
|
4
|
+
import { n as applyFieldWritePermissions, r as fields, t as applyFieldReadPermissions } from "./fields-CTd_CrKr.mjs";
|
|
5
|
+
import { i as NotFoundError, l as UnauthorizedError, r as ForbiddenError, t as ArcError, u as ValidationError } from "./errors-DBANPbGr.mjs";
|
|
6
|
+
import { t as requestContext } from "./requestContext-xi6OKBL-.mjs";
|
|
7
|
+
import { a as presets_exports, c as readOnly, i as ownerWithAdminBypass, n as authenticated, o as publicRead, r as fullPublic, s as publicReadAdminWrite, t as adminOnly } from "./presets-CeFtfDR8.mjs";
|
|
8
|
+
import { allOf, allowPublic, anyOf, createDynamicPermissionMatrix, createOrgPermissions, denyAll, requireAuth, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireTeamMembership, when } from "./permissions/index.mjs";
|
|
9
|
+
import { n as configureArcLogger, t as arcLog } from "./logger-ByrvQWZO.mjs";
|
|
10
|
+
|
|
11
|
+
//#region src/pipeline/guard.ts
|
|
12
|
+
/**
|
|
13
|
+
* Create a named guard.
|
|
14
|
+
*
|
|
15
|
+
* @param name - Guard name (for debugging/introspection)
|
|
16
|
+
* @param handlerOrOptions - Handler function or options object
|
|
17
|
+
*/
|
|
18
|
+
function guard(name, handlerOrOptions) {
|
|
19
|
+
const opts = typeof handlerOrOptions === "function" ? { handler: handlerOrOptions } : handlerOrOptions;
|
|
20
|
+
return {
|
|
21
|
+
_type: "guard",
|
|
22
|
+
name,
|
|
23
|
+
operations: opts.operations,
|
|
24
|
+
handler: opts.handler
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
//#endregion
|
|
29
|
+
//#region src/pipeline/transform.ts
|
|
30
|
+
/**
|
|
31
|
+
* Create a named transform.
|
|
32
|
+
*
|
|
33
|
+
* @param name - Transform name (for debugging/introspection)
|
|
34
|
+
* @param handlerOrOptions - Handler function or options object
|
|
35
|
+
*/
|
|
36
|
+
function transform(name, handlerOrOptions) {
|
|
37
|
+
const opts = typeof handlerOrOptions === "function" ? { handler: handlerOrOptions } : handlerOrOptions;
|
|
38
|
+
return {
|
|
39
|
+
_type: "transform",
|
|
40
|
+
name,
|
|
41
|
+
operations: opts.operations,
|
|
42
|
+
handler: opts.handler
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
//#endregion
|
|
47
|
+
//#region src/pipeline/intercept.ts
|
|
48
|
+
/**
|
|
49
|
+
* Create a named interceptor.
|
|
50
|
+
*
|
|
51
|
+
* @param name - Interceptor name (for debugging/introspection)
|
|
52
|
+
* @param handlerOrOptions - Handler function or options object
|
|
53
|
+
*/
|
|
54
|
+
function intercept(name, handlerOrOptions) {
|
|
55
|
+
const opts = typeof handlerOrOptions === "function" ? { handler: handlerOrOptions } : handlerOrOptions;
|
|
56
|
+
return {
|
|
57
|
+
_type: "interceptor",
|
|
58
|
+
name,
|
|
59
|
+
operations: opts.operations,
|
|
60
|
+
handler: opts.handler
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
//#endregion
|
|
65
|
+
//#region src/middleware/middleware.ts
|
|
66
|
+
/**
|
|
67
|
+
* Create a named middleware with priority and conditions.
|
|
68
|
+
*/
|
|
69
|
+
function middleware(name, options) {
|
|
70
|
+
return {
|
|
71
|
+
name,
|
|
72
|
+
operations: options.operations,
|
|
73
|
+
priority: options.priority ?? 10,
|
|
74
|
+
when: options.when,
|
|
75
|
+
handler: options.handler
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Sort named middlewares by priority (ascending — lower runs first).
|
|
80
|
+
* Returns a MiddlewareConfig map keyed by operation, ready to pass to `defineResource()`.
|
|
81
|
+
*/
|
|
82
|
+
function sortMiddlewares(middlewares) {
|
|
83
|
+
const sorted = [...middlewares].sort((a, b) => a.priority - b.priority);
|
|
84
|
+
const operations = CRUD_OPERATIONS;
|
|
85
|
+
const result = {};
|
|
86
|
+
for (const op of operations) {
|
|
87
|
+
const applicable = sorted.filter((m) => !m.operations || m.operations.length === 0 || m.operations.includes(op));
|
|
88
|
+
if (applicable.length > 0) result[op] = applicable.map((m) => {
|
|
89
|
+
if (!m.when) return m.handler;
|
|
90
|
+
const wrapped = async (request, reply) => {
|
|
91
|
+
if (await m.when(request)) return m.handler(request, reply);
|
|
92
|
+
};
|
|
93
|
+
return wrapped;
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
//#endregion
|
|
100
|
+
//#region src/index.ts
|
|
101
|
+
const version = "__ARC_VERSION__";
|
|
102
|
+
|
|
103
|
+
//#endregion
|
|
104
|
+
export { ArcError, BaseController, CRUD_OPERATIONS, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, ForbiddenError, HOOK_OPERATIONS, HOOK_PHASES, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, MongooseAdapter, NotFoundError, PrismaAdapter, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, UnauthorizedError, ValidationError, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, arcLog, assertValidConfig, authenticated, configureArcLogger, createDynamicPermissionMatrix, createMongooseAdapter, createOrgPermissions, createPrismaAdapter, defineResource, denyAll, fields, formatValidationErrors, fullPublic, getControllerScope, guard, intercept, middleware, ownerWithAdminBypass, presets_exports as permissions, pipe, publicRead, publicReadAdminWrite, readOnly, requestContext, requireAuth, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireTeamMembership, sortMiddlewares, transform, validateResourceConfig, version, when };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { t as DomainEvent } from "../EventTransport-BkUDYZEb.mjs";
|
|
2
|
+
import { WebSocketClient, WebSocketMessage } from "./websocket.mjs";
|
|
3
|
+
import { FastifyPluginAsync, FastifyRequest } from "fastify";
|
|
4
|
+
|
|
5
|
+
//#region src/integrations/event-gateway.d.ts
|
|
6
|
+
interface EventGatewayOptions {
|
|
7
|
+
/** Require auth for all real-time connections (default: true) */
|
|
8
|
+
auth?: boolean;
|
|
9
|
+
/** Custom auth function for WebSocket upgrade */
|
|
10
|
+
authenticate?: (request: unknown) => Promise<{
|
|
11
|
+
userId?: string;
|
|
12
|
+
organizationId?: string;
|
|
13
|
+
} | null>;
|
|
14
|
+
/** Filter events by org from request.scope (default: false) */
|
|
15
|
+
orgScoped?: boolean;
|
|
16
|
+
/** Room/subscription authorization policy */
|
|
17
|
+
roomPolicy?: (client: {
|
|
18
|
+
userId?: string;
|
|
19
|
+
organizationId?: string;
|
|
20
|
+
}, room: string) => boolean | Promise<boolean>;
|
|
21
|
+
/** Max message size from WS clients in bytes (default: 16384) */
|
|
22
|
+
maxMessageBytes?: number;
|
|
23
|
+
/** Max subscriptions per client (default: 100) */
|
|
24
|
+
maxSubscriptionsPerClient?: number;
|
|
25
|
+
/** SSE config. Set false to disable SSE. */
|
|
26
|
+
sse?: false | {
|
|
27
|
+
path?: string;
|
|
28
|
+
patterns?: string[];
|
|
29
|
+
heartbeat?: number;
|
|
30
|
+
filter?: (event: DomainEvent<unknown>, request: FastifyRequest) => boolean;
|
|
31
|
+
};
|
|
32
|
+
/** WebSocket config. Set false to disable WebSocket. */
|
|
33
|
+
ws?: false | {
|
|
34
|
+
path?: string;
|
|
35
|
+
resources?: string[];
|
|
36
|
+
heartbeatInterval?: number;
|
|
37
|
+
maxClientsPerRoom?: number;
|
|
38
|
+
exposeStats?: boolean | "authenticated";
|
|
39
|
+
onMessage?: (client: WebSocketClient, message: WebSocketMessage) => void | Promise<void>;
|
|
40
|
+
onConnect?: (client: WebSocketClient) => void | Promise<void>;
|
|
41
|
+
onDisconnect?: (client: WebSocketClient) => void | Promise<void>;
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
declare const eventGatewayPlugin: FastifyPluginAsync<EventGatewayOptions>;
|
|
45
|
+
//#endregion
|
|
46
|
+
export { EventGatewayOptions, eventGatewayPlugin as default, eventGatewayPlugin };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import fp from "fastify-plugin";
|
|
2
|
+
|
|
3
|
+
//#region src/integrations/event-gateway.ts
|
|
4
|
+
const eventGatewayPluginImpl = async (fastify, opts = {}) => {
|
|
5
|
+
const { auth = true, orgScoped = false, roomPolicy, maxMessageBytes, maxSubscriptionsPerClient, authenticate } = opts;
|
|
6
|
+
if (auth && !authenticate && !fastify.hasDecorator("authenticate")) throw new Error("[arc-event-gateway] auth is true but fastify.authenticate is not registered. Register an auth plugin first, provide a custom authenticate function, or set auth: false.");
|
|
7
|
+
if (opts.sse !== false) {
|
|
8
|
+
const { default: ssePlugin } = await import("../sse-DkqQ1uxb.mjs").then((n) => n.r);
|
|
9
|
+
await fastify.register(ssePlugin, {
|
|
10
|
+
path: opts.sse?.path ?? "/events/stream",
|
|
11
|
+
requireAuth: auth,
|
|
12
|
+
patterns: opts.sse?.patterns ?? ["*"],
|
|
13
|
+
heartbeat: opts.sse?.heartbeat ?? 3e4,
|
|
14
|
+
orgScoped,
|
|
15
|
+
filter: opts.sse?.filter
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
if (opts.ws !== false) {
|
|
19
|
+
const { websocketPlugin } = await import("./websocket.mjs");
|
|
20
|
+
await fastify.register(websocketPlugin, {
|
|
21
|
+
path: opts.ws?.path ?? "/ws",
|
|
22
|
+
auth,
|
|
23
|
+
authenticate,
|
|
24
|
+
resources: opts.ws?.resources ?? [],
|
|
25
|
+
heartbeatInterval: opts.ws?.heartbeatInterval ?? 3e4,
|
|
26
|
+
maxClientsPerRoom: opts.ws?.maxClientsPerRoom,
|
|
27
|
+
roomPolicy,
|
|
28
|
+
maxMessageBytes,
|
|
29
|
+
maxSubscriptionsPerClient,
|
|
30
|
+
exposeStats: opts.ws?.exposeStats,
|
|
31
|
+
onMessage: opts.ws?.onMessage,
|
|
32
|
+
onConnect: opts.ws?.onConnect,
|
|
33
|
+
onDisconnect: opts.ws?.onDisconnect
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
const eventGatewayPlugin = fp(eventGatewayPluginImpl, {
|
|
38
|
+
name: "arc-event-gateway",
|
|
39
|
+
fastify: "5.x"
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
export { eventGatewayPlugin as default, eventGatewayPlugin };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { WebSocketClient, WebSocketMessage, WebSocketPluginOptions } from "./websocket.mjs";
|
|
2
|
+
import { EventGatewayOptions } from "./event-gateway.mjs";
|
|
3
|
+
import { StreamlinePluginOptions, WorkflowLike, WorkflowRunLike } from "./streamline.mjs";
|
|
4
|
+
import { JobDefinition, JobDispatchOptions, JobDispatcher, JobMeta, JobsPluginOptions, QueueStats } from "./jobs.mjs";
|
|
5
|
+
export { type EventGatewayOptions, type JobDefinition, type JobDispatchOptions, type JobDispatcher, type JobMeta, type JobsPluginOptions, type QueueStats, type StreamlinePluginOptions, type WebSocketClient, type WebSocketMessage, type WebSocketPluginOptions, type WorkflowLike, type WorkflowRunLike };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { };
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { FastifyPluginAsync } from "fastify";
|
|
2
|
+
|
|
3
|
+
//#region src/integrations/jobs.d.ts
|
|
4
|
+
interface JobDefinition<TData = unknown, TResult = unknown> {
|
|
5
|
+
/** Unique job name */
|
|
6
|
+
name: string;
|
|
7
|
+
/** Job handler function */
|
|
8
|
+
handler: (data: TData, meta: JobMeta) => Promise<TResult>;
|
|
9
|
+
/** Number of retries on failure (default: 3) */
|
|
10
|
+
retries?: number;
|
|
11
|
+
/** Backoff strategy */
|
|
12
|
+
backoff?: {
|
|
13
|
+
type: 'exponential' | 'fixed';
|
|
14
|
+
delay: number;
|
|
15
|
+
};
|
|
16
|
+
/** Job timeout in ms (default: 30000) */
|
|
17
|
+
timeout?: number;
|
|
18
|
+
/** Concurrency per worker (default: 1) */
|
|
19
|
+
concurrency?: number;
|
|
20
|
+
/** Rate limit: max jobs per duration */
|
|
21
|
+
rateLimit?: {
|
|
22
|
+
max: number;
|
|
23
|
+
duration: number;
|
|
24
|
+
};
|
|
25
|
+
/** Dead letter queue name (default: '{name}:dead') */
|
|
26
|
+
deadLetterQueue?: string;
|
|
27
|
+
}
|
|
28
|
+
interface JobMeta {
|
|
29
|
+
jobId: string;
|
|
30
|
+
attemptsMade: number;
|
|
31
|
+
timestamp: number;
|
|
32
|
+
}
|
|
33
|
+
interface JobDispatchOptions {
|
|
34
|
+
/** Delay job execution by ms */
|
|
35
|
+
delay?: number;
|
|
36
|
+
/** Job priority (lower = higher priority) */
|
|
37
|
+
priority?: number;
|
|
38
|
+
/** Unique job ID (for deduplication) */
|
|
39
|
+
jobId?: string;
|
|
40
|
+
/** Remove job after completion */
|
|
41
|
+
removeOnComplete?: boolean | number;
|
|
42
|
+
/** Remove job after failure */
|
|
43
|
+
removeOnFail?: boolean | number;
|
|
44
|
+
}
|
|
45
|
+
interface JobsPluginOptions {
|
|
46
|
+
/** Redis connection options (passed to BullMQ) */
|
|
47
|
+
connection: {
|
|
48
|
+
host: string;
|
|
49
|
+
port: number;
|
|
50
|
+
password?: string;
|
|
51
|
+
db?: number;
|
|
52
|
+
} | unknown;
|
|
53
|
+
/** Job definitions to register */
|
|
54
|
+
jobs: JobDefinition[];
|
|
55
|
+
/** URL prefix for job management endpoints (default: '/jobs') */
|
|
56
|
+
prefix?: string;
|
|
57
|
+
/** Bridge job events to Arc's event bus (default: true) */
|
|
58
|
+
bridgeEvents?: boolean;
|
|
59
|
+
/** Default job options applied to all jobs */
|
|
60
|
+
defaults?: {
|
|
61
|
+
retries?: number;
|
|
62
|
+
backoff?: {
|
|
63
|
+
type: 'exponential' | 'fixed';
|
|
64
|
+
delay: number;
|
|
65
|
+
};
|
|
66
|
+
timeout?: number;
|
|
67
|
+
removeOnComplete?: boolean | number;
|
|
68
|
+
removeOnFail?: boolean | number;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
interface JobDispatcher {
|
|
72
|
+
dispatch<TData = unknown>(name: string, data: TData, options?: JobDispatchOptions): Promise<{
|
|
73
|
+
jobId: string;
|
|
74
|
+
}>;
|
|
75
|
+
getQueue(name: string): unknown | null;
|
|
76
|
+
getStats(): Promise<Record<string, QueueStats>>;
|
|
77
|
+
close(): Promise<void>;
|
|
78
|
+
}
|
|
79
|
+
interface QueueStats {
|
|
80
|
+
waiting: number;
|
|
81
|
+
active: number;
|
|
82
|
+
completed: number;
|
|
83
|
+
failed: number;
|
|
84
|
+
delayed: number;
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Define a background job with typed data and configuration.
|
|
88
|
+
*
|
|
89
|
+
* @example
|
|
90
|
+
* const processImage = defineJob({
|
|
91
|
+
* name: 'process-image',
|
|
92
|
+
* handler: async (data: { url: string; width: number }) => {
|
|
93
|
+
* return await sharp(data.url).resize(data.width).toBuffer();
|
|
94
|
+
* },
|
|
95
|
+
* retries: 3,
|
|
96
|
+
* timeout: 60000,
|
|
97
|
+
* });
|
|
98
|
+
*/
|
|
99
|
+
declare function defineJob<TData = unknown, TResult = unknown>(definition: JobDefinition<TData, TResult>): JobDefinition<TData, TResult>;
|
|
100
|
+
/** Pluggable BullMQ job queue integration for Arc */
|
|
101
|
+
declare const jobsPlugin: FastifyPluginAsync<JobsPluginOptions>;
|
|
102
|
+
//#endregion
|
|
103
|
+
export { JobDefinition, JobDispatchOptions, JobDispatcher, JobMeta, JobsPluginOptions, QueueStats, jobsPlugin as default, jobsPlugin, defineJob };
|