@classytic/arc 2.17.0 → 2.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2,7 +2,7 @@ import { o as DEFAULT_TENANT_FIELD } from "./constants-TrJVIJl0.mjs";
2
2
  import { arcLog } from "./logger/index.mjs";
3
3
  import { d as createDomainError, f as createError, i as NotFoundError, r as ForbiddenError } from "./errors-j4aJm1Wg.mjs";
4
4
  import { b as isElevated, c as getOrgId } from "./types-Bi0r0vjG.mjs";
5
- import { I as simpleEqualityMatcher, b as ArcQueryParser, o as scheduleBackground, t as getUserId } from "./utils-CvD3glpM.mjs";
5
+ import { I as simpleEqualityMatcher, b as ArcQueryParser, o as scheduleBackground, t as getUserId } from "./utils-BMQK8mRl.mjs";
6
6
  import { w as BodySanitizer } from "./routerShared-nCyJGOKX.mjs";
7
7
  import { t as buildQueryKey } from "./keys-DopsCuyQ.mjs";
8
8
  //#region src/core/AccessControl.ts
@@ -1,5 +1,5 @@
1
1
  import { a as DEFAULT_SORT, c as HOOK_OPERATIONS, d as MAX_REGEX_LENGTH, f as MAX_SEARCH_LENGTH, h as SYSTEM_FIELDS, i as DEFAULT_MAX_LIMIT, l as HOOK_PHASES, m as RESERVED_QUERY_PARAMS, n as DEFAULT_ID_FIELD, o as DEFAULT_TENANT_FIELD, p as MUTATION_OPERATIONS, r as DEFAULT_LIMIT, s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS, u as MAX_FILTER_DEPTH } from "../constants-TrJVIJl0.mjs";
2
- import { a as BulkMixin, c as collectReadBlockedFields, i as SlugMixin, l as isFieldReadable, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, s as QueryResolver, t as BaseController, u as AccessControl } from "../BaseController-Dmeh4Y_y.mjs";
2
+ import { a as BulkMixin, c as collectReadBlockedFields, i as SlugMixin, l as isFieldReadable, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, s as QueryResolver, t as BaseController, u as AccessControl } from "../BaseController-CgHomZ4d.mjs";
3
3
  import { S as sendControllerResponse, _ as createCrudHandlers, b as getControllerContext, v as createFastifyHandler, w as BodySanitizer, x as getControllerScope, y as createRequestContext } from "../routerShared-nCyJGOKX.mjs";
4
- import { a as defineResource, c as createCrudRouter, i as defineResourceVariants, l as createPermissionMiddleware, n as getEntityIdField, o as ResourceDefinition, r as getEntityQuery, s as defineAction, t as getEntityId, u as defineAggregation } from "../core-DYJvu7aI.mjs";
4
+ import { a as defineResource, c as createCrudRouter, i as defineResourceVariants, l as createPermissionMiddleware, n as getEntityIdField, o as ResourceDefinition, r as getEntityQuery, s as defineAction, t as getEntityId, u as defineAggregation } from "../core-D8tpQ4ZL.mjs";
5
5
  export { AccessControl, BaseController, BaseCrudController, BodySanitizer, BulkMixin, CRUD_OPERATIONS, DEFAULT_ID_FIELD, DEFAULT_LIMIT, DEFAULT_MAX_LIMIT, DEFAULT_SORT, DEFAULT_TENANT_FIELD, DEFAULT_UPDATE_METHOD, HOOK_OPERATIONS, HOOK_PHASES, MAX_FILTER_DEPTH, MAX_REGEX_LENGTH, MAX_SEARCH_LENGTH, MUTATION_OPERATIONS, QueryResolver, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, SlugMixin, SoftDeleteMixin, TreeMixin, collectReadBlockedFields, createCrudHandlers, createCrudRouter, createFastifyHandler, createPermissionMiddleware, createRequestContext, defineAction, defineAggregation, defineResource, defineResourceVariants, getControllerContext, getControllerScope, getEntityId, getEntityIdField, getEntityQuery, isFieldReadable, sendControllerResponse };
@@ -1,7 +1,7 @@
1
1
  import { s as DEFAULT_UPDATE_METHOD, t as CRUD_OPERATIONS } from "./constants-TrJVIJl0.mjs";
2
2
  import { arcLog } from "./logger/index.mjs";
