@jini-ai/agent-plugins 0.4.7 → 0.6.10

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 (212) hide show
  1. package/CHANGELOG.md +24 -2
  2. package/README.md +46 -0
  3. package/dist/admin-surfaces/action-dispatcher.d.ts +37 -0
  4. package/dist/admin-surfaces/action-dispatcher.d.ts.map +1 -0
  5. package/dist/admin-surfaces/action-dispatcher.js +69 -0
  6. package/dist/admin-surfaces/action-dispatcher.js.map +1 -0
  7. package/dist/admin-surfaces/action-schema.d.ts +56 -0
  8. package/dist/admin-surfaces/action-schema.d.ts.map +1 -0
  9. package/dist/admin-surfaces/action-schema.js +167 -0
  10. package/dist/admin-surfaces/action-schema.js.map +1 -0
  11. package/dist/admin-surfaces/action-tools.d.ts +40 -0
  12. package/dist/admin-surfaces/action-tools.d.ts.map +1 -0
  13. package/dist/admin-surfaces/action-tools.js +52 -0
  14. package/dist/admin-surfaces/action-tools.js.map +1 -0
  15. package/dist/admin-surfaces/callback-field-inbox.d.ts +35 -0
  16. package/dist/admin-surfaces/callback-field-inbox.d.ts.map +1 -0
  17. package/dist/admin-surfaces/callback-field-inbox.js +53 -0
  18. package/dist/admin-surfaces/callback-field-inbox.js.map +1 -0
  19. package/dist/admin-surfaces/capability-declarations.d.ts +41 -0
  20. package/dist/admin-surfaces/capability-declarations.d.ts.map +1 -0
  21. package/dist/admin-surfaces/capability-declarations.js +102 -0
  22. package/dist/admin-surfaces/capability-declarations.js.map +1 -0
  23. package/dist/admin-surfaces/contribution.d.ts +49 -0
  24. package/dist/admin-surfaces/contribution.d.ts.map +1 -0
  25. package/dist/admin-surfaces/contribution.js +30 -0
  26. package/dist/admin-surfaces/contribution.js.map +1 -0
  27. package/dist/admin-surfaces/delivery-bindings.d.ts +76 -0
  28. package/dist/admin-surfaces/delivery-bindings.d.ts.map +1 -0
  29. package/dist/admin-surfaces/delivery-bindings.js +99 -0
  30. package/dist/admin-surfaces/delivery-bindings.js.map +1 -0
  31. package/dist/admin-surfaces/descriptor.d.ts +69 -0
  32. package/dist/admin-surfaces/descriptor.d.ts.map +1 -0
  33. package/dist/admin-surfaces/descriptor.js +196 -0
  34. package/dist/admin-surfaces/descriptor.js.map +1 -0
  35. package/dist/admin-surfaces/external-links.d.ts +45 -0
  36. package/dist/admin-surfaces/external-links.d.ts.map +1 -0
  37. package/dist/admin-surfaces/external-links.js +70 -0
  38. package/dist/admin-surfaces/external-links.js.map +1 -0
  39. package/dist/admin-surfaces/host-validator.d.ts +62 -0
  40. package/dist/admin-surfaces/host-validator.d.ts.map +1 -0
  41. package/dist/admin-surfaces/host-validator.js +87 -0
  42. package/dist/admin-surfaces/host-validator.js.map +1 -0
  43. package/dist/admin-surfaces/index.d.ts +23 -0
  44. package/dist/admin-surfaces/index.d.ts.map +1 -0
  45. package/dist/admin-surfaces/index.js +21 -0
  46. package/dist/admin-surfaces/index.js.map +1 -0
  47. package/dist/admin-surfaces/protocol.d.ts +103 -0
  48. package/dist/admin-surfaces/protocol.d.ts.map +1 -0
  49. package/dist/admin-surfaces/protocol.js +25 -0
  50. package/dist/admin-surfaces/protocol.js.map +1 -0
  51. package/dist/admin-surfaces/sandbox.d.ts +78 -0
  52. package/dist/admin-surfaces/sandbox.d.ts.map +1 -0
  53. package/dist/admin-surfaces/sandbox.js +92 -0
  54. package/dist/admin-surfaces/sandbox.js.map +1 -0
  55. package/dist/admin-surfaces/settings-value.d.ts +28 -0
  56. package/dist/admin-surfaces/settings-value.d.ts.map +1 -0
  57. package/dist/admin-surfaces/settings-value.js +45 -0
  58. package/dist/admin-surfaces/settings-value.js.map +1 -0
  59. package/dist/admin-surfaces/surface-capabilities.d.ts +167 -0
  60. package/dist/admin-surfaces/surface-capabilities.d.ts.map +1 -0
  61. package/dist/admin-surfaces/surface-capabilities.js +215 -0
  62. package/dist/admin-surfaces/surface-capabilities.js.map +1 -0
  63. package/dist/admin-surfaces/surface-client.d.ts +116 -0
  64. package/dist/admin-surfaces/surface-client.d.ts.map +1 -0
  65. package/dist/admin-surfaces/surface-client.js +219 -0
  66. package/dist/admin-surfaces/surface-client.js.map +1 -0
  67. package/dist/admin-surfaces/surface-handlers.d.ts +111 -0
  68. package/dist/admin-surfaces/surface-handlers.d.ts.map +1 -0
  69. package/dist/admin-surfaces/surface-handlers.js +172 -0
  70. package/dist/admin-surfaces/surface-handlers.js.map +1 -0
  71. package/dist/admin-surfaces/theme.d.ts +59 -0
  72. package/dist/admin-surfaces/theme.d.ts.map +1 -0
  73. package/dist/admin-surfaces/theme.js +57 -0
  74. package/dist/admin-surfaces/theme.js.map +1 -0
  75. package/dist/folder-zip-node.d.ts.map +1 -0
  76. package/dist/folder-zip-node.js +59 -49
  77. package/dist/folder-zip-node.js.map +1 -0
  78. package/dist/folder-zip.d.ts.map +1 -0
  79. package/dist/folder-zip.js +9 -7
  80. package/dist/folder-zip.js.map +1 -0
  81. package/dist/index.d.ts.map +1 -0
  82. package/dist/index.js.map +1 -0
  83. package/dist/lifecycle/activation.d.ts.map +1 -0
  84. package/dist/lifecycle/activation.js.map +1 -0
  85. package/dist/lifecycle/automatic-use.d.ts +79 -0
  86. package/dist/lifecycle/automatic-use.d.ts.map +1 -0
  87. package/dist/lifecycle/automatic-use.js +165 -0
  88. package/dist/lifecycle/automatic-use.js.map +1 -0
  89. package/dist/lifecycle/bundled-digests.d.ts.map +1 -0
  90. package/dist/lifecycle/bundled-digests.js.map +1 -0
  91. package/dist/lifecycle/bundled-source-archive.d.ts.map +1 -0
  92. package/dist/lifecycle/bundled-source-archive.js.map +1 -0
  93. package/dist/lifecycle/capability-projection.d.ts.map +1 -0
  94. package/dist/lifecycle/capability-projection.js.map +1 -0
  95. package/dist/lifecycle/compatibility-metadata.d.ts +19 -0
  96. package/dist/lifecycle/compatibility-metadata.d.ts.map +1 -0
  97. package/dist/lifecycle/compatibility-metadata.js +45 -0
  98. package/dist/lifecycle/compatibility-metadata.js.map +1 -0
  99. package/dist/lifecycle/compatibility.d.ts +52 -0
  100. package/dist/lifecycle/compatibility.d.ts.map +1 -0
  101. package/dist/lifecycle/compatibility.js +60 -0
  102. package/dist/lifecycle/compatibility.js.map +1 -0
  103. package/dist/lifecycle/contribution-loader.d.ts.map +1 -0
  104. package/dist/lifecycle/contribution-loader.js.map +1 -0
  105. package/dist/lifecycle/fetch-archive.d.ts.map +1 -0
  106. package/dist/lifecycle/fetch-archive.js +26 -24
  107. package/dist/lifecycle/fetch-archive.js.map +1 -0
  108. package/dist/lifecycle/index.d.ts +14 -2
  109. package/dist/lifecycle/index.d.ts.map +1 -0
  110. package/dist/lifecycle/index.js +8 -1
  111. package/dist/lifecycle/index.js.map +1 -0
  112. package/dist/lifecycle/install-errors.d.ts.map +1 -0
  113. package/dist/lifecycle/install-errors.js.map +1 -0
  114. package/dist/lifecycle/install-from-url.d.ts.map +1 -0
  115. package/dist/lifecycle/install-from-url.js.map +1 -0
  116. package/dist/lifecycle/install.d.ts.map +1 -0
  117. package/dist/lifecycle/install.js +7 -0
  118. package/dist/lifecycle/install.js.map +1 -0
  119. package/dist/lifecycle/installed-package-index.d.ts.map +1 -0
  120. package/dist/lifecycle/installed-package-index.js +41 -29
  121. package/dist/lifecycle/installed-package-index.js.map +1 -0
  122. package/dist/lifecycle/installed-package-roots.d.ts.map +1 -0
  123. package/dist/lifecycle/installed-package-roots.js +28 -20
  124. package/dist/lifecycle/installed-package-roots.js.map +1 -0
  125. package/dist/lifecycle/layout.d.ts.map +1 -0
  126. package/dist/lifecycle/layout.js.map +1 -0
  127. package/dist/lifecycle/manifest.d.ts +13 -0
  128. package/dist/lifecycle/manifest.d.ts.map +1 -0
  129. package/dist/lifecycle/manifest.js +115 -101
  130. package/dist/lifecycle/manifest.js.map +1 -0
  131. package/dist/lifecycle/mcp-provisioning.d.ts.map +1 -0
  132. package/dist/lifecycle/mcp-provisioning.js.map +1 -0
  133. package/dist/lifecycle/node.d.ts.map +1 -0
  134. package/dist/lifecycle/node.js.map +1 -0
  135. package/dist/lifecycle/package-paths.d.ts.map +1 -0
  136. package/dist/lifecycle/package-paths.js +3 -3
  137. package/dist/lifecycle/package-paths.js.map +1 -0
  138. package/dist/lifecycle/persistent-state.d.ts.map +1 -0
  139. package/dist/lifecycle/persistent-state.js.map +1 -0
  140. package/dist/lifecycle/ports.d.ts +1 -1
  141. package/dist/lifecycle/ports.d.ts.map +1 -0
  142. package/dist/lifecycle/ports.js.map +1 -0
  143. package/dist/lifecycle/provider-contribution.d.ts +65 -0
  144. package/dist/lifecycle/provider-contribution.d.ts.map +1 -0
  145. package/dist/lifecycle/provider-contribution.js +93 -0
  146. package/dist/lifecycle/provider-contribution.js.map +1 -0
  147. package/dist/lifecycle/resolve-agent-plugin-refs.d.ts.map +1 -0
  148. package/dist/lifecycle/resolve-agent-plugin-refs.js +15 -2
  149. package/dist/lifecycle/resolve-agent-plugin-refs.js.map +1 -0
  150. package/dist/lifecycle/retire-bundled.d.ts.map +1 -0
  151. package/dist/lifecycle/retire-bundled.js +20 -18
  152. package/dist/lifecycle/retire-bundled.js.map +1 -0
  153. package/dist/lifecycle/search.d.ts +6 -1
  154. package/dist/lifecycle/search.d.ts.map +1 -0
  155. package/dist/lifecycle/search.js +45 -7
  156. package/dist/lifecycle/search.js.map +1 -0
  157. package/dist/lifecycle/seed-bundled.d.ts.map +1 -0
  158. package/dist/lifecycle/seed-bundled.js.map +1 -0
  159. package/dist/lifecycle/set-enabled.d.ts +2 -1
  160. package/dist/lifecycle/set-enabled.d.ts.map +1 -0
  161. package/dist/lifecycle/set-enabled.js +52 -8
  162. package/dist/lifecycle/set-enabled.js.map +1 -0
  163. package/dist/lifecycle/skill-file-reader.d.ts.map +1 -0
  164. package/dist/lifecycle/skill-file-reader.js +85 -71
  165. package/dist/lifecycle/skill-file-reader.js.map +1 -0
  166. package/dist/lifecycle/tools/capabilities.d.ts +199 -0
  167. package/dist/lifecycle/tools/capabilities.d.ts.map +1 -0
  168. package/dist/lifecycle/tools/capabilities.js +213 -0
  169. package/dist/lifecycle/tools/capabilities.js.map +1 -0
  170. package/dist/lifecycle/tools/definition.d.ts +32 -0
  171. package/dist/lifecycle/tools/definition.d.ts.map +1 -0
  172. package/dist/lifecycle/tools/definition.js +33 -0
  173. package/dist/lifecycle/tools/definition.js.map +1 -0
  174. package/dist/lifecycle/tools/index.d.ts +10 -0
  175. package/dist/lifecycle/tools/index.d.ts.map +1 -0
  176. package/dist/lifecycle/tools/index.js +10 -0
  177. package/dist/lifecycle/tools/index.js.map +1 -0
  178. package/dist/lifecycle/tools/manifest.d.ts +33 -0
  179. package/dist/lifecycle/tools/manifest.d.ts.map +1 -0
  180. package/dist/lifecycle/tools/manifest.js +89 -0
  181. package/dist/lifecycle/tools/manifest.js.map +1 -0
  182. package/dist/lifecycle/tools/projection.d.ts +90 -0
  183. package/dist/lifecycle/tools/projection.d.ts.map +1 -0
  184. package/dist/lifecycle/tools/projection.js +283 -0
  185. package/dist/lifecycle/tools/projection.js.map +1 -0
  186. package/dist/lifecycle/trusted-plugin-files.d.ts.map +1 -0
  187. package/dist/lifecycle/trusted-plugin-files.js.map +1 -0
  188. package/dist/lifecycle/types.d.ts +2 -0
  189. package/dist/lifecycle/types.d.ts.map +1 -0
  190. package/dist/lifecycle/types.js.map +1 -0
  191. package/dist/lifecycle/uninstall.d.ts +3 -1
  192. package/dist/lifecycle/uninstall.d.ts.map +1 -0
  193. package/dist/lifecycle/uninstall.js +51 -27
  194. package/dist/lifecycle/uninstall.js.map +1 -0
  195. package/dist/lifecycle/update-plan.d.ts +18 -0
  196. package/dist/lifecycle/update-plan.d.ts.map +1 -0
  197. package/dist/lifecycle/update-plan.js +22 -0
  198. package/dist/lifecycle/update-plan.js.map +1 -0
  199. package/dist/lifecycle/update-store.d.ts +71 -0
  200. package/dist/lifecycle/update-store.d.ts.map +1 -0
  201. package/dist/lifecycle/update-store.js +150 -0
  202. package/dist/lifecycle/update-store.js.map +1 -0
  203. package/dist/lifecycle/update.d.ts +55 -0
  204. package/dist/lifecycle/update.d.ts.map +1 -0
  205. package/dist/lifecycle/update.js +321 -0
  206. package/dist/lifecycle/update.js.map +1 -0
  207. package/dist/lifecycle/yauzl-archive-reader.d.ts.map +1 -0
  208. package/dist/lifecycle/yauzl-archive-reader.js.map +1 -0
  209. package/dist/manifest.d.ts.map +1 -0
  210. package/dist/manifest.js.map +1 -0
  211. package/package.json +39 -7
  212. package/ui-ux-design/plugin.json +7 -2
