@classytic/arc 2.7.3 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/{HookSystem-D7lfx--K.mjs → HookSystem-BjFu7zf1.mjs} +3 -2
- 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/index.mjs +2 -2
- package/dist/auth/redis-session.d.mts +1 -1
- package/dist/{betterAuthOpenApi-CCw3YX0g.mjs → betterAuthOpenApi-CHCIuA-p.mjs} +1 -1
- package/dist/cache/index.d.mts +2 -2
- package/dist/cache/index.mjs +1 -1
- package/dist/cli/commands/docs.mjs +2 -2
- package/dist/cli/commands/generate.mjs +1 -1
- package/dist/cli/commands/introspect.mjs +1 -1
- package/dist/core/index.d.mts +2 -2
- package/dist/core/index.mjs +3 -2
- package/dist/core-BfrfxNqO.mjs +34 -0
- package/dist/{core-BWekSEju.mjs → createActionRouter-CbkIAaGh.mjs} +6 -36
- package/dist/{createApp-D7e77m8C.mjs → createApp-Cy8eUNKQ.mjs} +10 -10
- package/dist/{defineResource-DZzyl4a4.mjs → defineResource-CovBXvTB.mjs} +75 -9
- 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/{elevation-By_p2lnn.mjs → elevation-BBGFjzIP.mjs} +1 -1
- package/dist/{errorHandler-pCpEtNd7.d.mts → errorHandler-BeN-ERN7.d.mts} +1 -1
- package/dist/{eventPlugin-CdvUoUna.d.mts → eventPlugin-CAOWMQS8.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.d.mts +1 -1
- package/dist/factory/index.d.mts +1 -1
- package/dist/factory/index.mjs +7 -6
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.mjs +1 -1
- package/dist/idempotency/index.d.mts +3 -3
- package/dist/idempotency/mongodb.d.mts +1 -1
- package/dist/idempotency/mongodb.mjs +1 -3
- package/dist/idempotency/redis.d.mts +1 -1
- package/dist/{index-C9eYNjGR.d.mts → index-BpMhrFgn.d.mts} +1 -1
- package/dist/{index-B0extFr4.d.mts → index-CBru2y5Y.d.mts} +3 -3
- package/dist/{index-BjShrzoj.d.mts → index-qct60lnl.d.mts} +14 -14
- package/dist/index.d.mts +7 -7
- package/dist/index.mjs +4 -4
- 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/integrations/streamline.d.mts +39 -7
- package/dist/integrations/streamline.mjs +106 -4
- package/dist/{interface-B91alUzq.d.mts → interface-IJqN3pXK.d.mts} +145 -4
- package/dist/{mongodb-Cgu9F1Nd.d.mts → mongodb-B1eVtFhw.d.mts} +1 -1
- package/dist/{mongodb-B7zupyck.d.mts → mongodb-NShVZDMr.d.mts} +1 -1
- package/dist/{openapi-BBSTVcMm.mjs → openapi-AYLVjqVe.mjs} +1 -1
- package/dist/org/index.d.mts +2 -2
- package/dist/permissions/index.d.mts +3 -3
- package/dist/plugins/index.d.mts +4 -4
- package/dist/plugins/index.mjs +8 -8
- 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/multiTenant.d.mts +1 -1
- package/dist/{queryCachePlugin-Ckl71mkc.d.mts → queryCachePlugin-BCFVXnxK.d.mts} +1 -1
- package/dist/{redis-3TQxm2VZ.d.mts → redis-Bunu3qWg.d.mts} +1 -1
- package/dist/{redis-stream-Dag5LFa9.d.mts → redis-stream-CF1lrKVk.d.mts} +1 -1
- package/dist/registry/index.d.mts +1 -1
- package/dist/registry/index.mjs +2 -2
- package/dist/{resourceToTools-BJkoQoUP.mjs → resourceToTools-C_1SMiCz.mjs} +1 -1
- package/dist/rpc/index.d.mts +1 -1
- package/dist/{schemaConverter-0TyONAwM.mjs → schemaConverter-Y5EejTnJ.mjs} +1 -4
- package/dist/scope/index.d.mts +2 -2
- package/dist/scope/index.mjs +1 -1
- package/dist/{sse-6W0hjVS_.mjs → sse-CD5Hghpu.mjs} +1 -1
- package/dist/testing/index.d.mts +2 -2
- package/dist/testing/index.mjs +1 -1
- package/dist/types/index.d.mts +5 -5
- package/dist/{types-B4BNthET.d.mts → types-BoaZHr-2.d.mts} +1 -1
- package/dist/{types-C5g2oRC7.d.mts → types-Ct0PUUSp.d.mts} +1 -1
- package/dist/{types-2FlNl0mL.d.mts → types-gUxAIZHp.d.mts} +13 -9
- package/dist/utils/index.d.mts +3 -3
- package/dist/utils/index.mjs +1 -1
- package/package.json +8 -7
- package/skills/arc/SKILL.md +23 -4
- package/skills/arc/references/integrations.md +1 -1
- package/skills/arc/references/mcp.md +2 -0
- /package/dist/{EventTransport-C4VheKeC.d.mts → EventTransport-n1KBxC_N.d.mts} +0 -0
- /package/dist/{ResourceRegistry-DsHiG9cL.mjs → ResourceRegistry-BOtJuRCs.mjs} +0 -0
- /package/dist/{caching-5DtLwIqb.mjs → caching-CHH-iHs3.mjs} +0 -0
- /package/dist/{circuitBreaker-BBPDt-J_.d.mts → circuitBreaker-BGVoB1hD.d.mts} +0 -0
- /package/dist/{elevation-D7WK0RXq.d.mts → elevation-UJO3-NvX.d.mts} +0 -0
- /package/dist/{errorHandler-CH8wk1eD.mjs → errorHandler-BW08lEiy.mjs} +0 -0
- /package/dist/{errors-BS6lZvWy.d.mts → errors-BI8kEKsO.d.mts} +0 -0
- /package/dist/{eventPlugin-B6U_nCFU.mjs → eventPlugin-x4jo3sG0.mjs} +0 -0
- /package/dist/{externalPaths-iba7jD3d.d.mts → externalPaths-BQ8QijNH.d.mts} +0 -0
- /package/dist/{fields-D4nMDqnK.d.mts → fields-DoeDgh2b.d.mts} +0 -0
- /package/dist/{interface-CSbZdv_3.d.mts → interface-CkkWm5uR.d.mts} +0 -0
- /package/dist/{interface-CG7oRZjX.d.mts → interface-bpoLKKqx.d.mts} +0 -0
- /package/dist/{logger-DLg8-Ueg.mjs → logger-CDjpjySd.mjs} +0 -0
- /package/dist/{metrics-Qnvwc-LQ.mjs → metrics-DuhiSEZI.mjs} +0 -0
- /package/dist/{mongodb-B7X7P1P8.mjs → mongodb-5Ff3w8jy.mjs} +0 -0
- /package/dist/{pluralize-Dckfq6US.mjs → pluralize-BneOJkpi.mjs} +0 -0
- /package/dist/{queryCachePlugin-CwTpR04-.mjs → queryCachePlugin-D0iIVhW_.mjs} +0 -0
- /package/dist/{registry-B3lRFBWo.mjs → registry-B0Wl7uVV.mjs} +0 -0
- /package/dist/{replyHelpers-uDUIYh7u.mjs → replyHelpers-CXtJDAZ0.mjs} +0 -0
- /package/dist/{sessionManager-CEo9jwPI.d.mts → sessionManager-BkzVU8h2.d.mts} +0 -0
- /package/dist/{tracing-DEqdGkr-.d.mts → tracing-xqXzWeaf.d.mts} +0 -0
- /package/dist/{types--D3vvfdt.d.mts → types-CN6JvmYz.d.mts} +0 -0
- /package/dist/{versioning-CdBbFefk.mjs → versioning-CPU_5Xfs.mjs} +0 -0
package/dist/factory/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as edgePreset, c as testingPreset, i as developmentPreset, n as createApp, o as getPreset, s as productionPreset, t as ArcFactory } from "../createApp-
|
|
1
|
+
import { a as edgePreset, c as testingPreset, i as developmentPreset, n as createApp, o as getPreset, s as productionPreset, t as ArcFactory } from "../createApp-Cy8eUNKQ.mjs";
|
|
2
2
|
import { readdir } from "node:fs/promises";
|
|
3
3
|
import { dirname, join, resolve } from "node:path";
|
|
4
4
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
@@ -163,14 +163,15 @@ async function loadResources(dir, options = {}) {
|
|
|
163
163
|
}
|
|
164
164
|
resources.push(resource);
|
|
165
165
|
}
|
|
166
|
-
|
|
166
|
+
const log = silent ? void 0 : options?.logger;
|
|
167
|
+
if (log) {
|
|
167
168
|
if (failed.length) {
|
|
168
|
-
|
|
169
|
-
for (const f of failed)
|
|
169
|
+
log.warn(`[arc] loadResources: ${failed.length} file(s) failed to import:`);
|
|
170
|
+
for (const f of failed) log.warn(` - ${f}`);
|
|
170
171
|
}
|
|
171
172
|
if (skipped.length) {
|
|
172
|
-
|
|
173
|
-
for (const f of skipped)
|
|
173
|
+
log.warn(`[arc] loadResources: ${skipped.length} file(s) skipped (no default export with toPlugin):`);
|
|
174
|
+
for (const f of skipped) log.warn(` - ${f}`);
|
|
174
175
|
}
|
|
175
176
|
}
|
|
176
177
|
return resources;
|
package/dist/hooks/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Cn as defineHook, Sn as createHookSystem, _n as afterDelete, bn as beforeDelete, cn as DefineHookOptions, dn as HookOperation, fn as HookPhase, gn as afterCreate, hn as HookSystemOptions, ln as HookContext, mn as HookSystem, pn as HookRegistration, un as HookHandler, vn as afterUpdate, xn as beforeUpdate, yn as beforeCreate } from "../interface-IJqN3pXK.mjs";
|
|
2
2
|
export { type DefineHookOptions, type HookContext, type HookHandler, type HookOperation, type HookPhase, type HookRegistration, HookSystem, type HookSystemOptions, afterCreate, afterDelete, afterUpdate, beforeCreate, beforeDelete, beforeUpdate, createHookSystem, defineHook };
|
package/dist/hooks/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as beforeCreate, c as createHookSystem, i as afterUpdate, l as defineHook, n as afterCreate, o as beforeDelete, r as afterDelete, s as beforeUpdate, t as HookSystem } from "../HookSystem-
|
|
1
|
+
import { a as beforeCreate, c as createHookSystem, i as afterUpdate, l as defineHook, n as afterCreate, o as beforeDelete, r as afterDelete, s as beforeUpdate, t as HookSystem } from "../HookSystem-BjFu7zf1.mjs";
|
|
2
2
|
export { HookSystem, afterCreate, afterDelete, afterUpdate, beforeCreate, beforeDelete, beforeUpdate, createHookSystem, defineHook };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { i as createIdempotencyResult, n as IdempotencyResult, r as IdempotencyStore, t as IdempotencyLock } from "../interface-
|
|
2
|
-
import { n as MongoIdempotencyStoreOptions } from "../mongodb-
|
|
3
|
-
import { r as RedisIdempotencyStoreOptions, t as RedisClient } from "../redis-
|
|
1
|
+
import { i as createIdempotencyResult, n as IdempotencyResult, r as IdempotencyStore, t as IdempotencyLock } from "../interface-CkkWm5uR.mjs";
|
|
2
|
+
import { n as MongoIdempotencyStoreOptions } from "../mongodb-NShVZDMr.mjs";
|
|
3
|
+
import { r as RedisIdempotencyStoreOptions, t as RedisClient } from "../redis-Bunu3qWg.mjs";
|
|
4
4
|
import { FastifyPluginAsync } from "fastify";
|
|
5
5
|
|
|
6
6
|
//#region src/idempotency/idempotencyPlugin.d.ts
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as MongoIdempotencyStoreOptions, t as MongoIdempotencyStore } from "../mongodb-
|
|
1
|
+
import { n as MongoIdempotencyStoreOptions, t as MongoIdempotencyStore } from "../mongodb-NShVZDMr.mjs";
|
|
2
2
|
export { MongoIdempotencyStore, type MongoIdempotencyStoreOptions };
|
|
@@ -9,9 +9,7 @@ var MongoIdempotencyStore = class {
|
|
|
9
9
|
this.connection = options.connection;
|
|
10
10
|
this.collectionName = options.collection ?? "arc_idempotency";
|
|
11
11
|
this.ttlMs = options.ttlMs ?? 864e5;
|
|
12
|
-
if (options.createIndex !== false) this.ensureIndex().catch((
|
|
13
|
-
console.warn("[MongoIdempotencyStore] Failed to create index:", err);
|
|
14
|
-
});
|
|
12
|
+
if (options.createIndex !== false) this.ensureIndex().catch(() => {});
|
|
15
13
|
}
|
|
16
14
|
get collection() {
|
|
17
15
|
return this.connection.db.collection(this.collectionName);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as RedisIdempotencyStore, r as RedisIdempotencyStoreOptions, t as RedisClient } from "../redis-
|
|
1
|
+
import { n as RedisIdempotencyStore, r as RedisIdempotencyStoreOptions, t as RedisClient } from "../redis-Bunu3qWg.mjs";
|
|
2
2
|
export { type RedisClient, RedisIdempotencyStore, type RedisIdempotencyStoreOptions };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Y as OpenApiSchemas, Yt as CrudRepository, Z as ParsedQuery, c as ValidationResult, n as AdapterSchemaContext, nt as QueryParserInterface, o as RepositoryLike, r as DataAdapter, s as SchemaMetadata, vt as RouteSchemaOptions } from "./interface-IJqN3pXK.mjs";
|
|
2
2
|
import { Model } from "mongoose";
|
|
3
3
|
|
|
4
4
|
//#region src/adapters/mongoose.d.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { r as RequestScope } from "./types
|
|
2
|
-
import { n as PermissionContext, r as PermissionResult, t as PermissionCheck } from "./types-
|
|
3
|
-
import { i as CacheStore, t as CacheLogger } from "./interface-
|
|
1
|
+
import { r as RequestScope } from "./types-CN6JvmYz.mjs";
|
|
2
|
+
import { n as PermissionContext, r as PermissionResult, t as PermissionCheck } from "./types-BoaZHr-2.mjs";
|
|
3
|
+
import { i as CacheStore, t as CacheLogger } from "./interface-bpoLKKqx.mjs";
|
|
4
4
|
import { FastifyRequest } from "fastify";
|
|
5
5
|
|
|
6
6
|
//#region src/permissions/applyPermissionResult.d.ts
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { r as RequestScope } from "./types
|
|
2
|
-
import {
|
|
3
|
-
import { t as PermissionCheck } from "./types-
|
|
1
|
+
import { r as RequestScope } from "./types-CN6JvmYz.mjs";
|
|
2
|
+
import { D as CrudRouterOptions, Ht as IControllerResponse, N as FastifyWithDecorators, T as CrudController, Ut as IRequestContext, Vt as IController, ct as RequestWithExtras, m as AnyRecord, ot as RequestContext, qt as ResourceDefinition, ut as ResourceConfig } from "./interface-IJqN3pXK.mjs";
|
|
3
|
+
import { t as PermissionCheck } from "./types-BoaZHr-2.mjs";
|
|
4
4
|
import { FastifyInstance, FastifyReply, FastifyRequest, RouteHandlerMethod } from "fastify";
|
|
5
5
|
|
|
6
6
|
//#region src/constants.d.ts
|
|
@@ -60,7 +60,7 @@ declare const RESERVED_QUERY_PARAMS: Readonly<Set<string>>;
|
|
|
60
60
|
* @param req - Full Fastify request object
|
|
61
61
|
* @returns Action result (will be wrapped in success response)
|
|
62
62
|
*/
|
|
63
|
-
type ActionHandler<TData =
|
|
63
|
+
type ActionHandler<TData = Record<string, unknown>, TResult = unknown> = (id: string, data: TData, req: RequestWithExtras) => Promise<TResult>;
|
|
64
64
|
/**
|
|
65
65
|
* Action router configuration
|
|
66
66
|
*/
|
|
@@ -68,31 +68,31 @@ interface ActionRouterConfig {
|
|
|
68
68
|
/**
|
|
69
69
|
* OpenAPI tag for grouping routes
|
|
70
70
|
*/
|
|
71
|
-
tag?: string;
|
|
71
|
+
readonly tag?: string;
|
|
72
72
|
/**
|
|
73
73
|
* Action handlers map
|
|
74
74
|
* @example { approve: (id, data, req) => service.approve(id), ... }
|
|
75
75
|
*/
|
|
76
|
-
actions: Record<string, ActionHandler>;
|
|
76
|
+
readonly actions: Record<string, ActionHandler>;
|
|
77
77
|
/**
|
|
78
78
|
* Per-action permission checks (PermissionCheck functions)
|
|
79
79
|
* @example { approve: requireRoles(['admin', 'manager']), cancel: requireRoles(['admin']) }
|
|
80
80
|
*/
|
|
81
|
-
actionPermissions?: Record<string, PermissionCheck>;
|
|
81
|
+
readonly actionPermissions?: Record<string, PermissionCheck>;
|
|
82
82
|
/**
|
|
83
83
|
* Per-action JSON schema for body validation
|
|
84
84
|
* @example { dispatch: { transport: { type: 'object' } } }
|
|
85
85
|
*/
|
|
86
|
-
actionSchemas?: Record<string, Record<string,
|
|
86
|
+
readonly actionSchemas?: Record<string, Record<string, unknown>>;
|
|
87
87
|
/**
|
|
88
88
|
* Global permission check applied to all actions (if action-specific not defined)
|
|
89
89
|
*/
|
|
90
|
-
globalAuth?: PermissionCheck;
|
|
90
|
+
readonly globalAuth?: PermissionCheck;
|
|
91
91
|
/**
|
|
92
92
|
* Optional idempotency service
|
|
93
93
|
* If provided, will handle idempotency-key header
|
|
94
94
|
*/
|
|
95
|
-
idempotencyService?: IdempotencyService;
|
|
95
|
+
readonly idempotencyService?: IdempotencyService;
|
|
96
96
|
/**
|
|
97
97
|
* Custom error handler for action execution failures
|
|
98
98
|
* @param error - The error thrown by action handler
|
|
@@ -100,7 +100,7 @@ interface ActionRouterConfig {
|
|
|
100
100
|
* @param id - The resource ID
|
|
101
101
|
* @returns Status code and error response
|
|
102
102
|
*/
|
|
103
|
-
onError?: (error: Error, action: string, id: string) => {
|
|
103
|
+
readonly onError?: (error: Error, action: string, id: string) => {
|
|
104
104
|
statusCode: number;
|
|
105
105
|
error: string;
|
|
106
106
|
code?: string;
|
|
@@ -111,11 +111,11 @@ interface ActionRouterConfig {
|
|
|
111
111
|
* Apps can provide their own implementation
|
|
112
112
|
*/
|
|
113
113
|
interface IdempotencyService {
|
|
114
|
-
check(key: string, payload:
|
|
114
|
+
check(key: string, payload: unknown): Promise<{
|
|
115
115
|
isNew: boolean;
|
|
116
|
-
existingResult?:
|
|
116
|
+
existingResult?: unknown;
|
|
117
117
|
}>;
|
|
118
|
-
complete(key: string | undefined, result:
|
|
118
|
+
complete(key: string | undefined, result: unknown): Promise<void>;
|
|
119
119
|
fail(key: string | undefined, error: Error): Promise<void>;
|
|
120
120
|
}
|
|
121
121
|
/**
|
package/dist/index.d.mts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { $ as
|
|
2
|
-
import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, t as FieldPermission } from "./fields-
|
|
3
|
-
import { i as UserBase, n as PermissionContext, r as PermissionResult, t as PermissionCheck } from "./types-
|
|
4
|
-
import { l as createMongooseAdapter, o as createPrismaAdapter, s as MongooseAdapter, t as PrismaAdapter } from "./index-
|
|
5
|
-
import { A as MutationOperation, C as HOOK_PHASES, D as MAX_REGEX_LENGTH, E as MAX_FILTER_DEPTH, M as SYSTEM_FIELDS, O as MAX_SEARCH_LENGTH, S as HOOK_OPERATIONS, T as HookPhase, _ as DEFAULT_LIMIT, a as getControllerScope, b as DEFAULT_TENANT_FIELD, g as DEFAULT_ID_FIELD, h as CrudOperation, j as RESERVED_QUERY_PARAMS, k as MUTATION_OPERATIONS, m as CRUD_OPERATIONS, s as defineResourceVariants, v as DEFAULT_MAX_LIMIT, w as HookOperation, x as DEFAULT_UPDATE_METHOD, y as DEFAULT_SORT } from "./index-
|
|
6
|
-
import { C as authenticated, D as publicRead, E as presets_d_exports, O as publicReadAdminWrite, S as adminOnly, T as ownerWithAdminBypass, _ as requireScopeContext, a as allOf, c as createDynamicPermissionMatrix, d as requireAuth, f as requireOrgInScope, g as requireRoles, h as requireOwnership, k as readOnly, l as createOrgPermissions, m as requireOrgRole, n as DynamicPermissionMatrix, o as allowPublic, p as requireOrgMembership, r as DynamicPermissionMatrixConfig, s as anyOf, u as denyAll, v as requireServiceScope, w as fullPublic, x as when, y as requireTeamMembership } from "./index-
|
|
7
|
-
import { a as NotFoundError, d as ValidationError, f as createDomainError, i as ForbiddenError, t as ArcError, u as UnauthorizedError } from "./errors-
|
|
1
|
+
import { $ as PresetFunction, $t as QueryOptions, At as BaseController, B as InferResourceDoc, C as ConfigError, Ct as TypedResourceConfig, D as CrudRouterOptions, Dt as ValidationResult$1, E as CrudRouteKey, Et as ValidateOptions, F as GracefulShutdownOptions, H as IntrospectionPluginOptions, Ht as IControllerResponse, I as HealthCheck, Jt as defineResource, K as MiddlewareConfig, L as HealthOptions, M as FastifyWithAuth, N as FastifyWithDecorators, O as CrudSchemas, Ot as envelope, P as FieldRule, R as InferAdapterDoc, St as TypedRepository, T as CrudController, Tt as UserOrganization, U as JWTPayload, Ut as IRequestContext, V as IntrospectionData, Vt as IController, Wt as RouteHandler, X as OwnershipCheck, Yt as CrudRepository, Zt as PaginatedResult, _ as ArcInternalMetadata, a as RelationMetadata, an as PipelineContext, at as RegistryStats, b as AuthPluginOptions, c as ValidationResult, ct as RequestWithExtras, en as Guard, gt as RouteHandlerMethod, h as ApiResponse, i as FieldMetadata, in as PipelineConfig, it as RegistryEntry, j as FastifyRequestExtras, jt as BaseControllerOptions, k as EventDefinition, m as AnyRecord, nn as NextFunction, o as RepositoryLike, on as PipelineStep, ot as RequestContext, p as AdditionalRoute, pt as ResourceMetadata, q as MiddlewareHandler, qt as ResourceDefinition, r as DataAdapter, rn as OperationFilter, rt as RateLimitConfig, s as SchemaMetadata, sn as Transform, st as RequestIdOptions, tn as Interceptor, tt as PresetResult, ut as ResourceConfig, v as ArcRequest, vt as RouteSchemaOptions, xt as TypedController, yt as ServiceContext, z as InferDocType, zt as ControllerLike } from "./interface-IJqN3pXK.mjs";
|
|
2
|
+
import { a as applyFieldWritePermissions, i as applyFieldReadPermissions, n as FieldPermissionMap, o as fields, t as FieldPermission } from "./fields-DoeDgh2b.mjs";
|
|
3
|
+
import { i as UserBase, n as PermissionContext, r as PermissionResult, t as PermissionCheck } from "./types-BoaZHr-2.mjs";
|
|
4
|
+
import { l as createMongooseAdapter, o as createPrismaAdapter, s as MongooseAdapter, t as PrismaAdapter } from "./index-BpMhrFgn.mjs";
|
|
5
|
+
import { A as MutationOperation, C as HOOK_PHASES, D as MAX_REGEX_LENGTH, E as MAX_FILTER_DEPTH, M as SYSTEM_FIELDS, O as MAX_SEARCH_LENGTH, S as HOOK_OPERATIONS, T as HookPhase, _ as DEFAULT_LIMIT, a as getControllerScope, b as DEFAULT_TENANT_FIELD, g as DEFAULT_ID_FIELD, h as CrudOperation, j as RESERVED_QUERY_PARAMS, k as MUTATION_OPERATIONS, m as CRUD_OPERATIONS, s as defineResourceVariants, v as DEFAULT_MAX_LIMIT, w as HookOperation, x as DEFAULT_UPDATE_METHOD, y as DEFAULT_SORT } from "./index-qct60lnl.mjs";
|
|
6
|
+
import { C as authenticated, D as publicRead, E as presets_d_exports, O as publicReadAdminWrite, S as adminOnly, T as ownerWithAdminBypass, _ as requireScopeContext, a as allOf, c as createDynamicPermissionMatrix, d as requireAuth, f as requireOrgInScope, g as requireRoles, h as requireOwnership, k as readOnly, l as createOrgPermissions, m as requireOrgRole, n as DynamicPermissionMatrix, o as allowPublic, p as requireOrgMembership, r as DynamicPermissionMatrixConfig, s as anyOf, u as denyAll, v as requireServiceScope, w as fullPublic, x as when, y as requireTeamMembership } from "./index-CBru2y5Y.mjs";
|
|
7
|
+
import { a as NotFoundError, d as ValidationError, f as createDomainError, i as ForbiddenError, t as ArcError, u as UnauthorizedError } from "./errors-BI8kEKsO.mjs";
|
|
8
8
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
9
9
|
import { RouteHandlerMethod as RouteHandlerMethod$1 } from "fastify";
|
|
10
10
|
|
package/dist/index.mjs
CHANGED
|
@@ -3,12 +3,12 @@ import { a as createMongooseAdapter, i as MongooseAdapter, r as createPrismaAdap
|
|
|
3
3
|
import { t as BaseController } from "./BaseController-CpMfCXdn.mjs";
|
|
4
4
|
import { envelope } from "./types/index.mjs";
|
|
5
5
|
import { n as applyFieldWritePermissions, r as fields, t as applyFieldReadPermissions } from "./fields-ipsbIRPK.mjs";
|
|
6
|
-
import { t as defineResourceVariants } from "./core-BWekSEju.mjs";
|
|
7
6
|
import { t as requestContext } from "./requestContext-xHIKedG6.mjs";
|
|
8
7
|
import { d as createDomainError, i as NotFoundError, l as UnauthorizedError, r as ForbiddenError, t as ArcError, u as ValidationError } from "./errors-Cg58SLNi.mjs";
|
|
9
|
-
import { a as validateResourceConfig, f as getControllerScope, i as formatValidationErrors, m as pipe, n as defineResource, r as assertValidConfig, t as ResourceDefinition } from "./defineResource-
|
|
8
|
+
import { a as validateResourceConfig, f as getControllerScope, i as formatValidationErrors, m as pipe, n as defineResource, r as assertValidConfig, t as ResourceDefinition } from "./defineResource-CovBXvTB.mjs";
|
|
10
9
|
import { C as publicRead, S as presets_exports, T as readOnly, _ as when, a as createOrgPermissions, b as fullPublic, c as requireOrgInScope, d as requireOwnership, f as requireRoles, h as requireTeamMembership, i as createDynamicPermissionMatrix, l as requireOrgMembership, m as requireServiceScope, n as allowPublic, o as denyAll, p as requireScopeContext, r as anyOf, s as requireAuth, t as allOf, u as requireOrgRole, v as adminOnly, w as publicReadAdminWrite, x as ownerWithAdminBypass, y as authenticated } from "./permissions-CH4cNwJi.mjs";
|
|
11
|
-
import {
|
|
10
|
+
import { t as defineResourceVariants } from "./core-BfrfxNqO.mjs";
|
|
11
|
+
import { n as configureArcLogger, t as arcLog } from "./logger-CDjpjySd.mjs";
|
|
12
12
|
//#region src/middleware/middleware.ts
|
|
13
13
|
/**
|
|
14
14
|
* Named Middleware — Priority-based, conditional middleware execution.
|
|
@@ -128,6 +128,6 @@ function transform(name, handlerOrOptions) {
|
|
|
128
128
|
}
|
|
129
129
|
//#endregion
|
|
130
130
|
//#region src/index.ts
|
|
131
|
-
const version = "2.
|
|
131
|
+
const version = "2.8.0";
|
|
132
132
|
//#endregion
|
|
133
133
|
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, createDomainError, createDynamicPermissionMatrix, createMongooseAdapter, createOrgPermissions, createPrismaAdapter, defineResource, defineResourceVariants, denyAll, envelope, fields, formatValidationErrors, fullPublic, getControllerScope, guard, intercept, middleware, ownerWithAdminBypass, presets_exports as permissions, pipe, publicRead, publicReadAdminWrite, readOnly, requestContext, requireAuth, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, sortMiddlewares, transform, validateResourceConfig, version, when };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as DomainEvent } from "../EventTransport-
|
|
1
|
+
import { t as DomainEvent } from "../EventTransport-n1KBxC_N.mjs";
|
|
2
2
|
import { WebSocketClient, WebSocketMessage } from "./websocket.mjs";
|
|
3
3
|
import { FastifyPluginAsync, FastifyRequest } from "fastify";
|
|
4
4
|
|
|
@@ -4,7 +4,7 @@ const eventGatewayPluginImpl = async (fastify, opts = {}) => {
|
|
|
4
4
|
const { auth = true, orgScoped = false, roomPolicy, maxMessageBytes, maxSubscriptionsPerClient, authenticate } = opts;
|
|
5
5
|
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.");
|
|
6
6
|
if (opts.sse !== false) {
|
|
7
|
-
const { default: ssePlugin } = await import("../sse-
|
|
7
|
+
const { default: ssePlugin } = await import("../sse-CD5Hghpu.mjs").then((n) => n.r);
|
|
8
8
|
await fastify.register(ssePlugin, {
|
|
9
9
|
path: opts.sse?.path ?? "/events/stream",
|
|
10
10
|
requireAuth: auth,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { WebSocketClient, WebSocketMessage, WebSocketPluginOptions } from "./websocket.mjs";
|
|
2
2
|
import { EventGatewayOptions } from "./event-gateway.mjs";
|
|
3
3
|
import { JobDefinition, JobDispatchOptions, JobDispatcher, JobMeta, JobsPluginOptions, QueueStats } from "./jobs.mjs";
|
|
4
|
-
import { c as McpResourceConfig, f as ToolAnnotations, i as CrudOperation, l as PromptDefinition, m as ToolDefinition, n as CallToolResult, o as McpAuthResult, p as ToolContext, r as CreateMcpServerConfig, s as McpPluginOptions, t as BetterAuthHandler } from "../types-
|
|
4
|
+
import { c as McpResourceConfig, f as ToolAnnotations, i as CrudOperation, l as PromptDefinition, m as ToolDefinition, n as CallToolResult, o as McpAuthResult, p as ToolContext, r as CreateMcpServerConfig, s as McpPluginOptions, t as BetterAuthHandler } from "../types-Ct0PUUSp.mjs";
|
|
5
5
|
import { StreamlinePluginOptions, WorkflowLike, WorkflowRunLike } from "./streamline.mjs";
|
|
6
6
|
import { WebhookDeliveryRecord, WebhookManager, WebhookPluginOptions, WebhookStore, WebhookSubscription } from "./webhooks.mjs";
|
|
7
7
|
export { type BetterAuthHandler, type CallToolResult, type CreateMcpServerConfig, type CrudOperation, type EventGatewayOptions, type JobDefinition, type JobDispatchOptions, type JobDispatcher, type JobMeta, type JobsPluginOptions, type McpAuthResult, type McpPluginOptions, type McpResourceConfig, type PromptDefinition, type QueueStats, type StreamlinePluginOptions, type ToolAnnotations, type ToolContext, type ToolDefinition, type WebSocketClient, type WebSocketMessage, type WebSocketPluginOptions, type WebhookDeliveryRecord, type WebhookManager, type WebhookPluginOptions, type WebhookStore, type WebhookSubscription, type WorkflowLike, type WorkflowRunLike };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as McpAuthResolver, c as McpResourceConfig, d as SessionEntry, f as ToolAnnotations, i as CrudOperation, l as PromptDefinition, m as ToolDefinition, n as CallToolResult, o as McpAuthResult, p as ToolContext, r as CreateMcpServerConfig, s as McpPluginOptions, t as BetterAuthHandler, u as PromptResult } from "../../types-
|
|
1
|
+
import { qt as ResourceDefinition } from "../../interface-IJqN3pXK.mjs";
|
|
2
|
+
import { a as McpAuthResolver, c as McpResourceConfig, d as SessionEntry, f as ToolAnnotations, i as CrudOperation, l as PromptDefinition, m as ToolDefinition, n as CallToolResult, o as McpAuthResult, p as ToolContext, r as CreateMcpServerConfig, s as McpPluginOptions, t as BetterAuthHandler, u as PromptResult } from "../../types-Ct0PUUSp.mjs";
|
|
3
3
|
import { FastifyPluginAsync } from "fastify";
|
|
4
4
|
import { z } from "zod";
|
|
5
5
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as fieldRulesToZod, r as createMcpServer, t as resourceToTools } from "../../resourceToTools-
|
|
1
|
+
import { n as fieldRulesToZod, r as createMcpServer, t as resourceToTools } from "../../resourceToTools-C_1SMiCz.mjs";
|
|
2
2
|
import { createHash } from "node:crypto";
|
|
3
3
|
import fp from "fastify-plugin";
|
|
4
4
|
//#region src/integrations/mcp/definePrompt.ts
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { r as createMcpServer, t as resourceToTools } from "../../resourceToTools-
|
|
1
|
+
import { r as createMcpServer, t as resourceToTools } from "../../resourceToTools-C_1SMiCz.mjs";
|
|
2
2
|
//#region src/integrations/mcp/testing.ts
|
|
3
3
|
/**
|
|
4
4
|
* @classytic/arc/mcp/testing — MCP Test Utilities
|
|
@@ -1,28 +1,44 @@
|
|
|
1
1
|
import { FastifyPluginAsync } from "fastify";
|
|
2
2
|
|
|
3
3
|
//#region src/integrations/streamline.d.ts
|
|
4
|
+
/** Start options — matches @classytic/streamline v2.1 StartOptions */
|
|
5
|
+
interface WorkflowStartOptions {
|
|
6
|
+
meta?: Record<string, unknown>;
|
|
7
|
+
idempotencyKey?: string;
|
|
8
|
+
priority?: number;
|
|
9
|
+
}
|
|
4
10
|
/** Minimal workflow interface — matches @classytic/streamline's createWorkflow() return */
|
|
5
11
|
interface WorkflowLike {
|
|
6
12
|
definition: {
|
|
7
13
|
id: string;
|
|
8
14
|
name?: string;
|
|
9
|
-
steps: Record<string, unknown
|
|
15
|
+
steps: Record<string, unknown> | unknown[];
|
|
10
16
|
};
|
|
11
17
|
engine: {
|
|
12
|
-
start(input: unknown,
|
|
18
|
+
start(input: unknown, options?: WorkflowStartOptions): Promise<WorkflowRunLike>;
|
|
13
19
|
execute(runId: string): Promise<WorkflowRunLike>;
|
|
14
20
|
resume(runId: string, payload?: unknown): Promise<WorkflowRunLike>;
|
|
15
21
|
cancel(runId: string): Promise<WorkflowRunLike>;
|
|
16
22
|
pause?(runId: string): Promise<WorkflowRunLike>;
|
|
17
23
|
rewindTo?(runId: string, stepId: string): Promise<WorkflowRunLike>;
|
|
18
24
|
get(runId: string): Promise<WorkflowRunLike | null>;
|
|
25
|
+
waitFor?(runId: string, options?: {
|
|
26
|
+
timeout?: number;
|
|
27
|
+
}): Promise<WorkflowRunLike>;
|
|
19
28
|
shutdown?(): void;
|
|
20
29
|
};
|
|
21
|
-
start(input: unknown,
|
|
30
|
+
start(input: unknown, options?: WorkflowStartOptions): Promise<WorkflowRunLike>;
|
|
22
31
|
resume(runId: string, payload?: unknown): Promise<WorkflowRunLike>;
|
|
23
32
|
cancel(runId: string): Promise<WorkflowRunLike>;
|
|
24
33
|
get(runId: string): Promise<WorkflowRunLike | null>;
|
|
25
34
|
shutdown?(): void;
|
|
35
|
+
/** Streamline container for event bridging (streamline >=2.1) */
|
|
36
|
+
container?: {
|
|
37
|
+
eventBus: {
|
|
38
|
+
on(event: string, listener: (...args: unknown[]) => void): void;
|
|
39
|
+
off(event: string, listener: (...args: unknown[]) => void): void;
|
|
40
|
+
};
|
|
41
|
+
};
|
|
26
42
|
}
|
|
27
43
|
interface WorkflowRunLike {
|
|
28
44
|
_id: string;
|
|
@@ -30,11 +46,14 @@ interface WorkflowRunLike {
|
|
|
30
46
|
status: string;
|
|
31
47
|
context?: unknown;
|
|
32
48
|
input?: unknown;
|
|
33
|
-
steps?:
|
|
49
|
+
steps?: unknown[];
|
|
34
50
|
error?: unknown;
|
|
51
|
+
idempotencyKey?: string;
|
|
52
|
+
priority?: number;
|
|
53
|
+
concurrencyKey?: string;
|
|
54
|
+
stepLogs?: unknown[];
|
|
35
55
|
createdAt?: Date;
|
|
36
56
|
updatedAt?: Date;
|
|
37
|
-
[key: string]: unknown;
|
|
38
57
|
}
|
|
39
58
|
interface StreamlinePluginOptions {
|
|
40
59
|
/** Array of workflows created with createWorkflow() */
|
|
@@ -43,8 +62,21 @@ interface StreamlinePluginOptions {
|
|
|
43
62
|
prefix?: string;
|
|
44
63
|
/** Require authentication for all workflow endpoints (default: true) */
|
|
45
64
|
auth?: boolean;
|
|
46
|
-
/** Connect workflow events to Arc's event bus (default: true) */
|
|
65
|
+
/** Connect workflow lifecycle events to Arc's event bus (default: true) */
|
|
47
66
|
bridgeEvents?: boolean;
|
|
67
|
+
/**
|
|
68
|
+
* Bridge step-level events (step:started, step:completed, step:failed) to Arc's event bus.
|
|
69
|
+
* Disabled by default — enable for dashboards or monitoring.
|
|
70
|
+
* Requires the workflow to expose `container.eventBus` (streamline >=2.1).
|
|
71
|
+
* @default false
|
|
72
|
+
*/
|
|
73
|
+
bridgeStepEvents?: boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Enable SSE streaming endpoint: GET /:workflowId/runs/:runId/stream
|
|
76
|
+
* Streams step-level events as Server-Sent Events for live UI updates.
|
|
77
|
+
* @default false
|
|
78
|
+
*/
|
|
79
|
+
enableStreaming?: boolean;
|
|
48
80
|
/** Custom permission check for workflow operations */
|
|
49
81
|
permissions?: {
|
|
50
82
|
start?: (request: unknown) => boolean | Promise<boolean>;
|
|
@@ -57,4 +89,4 @@ interface StreamlinePluginOptions {
|
|
|
57
89
|
/** Pluggable streamline integration for Arc */
|
|
58
90
|
declare const streamlinePlugin: FastifyPluginAsync<StreamlinePluginOptions>;
|
|
59
91
|
//#endregion
|
|
60
|
-
export { StreamlinePluginOptions, WorkflowLike, WorkflowRunLike, streamlinePlugin };
|
|
92
|
+
export { StreamlinePluginOptions, WorkflowLike, WorkflowRunLike, WorkflowStartOptions, streamlinePlugin };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
//#region src/integrations/streamline.ts
|
|
2
2
|
const streamlinePluginImpl = async (fastify, options) => {
|
|
3
|
-
const { workflows, prefix = "/workflows", auth = true, bridgeEvents = true, permissions: perms } = options;
|
|
3
|
+
const { workflows, prefix = "/workflows", auth = true, bridgeEvents = true, bridgeStepEvents = false, enableStreaming = false, permissions: perms } = options;
|
|
4
4
|
const registry = /* @__PURE__ */ new Map();
|
|
5
5
|
for (const wf of workflows) {
|
|
6
6
|
const id = wf.definition.id;
|
|
@@ -22,8 +22,12 @@ const streamlinePluginImpl = async (fastify, options) => {
|
|
|
22
22
|
success: false,
|
|
23
23
|
error: "Forbidden"
|
|
24
24
|
});
|
|
25
|
-
const { input, meta } = request.body ?? {};
|
|
26
|
-
const run = await wf.start(input,
|
|
25
|
+
const { input, meta, idempotencyKey, priority } = request.body ?? {};
|
|
26
|
+
const run = await wf.start(input, {
|
|
27
|
+
meta,
|
|
28
|
+
idempotencyKey,
|
|
29
|
+
priority
|
|
30
|
+
});
|
|
27
31
|
if (bridgeEvents && fastify.events?.publish) try {
|
|
28
32
|
await fastify.events.publish(`workflow.${id}.started`, {
|
|
29
33
|
runId: run._id,
|
|
@@ -105,6 +109,26 @@ const streamlinePluginImpl = async (fastify, options) => {
|
|
|
105
109
|
data: run
|
|
106
110
|
};
|
|
107
111
|
});
|
|
112
|
+
fastify.post(`${routePrefix}/runs/:runId/execute`, { preHandler: authPreHandler }, async (request, _reply) => {
|
|
113
|
+
const { runId } = request.params;
|
|
114
|
+
return {
|
|
115
|
+
success: true,
|
|
116
|
+
data: await wf.engine.execute(runId)
|
|
117
|
+
};
|
|
118
|
+
});
|
|
119
|
+
if (wf.engine.waitFor) fastify.get(`${routePrefix}/runs/:runId/wait`, { preHandler: authPreHandler }, async (request, reply) => {
|
|
120
|
+
if (!await checkPerm("get", request)) return reply.status(403).send({
|
|
121
|
+
success: false,
|
|
122
|
+
error: "Forbidden"
|
|
123
|
+
});
|
|
124
|
+
const { runId } = request.params;
|
|
125
|
+
const { timeout } = request.query ?? {};
|
|
126
|
+
const timeoutMs = timeout ? Number.parseInt(timeout, 10) : 3e4;
|
|
127
|
+
return {
|
|
128
|
+
success: true,
|
|
129
|
+
data: await wf.engine.waitFor(runId, { timeout: Math.min(timeoutMs, 12e4) })
|
|
130
|
+
};
|
|
131
|
+
});
|
|
108
132
|
if (wf.engine.pause) fastify.post(`${routePrefix}/runs/:runId/pause`, { preHandler: authPreHandler }, async (request, _reply) => {
|
|
109
133
|
const { runId } = request.params;
|
|
110
134
|
return {
|
|
@@ -124,6 +148,84 @@ const streamlinePluginImpl = async (fastify, options) => {
|
|
|
124
148
|
data: await wf.engine.rewindTo?.(runId, stepId)
|
|
125
149
|
};
|
|
126
150
|
});
|
|
151
|
+
if (bridgeStepEvents && wf.container?.eventBus && fastify.events?.publish) for (const eventName of [
|
|
152
|
+
"step:started",
|
|
153
|
+
"step:completed",
|
|
154
|
+
"step:failed",
|
|
155
|
+
"step:skipped",
|
|
156
|
+
"step:retry-scheduled"
|
|
157
|
+
]) wf.container.eventBus.on(eventName, (payload) => {
|
|
158
|
+
const p = payload;
|
|
159
|
+
fastify.events.publish(`workflow.${id}.${eventName}`, {
|
|
160
|
+
runId: p?.runId,
|
|
161
|
+
stepId: p?.stepId,
|
|
162
|
+
workflowId: id,
|
|
163
|
+
...p
|
|
164
|
+
}).catch((err) => {
|
|
165
|
+
fastify.log.warn({
|
|
166
|
+
err,
|
|
167
|
+
workflowId: id
|
|
168
|
+
}, `Failed to bridge ${eventName}`);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
if (enableStreaming && wf.container?.eventBus) fastify.get(`${routePrefix}/runs/:runId/stream`, { preHandler: authPreHandler }, async (request, reply) => {
|
|
172
|
+
if (!await checkPerm("get", request)) return reply.status(403).send({
|
|
173
|
+
success: false,
|
|
174
|
+
error: "Forbidden"
|
|
175
|
+
});
|
|
176
|
+
const { runId } = request.params;
|
|
177
|
+
if (!await wf.get(runId)) return reply.status(404).send({
|
|
178
|
+
success: false,
|
|
179
|
+
error: "Workflow run not found"
|
|
180
|
+
});
|
|
181
|
+
reply.raw.writeHead(200, {
|
|
182
|
+
"Content-Type": "text/event-stream",
|
|
183
|
+
"Cache-Control": "no-cache",
|
|
184
|
+
Connection: "keep-alive"
|
|
185
|
+
});
|
|
186
|
+
const events = [
|
|
187
|
+
"step:started",
|
|
188
|
+
"step:completed",
|
|
189
|
+
"step:failed",
|
|
190
|
+
"step:skipped",
|
|
191
|
+
"workflow:completed",
|
|
192
|
+
"workflow:failed",
|
|
193
|
+
"workflow:cancelled"
|
|
194
|
+
];
|
|
195
|
+
const listeners = [];
|
|
196
|
+
let closed = false;
|
|
197
|
+
const send = (event, data) => {
|
|
198
|
+
if (closed) return;
|
|
199
|
+
try {
|
|
200
|
+
reply.raw.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`);
|
|
201
|
+
} catch {
|
|
202
|
+
cleanup();
|
|
203
|
+
}
|
|
204
|
+
};
|
|
205
|
+
const cleanup = () => {
|
|
206
|
+
if (closed) return;
|
|
207
|
+
closed = true;
|
|
208
|
+
for (const { event, fn } of listeners) wf.container?.eventBus.off(event, fn);
|
|
209
|
+
listeners.length = 0;
|
|
210
|
+
try {
|
|
211
|
+
reply.raw.end();
|
|
212
|
+
} catch {}
|
|
213
|
+
};
|
|
214
|
+
for (const eventName of events) {
|
|
215
|
+
const fn = (payload) => {
|
|
216
|
+
const p = payload;
|
|
217
|
+
if (p?.runId !== runId) return;
|
|
218
|
+
send(eventName, p);
|
|
219
|
+
if (eventName === "workflow:completed" || eventName === "workflow:failed" || eventName === "workflow:cancelled") cleanup();
|
|
220
|
+
};
|
|
221
|
+
wf.container.eventBus.on(eventName, fn);
|
|
222
|
+
listeners.push({
|
|
223
|
+
event: eventName,
|
|
224
|
+
fn
|
|
225
|
+
});
|
|
226
|
+
}
|
|
227
|
+
request.raw.on("close", cleanup);
|
|
228
|
+
});
|
|
127
229
|
}
|
|
128
230
|
fastify.get(prefix, { preHandler: authPreHandler }, async () => {
|
|
129
231
|
return {
|
|
@@ -131,7 +233,7 @@ const streamlinePluginImpl = async (fastify, options) => {
|
|
|
131
233
|
data: Array.from(registry.entries()).map(([id, wf]) => ({
|
|
132
234
|
id,
|
|
133
235
|
name: wf.definition.name ?? id,
|
|
134
|
-
steps: Object.keys(wf.definition.steps)
|
|
236
|
+
steps: Array.isArray(wf.definition.steps) ? wf.definition.steps.map((s) => s.id ?? String(s)) : Object.keys(wf.definition.steps)
|
|
135
237
|
}))
|
|
136
238
|
};
|
|
137
239
|
});
|