3
- import { N as assertValidConfig, f as getDefaultCrudSchemas, i as pipeUIMessageStreamToReply, r as isReadableStream } from "./utils-CvD3glpM.mjs";
4
- import { t as BaseController } from "./BaseController-Dmeh4Y_y.mjs";
3
+ import { N as assertValidConfig, f as getDefaultCrudSchemas, i as pipeUIMessageStreamToReply, r as isReadableStream } from "./utils-BMQK8mRl.mjs";
4
+ import { t as BaseController } from "./BaseController-CgHomZ4d.mjs";
5
5
  import { t as applyPresets } from "./presets-BYbPobbF.mjs";
6
6
  import { n as convertRouteSchema, t as convertOpenApiSchemas } from "./schemaConverter-De34B1ZG.mjs";
7
7
  import { t as hasEvents } from "./typeGuards-BzkXkvVv.mjs";
package/dist/index.mjs CHANGED
@@ -1,10 +1,10 @@
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-TrJVIJl0.mjs";
2
2
  import { d as createDomainError, i as NotFoundError, l as UnauthorizedError, r as ForbiddenError, t as ArcError, u as ValidationError } from "./errors-j4aJm1Wg.mjs";
3
- import { a as BulkMixin, i as SlugMixin, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, t as BaseController } from "./BaseController-Dmeh4Y_y.mjs";
3
+ import { a as BulkMixin, i as SlugMixin, n as TreeMixin, o as BaseCrudController, r as SoftDeleteMixin, t as BaseController } from "./BaseController-CgHomZ4d.mjs";
4
4
  import { C as requireAuth, D as when, M as applyFieldWritePermissions, N as fields, T as requireRoles, _ as requireTeamMembership, a as presets_exports, b as anyOf, c as readOnly, d as createOrgPermissions, f as requireOrgInScope, g as requireServiceScope, h as requireScopeContext, i as ownerWithAdminBypass, j as applyFieldReadPermissions, m as requireOrgRole, n as authenticated, o as publicRead, p as requireOrgMembership, r as fullPublic, s as publicReadAdminWrite, t as adminOnly, u as createDynamicPermissionMatrix, v as allOf, w as requireOwnership, x as denyAll, y as allowPublic } from "./permissions-B1Qy55fg.mjs";
5
5
  import { x as getControllerScope } from "./routerShared-nCyJGOKX.mjs";
6
- import { a as defineResource, i as defineResourceVariants, o as ResourceDefinition, s as defineAction, u as defineAggregation } from "./core-DYJvu7aI.mjs";
6
+ import { a as defineResource, i as defineResourceVariants, o as ResourceDefinition, s as defineAction, u as defineAggregation } from "./core-D8tpQ4ZL.mjs";
7
7
  //#region src/index.ts
8
- const version = "2.17.0";
8
+ const version = "2.17.1";
9
9
  //#endregion
10
10
  export { ArcError, BaseController, BaseCrudController, BulkMixin, 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, NotFoundError, RESERVED_QUERY_PARAMS, ResourceDefinition, SYSTEM_FIELDS, SlugMixin, SoftDeleteMixin, TreeMixin, UnauthorizedError, ValidationError, adminOnly, allOf, allowPublic, anyOf, applyFieldReadPermissions, applyFieldWritePermissions, authenticated, createDomainError, createDynamicPermissionMatrix, createOrgPermissions, defineAction, defineAggregation, defineResource, defineResourceVariants, denyAll, fields, fullPublic, getControllerScope, ownerWithAdminBypass, presets_exports as permissions, publicRead, publicReadAdminWrite, readOnly, requireAuth, requireOrgInScope, requireOrgMembership, requireOrgRole, requireOwnership, requireRoles, requireScopeContext, requireServiceScope, requireTeamMembership, version, when };
@@ -1,4 +1,4 @@
1
- import { a as defaultCrudDescription, c as mcpHandlerAdapter, d as toCallToolResult, f as toCallToolSuccess, h as resolveToolCollisions, i as fieldRulesToZod, l as permissionDeniedResult, m as createMcpServer, n as mcpPlugin, o as resolveCrudDescription, p as buildRequestContext, r as resourceToTools, s as invokeController, t as filterResourcesForMcp, u as toCallToolError } from "../../mcpPlugin-hZE00H74.mjs";
1
+ import { a as defaultCrudDescription, c as mcpHandlerAdapter, d as toCallToolResult, f as toCallToolSuccess, h as resolveToolCollisions, i as fieldRulesToZod, l as permissionDeniedResult, m as createMcpServer, n as mcpPlugin, o as resolveCrudDescription, p as buildRequestContext, r as resourceToTools, s as invokeController, t as filterResourcesForMcp, u as toCallToolError } from "../../mcpPlugin-C6FViZXw.mjs";
2
2
  //#region src/integrations/mcp/defineTool.ts
