@jami-studio/core 0.92.31 → 0.92.33

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.
Files changed (37) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/core/CHANGELOG.md +12 -0
  3. package/corpus/core/package.json +1 -1
  4. package/corpus/core/src/deploy/build.ts +4234 -4127
  5. package/corpus/core/src/file-upload/types.ts +9 -0
  6. package/corpus/core/src/shared/global-scope.ts +32 -0
  7. package/corpus/core/src/shared/workspace-app-audience.ts +14 -3
  8. package/corpus/templates/analytics/changelog/2026-07-11-tracking-and-session-replay-ingest-endpoints-are-reachable-f.md +6 -0
  9. package/corpus/templates/analytics/package.json +9 -0
  10. package/corpus/templates/clips/actions/create-recording.ts +16 -1
  11. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +60 -14
  12. package/corpus/templates/clips/app/routes/record.tsx +35 -9
  13. package/corpus/templates/clips/changelog/2026-07-11-uploads-now-stream-straight-to-s3-compatible-storage-r2-s3-m.md +6 -0
  14. package/corpus/templates/clips/server/lib/s3-upload-provider.ts +256 -0
  15. package/corpus/templates/clips/server/lib/streaming-upload-mode.ts +9 -3
  16. package/corpus/templates/clips/server/lib/upload-chunk-limits.ts +19 -0
  17. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +15 -4
  18. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/reset-chunks.post.ts +49 -1
  19. package/dist/deploy/build.d.ts +37 -1
  20. package/dist/deploy/build.d.ts.map +1 -1
  21. package/dist/deploy/build.js +769 -676
  22. package/dist/deploy/build.js.map +1 -1
  23. package/dist/file-upload/types.d.ts +9 -0
  24. package/dist/file-upload/types.d.ts.map +1 -1
  25. package/dist/file-upload/types.js.map +1 -1
  26. package/dist/notifications/routes.d.ts +1 -1
  27. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  28. package/dist/resources/handlers.d.ts +1 -1
  29. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  30. package/dist/shared/global-scope.d.ts +4 -0
  31. package/dist/shared/global-scope.d.ts.map +1 -1
  32. package/dist/shared/global-scope.js +27 -0
  33. package/dist/shared/global-scope.js.map +1 -1
  34. package/dist/shared/workspace-app-audience.d.ts.map +1 -1
  35. package/dist/shared/workspace-app-audience.js +12 -3
  36. package/dist/shared/workspace-app-audience.js.map +1 -1
  37. package/package.json +1 -1