@@ -0,0 +1,111 @@
1
+ /**
2
+ * @file Plugin-supplied server-side handlers for admin surfaces: a surface may name a contained
3
+ * `.mjs` `handlerModule` that answers its declared actions and may provide its bootstrap data.
4
+ *
5
+ * Why it exists: without it a host can only answer a surface's actions with its own code, so a
6
+ * provider plugin cannot ship a working settings or resource-chooser screen. Why it is safe to run plugin code
7
+ * here: the module loads only through the lifecycle's one executable loader
8
+ * (`defineExecutablePluginContribution`: active plugin, shipped digest, on-disk containment), it
9
+ * receives host capability ports (never a raw secret) through the admin-surface capability session
10
+ * (`./surface-capabilities.ts`: only the surface's declared connections and config, revoked on disable,
11
+ * results and errors scanned for tokens the call obtained, the same gate as executable tools), and the
12
+ * dispatcher still checks the declared input and result schemas around it.
13
+ * Bootstrap data is the one answer allowed to carry an access token (a surface may need a short-lived
14
+ * one); it must match the surface's declared `bootstrap` schema and is never cached by the host.
15
+ */
16
+ import { type LoadedPluginContribution, type PluginContributionDefinition } from '../lifecycle/contribution-loader.js';
17
+ import type { IssuedTokenMemories } from '../lifecycle/tools/capabilities.js';
18
+ import { type AdminSurfaceCapabilities, type AdminSurfaceCapabilitiesPort } from './surface-capabilities.js';
19
+ import { type AdminSurfaceActionHandler } from './action-dispatcher.js';
20
+ import { type AdminSurfaceDescriptor } from './descriptor.js';
21
+ /** Who a call is for. The host route establishes it; plugin and surface ids are rebound to the
22
+ * loaded module's own before a handler sees them. */
23
+ export interface AdminSurfaceHandlerContext {
24
+ readonly workspaceId: string;
25
+ readonly principalId?: string;
26
+ readonly pluginId: string;
27
+ readonly surfaceId: string;
28
+ }
29
+ /** Which kind of host is running the surface, so a plugin picks its flow (for example a sign-in in
30
+ * the system browser on desktop) without inferring it from config. */
31
+ export type AdminSurfaceHostKind = 'hosted' | 'desktop';
32
+ /** The context a handler sees: the route's context plus the plugin's own declared connection ids
33
+ * (ids, never refs: the host resolves the ref, so a plugin can never name another plugin's connection)
34
+ * and the host kind the host was built with (never a caller's or the plugin's value). */
35
+ export interface AdminSurfacePluginContext extends AdminSurfaceHandlerContext {
36
+ readonly connectionIds: readonly string[];
37
+ readonly hostKind: AdminSurfaceHostKind;
38
+ }
39
+ /** What a bootstrap provider receives. */
40
+ export interface AdminSurfaceBootstrapCall {
41
+ readonly capabilities: AdminSurfaceCapabilities;
42
+ readonly context: AdminSurfacePluginContext;
43
+ }
44
+ /** What an action handler receives. `input` already matched the action's declared input schema. */
45
+ export interface AdminSurfaceHandlerCall extends AdminSurfaceBootstrapCall {
46
+ readonly input: unknown;
47
+ /** Builds a surface-safe failure to throw: `code` (lowercase hyphenated) and `message` reach the frame. */
48
+ readonly fail: (required: {
49
+ readonly code: string;
50
+ readonly message: string;
51
+ }, optional?: {
52
+ readonly retryable?: boolean;
53
+ }) => Error;
54
+ }
55
+ /** What a handler module's default export must be. */
56
+ export interface AdminSurfaceHandlerModule {
57
+ /** Keyed by declared action name; a declared action without one answers `action-unavailable`. */
58
+ readonly actions: Readonly<Record<string, (required: AdminSurfaceHandlerCall, optional?: Record<string, never>) => unknown>>;
59
+ /** Data the surface starts with; requires a `bootstrap` schema on the surface. */
60
+ readonly bootstrap?: (required: AdminSurfaceBootstrapCall, optional?: Record<string, never>) => unknown;
61
+ }
62
+ type HandledSurface = AdminSurfaceDescriptor & {
63
+ readonly handlerModule: string;
64
+ };
65
+ export type LoadedAdminSurfaceHandlers = LoadedPluginContribution<HandledSurface, AdminSurfaceHandlerModule>;
66
+ export declare const ADMIN_SURFACE_PLUGIN_DISABLED_MESSAGE = "This plugin was disabled, so its admin surface cannot act. Re-enable the plugin and reopen the surface.";
67
+ /**
68
+ * The executable contribution for the host's surfaces file (the same file `defineAdminSurfaceContribution`
69
+ * reads): one item per surface that names a `handlerModule`.
70
+ * @param required.filename - The host-named surfaces file at the plugin root.
71
+ * @complexity O(1); each load parses the file and performs one contained import per handled surface.
72
+ */
73
+ export declare function defineAdminSurfaceHandlerContribution(required: {
74
+ readonly filename: string;
75
+ }, _optional?: Record<string, never>): PluginContributionDefinition<HandledSurface, LoadedAdminSurfaceHandlers>;
76
+ /**
77
+ * Holds the admitted handler modules and answers for them. Call `sync` with every load of
78
+ * `defineAdminSurfaceHandlerContribution` (on boot and on every activation change); a surface missing
79
+ * from a load loses its handlers, and capabilities its module kept are revoked.
80
+ * @param required.capabilities - Host port building one call's admin-surface capabilities.
81
+ * @param required.issuedTokens - Per-plugin token memory shared with the plugin's tool projection.
82
+ * @param required.hostKind - The kind of host this process is; every handler and bootstrap call sees it.
83
+ * @throws TypeError when `hostKind` is neither `hosted` nor `desktop`.
84
+ * @returns `sync`, plus `handlersFor` and `bootstrapData` for the host's action dispatcher and bootstrap route.
85
+ * @complexity sync is O(s + a) surfaces and actions; lookups are O(1).
86
+ */
87
+ export declare function createAdminSurfaceHandlerHost(required: {
88
+ readonly capabilities: AdminSurfaceCapabilitiesPort;
89
+ readonly issuedTokens: IssuedTokenMemories;
90
+ readonly hostKind: AdminSurfaceHostKind;
91
+ }, _optional?: Record<string, never>): {
92
+ /** Admits one load result. @returns The loader's refusals plus this seam's own, in order. */
93
+ sync(input: {
94
+ readonly loaded: readonly LoadedAdminSurfaceHandlers[];
95
+ readonly refusals: readonly string[];
96
+ }, _options?: Record<string, never>): {
97
+ readonly refusals: readonly string[];
98
+ };
99
+ /** The plugin's handlers for one surface (empty when none are admitted), for `createAdminSurfaceActionDispatcher`. */
100
+ handlersFor(input: {
101
+ readonly pluginId: string;
102
+ readonly surfaceId: string;
103
+ }, _options?: Record<string, never>): Readonly<Record<string, AdminSurfaceActionHandler<AdminSurfaceHandlerContext>>>;
104
+ /** The plugin's bootstrap data for `context`'s surface, or null when it provides none.
105
+ * @throws Error when the data does not match the declared schema (the message names a path, never a value). */
106
+ bootstrapData(input: {
107
+ readonly context: AdminSurfaceHandlerContext;
108
+ }, _options?: Record<string, never>): Promise<unknown>;
109
+ };
110
+ export {};
111
+ //# sourceMappingURL=surface-handlers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface-handlers.d.ts","sourceRoot":"","sources":["../../src/admin-surfaces/surface-handlers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,172 @@
1
+ /**
2
+ * @file Plugin-supplied server-side handlers for admin surfaces: a surface may name a contained
3
+ * `.mjs` `handlerModule` that answers its declared actions and may provide its bootstrap data.
4
+ *
5
+ * Why it exists: without it a host can only answer a surface's actions with its own code, so a
6
+ * provider plugin cannot ship a working settings or resource-chooser screen. Why it is safe to run plugin code
7
+ * here: the module loads only through the lifecycle's one executable loader
8
+ * (`defineExecutablePluginContribution`: active plugin, shipped digest, on-disk containment), it
9
+ * receives host capability ports (never a raw secret) through the admin-surface capability session
10
+ * (`./surface-capabilities.ts`: only the surface's declared connections and config, revoked on disable,
11
+ * results and errors scanned for tokens the call obtained, the same gate as executable tools), and the
12
+ * dispatcher still checks the declared input and result schemas around it.
13
+ * Bootstrap data is the one answer allowed to carry an access token (a surface may need a short-lived
14
+ * one); it must match the surface's declared `bootstrap` schema and is never cached by the host.
15
+ */
16
+ import { defineExecutablePluginContribution } from '../lifecycle/contribution-loader.js';
17
+ import { openAdminSurfaceCapabilitySession } from './surface-capabilities.js';
18
+ import { AdminSurfaceActionError } from './action-dispatcher.js';
19
+ import { validateAdminSurfaceActionValue } from './action-schema.js';
20
+ import { parseAdminSurfacesFile } from './descriptor.js';
21
+ const HOST_KINDS = ['hosted', 'desktop'];
22
+ export const ADMIN_SURFACE_PLUGIN_DISABLED_MESSAGE = 'This plugin was disabled, so its admin surface cannot act. Re-enable the plugin and reopen the surface.';
23
+ const FAILURE_CODE_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
24
+ const MAX_FAILURE_CODE_LENGTH = 64;
25
+ const MAX_FAILURE_MESSAGE_LENGTH = 300;
26
+ const isFunction = (value) => typeof value === 'function';
27
+ const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
28
+ /** The module's export as a handler module, or why not. Shape only; declarations are checked at sync. @complexity O(a) exported actions. */
29
+ function validateHandlerModule({ exported }) {
30
+ if (!isRecord(exported))
31
+ return "its module's default export is not an object";
32
+ if (!isRecord(exported.actions) || !Object.values(exported.actions).every(isFunction))
33
+ return "its module's default export needs an actions object of functions";
34
+ if (exported.bootstrap !== undefined && !isFunction(exported.bootstrap))
35
+ return 'bootstrap must be a function';
36
+ return exported;
37
+ }
38
+ /**
39
+ * The executable contribution for the host's surfaces file (the same file `defineAdminSurfaceContribution`
40
+ * reads): one item per surface that names a `handlerModule`.
41
+ * @param required.filename - The host-named surfaces file at the plugin root.
42
+ * @complexity O(1); each load parses the file and performs one contained import per handled surface.
43
+ */
44
+ export function defineAdminSurfaceHandlerContribution(required, _optional = {}) {
45
+ return defineExecutablePluginContribution({
46
+ filename: required.filename, contribution: 'admin surface handlers',
47
+ parse: ({ raw }) => {
48
+ const parsed = parseAdminSurfacesFile({ raw });
49
+ return parsed.ok ? { ok: true, descriptors: parsed.descriptors.filter((descriptor) => descriptor.handlerModule !== undefined) } : parsed;
50
+ },
51
+ modulePath: ({ descriptor }) => descriptor.handlerModule, validate: validateHandlerModule,
52
+ refusal: ({ plugin, descriptor, reason }) => `admin surface handlers for '${descriptor.id}' from '${plugin.pluginId}' were not loaded: ${reason}`,
53
+ });
54
+ }
55
+ /** A surface-safe failure, or a generic one when the plugin's code is not a valid id. @complexity O(1). */
56
+ function fail(required, optional = {}) {
57
+ const { code, message } = required;
58
+ if (typeof code !== 'string' || code.length > MAX_FAILURE_CODE_LENGTH || !FAILURE_CODE_PATTERN.test(code))
59
+ return new Error('a plugin failure used an invalid code');
60
+ return new AdminSurfaceActionError({ code, message: String(message).slice(0, MAX_FAILURE_MESSAGE_LENGTH) }, { retryable: optional.retryable === true });
61
+ }
62
+ /** Why a loaded module cannot answer for its surface, or null. @complexity O(a) exported actions. */
63
+ function admissionRefusal({ descriptor, module }) {
64
+ const undeclared = Object.keys(module.actions).find((name) => !descriptor.actions.some((action) => action.name === name));
65
+ if (undeclared !== undefined)
66
+ return `it exports a handler for undeclared action '${undeclared.slice(0, 64)}'`;
67
+ return module.bootstrap !== undefined && descriptor.bootstrap === undefined ? 'it exports bootstrap() but the surface declares no bootstrap schema' : null;
68
+ }
69
+ /** Plugin and surface ids cannot contain NUL, so the key is unambiguous. */
70
+ const keyOf = (pluginId, surfaceId) => `${pluginId}\u0000${surfaceId}`;
71
+ /**
72
+ * Holds the admitted handler modules and answers for them. Call `sync` with every load of
73
+ * `defineAdminSurfaceHandlerContribution` (on boot and on every activation change); a surface missing
74
+ * from a load loses its handlers, and capabilities its module kept are revoked.
75
+ * @param required.capabilities - Host port building one call's admin-surface capabilities.
76
+ * @param required.issuedTokens - Per-plugin token memory shared with the plugin's tool projection.
77
+ * @param required.hostKind - The kind of host this process is; every handler and bootstrap call sees it.
78
+ * @throws TypeError when `hostKind` is neither `hosted` nor `desktop`.
79
+ * @returns `sync`, plus `handlersFor` and `bootstrapData` for the host's action dispatcher and bootstrap route.
80
+ * @complexity sync is O(s + a) surfaces and actions; lookups are O(1).
81
+ */
82
+ export function createAdminSurfaceHandlerHost(required, _optional = {}) {
83
+ // Checked at run time too: a JavaScript host may pass an unchecked config value, and a plugin would pick its flow from it.
84
+ if (!HOST_KINDS.includes(required.hostKind))
85
+ throw new TypeError("createAdminSurfaceHandlerHost: hostKind must be 'hosted' or 'desktop'.");
86
+ const { hostKind } = required;
87
+ let admitted = new Map();
88
+ /** One call's capability session, scoped to the loaded plugin and the route's workspace/principal. */
89
+ function sessionFor(self, context) {
90
+ const { pluginId, descriptor } = self.loaded;
91
+ const principal = context.principalId === undefined ? {} : { principalId: context.principalId };
92
+ const capabilities = required.capabilities({ pluginId, workspaceId: context.workspaceId, ...principal });
93
+ const session = openAdminSurfaceCapabilitySession({ capabilities, isLive: self.isLive, declared: descriptor, issued: self.issued }, { ...(principal.principalId !== undefined && { actorId: principal.principalId }) });
94
+ const connectionIds = (descriptor.connections ?? []).map((connection) => connection.id);
95
+ return { session, context: { workspaceId: context.workspaceId, ...principal, pluginId, surfaceId: descriptor.id, connectionIds, hostKind } };
96
+ }
97
+ function actionHandler(self, run) {
98
+ return async ({ payload, context: caller }) => {
99
+ if (!self.isLive())
100
+ throw new AdminSurfaceActionError({ code: 'plugin-disabled', message: ADMIN_SURFACE_PLUGIN_DISABLED_MESSAGE });
101
+ const { session, context } = sessionFor(self, caller);
102
+ try {
103
+ return session.release({ value: await run({ input: payload, capabilities: session.capabilities, context, fail }) });
104
+ }
105
+ catch (error) {
106
+ throw session.sanitize({ error });
107
+ }
108
+ };
109
+ }
110
+ /** A generation for one surface; live only while `admitted` holds this exact object. */
111
+ function admit(key, loaded) {
112
+ const declared = loaded.descriptor.actions.filter((action) => Object.hasOwn(loaded.module.actions, action.name));
113
+ const self = { loaded, handlers: {}, isLive: () => admitted.get(key) === self, issued: required.issuedTokens.forPlugin({ pluginId: loaded.pluginId }) };
114
+ Object.assign(self.handlers, Object.fromEntries(declared.map((action) => [action.name, actionHandler(self, loaded.module.actions[action.name])])));
115
+ return Object.freeze(self);
116
+ }
117
+ /** The previous generation when module and declaration are unchanged, so re-syncing never revokes it. */
118
+ function unchanged(previous, loaded) {
119
+ const same = previous !== undefined && previous.loaded.module === loaded.module && JSON.stringify(previous.loaded.descriptor) === JSON.stringify(loaded.descriptor);
120
+ return same ? previous : undefined;
121
+ }
122
+ return {
123
+ /** Admits one load result. @returns The loader's refusals plus this seam's own, in order. */
124
+ sync(input, _options = {}) {
125
+ const refusals = [...input.refusals];
126
+ const claims = new Map();
127
+ for (const entry of input.loaded)
128
+ claims.set(keyOf(entry.pluginId, entry.descriptor.id), (claims.get(keyOf(entry.pluginId, entry.descriptor.id)) ?? 0) + 1);
129
+ const next = new Map();
130
+ const previous = admitted;
131
+ for (const entry of input.loaded) {
132
+ const key = keyOf(entry.pluginId, entry.descriptor.id);
133
+ const reason = claims.get(key) > 1 ? 'more than one handler module claims this surface' : admissionRefusal(entry);
134
+ const line = `admin surface handlers for '${entry.descriptor.id}' from '${entry.pluginId}' were not loaded: ${reason}`;
135
+ if (reason !== null) {
136
+ if (!refusals.includes(line))
137
+ refusals.push(line);
138
+ continue;
139
+ }
140
+ next.set(key, unchanged(previous.get(key), entry) ?? admit(key, entry));
141
+ }
142
+ admitted = next;
143
+ return { refusals };
144
+ },
145
+ /** The plugin's handlers for one surface (empty when none are admitted), for `createAdminSurfaceActionDispatcher`. */
146
+ handlersFor(input, _options = {}) {
147
+ return admitted.get(keyOf(input.pluginId, input.surfaceId))?.handlers ?? {};
148
+ },
149
+ /** The plugin's bootstrap data for `context`'s surface, or null when it provides none.
150
+ * @throws Error when the data does not match the declared schema (the message names a path, never a value). */
151
+ async bootstrapData(input, _options = {}) {
152
+ const self = admitted.get(keyOf(input.context.pluginId, input.context.surfaceId));
153
+ const provide = self?.loaded.module.bootstrap;
154
+ if (self === undefined || provide === undefined)
155
+ return null;
156
+ const { session, context } = sessionFor(self, input.context);
157
+ let data;
158
+ try {
159
+ data = await provide({ capabilities: session.capabilities, context });
160
+ }
161
+ catch (error) {
162
+ throw session.sanitize({ error });
163
+ }
164
+ // Admission guarantees a schema whenever the module provides bootstrap data.
165
+ const violation = validateAdminSurfaceActionValue({ schema: self.loaded.descriptor.bootstrap, value: data });
166
+ if (violation !== null)
167
+ throw new Error(`Admin surface '${context.surfaceId}' from '${context.pluginId}' returned bootstrap data outside its declared schema (${violation}); report it to the plugin author.`);
168
+ return data;
169
+ },
170
+ };
171
+ }
172
+ //# sourceMappingURL=surface-handlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"surface-handlers.js","sourceRoot":"","sources":["../../src/admin-surfaces/surface-handlers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,kCAAkC,EAAoE,MAAM,qCAAqC,CAAC;AAE3J,OAAO,EAAE,iCAAiC,EAAoE,MAAM,2BAA2B,CAAC;AAChJ,OAAO,EAAE,uBAAuB,EAAkC,MAAM,wBAAwB,CAAC;AACjG,OAAO,EAAE,+BAA+B,EAAiC,MAAM,oBAAoB,CAAC;AACpG,OAAO,EAAE,sBAAsB,EAA+B,MAAM,iBAAiB,CAAC;AActF,MAAM,UAAU,GAAsB,CAAC,QAAQ,EAAE,SAAS,CAA2C,CAAC;AAkCtG,MAAM,CAAC,MAAM,qCAAqC,GAAG,yGAAyG,CAAC;AAC/J,MAAM,oBAAoB,GAAG,4BAA4B,CAAC;AAC1D,MAAM,uBAAuB,GAAG,EAAE,CAAC;AACnC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAEvC,MAAM,UAAU,GAAG,CAAC,KAAc,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,UAAU,CAAC;AACnE,MAAM,QAAQ,GAAG,CAAC,KAAc,EAA8C,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAEtJ,4IAA4I;AAC5I,SAAS,qBAAqB,CAAC,EAAE,QAAQ,EAAkC;IACzE,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,OAAO,8CAA8C,CAAC;IAC/E,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC;QAAE,OAAO,kEAAkE,CAAC;IACjK,IAAI,QAAQ,CAAC,SAAS,KAAK,SAAS,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,8BAA8B,CAAC;IAC/G,OAAO,QAAgD,CAAC;AAC1D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qCAAqC,CACnD,QAAuC,EACvC,YAAmC,EAAE;IAErC,OAAO,kCAAkC,CAA4C;QACnF,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,YAAY,EAAE,wBAAwB;QACnE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE;YACjB,MAAM,MAAM,GAAG,sBAAsB,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;YAC/C,OAAO,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,UAAU,EAAgC,EAAE,CAAC,UAAU,CAAC,aAAa,KAAK,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;QACzK,CAAC;QACD,UAAU,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC,UAAU,CAAC,aAAa,EAAE,QAAQ,EAAE,qBAAqB;QACzF,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,+BAA+B,UAAU,CAAC,EAAE,WAAW,MAAM,CAAC,QAAQ,sBAAsB,MAAM,EAAE;KAClJ,CAAC,CAAC;AACL,CAAC;AAED,2GAA2G;AAC3G,SAAS,IAAI,CAAC,QAA6D,EAAE,WAA6C,EAAE;IAC1H,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,QAAQ,CAAC;IACnC,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,uBAAuB,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IACrK,OAAO,IAAI,uBAAuB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,0BAA0B,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC,CAAC;AAC1J,CAAC;AAED,qGAAqG;AACrG,SAAS,gBAAgB,CAAC,EAAE,UAAU,EAAE,MAAM,EAA8B;IAC1E,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC;IAC1H,IAAI,UAAU,KAAK,SAAS;QAAE,OAAO,+CAA+C,UAAU,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC;IAC/G,OAAO,MAAM,CAAC,SAAS,KAAK,SAAS,IAAI,UAAU,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,qEAAqE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7J,CAAC;AAUD,4EAA4E;AAC5E,MAAM,KAAK,GAAG,CAAC,QAAgB,EAAE,SAAiB,EAAE,EAAE,CAAC,GAAG,QAAQ,SAAS,SAAS,EAAE,CAAC;AAEvF;;;;;;;;;;GAUG;AACH,MAAM,UAAU,6BAA6B,CAAC,QAAsJ,EAAE,YAAmC,EAAE;IACzO,2HAA2H;IAC3H,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC;QAAE,MAAM,IAAI,SAAS,CAAC,wEAAwE,CAAC,CAAC;IAC3I,MAAM,EAAE,QAAQ,EAAE,GAAG,QAAQ,CAAC;IAC9B,IAAI,QAAQ,GAAG,IAAI,GAAG,EAA2B,CAAC;IAElD,sGAAsG;IACtG,SAAS,UAAU,CAAC,IAAqB,EAAE,OAAmC;QAC5E,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC;QAC7C,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,CAAC;QAChG,MAAM,YAAY,GAAG,QAAQ,CAAC,YAAY,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,GAAG,SAAS,EAAE,CAAC,CAAC;QACzG,MAAM,OAAO,GAAG,iCAAiC,CAAC,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,GAAG,CAAC,SAAS,CAAC,WAAW,KAAK,SAAS,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC,CAAC;QACxN,MAAM,aAAa,GAAG,CAAC,UAAU,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACxF,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,WAAW,EAAE,GAAG,SAAS,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC,EAAE,EAAE,aAAa,EAAE,QAAQ,EAAE,EAAE,CAAC;IAC/I,CAAC;IAED,SAAS,aAAa,CAAC,IAAqB,EAAE,GAAiD;QAC7F,OAAO,KAAK,EAAE,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE;YAC5C,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE;gBAAE,MAAM,IAAI,uBAAuB,CAAC,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,qCAAqC,EAAE,CAAC,CAAC;YACnI,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;YACtD,IAAI,CAAC;gBAAC,OAAO,OAAO,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,MAAM,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;YAAC,CAAC;YAC5H,OAAO,KAAK,EAAE,CAAC;gBAAC,MAAM,OAAO,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YAAC,CAAC;QACtD,CAAC,CAAC;IACJ,CAAC;IAED,wFAAwF;IACxF,SAAS,KAAK,CAAC,GAAW,EAAE,MAAkC;QAC5D,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;QACjH,MAAM,IAAI,GAAoB,EAAE,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC,EAAE,CAAC;QACzK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACpJ,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAC7B,CAAC;IAED,yGAAyG;IACzG,SAAS,SAAS,CAAC,QAAqC,EAAE,MAAkC;QAC1F,MAAM,IAAI,GAAG,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;QACpK,OAAO,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC;IACrC,CAAC;IAED,OAAO;QACL,6FAA6F;QAC7F,IAAI,CAAC,KAAuG,EAAE,WAAkC,EAAE;YAChJ,MAAM,QAAQ,GAAG,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC;YACrC,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;YACzC,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM;gBAAE,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5J,MAAM,IAAI,GAAG,IAAI,GAAG,EAA2B,CAAC;YAChD,MAAM,QAAQ,GAAG,QAAQ,CAAC;YAC1B,KAAK,MAAM,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;gBACjC,MAAM,GAAG,GAAG,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;gBACvD,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAE,GAAG,CAAC,CAAC,CAAC,CAAC,kDAAkD,CAAC,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;gBACnH,MAAM,IAAI,GAAG,+BAA+B,KAAK,CAAC,UAAU,CAAC,EAAE,WAAW,KAAK,CAAC,QAAQ,sBAAsB,MAAM,EAAE,CAAC;gBACvH,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;oBAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC;wBAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;oBAAC,SAAS;gBAAC,CAAC;gBACrF,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,KAAK,CAAC,IAAI,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;YAC1E,CAAC;YACD,QAAQ,GAAG,IAAI,CAAC;YAChB,OAAO,EAAE,QAAQ,EAAE,CAAC;QACtB,CAAC;QACD,sHAAsH;QACtH,WAAW,CAAC,KAAgE,EAAE,WAAkC,EAAE;YAChH,OAAO,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,QAAQ,IAAI,EAAE,CAAC;QAC9E,CAAC;QACD;uHAC+G;QAC/G,KAAK,CAAC,aAAa,CAAC,KAAuD,EAAE,WAAkC,EAAE;YAC/G,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC;YAClF,MAAM,OAAO,GAAG,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC;YAC9C,IAAI,IAAI,KAAK,SAAS,IAAI,OAAO,KAAK,SAAS;gBAAE,OAAO,IAAI,CAAC;YAC7D,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,GAAG,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC;YAC7D,IAAI,IAAa,CAAC;YAClB,IAAI,CAAC;gBAAC,IAAI,GAAG,MAAM,OAAO,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,OAAO,EAAE,CAAC,CAAC;YAAC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAAC,MAAM,OAAO,CAAC,QAAQ,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YAAC,CAAC;YACnI,6EAA6E;YAC7E,MAAM,SAAS,GAAG,+BAA+B,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,SAAqC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;YACzI,IAAI,SAAS,KAAK,IAAI;gBAAE,MAAM,IAAI,KAAK,CAAC,kBAAkB,OAAO,CAAC,SAAS,WAAW,OAAO,CAAC,QAAQ,0DAA0D,SAAS,oCAAoC,CAAC,CAAC;YAC/M,OAAO,IAAI,CAAC;QACd,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * @file The host's design tokens for plugin surfaces: which `--jini-*` custom properties a host
3
+ * shares with every surface frame, how it reads their current values, and the envelope that sends
4
+ * a change after init.
5
+ *
6
+ * Why: a surface is a sandboxed frame without `allow-same-origin`, so it cannot see the admin's
7
+ * stylesheets, and its CSP allows only its own files. Values posted in a message are the only way
8
+ * its screens can match the admin and follow a light/dark or admin-theme change. The surface client
9
+ * applies them as custom properties on its root (CSSOM, which the CSP allows; never a style
10
+ * attribute or a stylesheet), so a surface writes `var(--jini-primary, <fallback>)` and looks right
11
+ * with or without a host that sends tokens.
12
+ *
13
+ * Values are text a host computed from its own CSS; anything that could fetch (`url(`, `image-set(`)
14
+ * or leave a declaration (`;`, braces) is dropped here and again in the surface client.
15
+ */
16
+ import { ADMIN_SURFACE_PROTOCOL, ADMIN_SURFACE_PROTOCOL_VERSION } from './protocol.js';
17
+ /** The shared vocabulary: colours, type, radius, spacing, depth and focus. A host may send fewer. */
18
+ export declare const ADMIN_SURFACE_THEME_TOKENS: readonly ["--jini-bg", "--jini-surface", "--jini-bg-subtle", "--jini-text", "--jini-text-muted", "--jini-border", "--jini-border-strong", "--jini-primary", "--jini-primary-ink", "--jini-link", "--jini-danger", "--jini-danger-bg", "--jini-success", "--jini-success-bg", "--jini-warning", "--jini-warning-bg", "--jini-font-ui", "--jini-font-mono", "--jini-font-size-xs", "--jini-font-size-sm", "--jini-font-size-base", "--jini-font-size-md", "--jini-radius-sm", "--jini-radius", "--jini-radius-md", "--jini-radius-pill", "--jini-space-1", "--jini-space-2", "--jini-space-3", "--jini-space-4", "--jini-shadow-xs", "--jini-shadow-sm", "--jini-control-bg", "--jini-control-border", "--jini-control-shadow-focus", "--jini-overlay-tooltip-bg", "--jini-overlay-tooltip-text", "--jini-overlay-tooltip-border"];
19
+ export type AdminSurfaceThemeToken = (typeof ADMIN_SURFACE_THEME_TOKENS)[number];
20
+ export type AdminSurfaceColorScheme = 'light' | 'dark';
21
+ /** What a surface receives: the scheme for native controls plus the token values. */
22
+ export interface AdminSurfaceTheme {
23
+ readonly scheme: AdminSurfaceColorScheme;
24
+ readonly tokens: Readonly<Partial<Record<AdminSurfaceThemeToken, string>>>;
25
+ }
26
+ /** Host page -> surface after init, whenever the admin's theme or colour scheme changes. */
27
+ export interface AdminSurfaceThemeMessage {
28
+ readonly protocol: typeof ADMIN_SURFACE_PROTOCOL;
29
+ readonly version: typeof ADMIN_SURFACE_PROTOCOL_VERSION;
30
+ readonly kind: 'theme';
31
+ readonly mountId: string;
32
+ readonly theme: AdminSurfaceTheme;
33
+ }
34
+ /** Whether `value` is plain declaration text that cannot fetch anything or end its declaration.
35
+ * @complexity O(n) in the value length. */
36
+ export declare function isSafeAdminSurfaceThemeValue(value: unknown): value is string;
37
+ /**
38
+ * Reads the shared tokens from the host's computed style.
39
+ * @param required.style - Usually `getComputedStyle(element)` for the element the admin theme is on.
40
+ * @param optional.sources - Where to read a token when the host draws with its own name for it
41
+ * (e.g. `{ '--jini-text': '--fg' }`); unnamed tokens are read under their own name.
42
+ * @returns Only the tokens with a safe, non-empty value.
43
+ * @complexity O(t) tokens.
44
+ */
45
+ export declare function readAdminSurfaceTheme(required: {
46
+ readonly style: {
47
+ getPropertyValue(name: string): string;
48
+ };
49
+ readonly scheme: AdminSurfaceColorScheme;
50
+ }, optional?: {
51
+ readonly sources?: Readonly<Partial<Record<AdminSurfaceThemeToken, string>>>;
52
+ }): AdminSurfaceTheme;
53
+ /** Builds the envelope that sends a changed theme to one mount's frame.
54
+ * @complexity O(1). */
55
+ export declare function adminSurfaceThemeMessage(required: {
56
+ readonly mountId: string;
57
+ readonly theme: AdminSurfaceTheme;
58
+ }, _optional?: Record<string, never>): AdminSurfaceThemeMessage;
59
+ //# sourceMappingURL=theme.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.d.ts","sourceRoot":"","sources":["../../src/admin-surfaces/theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,sBAAsB,EAAE,8BAA8B,EAAE,MAAM,eAAe,CAAC;AAEvF,qGAAqG;AACrG,eAAO,MAAM,0BAA0B,kyBAS5B,CAAC;AAEZ,MAAM,MAAM,sBAAsB,GAAG,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,CAAC,CAAC;AACjF,MAAM,MAAM,uBAAuB,GAAG,OAAO,GAAG,MAAM,CAAC;AAEvD,qFAAqF;AACrF,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;CAC5E;AAED,4FAA4F;AAC5F,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,QAAQ,EAAE,OAAO,sBAAsB,CAAC;IACjD,QAAQ,CAAC,OAAO,EAAE,OAAO,8BAA8B,CAAC;IACxD,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAC;CACnC;AAKD;2CAC2C;AAC3C,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAE5E;AAED;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE;QAAE,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAA;CAAE,EAClH,QAAQ,GAAE;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,sBAAsB,EAAE,MAAM,CAAC,CAAC,CAAC,CAAA;CAAO,GAC9F,iBAAiB,CAOnB;AAED;uBACuB;AACvB,wBAAgB,wBAAwB,CAAC,QAAQ,EAAE;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,iBAAiB,CAAA;CAAE,EAAE,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAM,GAAG,wBAAwB,CAEnL"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * @file The host's design tokens for plugin surfaces: which `--jini-*` custom properties a host
3
+ * shares with every surface frame, how it reads their current values, and the envelope that sends
4
+ * a change after init.
5
+ *
6
+ * Why: a surface is a sandboxed frame without `allow-same-origin`, so it cannot see the admin's
7
+ * stylesheets, and its CSP allows only its own files. Values posted in a message are the only way
8
+ * its screens can match the admin and follow a light/dark or admin-theme change. The surface client
9
+ * applies them as custom properties on its root (CSSOM, which the CSP allows; never a style
10
+ * attribute or a stylesheet), so a surface writes `var(--jini-primary, <fallback>)` and looks right
11
+ * with or without a host that sends tokens.
12
+ *
13
+ * Values are text a host computed from its own CSS; anything that could fetch (`url(`, `image-set(`)
14
+ * or leave a declaration (`;`, braces) is dropped here and again in the surface client.
15
+ */
16
+ import { ADMIN_SURFACE_PROTOCOL, ADMIN_SURFACE_PROTOCOL_VERSION } from './protocol.js';
17
+ /** The shared vocabulary: colours, type, radius, spacing, depth and focus. A host may send fewer. */
18
+ export const ADMIN_SURFACE_THEME_TOKENS = Object.freeze([
19
+ '--jini-bg', '--jini-surface', '--jini-bg-subtle', '--jini-text', '--jini-text-muted',
20
+ '--jini-border', '--jini-border-strong', '--jini-primary', '--jini-primary-ink', '--jini-link',
21
+ '--jini-danger', '--jini-danger-bg', '--jini-success', '--jini-success-bg', '--jini-warning', '--jini-warning-bg',
22
+ '--jini-font-ui', '--jini-font-mono', '--jini-font-size-xs', '--jini-font-size-sm', '--jini-font-size-base', '--jini-font-size-md',
23
+ '--jini-radius-sm', '--jini-radius', '--jini-radius-md', '--jini-radius-pill',
24
+ '--jini-space-1', '--jini-space-2', '--jini-space-3', '--jini-space-4',
25
+ '--jini-shadow-xs', '--jini-shadow-sm', '--jini-control-bg', '--jini-control-border', '--jini-control-shadow-focus',
26
+ '--jini-overlay-tooltip-bg', '--jini-overlay-tooltip-text', '--jini-overlay-tooltip-border',
27
+ ]);
28
+ const MAX_VALUE_LENGTH = 200;
29
+ const UNSAFE_VALUE = /url\(|image\(|image-set\(|[;{}<>\\@]/i;
30
+ /** Whether `value` is plain declaration text that cannot fetch anything or end its declaration.
31
+ * @complexity O(n) in the value length. */
32
+ export function isSafeAdminSurfaceThemeValue(value) {
33
+ return typeof value === 'string' && value.length > 0 && value.length <= MAX_VALUE_LENGTH && !UNSAFE_VALUE.test(value);
34
+ }
35
+ /**
36
+ * Reads the shared tokens from the host's computed style.
37
+ * @param required.style - Usually `getComputedStyle(element)` for the element the admin theme is on.
38
+ * @param optional.sources - Where to read a token when the host draws with its own name for it
39
+ * (e.g. `{ '--jini-text': '--fg' }`); unnamed tokens are read under their own name.
40
+ * @returns Only the tokens with a safe, non-empty value.
41
+ * @complexity O(t) tokens.
42
+ */
43
+ export function readAdminSurfaceTheme(required, optional = {}) {
44
+ const tokens = {};
45
+ for (const token of ADMIN_SURFACE_THEME_TOKENS) {
46
+ const value = required.style.getPropertyValue(optional.sources?.[token] ?? token).trim();
47
+ if (isSafeAdminSurfaceThemeValue(value))
48
+ tokens[token] = value;
49
+ }
50
+ return { scheme: required.scheme, tokens };
51
+ }
52
+ /** Builds the envelope that sends a changed theme to one mount's frame.
53
+ * @complexity O(1). */
54
+ export function adminSurfaceThemeMessage(required, _optional = {}) {
55
+ return { protocol: ADMIN_SURFACE_PROTOCOL, version: ADMIN_SURFACE_PROTOCOL_VERSION, kind: 'theme', mountId: required.mountId, theme: required.theme };
56
+ }
57
+ //# sourceMappingURL=theme.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"theme.js","sourceRoot":"","sources":["../../src/admin-surfaces/theme.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,sBAAsB,EAAE,8BAA8B,EAAE,MAAM,eAAe,CAAC;AAEvF,qGAAqG;AACrG,MAAM,CAAC,MAAM,0BAA0B,GAAG,MAAM,CAAC,MAAM,CAAC;IACtD,WAAW,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,aAAa,EAAE,mBAAmB;IACrF,eAAe,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,aAAa;IAC9F,eAAe,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,mBAAmB;IACjH,gBAAgB,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,qBAAqB;IAClI,kBAAkB,EAAE,eAAe,EAAE,kBAAkB,EAAE,oBAAoB;IAC7E,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,gBAAgB;IACtE,kBAAkB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,uBAAuB,EAAE,6BAA6B;IACnH,2BAA2B,EAAE,6BAA6B,EAAE,+BAA+B;CACnF,CAAC,CAAC;AAoBZ,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAC7B,MAAM,YAAY,GAAG,uCAAuC,CAAC;AAE7D;2CAC2C;AAC3C,MAAM,UAAU,4BAA4B,CAAC,KAAc;IACzD,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,IAAI,gBAAgB,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACxH,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,qBAAqB,CACnC,QAAkH,EAClH,WAA6F,EAAE;IAE/F,MAAM,MAAM,GAAoD,EAAE,CAAC;IACnE,KAAK,MAAM,KAAK,IAAI,0BAA0B,EAAE,CAAC;QAC/C,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,gBAAgB,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;QACzF,IAAI,4BAA4B,CAAC,KAAK,CAAC;YAAE,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;IACjE,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;AAC7C,CAAC;AAED;uBACuB;AACvB,MAAM,UAAU,wBAAwB,CAAC,QAAyE,EAAE,YAAmC,EAAE;IACvJ,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,OAAO,EAAE,8BAA8B,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC;AACxJ,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder-zip-node.d.ts","sourceRoot":"","sources":["../src/folder-zip-node.ts"],"names":[],"mappings":"AAqDA;;;;;GAKG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAAE,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAiB7I"}
@@ -2,6 +2,59 @@ import * as fs from "node:fs/promises";
2
2
  import { constants } from "node:fs";
3
3
  import path from "node:path";
4
4
  import { FOLDER_MAX_FILES, FOLDER_UNREADABLE, FolderZipError, zipFolderFiles } from "./folder-zip.js";
5
+ async function readLocalFile(required, _optional = {}) {
6
+ const { filesystem, root, filename, name, maxBytes } = required;
7
+ if (await filesystem.realpath(filename) !== filename)
8
+ throw new FolderZipError("unreadable", FOLDER_UNREADABLE);
9
+ // O_NOFOLLOW refuses a file replaced with a symlink between enumeration and opening.
10
+ const file = await filesystem.open(filename, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
11
+ try {
12
+ const info = await file.stat();
13
+ if (!info.isFile())
14
+ throw new FolderZipError("unreadable", FOLDER_UNREADABLE);
15
+ const total = required.total + info.size;
16
+ if (total > maxBytes)
17
+ throw new FolderZipError("too-large", "Folder is over the upload limit.");
18
+ // One extra byte detects growth without an unbounded readFile allocation.
19
+ const bytes = Buffer.alloc(info.size + 1);
20
+ let length = 0;
21
+ while (length < bytes.length) {
22
+ const read = await file.read(bytes, length, bytes.length - length, null);
23
+ if (read.bytesRead === 0)
24
+ break;
25
+ length += read.bytesRead;
26
+ }
27
+ if (length !== info.size)
28
+ throw new FolderZipError("unreadable", FOLDER_UNREADABLE);
29
+ const picked = new File([new Uint8Array(bytes.subarray(0, length))], name);
30
+ Object.defineProperty(picked, "webkitRelativePath", { value: `folder/${path.relative(root, filename).split(path.sep).join("/")}` });
31
+ return { file: picked, total };
32
+ }
33
+ finally {
34
+ await file.close();
35
+ }
36
+ }
37
+ async function collectDirectory(required, _optional = {}) {
38
+ const { filesystem, root, directory, collection, maxBytes } = required;
39
+ if (!(await filesystem.lstat(directory)).isDirectory() || await filesystem.realpath(directory) !== directory)
40
+ throw new FolderZipError("unreadable", FOLDER_UNREADABLE);
41
+ const handle = await filesystem.opendir(directory);
42
+ // Mutate the traversal's owned buffers so visiting directories does not copy accumulated files.
43
+ for await (const entry of handle) {
44
+ if (++collection.entries > FOLDER_MAX_FILES)
45
+ throw new FolderZipError("too-many", `More than ${FOLDER_MAX_FILES} entries.`);
46
+ const filename = path.join(directory, entry.name);
47
+ if (entry.isDirectory()) {
48
+ collection.pending.push(filename);
49
+ continue;
50
+ }
51
+ if (!entry.isFile())
52
+ throw new FolderZipError("unreadable", FOLDER_UNREADABLE);
53
+ const result = await readLocalFile({ filesystem, root, filename, name: entry.name, total: collection.total, maxBytes });
54
+ collection.total = result.total;
55
+ collection.files.push(result.file);
56
+ }
57
+ }
5
58
  /** Reads a local folder into the browser upload encoder. Refuses links/special files and bounds
6
59
  * entries and bytes before allocation; the resulting ZIP still requires the install validator.
7
60
  * @throws {FolderZipError} Empty, unreadable, linked, or over-limit folders.
@@ -9,58 +62,15 @@ import { FOLDER_MAX_FILES, FOLDER_UNREADABLE, FolderZipError, zipFolderFiles } f
9
62
  * bounded to 4096 entries and maxBytes. No network I/O.
10
63
  */
11
64
  export async function zipLocalFolder(required, _optional = {}) {
12
- const files = [];
13
- let entries = 0;
14
- let total = 0;
65
+ const collection = { files: [], pending: [], entries: 0, total: 0 };
15
66
  try {
16
67
  const root = await fs.realpath(required.path);
17
- const pending = [root];
18
- while (pending.length) {
19
- const directory = pending.pop();
20
- if (!(await fs.lstat(directory)).isDirectory() || await fs.realpath(directory) !== directory)
21
- throw new FolderZipError("unreadable", FOLDER_UNREADABLE);
22
- const handle = await fs.opendir(directory);
23
- for await (const entry of handle) {
24
- if (++entries > FOLDER_MAX_FILES)
25
- throw new FolderZipError("too-many", `More than ${FOLDER_MAX_FILES} entries.`);
26
- const filename = path.join(directory, entry.name);
27
- if (entry.isDirectory()) {
28
- pending.push(filename);
29
- continue;
30
- }
31
- if (!entry.isFile())
32
- throw new FolderZipError("unreadable", FOLDER_UNREADABLE);
33
- if (await fs.realpath(filename) !== filename)
34
- throw new FolderZipError("unreadable", FOLDER_UNREADABLE);
35
- // O_NOFOLLOW refuses a file replaced with a symlink between enumeration and opening.
36
- const file = await fs.open(filename, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
37
- try {
38
- const info = await file.stat();
39
- if (!info.isFile())
40
- throw new FolderZipError("unreadable", FOLDER_UNREADABLE);
41
- total += info.size;
42
- if (total > required.maxBytes)
43
- throw new FolderZipError("too-large", "Folder is over the upload limit.");
44
- // One extra byte detects growth without an unbounded readFile allocation.
45
- const bytes = Buffer.alloc(info.size + 1);
46
- let length = 0;
47
- while (length < bytes.length) {
48
- const read = await file.read(bytes, length, bytes.length - length, null);
49
- if (read.bytesRead === 0)
50
- break;
51
- length += read.bytesRead;
52
- }
53
- if (length !== info.size)
54
- throw new FolderZipError("unreadable", FOLDER_UNREADABLE);
55
- const picked = new File([new Uint8Array(bytes.subarray(0, length))], entry.name);
56
- Object.defineProperty(picked, "webkitRelativePath", { value: `folder/${path.relative(root, filename).split(path.sep).join("/")}` });
57
- files.push(picked);
58
- }
59
- finally {
60
- await file.close();
61
- }
62
- }
68
+ collection.pending.push(root);
69
+ while (collection.pending.length) {
70
+ const directory = collection.pending.pop();
71
+ await collectDirectory({ filesystem: fs, root, directory, collection, maxBytes: required.maxBytes });
63
72
  }
73
+ const { files } = collection;
64
74
  // Stable order gives repeat local-folder installs identical ZIP digests.
65
75
  files.sort((a, b) => a.webkitRelativePath < b.webkitRelativePath ? -1 : a.webkitRelativePath > b.webkitRelativePath ? 1 : 0);
66
76
  return new Uint8Array(await (await zipFolderFiles({ files, maxBytes: required.maxBytes })).arrayBuffer());
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder-zip-node.js","sourceRoot":"","sources":["../src/folder-zip-node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder-zip.d.ts","sourceRoot":"","sources":["../src/folder-zip.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,0DAA0D;AAC1D,eAAO,MAAM,YAAY,0BAA0B,CAAC;AACpD,eAAO,MAAM,iBAAiB,2CAA2C,CAAC;AAC1E;iCACiC;AACjC,eAAO,MAAM,gBAAgB,OAAO,CAAC;AAErC,qBAAa,cAAe,SAAQ,KAAK;IAC3B,QAAQ,CAAC,MAAM,EAAE,OAAO,GAAG,WAAW,GAAG,UAAU,GAAG,YAAY;gBAAzD,MAAM,EAAE,OAAO,GAAG,WAAW,GAAG,UAAU,GAAG,YAAY,EAAE,OAAO,EAAE,MAAM;CAChG;AAgBD,0CAA0C;AAC1C,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,CAI/C;AAgBD;;;;;;;;;GASG;AACH,wBAAsB,cAAc,CAAC,QAAQ,EAAE;IAAE,KAAK,EAAE,SAAS,IAAI,EAAE,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,EAAE,SAAS,GAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CA2CjJ"}
@@ -50,6 +50,14 @@ function entryPath(file) {
50
50
  const slash = relative.indexOf("/");
51
51
  return slash < 0 ? { folder: "", path: relative } : { folder: relative.slice(0, slash), path: relative.slice(slash + 1) };
52
52
  }
53
+ async function readFolderFile(required, _optional = {}) {
54
+ try {
55
+ return new Uint8Array(await required.file.arrayBuffer());
56
+ }
57
+ catch {
58
+ throw new FolderZipError("unreadable", FOLDER_UNREADABLE);
59
+ }
60
+ }
53
61
  /**
54
62
  * Zips the files of one picked folder.
55
63
  *
@@ -76,13 +84,7 @@ export async function zipFolderFiles(required, _optional = {}) {
76
84
  for (const file of files) {
77
85
  const entry = entryPath(file);
78
86
  folder ||= entry.folder;
79
- let data;
80
- try {
81
- data = new Uint8Array(await file.arrayBuffer());
82
- }
83
- catch {
84
- throw new FolderZipError("unreadable", FOLDER_UNREADABLE);
85
- }
87
+ const data = await readFolderFile({ file });
86
88
  const name = encoder.encode(entry.path);
87
89
  const crc = crc32(data);
88
90
  // Bit 11: the name is UTF-8, so a reader never decodes it as CP437.
@@ -0,0 +1 @@
1
+ {"version":3,"file":"folder-zip.js","sourceRoot":"","sources":["../src/folder-zip.ts"],"names":[],"mappings":"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"}