3
3
  /**
4
4
  * Define a type-safe MCP tool.
@@ -1,4 +1,4 @@
1
- import { m as createMcpServer, r as resourceToTools, t as filterResourcesForMcp } from "../../mcpPlugin-hZE00H74.mjs";
1
+ import { m as createMcpServer, r as resourceToTools, t as filterResourcesForMcp } from "../../mcpPlugin-C6FViZXw.mjs";
2
2
  //#region src/integrations/mcp/testing.ts
3
3
  /**
4
4
  * @classytic/arc/mcp/testing — MCP Test Utilities
@@ -1,5 +1,5 @@
1
1
  import { p as isArcError, t as ArcError } from "./errors-j4aJm1Wg.mjs";
2
- import { t as BaseController } from "./BaseController-Dmeh4Y_y.mjs";
2
+ import { t as BaseController } from "./BaseController-CgHomZ4d.mjs";
3
3
  import { L as normalizePermissionResult } from "./permissions-B1Qy55fg.mjs";
4
4
  import { t as executePipeline } from "./pipe-DiCyvyPN.mjs";
5
5
  import { f as resolvePipelineSteps } from "./routerShared-nCyJGOKX.mjs";
@@ -3,9 +3,9 @@ import { a as arcCorePlugin, i as _default, n as ArcCorePluginOptions, r as Plug
3
3
  import { _ as HealthOptions, a as MetricsCollector, c as metricsPlugin, d as ssePlugin, f as CachingOptions, g as HealthCheck, h as cachingPlugin, i as MetricEntry, l as SSEOptions, m as _default$1, n as _default$7, o as MetricsOptions, p as CachingRule, r as versioningPlugin, s as _default$4, t as VersioningOptions, u as _default$6, v as _default$3, y as healthPlugin } from "../versioning-5H4930tj.mjs";
4
4
  import { i as errorHandlerPlugin, n as ErrorMapper, r as defaultIsDuplicateKeyError, t as ErrorHandlerOptions } from "../errorHandler-DuqTqeqn.mjs";
5
5
  import { t as TracingOptions } from "../tracing-bRqqUxFO.mjs";
6
+ import * as _$node_stream0 from "node:stream";
6
7
  import { PaginatedResult } from "@classytic/repo-core/pagination";
7
8
  import { FastifyInstance, FastifyPluginAsync } from "fastify";
8
- import * as _$node_stream0 from "node:stream";
9
9
 
10
10
  //#region src/plugins/createPlugin.d.ts
11
11
  interface PluginResourceResult {
@@ -58,7 +58,7 @@ try {
58
58
  function createTracerProvider(options) {
59
59
  if (!isAvailable || !NodeTracerProvider || !BatchSpanProcessor || !OTLPTraceExporter) return null;
60
60
  const { serviceName = "@classytic/arc", serviceVersion, exporterUrl = "http://localhost:4318/v1/traces" } = options;
61
- const resolvedVersion = serviceVersion ?? "2.17.0";
61
+ const resolvedVersion = serviceVersion ?? "2.17.1";
62
62
  const exporter = new OTLPTraceExporter({ url: exporterUrl });
63
63
  const provider = new NodeTracerProvider({ resource: { attributes: {
64
64
  "service.name": serviceName,
@@ -1,5 +1,5 @@
1
1
  import { a as OrgAccessDeniedError, c as ServiceUnavailableError, d as createDomainError, f as createError, i as NotFoundError, l as UnauthorizedError, n as ConflictError, o as OrgRequiredError, p as isArcError, r as ForbiddenError, s as RateLimitError, t as ArcError, u as ValidationError } from "../errors-j4aJm1Wg.mjs";
2
- import { A as CircuitState, C as defineGuard, D as CircuitBreaker, E as withCompensation, F as validateResourceConfig, I as simpleEqualityMatcher, M as createCircuitBreakerRegistry, N as assertValidConfig, O as CircuitBreakerError, P as formatValidationErrors, S as handleRaw, T as defineCompensation, _ as paginationSchema, a as createStateMachine, b as ArcQueryParser, c as bareListResponse, d as errorDetailSchema, f as getDefaultCrudSchemas, g as offsetListResponse, h as listResponse, i as pipeUIMessageStreamToReply, j as createCircuitBreaker, k as CircuitBreakerRegistry, l as deleteResponse, m as keysetListResponse, n as UI_MESSAGE_STREAM_HEADERS, o as scheduleBackground, p as getListQueryParams, r as isReadableStream, s as aggregateListResponse, t as getUserId, u as errorContractSchema, v as queryParams, w as defineErrorMapper, x as createQueryParser, y as responses } from "../utils-CvD3glpM.mjs";
2
+ import { A as CircuitState, C as defineGuard, D as CircuitBreaker, E as withCompensation, F as validateResourceConfig, I as simpleEqualityMatcher, M as createCircuitBreakerRegistry, N as assertValidConfig, O as CircuitBreakerError, P as formatValidationErrors, S as handleRaw, T as defineCompensation, _ as paginationSchema, a as createStateMachine, b as ArcQueryParser, c as bareListResponse, d as errorDetailSchema, f as getDefaultCrudSchemas, g as offsetListResponse, h as listResponse, i as pipeUIMessageStreamToReply, j as createCircuitBreaker, k as CircuitBreakerRegistry, l as deleteResponse, m as keysetListResponse, n as UI_MESSAGE_STREAM_HEADERS, o as scheduleBackground, p as getListQueryParams, r as isReadableStream, s as aggregateListResponse, t as getUserId, u as errorContractSchema, v as queryParams, w as defineErrorMapper, x as createQueryParser, y as responses } from "../utils-BMQK8mRl.mjs";
3
3
  import { a as toJsonSchema, i as isZodSchema, n as convertRouteSchema, r as isJsonSchema, t as convertOpenApiSchemas } from "../schemaConverter-De34B1ZG.mjs";
4
4
  import { t as hasEvents } from "../typeGuards-BzkXkvVv.mjs";
5
5
  export { ArcError, ArcQueryParser, CircuitBreaker, CircuitBreakerError, CircuitBreakerRegistry, CircuitState, ConflictError, ForbiddenError, NotFoundError, OrgAccessDeniedError, OrgRequiredError, RateLimitError, ServiceUnavailableError, UI_MESSAGE_STREAM_HEADERS, UnauthorizedError, ValidationError, aggregateListResponse, assertValidConfig, bareListResponse, convertOpenApiSchemas, convertRouteSchema, createCircuitBreaker, createCircuitBreakerRegistry, createDomainError, createError, createQueryParser, createStateMachine, defineCompensation, defineErrorMapper, defineGuard, deleteResponse, errorContractSchema, errorDetailSchema, formatValidationErrors, getDefaultCrudSchemas, getListQueryParams, getUserId, handleRaw, hasEvents, isArcError, isJsonSchema, isReadableStream, isZodSchema, keysetListResponse, listResponse, offsetListResponse, paginationSchema, pipeUIMessageStreamToReply, queryParams, responses, scheduleBackground, simpleEqualityMatcher, toJsonSchema, validateResourceConfig, withCompensation };
@@ -3,6 +3,7 @@ import { arcLog } from "./logger/index.mjs";
3
3
  import { t as ArcError } from "./errors-j4aJm1Wg.mjs";
4
4
  import { r as getAvailablePresets } from "./presets-BYbPobbF.mjs";
5
5
  import { errorContractSchema as errorContractSchema$1, errorDetailSchema as errorDetailSchema$1 } from "@classytic/repo-core/errors";
6
+ import { Readable } from "node:stream";
6
7
  //#region src/utils/simpleEqualityMatcher.ts
7
8
  /**
8
9
  * `simpleEqualityMatcher` — a minimal, dialect-agnostic flat-key equality
@@ -1672,6 +1673,23 @@ function createStateMachine(name, transitions = {}, options = {}) {
1672
1673
  //#endregion
1673
1674
  //#region src/utils/streaming.ts
1674
1675
  /**
1676
+ * Streaming helpers — adapters between Web `ReadableStream` producers
1677
+ * (Vercel AI SDK, OpenAI SDK, `fetch().body`, hand-built `TransformStream`s)
1678
+ * and Fastify's raw Node-stream reply.
1679
+ *
1680
+ * Why this exists: returning a `ReadableStream<UIMessageChunk>` from a
1681
+ * `streamResponse: true` arc route used to crash with
1682
+ * `chunk must be a string or Buffer` because Fastify cannot serialise
1683
+ * `UIMessageChunk` JSON objects directly. Every arc-ai host (sniffer,
1684
+ * spawn, downstream) reimplemented the same `JsonToSseTransformStream` +
1685
+ * SSE header boilerplate. `pipeUIMessageStreamToReply()` is that
1686
+ * boilerplate, owned once.
1687
+ *
1688
+ * arc stays peer-coupled to nothing: the helper accepts any
1689
+ * `ReadableStream<unknown>` and JSON-stringifies each chunk. It works
1690
+ * with `UIMessageChunk` from the AI SDK without importing it.
1691
+ */
1692
+ /**
1675
1693
  * Canonical SSE headers for AI-SDK-style UI message streams.
1676
1694
  *
1677
1695
  * `x-vercel-ai-ui-message-stream: v1` is the marker the Vercel AI SDK
@@ -1715,43 +1733,37 @@ const UI_MESSAGE_STREAM_HEADERS = {
1715
1733
  */