@@ -62,6 +62,15 @@ export interface FileUploadProvider {
62
62
  * during recording instead of assembling the full blob after stop().
63
63
  */
64
64
  resumable?: {
65
+ /**
66
+ * Provider-preferred chunk size in bytes. Servers surface this to upload
67
+ * clients so each relayed chunk maps to one provider part. S3-compatible
68
+ * multipart uploads require every part except the last to be >= 5 MiB
69
+ * (and R2 additionally requires uniform part sizes), so an S3-backed
70
+ * provider sets 5 MiB here while GCS-style providers can omit it and
71
+ * accept the client default.
72
+ */
73
+ preferredChunkBytes?: number;
65
74
  startSession(filename: string, mimeType: string, maxBytes: number): Promise<ResumableUploadSession>;
66
75
  relayChunk(session: ResumableUploadSession, contentRange: string, bytes: Uint8Array, options?: {
67
76
  mimeType?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/file-upload/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,eAAe;IAC9B,qBAAqB;IACrB,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC;IAC1B,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+FAA+F;IAC/F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4GAA4G;IAC5G,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,gDAAgD;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,0EAA0E;IAC1E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;qFAEqF;AACrF,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf;uEACmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,kBAAkB;IACjC,uCAAuC;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,YAAY,EAAE,MAAM,OAAO,CAAC;IAC5B;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAChD,wDAAwD;IACxD,MAAM,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC9D;;;;OAIG;IACH,SAAS,CAAC,EAAE;QACV,YAAY,CACV,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,sBAAsB,CAAC,CAAC;QACnC,UAAU,CACR,OAAO,EAAE,sBAAsB,EAC/B,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,UAAU,EACjB,OAAO,CAAC,EAAE;YAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,GAC9B,OAAO,CAAC,oBAAoB,CAAC,CAAC;QACjC,eAAe,CACb,OAAO,EAAE,sBAAsB,EAC/B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;YAAE,SAAS,CAAC,EAAE,OAAO,CAAC;YAAC,WAAW,CAAC,EAAE,OAAO,CAAA;SAAE,GACvD,OAAO,CAAC,MAAM,CAAC,CAAC;KACpB,CAAC;CACH"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/file-upload/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,eAAe;IAC9B,qBAAqB;IACrB,IAAI,EAAE,UAAU,GAAG,MAAM,CAAC;IAC1B,qDAAqD;IACrD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qEAAqE;IACrE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,+FAA+F;IAC/F,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,4GAA4G;IAC5G,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,gDAAgD;IAChD,GAAG,EAAE,MAAM,CAAC;IACZ,0EAA0E;IAC1E,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,4CAA4C;IAC5C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;qFAEqF;AACrF,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf;uEACmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,kBAAkB;IACjC,uCAAuC;IACvC,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,kFAAkF;IAClF,YAAY,EAAE,MAAM,OAAO,CAAC;IAC5B;;;OAGG;IACH,sBAAsB,CAAC,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC;IAChD,wDAAwD;IACxD,MAAM,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAC9D;;;;OAIG;IACH,SAAS,CAAC,EAAE;QACV;;;;;;;WAOG;QACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;QAC7B,YAAY,CACV,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,sBAAsB,CAAC,CAAC;QACnC,UAAU,CACR,OAAO,EAAE,sBAAsB,EAC/B,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,UAAU,EACjB,OAAO,CAAC,EAAE;YAAE,QAAQ,CAAC,EAAE,MAAM,CAAA;SAAE,GAC9B,OAAO,CAAC,oBAAoB,CAAC,CAAC;QACjC,eAAe,CACb,OAAO,EAAE,sBAAsB,EAC/B,QAAQ,EAAE,MAAM,EAChB,OAAO,CAAC,EAAE;YAAE,SAAS,CAAC,EAAE,OAAO,CAAC;YAAC,WAAW,CAAC,EAAE,OAAO,CAAA;SAAE,GACvD,OAAO,CAAC,MAAM,CAAC,CAAC;KACpB,CAAC;CACH"}
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/file-upload/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG","sourcesContent":["/**\r\n * File upload framework primitive.\r\n *\r\n * Templates call `uploadFile()` to upload a file and get back a URL.\r\n * The framework dispatches to whichever provider is registered (Builder.io\r\n * built-in, or a user-supplied one). If no provider is active, it falls back\r\n * to the SQL resources store — fine for dev, not recommended for production.\r\n */\r\n\r\nexport interface FileUploadInput {\r\n /** File contents. */\r\n data: Uint8Array | Buffer;\r\n /** Original filename, used for extension/display. */\r\n filename?: string;\r\n /** MIME type, e.g. \"image/png\". */\r\n mimeType?: string;\r\n /** Optional owner email for per-user scoping in fallback storage. */\r\n ownerEmail?: string;\r\n /** Builder.io upload hint: return one stable URL while compression finishes asynchronously. */\r\n stableUrl?: boolean;\r\n /** Builder.io upload hint: set false for internal artifacts that should not appear in the asset library. */\r\n recordAsset?: boolean;\r\n}\r\n\r\nexport interface FileUploadResult {\r\n /** Public URL where the file can be fetched. */\r\n url: string;\r\n /** Optional provider-specific id (e.g. resource id, Builder asset id). */\r\n id?: string;\r\n /** The provider that handled the upload. */\r\n provider: string;\r\n}\r\n\r\n/** Opaque session handle returned by {@link FileUploadProvider.resumable.startSession}.\r\n * `sessionId` is provider-specific (GCS Location URI, S3 UploadId, etc.).\r\n * `meta` holds any provider state needed for subsequent relay and complete calls. */\r\nexport interface ResumableUploadSession {\r\n sessionId: string;\r\n meta: Record<string, unknown>;\r\n}\r\n\r\nexport interface ResumableChunkResult {\r\n ok: boolean;\r\n status: number;\r\n /** Providers that need per-chunk state (e.g. S3 ETags) return updated meta\r\n * here; the chunk route merges it back into the stored session. */\r\n updatedMeta?: Record<string, unknown>;\r\n}\r\n\r\nexport interface FileUploadProvider {\r\n /** Unique id, e.g. \"builder\", \"s3\". */\r\n id: string;\r\n /** Human-readable name. */\r\n name: string;\r\n /** Returns true if this provider is configured from synchronous runtime state. */\r\n isConfigured: () => boolean;\r\n /**\r\n * Returns true if this provider is configured for the active request.\r\n * Use for DB-backed user/org/workspace secrets that require request context.\r\n */\r\n isConfiguredForRequest?: () => Promise<boolean>;\r\n /** Upload a file and return a URL. Throw on failure. */\r\n upload: (input: FileUploadInput) => Promise<FileUploadResult>;\r\n /**\r\n * Optional resumable/streaming upload capability.\r\n * When present, create-recording will initialise a session and stream chunks\r\n * during recording instead of assembling the full blob after stop().\r\n */\r\n resumable?: {\r\n startSession(\r\n filename: string,\r\n mimeType: string,\r\n maxBytes: number,\r\n ): Promise<ResumableUploadSession>;\r\n relayChunk(\r\n session: ResumableUploadSession,\r\n contentRange: string,\r\n bytes: Uint8Array,\r\n options?: { mimeType?: string },\r\n ): Promise<ResumableChunkResult>;\r\n completeSession(\r\n session: ResumableUploadSession,\r\n filename: string,\r\n options?: { stableUrl?: boolean; recordAsset?: boolean },\r\n ): Promise<string>;\r\n };\r\n}\r\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/file-upload/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG","sourcesContent":["/**\r\n * File upload framework primitive.\r\n *\r\n * Templates call `uploadFile()` to upload a file and get back a URL.\r\n * The framework dispatches to whichever provider is registered (Builder.io\r\n * built-in, or a user-supplied one). If no provider is active, it falls back\r\n * to the SQL resources store — fine for dev, not recommended for production.\r\n */\r\n\r\nexport interface FileUploadInput {\r\n /** File contents. */\r\n data: Uint8Array | Buffer;\r\n /** Original filename, used for extension/display. */\r\n filename?: string;\r\n /** MIME type, e.g. \"image/png\". */\r\n mimeType?: string;\r\n /** Optional owner email for per-user scoping in fallback storage. */\r\n ownerEmail?: string;\r\n /** Builder.io upload hint: return one stable URL while compression finishes asynchronously. */\r\n stableUrl?: boolean;\r\n /** Builder.io upload hint: set false for internal artifacts that should not appear in the asset library. */\r\n recordAsset?: boolean;\r\n}\r\n\r\nexport interface FileUploadResult {\r\n /** Public URL where the file can be fetched. */\r\n url: string;\r\n /** Optional provider-specific id (e.g. resource id, Builder asset id). */\r\n id?: string;\r\n /** The provider that handled the upload. */\r\n provider: string;\r\n}\r\n\r\n/** Opaque session handle returned by {@link FileUploadProvider.resumable.startSession}.\r\n * `sessionId` is provider-specific (GCS Location URI, S3 UploadId, etc.).\r\n * `meta` holds any provider state needed for subsequent relay and complete calls. */\r\nexport interface ResumableUploadSession {\r\n sessionId: string;\r\n meta: Record<string, unknown>;\r\n}\r\n\r\nexport interface ResumableChunkResult {\r\n ok: boolean;\r\n status: number;\r\n /** Providers that need per-chunk state (e.g. S3 ETags) return updated meta\r\n * here; the chunk route merges it back into the stored session. */\r\n updatedMeta?: Record<string, unknown>;\r\n}\r\n\r\nexport interface FileUploadProvider {\r\n /** Unique id, e.g. \"builder\", \"s3\". */\r\n id: string;\r\n /** Human-readable name. */\r\n name: string;\r\n /** Returns true if this provider is configured from synchronous runtime state. */\r\n isConfigured: () => boolean;\r\n /**\r\n * Returns true if this provider is configured for the active request.\r\n * Use for DB-backed user/org/workspace secrets that require request context.\r\n */\r\n isConfiguredForRequest?: () => Promise<boolean>;\r\n /** Upload a file and return a URL. Throw on failure. */\r\n upload: (input: FileUploadInput) => Promise<FileUploadResult>;\r\n /**\r\n * Optional resumable/streaming upload capability.\r\n * When present, create-recording will initialise a session and stream chunks\r\n * during recording instead of assembling the full blob after stop().\r\n */\r\n resumable?: {\r\n /**\r\n * Provider-preferred chunk size in bytes. Servers surface this to upload\r\n * clients so each relayed chunk maps to one provider part. S3-compatible\r\n * multipart uploads require every part except the last to be >= 5 MiB\r\n * (and R2 additionally requires uniform part sizes), so an S3-backed\r\n * provider sets 5 MiB here while GCS-style providers can omit it and\r\n * accept the client default.\r\n */\r\n preferredChunkBytes?: number;\r\n startSession(\r\n filename: string,\r\n mimeType: string,\r\n maxBytes: number,\r\n ): Promise<ResumableUploadSession>;\r\n relayChunk(\r\n session: ResumableUploadSession,\r\n contentRange: string,\r\n bytes: Uint8Array,\r\n options?: { mimeType?: string },\r\n ): Promise<ResumableChunkResult>;\r\n completeSession(\r\n session: ResumableUploadSession,\r\n filename: string,\r\n options?: { stableUrl?: boolean; recordAsset?: boolean },\r\n ): Promise<string>;\r\n };\r\n}\r\n"]}
@@ -28,7 +28,7 @@ export declare function createNotificationsHandler(): import("h3").EventHandlerW
28
28
  } | {
29
29
  count?: undefined;
30
30
  updated?: undefined;
31
- ok: boolean;
32
31
  error?: undefined;
32
+ ok: boolean;
33
33
  }>>;
34
34
  //# sourceMappingURL=routes.d.ts.map
@@ -73,6 +73,7 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
73
73
  offset?: unknown;
74
74
  limit?: unknown;
75
75
  }, {
76
+ deleted?: undefined;
76
77
  jobs: {
77
78
  id: string;
78
79
  name: string;
@@ -83,7 +84,6 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
83
84
  updatedAt: string;
84
85
  }[];
85
86
  total: number;
86
- deleted?: undefined;
87
87
  jobId?: undefined;
88
88
  } | {
89
89
  jobs?: undefined;
@@ -91,9 +91,9 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
91
91
  deleted: boolean;
92
92
  jobId: string;
93
93
  } | {
94
+ deleted?: undefined;
94
95
  jobs?: undefined;
95
96
  total?: undefined;
96
- deleted?: undefined;
97
97
  jobId?: undefined;
98
98
  hits: Record<string, unknown>[];
99
99
  offset: number;
@@ -49,8 +49,8 @@ export declare function handleUpdateResource(event: any): Promise<import("./stor
49
49
  }>;
50
50
  /** DELETE /_agent-native/resources/:id — delete a resource */
51
51
  export declare function handleDeleteResource(event: any): Promise<{
52
- error: string;
53
52
  ok?: undefined;
53
+ error: string;
54
54
  } | {
55
55
  error?: undefined;
56
56
  ok: boolean;
@@ -27,11 +27,11 @@ export declare function resolveAgentEngineApiKeyWriteTarget(event: H3Event, scop
27
27
  export declare function createAgentEngineApiKeyHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
28
28
  error: any;
29
29
  } | {
30
+ error?: undefined;
30
31
  ok: boolean;
31
32
  key: string;
32
33
  baseUrlKey?: string;
33
34
  scope: AgentEngineApiKeyScope;
34
- error?: undefined;
35
35
  }>>;
36
36
  export {};
37
37
  //# sourceMappingURL=agent-engine-api-key-route.d.ts.map
@@ -52,4 +52,8 @@ export declare function scopedGlobalKeyName(base: string): string;
52
52
  export declare function getScopedGlobal<T>(base: string, init: () => T): T;
53
53
  /** Test helper — delete the pinned singleton for `base` in the ACTIVE scope. */
54
54
  export declare function __deleteScopedGlobal(base: string): void;
55
+ /** Set (or clear with `null`) this module graph's baked env defaults. */
56
+ export declare function setModuleGraphEnvDefaults(defaults: Record<string, string> | null): void;
57
+ /** This module graph's baked default for `key`, or undefined. */
58
+ export declare function getModuleGraphEnvDefault(key: string): string | undefined;
55
59
  //# sourceMappingURL=global-scope.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"global-scope.d.ts","sourceRoot":"","sources":["../../src/shared/global-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAIH;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAGxD;AAED,0EAA0E;AAC1E,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAIjE;AAED,gFAAgF;AAChF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAGvD"}
1
+ {"version":3,"file":"global-scope.d.ts","sourceRoot":"","sources":["../../src/shared/global-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAIH;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,IAAI,CAGxD;AAED,0EAA0E;AAC1E,wBAAgB,gBAAgB,IAAI,MAAM,GAAG,IAAI,CAEhD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,GAAG,CAAC,CAIjE;AAED,gFAAgF;AAChF,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAGvD;AAqBD,yEAAyE;AACzE,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,GACtC,IAAI,CAGN;AAED,iEAAiE;AACjE,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAExE"}
@@ -67,4 +67,31 @@ export function __deleteScopedGlobal(base) {
67
67
  const key = Symbol.for(scopedGlobalKeyName(base));
68
68
  delete globalThis[key];
69
69
  }
70
+ /**
71
+ * Per-module-graph env defaults for unified workspace deployments.
72
+ *
73
+ * workerd has no filesystem and no ambient build env, so per-app workspace
74
+ * config (app id, base path, audience, public/protected route lists) must be
75
+ * baked into the artifact. It CANNOT go through `process.env`: the unified
76
+ * worker shares ONE `process.env` across every app's module graph, so the
77
+ * first app's baked values would poison every sibling (the exact issue-35
78
+ * class the scope id above exists for — observed live as every app stripping
79
+ * paths against dispatch's base path, 401ing all framework routes).
80
+ *
81
+ * Instead the generated scope-init module stores this graph's per-app values
82
+ * here (module scope = per app bundle), and env readers fall back to
83
+ * `getModuleGraphEnvDefault` when the ambient env lacks the key. Real runtime
84
+ * env still wins; dev/single-app graphs never set defaults, so behavior is
85
+ * unchanged there.
86
+ */
87
+ let moduleGraphEnvDefaults = null;
88
+ /** Set (or clear with `null`) this module graph's baked env defaults. */
89
+ export function setModuleGraphEnvDefaults(defaults) {
90
+ moduleGraphEnvDefaults =
91
+ defaults && Object.keys(defaults).length > 0 ? { ...defaults } : null;
92
+ }
93
+ /** This module graph's baked default for `key`, or undefined. */
94
+ export function getModuleGraphEnvDefault(key) {
95
+ return moduleGraphEnvDefaults?.[key];
96
+ }
70
97
  //# sourceMappingURL=global-scope.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"global-scope.js","sourceRoot":"","sources":["../../src/shared/global-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,IAAI,kBAAkB,GAAkB,IAAI,CAAC;AAE7C;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAiB;IAChD,MAAM,OAAO,GAAG,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AAChD,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,gBAAgB;IAC9B,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,kBAAkB,CAAC,CAAC,CAAC,GAAG,IAAI,SAAS,kBAAkB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAI,IAAY,EAAE,IAAa;IAC5D,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;IAClD,MAAM,CAAC,GAAG,UAAsD,CAAC;IACjE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;IAClD,OAAQ,UAAiD,CAAC,GAAG,CAAC,CAAC;AACjE,CAAC","sourcesContent":["/**\n * Per-module-graph global scope for globalThis-pinned framework registries.\n *\n * Why this exists: several framework registries (file-upload providers,\n * private-blob providers, shareable resources, event bus, notification\n * channels, tracking providers, secrets registry) pin their state on\n * `globalThis` so that multiple ESM graphs of ONE app (Vite dev + Nitro,\n * symlinked node_modules, dist/ vs src/) still share a single registry.\n *\n * On a unified workspace deployment (Cloudflare Pages `_worker.js` dispatcher\n * importing every app's worker into ONE isolate) that pinning goes too far:\n * each app's bundle keeps its own module graph — so module-scope state is\n * correctly per-app — but the `globalThis` pin collapses all apps' registries\n * into one shared map. Real-world failure: an upload POSTed to /assets was\n * served by the clips app's registered S3 provider (wrong object prefix).\n *\n * The fix: each app's generated worker entry calls `setGlobalScopeId(appId)`\n * from a scope-init module evaluated FIRST in the entry's import graph (ESM\n * evaluates imports depth-first in declaration order, so the scope is set\n * before any registry module initializes or registers built-ins). Registries\n * resolve their `globalThis` key LAZILY through `getScopedGlobal`, which\n * namespaces the key by the module graph's scope id. Result:\n *\n * - Unified worker: each app's core copy has its own scope id → per-app keys\n * → per-app registries. Cross-app state sharing is gone.\n * - Dev / single-app deployments: `setGlobalScopeId` is never called → keys\n * are unscoped → the original multi-graph dedupe behavior is preserved.\n *\n * This module must stay dependency-free: it is imported by the generated\n * scope-init module before anything else in the app bundle evaluates.\n */\n\nlet moduleGraphScopeId: string | null = null;\n\n/**\n * Set the global-registry scope for THIS module graph (this app's bundle).\n * Called by the generated worker entry's scope-init module on unified\n * workspace deployments. Pass `null` to clear (tests).\n */\nexport function setGlobalScopeId(id: string | null): void {\n const trimmed = typeof id === \"string\" ? id.trim() : \"\";\n moduleGraphScopeId = trimmed ? trimmed : null;\n}\n\n/** The active scope id for this module graph, or `null` when unscoped. */\nexport function getGlobalScopeId(): string | null {\n return moduleGraphScopeId;\n}\n\n/**\n * The fully-qualified global key name for `base` under the active scope.\n * Unscoped graphs get `base` unchanged, so existing dev-mode behavior\n * (one registry across all of an app's ESM graphs) is preserved.\n */\nexport function scopedGlobalKeyName(base: string): string {\n return moduleGraphScopeId ? `${base}::app:${moduleGraphScopeId}` : base;\n}\n\n/**\n * Lazily resolve (and initialize once) a globalThis-pinned singleton under\n * the scope-aware key for `base`. Registries MUST call this per access —\n * never capture the result in module scope — so a scope id set during\n * entry-module evaluation is honored by every later registration and read.\n */\nexport function getScopedGlobal<T>(base: string, init: () => T): T {\n const key = Symbol.for(scopedGlobalKeyName(base));\n const g = globalThis as unknown as Record<symbol, T | undefined>;\n return (g[key] ??= init());\n}\n\n/** Test helper — delete the pinned singleton for `base` in the ACTIVE scope. */\nexport function __deleteScopedGlobal(base: string): void {\n const key = Symbol.for(scopedGlobalKeyName(base));\n delete (globalThis as unknown as Record<symbol, unknown>)[key];\n}\n"]}
1
+ {"version":3,"file":"global-scope.js","sourceRoot":"","sources":["../../src/shared/global-scope.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,IAAI,kBAAkB,GAAkB,IAAI,CAAC;AAE7C;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,EAAiB;IAChD,MAAM,OAAO,GAAG,OAAO,EAAE,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACxD,kBAAkB,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AAChD,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,gBAAgB;IAC9B,OAAO,kBAAkB,CAAC;AAC5B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,OAAO,kBAAkB,CAAC,CAAC,CAAC,GAAG,IAAI,SAAS,kBAAkB,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1E,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAI,IAAY,EAAE,IAAa;IAC5D,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;IAClD,MAAM,CAAC,GAAG,UAAsD,CAAC;IACjE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC;IAClD,OAAQ,UAAiD,CAAC,GAAG,CAAC,CAAC;AACjE,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,IAAI,sBAAsB,GAAkC,IAAI,CAAC;AAEjE,yEAAyE;AACzE,MAAM,UAAU,yBAAyB,CACvC,QAAuC;IAEvC,sBAAsB;QACpB,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,QAAQ,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1E,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,wBAAwB,CAAC,GAAW;IAClD,OAAO,sBAAsB,EAAE,CAAC,GAAG,CAAC,CAAC;AACvC,CAAC","sourcesContent":["/**\n * Per-module-graph global scope for globalThis-pinned framework registries.\n *\n * Why this exists: several framework registries (file-upload providers,\n * private-blob providers, shareable resources, event bus, notification\n * channels, tracking providers, secrets registry) pin their state on\n * `globalThis` so that multiple ESM graphs of ONE app (Vite dev + Nitro,\n * symlinked node_modules, dist/ vs src/) still share a single registry.\n *\n * On a unified workspace deployment (Cloudflare Pages `_worker.js` dispatcher\n * importing every app's worker into ONE isolate) that pinning goes too far:\n * each app's bundle keeps its own module graph — so module-scope state is\n * correctly per-app — but the `globalThis` pin collapses all apps' registries\n * into one shared map. Real-world failure: an upload POSTed to /assets was\n * served by the clips app's registered S3 provider (wrong object prefix).\n *\n * The fix: each app's generated worker entry calls `setGlobalScopeId(appId)`\n * from a scope-init module evaluated FIRST in the entry's import graph (ESM\n * evaluates imports depth-first in declaration order, so the scope is set\n * before any registry module initializes or registers built-ins). Registries\n * resolve their `globalThis` key LAZILY through `getScopedGlobal`, which\n * namespaces the key by the module graph's scope id. Result:\n *\n * - Unified worker: each app's core copy has its own scope id → per-app keys\n * → per-app registries. Cross-app state sharing is gone.\n * - Dev / single-app deployments: `setGlobalScopeId` is never called → keys\n * are unscoped → the original multi-graph dedupe behavior is preserved.\n *\n * This module must stay dependency-free: it is imported by the generated\n * scope-init module before anything else in the app bundle evaluates.\n */\n\nlet moduleGraphScopeId: string | null = null;\n\n/**\n * Set the global-registry scope for THIS module graph (this app's bundle).\n * Called by the generated worker entry's scope-init module on unified\n * workspace deployments. Pass `null` to clear (tests).\n */\nexport function setGlobalScopeId(id: string | null): void {\n const trimmed = typeof id === \"string\" ? id.trim() : \"\";\n moduleGraphScopeId = trimmed ? trimmed : null;\n}\n\n/** The active scope id for this module graph, or `null` when unscoped. */\nexport function getGlobalScopeId(): string | null {\n return moduleGraphScopeId;\n}\n\n/**\n * The fully-qualified global key name for `base` under the active scope.\n * Unscoped graphs get `base` unchanged, so existing dev-mode behavior\n * (one registry across all of an app's ESM graphs) is preserved.\n */\nexport function scopedGlobalKeyName(base: string): string {\n return moduleGraphScopeId ? `${base}::app:${moduleGraphScopeId}` : base;\n}\n\n/**\n * Lazily resolve (and initialize once) a globalThis-pinned singleton under\n * the scope-aware key for `base`. Registries MUST call this per access —\n * never capture the result in module scope — so a scope id set during\n * entry-module evaluation is honored by every later registration and read.\n */\nexport function getScopedGlobal<T>(base: string, init: () => T): T {\n const key = Symbol.for(scopedGlobalKeyName(base));\n const g = globalThis as unknown as Record<symbol, T | undefined>;\n return (g[key] ??= init());\n}\n\n/** Test helper — delete the pinned singleton for `base` in the ACTIVE scope. */\nexport function __deleteScopedGlobal(base: string): void {\n const key = Symbol.for(scopedGlobalKeyName(base));\n delete (globalThis as unknown as Record<symbol, unknown>)[key];\n}\n\n/**\n * Per-module-graph env defaults for unified workspace deployments.\n *\n * workerd has no filesystem and no ambient build env, so per-app workspace\n * config (app id, base path, audience, public/protected route lists) must be\n * baked into the artifact. It CANNOT go through `process.env`: the unified\n * worker shares ONE `process.env` across every app's module graph, so the\n * first app's baked values would poison every sibling (the exact issue-35\n * class the scope id above exists for — observed live as every app stripping\n * paths against dispatch's base path, 401ing all framework routes).\n *\n * Instead the generated scope-init module stores this graph's per-app values\n * here (module scope = per app bundle), and env readers fall back to\n * `getModuleGraphEnvDefault` when the ambient env lacks the key. Real runtime\n * env still wins; dev/single-app graphs never set defaults, so behavior is\n * unchanged there.\n */\nlet moduleGraphEnvDefaults: Record<string, string> | null = null;\n\n/** Set (or clear with `null`) this module graph's baked env defaults. */\nexport function setModuleGraphEnvDefaults(\n defaults: Record<string, string> | null,\n): void {\n moduleGraphEnvDefaults =\n defaults && Object.keys(defaults).length > 0 ? { ...defaults } : null;\n}\n\n/** This module graph's baked default for `key`, or undefined. */\nexport function getModuleGraphEnvDefault(key: string): string | undefined {\n return moduleGraphEnvDefaults?.[key];\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-app-audience.d.ts","sourceRoot":"","sources":["../../src/shared/workspace-app-audience.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB,YAAI,UAAU,EAAE,QAAQ,CAAU,CAAC;AAEvE,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5E,eAAO,MAAM,8BAA8B,EAAE,oBAAiC,CAAC;AAE/E,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,OAAO,GACb,oBAAoB,CAEtB;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAyBtE;AAED,wBAAgB,2BAA2B,CACzC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACvC,oBAAoB,GAAG,SAAS,CAOlC;AAED,wBAAgB,8BAA8B,CAC5C,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACvC,uBAAuB,CAYzB;AAED,wBAAgB,mCAAmC,CACjD,GAAG,EAAE,OAAO,GACX,oBAAoB,GAAG,SAAS,CASlC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iCAAiC;IAChD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,wBAAgB,sCAAsC,CACpD,GAAG,EAAE,OAAO,GACX,iCAAiC,CAuBnC"}
1
+ {"version":3,"file":"workspace-app-audience.d.ts","sourceRoot":"","sources":["../../src/shared/workspace-app-audience.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,uBAAuB,YAAI,UAAU,EAAE,QAAQ,CAAU,CAAC;AAEvE,MAAM,MAAM,oBAAoB,GAAG,CAAC,OAAO,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5E,eAAO,MAAM,8BAA8B,EAAE,oBAAiC,CAAC;AAE/E,MAAM,WAAW,uBAAuB;IACtC,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B;AAED,wBAAgB,6BAA6B,CAC3C,KAAK,EAAE,OAAO,GACb,oBAAoB,CAEtB;AAED,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,CAyBtE;AAED,wBAAgB,2BAA2B,CACzC,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACvC,oBAAoB,GAAG,SAAS,CAYlC;AAED,wBAAgB,8BAA8B,CAC5C,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GACvC,uBAAuB,CAgBzB;AAED,wBAAgB,mCAAmC,CACjD,GAAG,EAAE,OAAO,GACX,oBAAoB,GAAG,SAAS,CASlC;AAED;;;;;;GAMG;AACH,MAAM,WAAW,iCAAiC;IAChD,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,wBAAgB,sCAAsC,CACpD,GAAG,EAAE,OAAO,GACX,iCAAiC,CAuBnC"}
@@ -1,3 +1,4 @@
1
+ import { getModuleGraphEnvDefault } from "./global-scope.js";
1
2
  export const WORKSPACE_APP_AUDIENCES = ["internal", "public"];
2
3
  export const DEFAULT_WORKSPACE_APP_AUDIENCE = "internal";
3
4
  export function normalizeWorkspaceAppAudience(value) {
@@ -32,18 +33,26 @@ export function normalizeWorkspaceAppPathList(value) {
32
33
  export function workspaceAppAudienceFromEnv(env) {
33
34
  const source = env ?? (typeof process !== "undefined" ? process.env : {});
34
35
  const raw = source.AGENT_NATIVE_WORKSPACE_APP_AUDIENCE ??
35
- source.VITE_AGENT_NATIVE_WORKSPACE_APP_AUDIENCE;
36
+ source.VITE_AGENT_NATIVE_WORKSPACE_APP_AUDIENCE ??
37
+ // Unified workerd deployments deliver per-app config via the module
38
+ // graph (shared process.env would cross-poison sibling apps).
39
+ (env === undefined
40
+ ? getModuleGraphEnvDefault("AGENT_NATIVE_WORKSPACE_APP_AUDIENCE")
41
+ : undefined);
36
42
  if (raw === undefined)
37
43
  return undefined;
38
44
  return normalizeWorkspaceAppAudience(raw);
39
45
  }
40
46
  export function workspaceAppRouteAccessFromEnv(env) {
41
47
  const source = env ?? (typeof process !== "undefined" ? process.env : {});
48
+ const moduleGraphFallback = (key) => env === undefined ? getModuleGraphEnvDefault(key) : undefined;
42
49
  return {
43
50
  publicPaths: normalizeWorkspaceAppPathList(source.AGENT_NATIVE_WORKSPACE_APP_PUBLIC_PATHS ??
44
- source.VITE_AGENT_NATIVE_WORKSPACE_APP_PUBLIC_PATHS),
51
+ source.VITE_AGENT_NATIVE_WORKSPACE_APP_PUBLIC_PATHS ??
52
+ moduleGraphFallback("AGENT_NATIVE_WORKSPACE_APP_PUBLIC_PATHS")),
45
53
  protectedPaths: normalizeWorkspaceAppPathList(source.AGENT_NATIVE_WORKSPACE_APP_PROTECTED_PATHS ??
46
- source.VITE_AGENT_NATIVE_WORKSPACE_APP_PROTECTED_PATHS),
54
+ source.VITE_AGENT_NATIVE_WORKSPACE_APP_PROTECTED_PATHS ??
55
+ moduleGraphFallback("AGENT_NATIVE_WORKSPACE_APP_PROTECTED_PATHS")),
47
56
  };
48
57
  }
49
58
  export function workspaceAppAudienceFromPackageJson(pkg) {
@@ -1 +1 @@
1
- {"version":3,"file":"workspace-app-audience.js","sourceRoot":"","sources":["../../src/shared/workspace-app-audience.ts"],"names":[],"mappings":"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","sourcesContent":["export const WORKSPACE_APP_AUDIENCES = [\"internal\", \"public\"] as const;\r\n\r\nexport type WorkspaceAppAudience = (typeof WORKSPACE_APP_AUDIENCES)[number];\r\n\r\nexport const DEFAULT_WORKSPACE_APP_AUDIENCE: WorkspaceAppAudience = \"internal\";\r\n\r\nexport interface WorkspaceAppRouteAccess {\r\n publicPaths: string[];\r\n protectedPaths: string[];\r\n}\r\n\r\nexport function normalizeWorkspaceAppAudience(\r\n value: unknown,\r\n): WorkspaceAppAudience {\r\n return value === \"public\" ? \"public\" : DEFAULT_WORKSPACE_APP_AUDIENCE;\r\n}\r\n\r\nexport function normalizeWorkspaceAppPathList(value: unknown): string[] {\r\n let rawPaths: unknown[] = [];\r\n if (Array.isArray(value)) {\r\n rawPaths = value;\r\n } else if (typeof value === \"string\") {\r\n const trimmed = value.trim();\r\n if (!trimmed) return [];\r\n try {\r\n const parsed = JSON.parse(trimmed);\r\n // When JSON parses to a non-array (e.g. a single quoted string\r\n // `\"/api\"`), use the parsed value, not the original quoted form —\r\n // otherwise the `/`-prefix filter below silently drops it.\r\n rawPaths = Array.isArray(parsed) ? parsed : [parsed];\r\n } catch {\r\n rawPaths = trimmed.split(\",\");\r\n }\r\n }\r\n\r\n const paths = rawPaths\r\n .map((entry) => (typeof entry === \"string\" ? entry.trim() : \"\"))\r\n .filter((entry) => entry.startsWith(\"/\"))\r\n .map((entry) =>\r\n entry.length > 1 && entry.endsWith(\"/\") ? entry.slice(0, -1) : entry,\r\n );\r\n return Array.from(new Set(paths));\r\n}\r\n\r\nexport function workspaceAppAudienceFromEnv(\r\n env?: Record<string, string | undefined>,\r\n): WorkspaceAppAudience | undefined {\r\n const source = env ?? (typeof process !== \"undefined\" ? process.env : {});\r\n const raw =\r\n source.AGENT_NATIVE_WORKSPACE_APP_AUDIENCE ??\r\n source.VITE_AGENT_NATIVE_WORKSPACE_APP_AUDIENCE;\r\n if (raw === undefined) return undefined;\r\n return normalizeWorkspaceAppAudience(raw);\r\n}\r\n\r\nexport function workspaceAppRouteAccessFromEnv(\r\n env?: Record<string, string | undefined>,\r\n): WorkspaceAppRouteAccess {\r\n const source = env ?? (typeof process !== \"undefined\" ? process.env : {});\r\n return {\r\n publicPaths: normalizeWorkspaceAppPathList(\r\n source.AGENT_NATIVE_WORKSPACE_APP_PUBLIC_PATHS ??\r\n source.VITE_AGENT_NATIVE_WORKSPACE_APP_PUBLIC_PATHS,\r\n ),\r\n protectedPaths: normalizeWorkspaceAppPathList(\r\n source.AGENT_NATIVE_WORKSPACE_APP_PROTECTED_PATHS ??\r\n source.VITE_AGENT_NATIVE_WORKSPACE_APP_PROTECTED_PATHS,\r\n ),\r\n };\r\n}\r\n\r\nexport function workspaceAppAudienceFromPackageJson(\r\n pkg: unknown,\r\n): WorkspaceAppAudience | undefined {\r\n const config = workspaceAppConfigFromPackageJson(pkg);\r\n const raw =\r\n config?.workspaceApp?.audience ??\r\n config?.workspace?.audience ??\r\n config?.audience ??\r\n config?.root?.workspaceAppAudience;\r\n if (raw === undefined) return undefined;\r\n return normalizeWorkspaceAppAudience(raw);\r\n}\r\n\r\n/**\r\n * Per-app route-access config read from a `package.json`. Each field is\r\n * `undefined` when the corresponding key is fully absent from every\r\n * supported alias chain — that lets callers distinguish \"user didn't say\"\r\n * from \"user set [] to clear inherited overrides\". `workspaceAppRouteAccess`\r\n * always emits a full `WorkspaceAppRouteAccess` for runtime consumption.\r\n */\r\nexport interface WorkspaceAppRouteAccessFromConfig {\r\n publicPaths?: string[];\r\n protectedPaths?: string[];\r\n}\r\n\r\nexport function workspaceAppRouteAccessFromPackageJson(\r\n pkg: unknown,\r\n): WorkspaceAppRouteAccessFromConfig {\r\n const config = workspaceAppConfigFromPackageJson(pkg);\r\n const rawPublic =\r\n config?.workspaceApp?.publicPaths ??\r\n config?.workspaceApp?.publicPagePaths ??\r\n config?.workspace?.publicPaths ??\r\n config?.publicPaths ??\r\n config?.root?.workspaceAppPublicPaths;\r\n const rawProtected =\r\n config?.workspaceApp?.protectedPaths ??\r\n config?.workspaceApp?.privatePaths ??\r\n config?.workspaceApp?.authRequiredPaths ??\r\n config?.workspace?.protectedPaths ??\r\n config?.protectedPaths ??\r\n config?.root?.workspaceAppProtectedPaths;\r\n return {\r\n ...(isPathConfigValueSet(rawPublic)\r\n ? { publicPaths: normalizeWorkspaceAppPathList(rawPublic) }\r\n : {}),\r\n ...(isPathConfigValueSet(rawProtected)\r\n ? { protectedPaths: normalizeWorkspaceAppPathList(rawProtected) }\r\n : {}),\r\n };\r\n}\r\n\r\n/**\r\n * Only treat a package.json field as \"explicitly set\" when its raw value is a\r\n * supported type — an array, a string, or explicit null. Garbage types like\r\n * `false`, `0`, or `{}` are ignored (left as undefined) so a typo such as\r\n * `\"publicPaths\": false` doesn't silently clear an inherited manifest\r\n * override. (`normalizeWorkspaceAppPathList` happily turns those into `[]`,\r\n * which without this guard would be indistinguishable from a deliberate\r\n * empty array.)\r\n */\r\nfunction isPathConfigValueSet(value: unknown): boolean {\r\n if (value === undefined) return false;\r\n if (value === null) return true;\r\n if (Array.isArray(value)) return true;\r\n return typeof value === \"string\";\r\n}\r\n\r\nfunction workspaceAppConfigFromPackageJson(pkg: unknown):\r\n | {\r\n root: Record<string, any>;\r\n workspaceApp?: Record<string, any>;\r\n workspace?: Record<string, any>;\r\n audience?: unknown;\r\n publicPaths?: unknown;\r\n protectedPaths?: unknown;\r\n }\r\n | undefined {\r\n if (!pkg || typeof pkg !== \"object\" || Array.isArray(pkg)) return undefined;\r\n const record = pkg as Record<string, any>;\r\n const config = record[\"agent-native\"] ?? record.agentNative;\r\n const nested =\r\n config && typeof config === \"object\" && !Array.isArray(config)\r\n ? (config as Record<string, any>)\r\n : {};\r\n const workspaceApp =\r\n nested.workspaceApp &&\r\n typeof nested.workspaceApp === \"object\" &&\r\n !Array.isArray(nested.workspaceApp)\r\n ? (nested.workspaceApp as Record<string, any>)\r\n : undefined;\r\n const workspace =\r\n nested.workspace &&\r\n typeof nested.workspace === \"object\" &&\r\n !Array.isArray(nested.workspace)\r\n ? (nested.workspace as Record<string, any>)\r\n : undefined;\r\n return {\r\n root: record,\r\n workspaceApp,\r\n workspace,\r\n audience: nested.audience,\r\n publicPaths: nested.publicPaths,\r\n protectedPaths: nested.protectedPaths,\r\n };\r\n}\r\n"]}
1
+ {"version":3,"file":"workspace-app-audience.js","sourceRoot":"","sources":["../../src/shared/workspace-app-audience.ts"],"names":[],"mappings":"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","sourcesContent":["import { getModuleGraphEnvDefault } from \"./global-scope.js\";\r\n\r\nexport const WORKSPACE_APP_AUDIENCES = [\"internal\", \"public\"] as const;\r\n\r\nexport type WorkspaceAppAudience = (typeof WORKSPACE_APP_AUDIENCES)[number];\r\n\r\nexport const DEFAULT_WORKSPACE_APP_AUDIENCE: WorkspaceAppAudience = \"internal\";\r\n\r\nexport interface WorkspaceAppRouteAccess {\r\n publicPaths: string[];\r\n protectedPaths: string[];\r\n}\r\n\r\nexport function normalizeWorkspaceAppAudience(\r\n value: unknown,\r\n): WorkspaceAppAudience {\r\n return value === \"public\" ? \"public\" : DEFAULT_WORKSPACE_APP_AUDIENCE;\r\n}\r\n\r\nexport function normalizeWorkspaceAppPathList(value: unknown): string[] {\r\n let rawPaths: unknown[] = [];\r\n if (Array.isArray(value)) {\r\n rawPaths = value;\r\n } else if (typeof value === \"string\") {\r\n const trimmed = value.trim();\r\n if (!trimmed) return [];\r\n try {\r\n const parsed = JSON.parse(trimmed);\r\n // When JSON parses to a non-array (e.g. a single quoted string\r\n // `\"/api\"`), use the parsed value, not the original quoted form —\r\n // otherwise the `/`-prefix filter below silently drops it.\r\n rawPaths = Array.isArray(parsed) ? parsed : [parsed];\r\n } catch {\r\n rawPaths = trimmed.split(\",\");\r\n }\r\n }\r\n\r\n const paths = rawPaths\r\n .map((entry) => (typeof entry === \"string\" ? entry.trim() : \"\"))\r\n .filter((entry) => entry.startsWith(\"/\"))\r\n .map((entry) =>\r\n entry.length > 1 && entry.endsWith(\"/\") ? entry.slice(0, -1) : entry,\r\n );\r\n return Array.from(new Set(paths));\r\n}\r\n\r\nexport function workspaceAppAudienceFromEnv(\r\n env?: Record<string, string | undefined>,\r\n): WorkspaceAppAudience | undefined {\r\n const source = env ?? (typeof process !== \"undefined\" ? process.env : {});\r\n const raw =\r\n source.AGENT_NATIVE_WORKSPACE_APP_AUDIENCE ??\r\n source.VITE_AGENT_NATIVE_WORKSPACE_APP_AUDIENCE ??\r\n // Unified workerd deployments deliver per-app config via the module\r\n // graph (shared process.env would cross-poison sibling apps).\r\n (env === undefined\r\n ? getModuleGraphEnvDefault(\"AGENT_NATIVE_WORKSPACE_APP_AUDIENCE\")\r\n : undefined);\r\n if (raw === undefined) return undefined;\r\n return normalizeWorkspaceAppAudience(raw);\r\n}\r\n\r\nexport function workspaceAppRouteAccessFromEnv(\r\n env?: Record<string, string | undefined>,\r\n): WorkspaceAppRouteAccess {\r\n const source = env ?? (typeof process !== \"undefined\" ? process.env : {});\r\n const moduleGraphFallback = (key: string) =>\r\n env === undefined ? getModuleGraphEnvDefault(key) : undefined;\r\n return {\r\n publicPaths: normalizeWorkspaceAppPathList(\r\n source.AGENT_NATIVE_WORKSPACE_APP_PUBLIC_PATHS ??\r\n source.VITE_AGENT_NATIVE_WORKSPACE_APP_PUBLIC_PATHS ??\r\n moduleGraphFallback(\"AGENT_NATIVE_WORKSPACE_APP_PUBLIC_PATHS\"),\r\n ),\r\n protectedPaths: normalizeWorkspaceAppPathList(\r\n source.AGENT_NATIVE_WORKSPACE_APP_PROTECTED_PATHS ??\r\n source.VITE_AGENT_NATIVE_WORKSPACE_APP_PROTECTED_PATHS ??\r\n moduleGraphFallback(\"AGENT_NATIVE_WORKSPACE_APP_PROTECTED_PATHS\"),\r\n ),\r\n };\r\n}\r\n\r\nexport function workspaceAppAudienceFromPackageJson(\r\n pkg: unknown,\r\n): WorkspaceAppAudience | undefined {\r\n const config = workspaceAppConfigFromPackageJson(pkg);\r\n const raw =\r\n config?.workspaceApp?.audience ??\r\n config?.workspace?.audience ??\r\n config?.audience ??\r\n config?.root?.workspaceAppAudience;\r\n if (raw === undefined) return undefined;\r\n return normalizeWorkspaceAppAudience(raw);\r\n}\r\n\r\n/**\r\n * Per-app route-access config read from a `package.json`. Each field is\r\n * `undefined` when the corresponding key is fully absent from every\r\n * supported alias chain — that lets callers distinguish \"user didn't say\"\r\n * from \"user set [] to clear inherited overrides\". `workspaceAppRouteAccess`\r\n * always emits a full `WorkspaceAppRouteAccess` for runtime consumption.\r\n */\r\nexport interface WorkspaceAppRouteAccessFromConfig {\r\n publicPaths?: string[];\r\n protectedPaths?: string[];\r\n}\r\n\r\nexport function workspaceAppRouteAccessFromPackageJson(\r\n pkg: unknown,\r\n): WorkspaceAppRouteAccessFromConfig {\r\n const config = workspaceAppConfigFromPackageJson(pkg);\r\n const rawPublic =\r\n config?.workspaceApp?.publicPaths ??\r\n config?.workspaceApp?.publicPagePaths ??\r\n config?.workspace?.publicPaths ??\r\n config?.publicPaths ??\r\n config?.root?.workspaceAppPublicPaths;\r\n const rawProtected =\r\n config?.workspaceApp?.protectedPaths ??\r\n config?.workspaceApp?.privatePaths ??\r\n config?.workspaceApp?.authRequiredPaths ??\r\n config?.workspace?.protectedPaths ??\r\n config?.protectedPaths ??\r\n config?.root?.workspaceAppProtectedPaths;\r\n return {\r\n ...(isPathConfigValueSet(rawPublic)\r\n ? { publicPaths: normalizeWorkspaceAppPathList(rawPublic) }\r\n : {}),\r\n ...(isPathConfigValueSet(rawProtected)\r\n ? { protectedPaths: normalizeWorkspaceAppPathList(rawProtected) }\r\n : {}),\r\n };\r\n}\r\n\r\n/**\r\n * Only treat a package.json field as \"explicitly set\" when its raw value is a\r\n * supported type — an array, a string, or explicit null. Garbage types like\r\n * `false`, `0`, or `{}` are ignored (left as undefined) so a typo such as\r\n * `\"publicPaths\": false` doesn't silently clear an inherited manifest\r\n * override. (`normalizeWorkspaceAppPathList` happily turns those into `[]`,\r\n * which without this guard would be indistinguishable from a deliberate\r\n * empty array.)\r\n */\r\nfunction isPathConfigValueSet(value: unknown): boolean {\r\n if (value === undefined) return false;\r\n if (value === null) return true;\r\n if (Array.isArray(value)) return true;\r\n return typeof value === \"string\";\r\n}\r\n\r\nfunction workspaceAppConfigFromPackageJson(pkg: unknown):\r\n | {\r\n root: Record<string, any>;\r\n workspaceApp?: Record<string, any>;\r\n workspace?: Record<string, any>;\r\n audience?: unknown;\r\n publicPaths?: unknown;\r\n protectedPaths?: unknown;\r\n }\r\n | undefined {\r\n if (!pkg || typeof pkg !== \"object\" || Array.isArray(pkg)) return undefined;\r\n const record = pkg as Record<string, any>;\r\n const config = record[\"agent-native\"] ?? record.agentNative;\r\n const nested =\r\n config && typeof config === \"object\" && !Array.isArray(config)\r\n ? (config as Record<string, any>)\r\n : {};\r\n const workspaceApp =\r\n nested.workspaceApp &&\r\n typeof nested.workspaceApp === \"object\" &&\r\n !Array.isArray(nested.workspaceApp)\r\n ? (nested.workspaceApp as Record<string, any>)\r\n : undefined;\r\n const workspace =\r\n nested.workspace &&\r\n typeof nested.workspace === \"object\" &&\r\n !Array.isArray(nested.workspace)\r\n ? (nested.workspace as Record<string, any>)\r\n : undefined;\r\n return {\r\n root: record,\r\n workspaceApp,\r\n workspace,\r\n audience: nested.audience,\r\n publicPaths: nested.publicPaths,\r\n protectedPaths: nested.protectedPaths,\r\n };\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jami-studio/core",
3
- "version": "0.92.31",
3
+ "version": "0.92.33",
4
4
  "description": "Framework for agent-native application development — where AI agents and UI share SQL state, actions, and context",
5
5
  "homepage": "https://github.com/studio-jami/jami-studio#readme",
6
6
  "bugs": {