1716
1734
  async function pipeUIMessageStreamToReply(reply, stream, options = {}) {
1717
1735
  const serialize = options.serialize ?? defaultSerialize;
1718
- const raw = reply.raw;
1719
- if (!raw.headersSent) {
1720
- const headers = options.headers ?? UI_MESSAGE_STREAM_HEADERS;
1721
- for (const [key, value] of Object.entries(headers)) raw.setHeader(key, value);
1722
- raw.statusCode = reply.statusCode;
1723
- raw.flushHeaders?.();
1724
- }
1736
+ const headers = options.headers ?? UI_MESSAGE_STREAM_HEADERS;
1737
+ for (const [key, value] of Object.entries(headers)) reply.header(key, value);
1725
1738
  const reader = stream.getReader();
1739
+ let cancelled = false;
1726
1740
  const onAbort = () => {
1741
+ cancelled = true;
1727
1742
  reader.cancel().catch(() => {});
1728
1743
  };
1729
1744
  reply.request.raw.once("close", onAbort);
1730
1745
  options.signal?.addEventListener("abort", onAbort, { once: true });
1731
- try {
1732
- while (true) {
1733
- const { value, done } = await reader.read();
1734
- if (done) break;
1735
- if (!raw.write(`data: ${serialize(value)}\n\n`)) await once(raw, "drain");
1746
+ async function* sseFrames() {
1747
+ try {
1748
+ while (true) {
1749
+ const { value, done } = await reader.read();
1750
+ if (done) break;
1751
+ yield `data: ${serialize(value)}\n\n`;
1752
+ }
1753
+ } catch (err) {
1754
+ if (!cancelled) yield `event: error\ndata: ${JSON.stringify({ message: String(err) })}\n\n`;
1755
+ } finally {
1756
+ reply.request.raw.removeListener("close", onAbort);
1757
+ options.signal?.removeEventListener("abort", onAbort);
1758
+ reader.releaseLock?.();
1736
1759
  }
1737
- } catch (err) {
1738
- if (!raw.writableEnded) raw.write(`event: error\ndata: ${JSON.stringify({ message: String(err) })}\n\n`);
1739
- throw err;
1740
- } finally {
1741
- reply.request.raw.removeListener("close", onAbort);
1742
- options.signal?.removeEventListener("abort", onAbort);
1743
- if (!raw.writableEnded) raw.end();
1744
- reader.releaseLock?.();
1745
1760
  }
1761
+ const nodeStream = Readable.from(sseFrames());
1762
+ await reply.send(nodeStream);
1746
1763
  }
1747
1764
  function defaultSerialize(chunk) {
1748
1765
  return typeof chunk === "string" ? chunk : JSON.stringify(chunk);
1749
1766
  }
1750
- function once(emitter, event) {
1751
- return new Promise((resolve) => {
1752
- emitter.once(event, () => resolve());
1753
- });
1754
- }
1755
1767
  /**
1756
1768
  * Heuristic — does this value look like a Web `ReadableStream`?
1757
1769
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classytic/arc",
3
- "version": "2.17.0",
3
+ "version": "2.17.1",
4
4
  "description": "Resource-oriented backend framework for Fastify - clean, minimal, powerful, tree-shakable",
5
5
  "type": "module",
6
6
  "exports": {