@bud.sh/app 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (115) hide show
  1. package/README.md +41 -31
  2. package/dist/client/assets/bud/design.js +1 -1
  3. package/dist/client/assets/canvas-Bih9EdKJ.js +1 -0
  4. package/dist/client/assets/difference-worker-Bzg-rizy.js +8 -0
  5. package/dist/client/assets/dist-CdE5wBkg.js +5 -0
  6. package/dist/client/assets/files-1dLuoM2f.js +1 -0
  7. package/dist/client/assets/i18n-CkO6VFI0.js +1 -0
  8. package/dist/client/assets/index-Cn2mxroU.css +2 -0
  9. package/dist/client/assets/{index-ChANGtl-.js → index-DtISWZp9.js} +2 -2
  10. package/dist/client/assets/pages-BJ-tNJ4J.js +1 -0
  11. package/dist/client/assets/{project-branches-DO897zM6.js → project-branches-Ce3rXrkc.js} +1 -1
  12. package/dist/client/assets/project-comments-CPUONfs8.js +1 -0
  13. package/dist/client/assets/project-thread-links-C-TGkq59.js +1 -0
  14. package/dist/client/assets/{project-threads-Lay351p4.js → project-threads-Bv7IDBgi.js} +105 -105
  15. package/dist/client/assets/project-work-DAE9-olg.js +1 -0
  16. package/dist/client/assets/{task-design-Avb2RO4w.js → task-design-CwySIAOl.js} +3 -3
  17. package/dist/client/assets/tasks-KWsCLi_h.js +3 -0
  18. package/dist/client/assets/wasm-inline-DSUyFn1L.js +1 -0
  19. package/dist/client/assets/workspace-CVdcfaaB.js +2 -0
  20. package/dist/client/index.html +3 -3
  21. package/dist/hosted/assets/{canvas-V36732ER.js → canvas-AII16n9i.js} +97 -6
  22. package/dist/hosted/assets/{comment-data-CF2ZV_3k.js → comment-data-BXfMElfx.js} +2004 -402
  23. package/dist/hosted/assets/dist-BCSTeNf4.js +4785 -0
  24. package/dist/hosted/assets/{files-DjSCjfU7.js → files-D_1yeAVO.js} +10 -5
  25. package/dist/hosted/assets/{pages-BzjzeuPu.js → pages-CN_SbKWA.js} +3 -3
  26. package/dist/hosted/assets/{project-branches-BT97J9i7.js → project-branches-Bxp0DCwg.js} +1 -1
  27. package/dist/hosted/assets/{project-thread-links-BRLgByEe.js → project-thread-links-KqQoKBLE.js} +76 -4
  28. package/dist/{node-host/assets/screen-CZXWJEds.js → hosted/assets/screen-DpAcDUKR.js} +29 -1
  29. package/dist/hosted/assets/tasks-D66LlwxM.js +1423 -0
  30. package/dist/hosted/assets/wasm-inline-Dl9tqabx.js +4 -0
  31. package/dist/hosted/hosted.js +7885 -6219
  32. package/dist/node/assets/Stream-CAm1eJ2n.js +16604 -0
  33. package/dist/{server/assets/bridge-B_Blt55E.js → node/assets/bridge-DQSBYHmw.js} +124 -290
  34. package/dist/node/assets/config-9_jWwNBh.js +1067 -0
  35. package/dist/node/assets/load-config.server-CMVtRVmO.js +261 -0
  36. package/dist/node/assets/module-3GgtT4Xs.js +308 -0
  37. package/dist/node/assets/server-DTQFuoX2.js +846 -0
  38. package/dist/node/assets/src-D-kG1GxB.js +2 -0
  39. package/dist/node/assets/{src-CerrKjID.js → src-Dwe9APUx.js} +93 -3
  40. package/dist/node/assets/src-DysjfbM8.js +8592 -0
  41. package/dist/node/bridge.js +1 -845
  42. package/dist/node/cli.js +206 -0
  43. package/dist/node/design.js +811 -13
  44. package/dist/node/index.js +2 -739
  45. package/dist/node/plugins.js +5711 -0
  46. package/dist/node/server.js +1 -6746
  47. package/dist/node/vite.js +121 -0
  48. package/dist/{server/assets/canvas-Dc1mYCwQ.js → node-host/assets/canvas-BeDoufy1.js} +97 -7
  49. package/dist/node-host/assets/{comment-data-DyIZNpfG.js → comment-data-DE2T9yTj.js} +1980 -376
  50. package/dist/node-host/assets/dist-BCSTeNf4.js +4785 -0
  51. package/dist/node-host/assets/{files-Dh2TiQZq.js → files-Dl-PTS09.js} +11 -6
  52. package/dist/node-host/assets/{pages-BxpjbYhs.js → pages-DL2sk6_U.js} +3 -3
  53. package/dist/node-host/assets/{project-branches-B7HUGiVK.js → project-branches-DGp5ELct.js} +1 -1
  54. package/dist/{server/assets/project-thread-links-CBOpf6zk.js → node-host/assets/project-thread-links-CgBV3Jcm.js} +76 -5
  55. package/dist/{hosted/assets/screen-CKp2C7kx.js → node-host/assets/screen-B55yyVfb.js} +29 -1
  56. package/dist/node-host/assets/tasks-DZRNkoxe.js +1425 -0
  57. package/dist/node-host/assets/wasm-inline-Dl9tqabx.js +4 -0
  58. package/dist/node-host/node-host.js +6127 -4438
  59. package/dist/server/assets/{branch-previews-ClkoJ0lM.js → branch-previews-DedrpnVR.js} +1555 -673
  60. package/dist/{node-host/assets/canvas-TRUfxfL5.js → server/assets/canvas-CJWQ-jjv.js} +98 -6
  61. package/dist/server/assets/{comment-data-CsjukwAW.js → comment-data-Rg42ToTW.js} +1666 -47
  62. package/dist/server/assets/dist-BCSTeNf4.js +4785 -0
  63. package/dist/server/assets/{events-iHpLGr3k.js → events-BH_rAu7O.js} +155 -20
  64. package/dist/server/assets/{files-E9mSFeoc.js → files-CPJqKeMo.js} +12 -7
  65. package/dist/server/assets/{listener-DN5TyOjJ.js → listener-D61O6PzF.js} +708 -12
  66. package/dist/server/assets/{pages-BBBXyJWV.js → pages-KJY_Ba92.js} +4 -4
  67. package/dist/server/assets/{project-branches-B0YIK6Ur.js → project-branches-qG9ACZvo.js} +2 -2
  68. package/dist/{node-host/assets/project-thread-links-CauJF0Cz.js → server/assets/project-thread-links-CqK0lqCF.js} +77 -4
  69. package/dist/{node-host/assets/tasks-request-ZWmbc8fE.js → server/assets/project-work-DoIwxWMm.js} +87 -2
  70. package/dist/server/assets/run-BJ8r5jSh.js +572 -0
  71. package/dist/server/assets/{screen-BIQA2mr4.js → screen-CBrHPFug.js} +30 -2
  72. package/dist/server/assets/{server-DxK-UB_Z.js → server-Dkbp5stG.js} +1521 -793
  73. package/dist/server/assets/{services-BRrgXYlT.js → services-BTfig8A8.js} +234 -997
  74. package/dist/server/assets/tasks-Bgu5Lg9Y.js +1427 -0
  75. package/dist/server/assets/wasm-inline-Dl9tqabx.js +4 -0
  76. package/dist/server/capture.js +1 -2
  77. package/dist/server/migration.js +569 -12
  78. package/dist/server/runtime.js +7 -5
  79. package/dist/server/server.js +3 -3
  80. package/dist/types/assets/{config-DIC2cf_S.d.ts → config-CvcYmE2s.d.ts} +188 -50
  81. package/dist/types/assets/{contract-CAT-XFNq.d.ts → contract-B7yuuqSn.d.ts} +44 -2
  82. package/dist/types/assets/{items-CaVkByHk.d.ts → items-BQdaVksf.d.ts} +12 -1
  83. package/dist/types/assets/memory-state-BBW-FAVA.d.ts +236 -0
  84. package/dist/types/assets/picker-Be5Gx4WR.d.ts +9 -0
  85. package/dist/types/assets/{task-design-xJOhRNWh.d.ts → task-design-BDHKFHpp.d.ts} +3 -1
  86. package/dist/types/bridge.d.ts +1 -1
  87. package/dist/types/companion.d.ts +3 -3
  88. package/dist/types/design.d.ts +2 -2
  89. package/dist/types/hosted.d.ts +3 -3
  90. package/dist/types/index.d.ts +2 -2
  91. package/dist/types/node-host.d.ts +2 -2
  92. package/dist/types/plugins.d.ts +445 -0
  93. package/dist/types/screen.d.ts +2 -2
  94. package/dist/types/server.d.ts +2 -228
  95. package/dist/types/vite.d.ts +16 -0
  96. package/package.json +19 -3
  97. package/dist/client/assets/canvas-Cu6R6xxT.js +0 -1
  98. package/dist/client/assets/difference-worker-jfTSn-Tw.js +0 -8
  99. package/dist/client/assets/files-js6ElfkU.js +0 -1
  100. package/dist/client/assets/i18n-DxqFr2mi.js +0 -1
  101. package/dist/client/assets/index-CFFxP0gS.css +0 -2
  102. package/dist/client/assets/pages-6_lhiQmz.js +0 -1
  103. package/dist/client/assets/project-comments-DFFKVpia.js +0 -1
  104. package/dist/client/assets/project-thread-links-NLFWQRD2.js +0 -1
  105. package/dist/client/assets/project-work-du0Y-L5Y.js +0 -1
  106. package/dist/client/assets/tasks-CA-E8bbK.js +0 -1
  107. package/dist/client/assets/tasks-request-C55IeuiP.js +0 -1
  108. package/dist/client/assets/workspace-Cw5HvX5d.js +0 -2
  109. package/dist/hosted/assets/tasks-Dj7AyBJB.js +0 -649
  110. package/dist/hosted/assets/tasks-request-DZob623r.js +0 -113
  111. package/dist/node-host/assets/tasks-Bs1IOpeU.js +0 -651
  112. package/dist/server/assets/project-work-qSKFO5yj.js +0 -88
  113. package/dist/server/assets/tasks-CiXodsLN.js +0 -652
  114. package/dist/server/assets/tasks-request-DhwCzpRi.js +0 -115
  115. package/dist/types/assets/picker-D1Bw3ndx.d.ts +0 -14
@@ -0,0 +1,261 @@
1
+ import { n as normalizeOrigin, r as resolveBudConfig } from "./config-9_jWwNBh.js";
2
+ import { A as await_, At as runPromise, Ct as provideContext, Dt as runCallbackWith, Et as runCallback, Ft as runSyncExit, Gt as tryPromise, Ht as sync, It as runSyncExitWith, Jt as withFiber, K as catchIf, Kt as try_, Ln as scopeRemoveFinalizerUnsafe, Lt as runSyncWith, Mn as void_$1, Mt as runPromiseExitWith, Nt as runPromiseWith, Ot as runFork, Pt as runSync, Sn as makeUnsafe, Ur as TaggedError, Ut as tap, X as die, Y as context, _n as provideMerge, _t as mapError, at as flatten, bn as close, dn as buildWithMemoMap, fn as effect, ft as gen, hn as mergeAll, j as runIn, jt as runPromiseExit, kt as runForkWith, mn as makeMemoMapUnsafe, pr as Service, qt as void_, rt as flatMap, vn as succeed, xn as forkUnsafe } from "./Stream-CAm1eJ2n.js";
3
+ import { C as Path, n as readText, t as nodeLayer, w as FileSystem } from "./src-DysjfbM8.js";
4
+ import { randomUUID } from "node:crypto";
5
+ import { pathToFileURL } from "node:url";
6
+ //#region ../project/src/server/errors.ts
7
+ /** Expected project startup/configuration failure; nested causes remain server-only. */
8
+ var ProjectError = class extends TaggedError("ProjectError") {};
9
+ //#endregion
10
+ //#region ../project/src/server/config.ts
11
+ /** Trusted executable configuration; tests replace evaluation independently of filesystem I/O. */
12
+ var ConfigModuleLoader = class extends Service()("@bud.sh/project/ConfigModuleLoader") {};
13
+ var configModuleLoaderLayer = succeed(ConfigModuleLoader, { load: (filename) => tryPromise({
14
+ try: async () => {
15
+ let url = pathToFileURL(filename);
16
+ url.searchParams.set("bud", randomUUID());
17
+ return (await import(
18
+ /* @vite-ignore */
19
+ url.href
20
+ )).default;
21
+ },
22
+ catch: (cause) => new ProjectError({
23
+ reason: "evaluate",
24
+ filename,
25
+ message: `Could not evaluate ${filename}: ${cause instanceof Error ? cause.message : "the config module failed"}`,
26
+ cause
27
+ })
28
+ }) });
29
+ /** Finds, evaluates and validates a project's bud.config.ts. */
30
+ var ProjectConfig = class extends Service()("@bud.sh/project/ProjectConfig") {};
31
+ function projectError(reason, message, filename) {
32
+ return (cause) => new ProjectError({
33
+ reason,
34
+ message,
35
+ filename,
36
+ cause
37
+ });
38
+ }
39
+ /** Discovers exactly one config and validates it before any companion listener is opened. */
40
+ var projectConfigLayer = effect(ProjectConfig, gen(function* () {
41
+ let fs = yield* FileSystem;
42
+ let path = yield* Path;
43
+ let loader = yield* ConfigModuleLoader;
44
+ let boundedRead = yield* context();
45
+ return { load: (directory) => gen(function* () {
46
+ if (typeof directory !== "string" || !directory.trim() || directory.includes("\0")) return yield* new ProjectError({
47
+ reason: "root",
48
+ message: "A valid project directory is required."
49
+ });
50
+ let root = yield* fs.realPath(path.resolve(directory)).pipe(mapError(projectError("root", `Cannot open project directory ${directory}.`)));
51
+ if ((yield* fs.stat(root).pipe(mapError(projectError("root", `Cannot inspect project directory ${root}.`)))).type !== "Directory") return yield* new ProjectError({
52
+ reason: "root",
53
+ message: `${root} is not a project directory.`
54
+ });
55
+ let files = [];
56
+ for (let name of ["bud.config.ts", "bud.config.js"]) {
57
+ let filename = path.join(root, name);
58
+ let info = yield* fs.stat(filename).pipe(catchIf((error) => error.reason._tag === "NotFound", () => void_), mapError(projectError("read", `Cannot inspect ${filename}.`, filename)));
59
+ if (!info) continue;
60
+ if (info.type !== "File") return yield* new ProjectError({
61
+ reason: "invalid",
62
+ filename,
63
+ message: `${filename} must be a regular config file.`
64
+ });
65
+ files.push(filename);
66
+ }
67
+ if (files.length !== 1) return yield* new ProjectError({
68
+ reason: files.length === 0 ? "missing" : "ambiguous",
69
+ message: files.length === 0 ? `Add bud.config.ts or bud.config.js in ${root}.` : "Keep exactly one bud.config.ts or bud.config.js."
70
+ });
71
+ let filename = files[0];
72
+ yield* readText(filename).pipe(provideContext(boundedRead), mapError((cause) => new ProjectError({
73
+ reason: "read",
74
+ filename,
75
+ message: `Cannot read ${filename}: ${cause.message}`,
76
+ cause
77
+ })));
78
+ let value = yield* loader.load(filename);
79
+ return {
80
+ root,
81
+ filename,
82
+ config: yield* try_({
83
+ try: () => resolveBudConfig(value),
84
+ catch: (cause) => new ProjectError({
85
+ reason: "invalid",
86
+ filename,
87
+ message: cause instanceof Error ? cause.message : "Invalid Bud configuration.",
88
+ cause
89
+ })
90
+ })
91
+ };
92
+ }) };
93
+ }));
94
+ Service()("@bud.sh/project/Project");
95
+ var invalidTarget = "The target must be an HTTP(S) origin without a path or credentials.";
96
+ /**
97
+ * Resolves the actual bound target port, retaining an explicit target override.
98
+ * @param config - Validated project configuration.
99
+ * @param address - The live target listener address.
100
+ * @param options - Target transport and host settings.
101
+ * @returns A validated preview origin or a typed startup failure.
102
+ */
103
+ function resolveTargetOrigin(config, address, options = {}) {
104
+ return try_({
105
+ try: () => {
106
+ if (config.targetOrigin) return normalizeOrigin(config.targetOrigin, invalidTarget);
107
+ if (!address || typeof address === "string" || !Number.isInteger(address.port) || address.port < 1 || address.port > 65535) throw new Error("Bud needs a listening Vite HTTP server to discover its port.");
108
+ let wildcard = (value) => [
109
+ "0.0.0.0",
110
+ "::",
111
+ ""
112
+ ].includes(value);
113
+ let host = typeof options.host === "string" && !wildcard(options.host) ? options.host : address.address && !wildcard(address.address) ? address.address : "127.0.0.1";
114
+ if (host.includes(":") && !host.startsWith("[")) host = `[${host}]`;
115
+ return normalizeOrigin(`${options.https ? "https" : "http"}://${host}:${address.port}`, invalidTarget);
116
+ },
117
+ catch: (cause) => new ProjectError({
118
+ reason: "target",
119
+ message: cause instanceof Error ? cause.message : "Cannot resolve the preview origin.",
120
+ cause
121
+ })
122
+ });
123
+ }
124
+ //#endregion
125
+ //#region ../../node_modules/.pnpm/effect@4.0.5/node_modules/effect/dist/ManagedRuntime.js
126
+ var TypeId = "~effect/ManagedRuntime";
127
+ /**
128
+ * Creates a `ManagedRuntime` from a layer.
129
+ *
130
+ * **When to use**
131
+ *
132
+ * Use to create a reusable runtime from a `Layer` for application entry points
133
+ * or integration code that runs many effects without rebuilding services.
134
+ *
135
+ * **Details**
136
+ *
137
+ * The layer is built lazily on first use and its context is cached for
138
+ * subsequent runs. Resources acquired by the layer are owned by the runtime and
139
+ * are released when `dispose` or `disposeEffect` is run. `options.memoMap` can
140
+ * be used to share layer memoization with other layer builds.
141
+ *
142
+ * **Gotchas**
143
+ *
144
+ * Dispose the runtime when it is no longer needed. A runtime cannot be reused
145
+ * after disposal.
146
+ *
147
+ * **Example** (Creating a managed runtime)
148
+ *
149
+ * ```ts import.meta.vitest
150
+ * import { Context, Effect, Layer, ManagedRuntime } from "effect"
151
+ *
152
+ * const notifications: Array<string> = []
153
+ *
154
+ * class Notifications extends Context.Service<Notifications, {
155
+ * readonly notify: (message: string) => Effect.Effect<void>
156
+ * }>()("Notifications") {
157
+ * static readonly layer = Layer.succeed(this)({
158
+ * notify: Effect.fn("Notifications.notify")((message) =>
159
+ * Effect.sync(() => notifications.push(message))
160
+ * )
161
+ * })
162
+ * }
163
+ *
164
+ * const runtime = ManagedRuntime.make(Notifications.layer)
165
+ *
166
+ * const program = Effect.flatMap(
167
+ * Notifications,
168
+ * (_) => _.notify("Hello, world!")
169
+ * ).pipe(Effect.ensuring(runtime.disposeEffect))
170
+ *
171
+ * await runtime.runPromise(program)
172
+ * notifications // => ["Hello, world!"]
173
+ * ```
174
+ *
175
+ * @see {@link ManagedRuntime} for the returned runtime interface
176
+ * @see {@link Layer.MemoMap} for shared layer memoization
177
+ * @see {@link Layer.build} for lower-level scoped layer construction
178
+ *
179
+ * @stability stable
180
+ * @category constructors
181
+ * @since 2.0.0
182
+ */
183
+ var make = (layer, options) => {
184
+ const memoMap = options?.memoMap ?? makeMemoMapUnsafe();
185
+ const scope = makeUnsafe("sequential");
186
+ const layerScope = forkUnsafe(scope, "sequential");
187
+ const fiberScope = forkUnsafe(scope, "parallel");
188
+ const defaultRunOptions = { onFiberStart: runIn(fiberScope) };
189
+ const mergeRunOptions = (options) => options ? {
190
+ ...options,
191
+ onFiberStart: options.onFiberStart ? (fiber) => {
192
+ defaultRunOptions.onFiberStart(fiber);
193
+ options.onFiberStart(fiber);
194
+ } : defaultRunOptions.onFiberStart
195
+ } : defaultRunOptions;
196
+ let buildFiber;
197
+ const contextEffect = withFiber((fiber) => {
198
+ if (!buildFiber) buildFiber = runFork(tap(buildWithMemoMap(layer, memoMap, layerScope), (context) => sync(() => {
199
+ self.cachedContext = context;
200
+ })), {
201
+ ...defaultRunOptions,
202
+ scheduler: fiber.cache.scheduler
203
+ });
204
+ return flatten(await_(buildFiber));
205
+ });
206
+ const self = {
207
+ [TypeId]: TypeId,
208
+ memoMap,
209
+ scope,
210
+ contextEffect,
211
+ cachedContext: void 0,
212
+ context() {
213
+ return self.cachedContext === void 0 ? runPromise(self.contextEffect) : Promise.resolve(self.cachedContext);
214
+ },
215
+ dispose() {
216
+ return runPromise(self.disposeEffect);
217
+ },
218
+ [Symbol.asyncDispose]() {
219
+ return self.dispose();
220
+ },
221
+ disposeEffect: withFiber((fiber) => {
222
+ for (let current = fiber; current; current = current._parent) scopeRemoveFinalizerUnsafe(fiberScope, current);
223
+ self.contextEffect = die("ManagedRuntime disposed");
224
+ self.cachedContext = void 0;
225
+ return close(self.scope, void_$1);
226
+ }),
227
+ runFork(effect, options) {
228
+ return self.cachedContext === void 0 ? runFork(provide(self, effect), mergeRunOptions(options)) : runForkWith(self.cachedContext)(effect, mergeRunOptions(options));
229
+ },
230
+ runCallback(effect, options) {
231
+ return self.cachedContext === void 0 ? runCallback(provide(self, effect), mergeRunOptions(options)) : runCallbackWith(self.cachedContext)(effect, mergeRunOptions(options));
232
+ },
233
+ runSyncExit(effect) {
234
+ return self.cachedContext === void 0 ? runSyncExit(provide(self, effect)) : runSyncExitWith(self.cachedContext)(effect);
235
+ },
236
+ runSync(effect) {
237
+ return self.cachedContext === void 0 ? runSync(provide(self, effect)) : runSyncWith(self.cachedContext)(effect);
238
+ },
239
+ runPromiseExit(effect, options) {
240
+ return self.cachedContext === void 0 ? runPromiseExit(provide(self, effect), mergeRunOptions(options)) : runPromiseExitWith(self.cachedContext)(effect, mergeRunOptions(options));
241
+ },
242
+ runPromise(effect, options) {
243
+ return self.cachedContext === void 0 ? runPromise(provide(self, effect), mergeRunOptions(options)) : runPromiseWith(self.cachedContext)(effect, mergeRunOptions(options));
244
+ }
245
+ };
246
+ return self;
247
+ };
248
+ function provide(managed, effect) {
249
+ return flatMap(managed.contextEffect, (context) => provideContext(effect, context));
250
+ }
251
+ //#endregion
252
+ //#region src/host/load-config.server.ts
253
+ /**
254
+ * A Node runtime that loads and resolves a project's bud.config.ts; dispose it when done.
255
+ * @returns The managed runtime.
256
+ */
257
+ function createConfigRuntime() {
258
+ return make(provideMerge(projectConfigLayer, mergeAll(nodeLayer(), configModuleLoaderLayer)));
259
+ }
260
+ //#endregion
261
+ export { ProjectError as i, resolveTargetOrigin as n, ProjectConfig as r, createConfigRuntime as t };
@@ -0,0 +1,308 @@
1
+ //#region ../picker-react-grab/src/lib/adapter.ts
2
+ /**
3
+ * The page side of `bud:react` and `bud:react-grab`: an element's component and source come from
4
+ * React's development build, its block is the component's outermost element, and with React Grab
5
+ * its own selection picks. It runs in the project's pages as module or script text, so it must not
6
+ * reference anything outside its own body. The line comes from React's own stack, mapped through
7
+ * the module's source map, so it is exact whichever React Grab a project runs; React Grab's own
8
+ * answer fills in what that can't find. Production builds keep no source, so only the DOM picker's
9
+ * own description remains.
10
+ * @param grab - The project's `react-grab` module, or null to read React alone. Importing it
11
+ * starts React Grab if it isn't yet.
12
+ * @param helpers - Resolves file names and source map positions.
13
+ * @returns The picker adapter.
14
+ */
15
+ function reactGrabAdapter(grab, helpers) {
16
+ let { sourceFile, projectFrames, sourceMapLookup } = helpers;
17
+ let plugin = "bud:picker";
18
+ let maps = /* @__PURE__ */ new Map();
19
+ let host = 5;
20
+ function fiberOf(element) {
21
+ let key = Object.keys(element).find((name) => name.startsWith("__reactFiber$"));
22
+ return key ? element[key] ?? null : null;
23
+ }
24
+ function outermost(component) {
25
+ let node = component.child;
26
+ while (node && node.tag !== host) node = node.child;
27
+ return node?.stateNode instanceof Element ? node.stateNode : null;
28
+ }
29
+ function sourceMap(url) {
30
+ let cached = maps.get(url);
31
+ if (cached) return cached;
32
+ cached = fetch(url).then((response) => response.ok ? response.text() : "").then(async (text) => {
33
+ let reference = /\/\/[#@] sourceMappingURL=(\S+)\s*$/.exec(text)?.[1];
34
+ let address = new URL(reference ?? `${url.replace(/[?#].*$/, "")}.map`, url);
35
+ if (address.protocol !== "data:" && address.origin !== location.origin) return null;
36
+ let response = await fetch(address);
37
+ let map = response.ok ? await response.json() : null;
38
+ let lookup = map && typeof map === "object" ? sourceMapLookup(map) : null;
39
+ return lookup ? {
40
+ lookup,
41
+ base: address.protocol === "data:" ? url : address.href
42
+ } : null;
43
+ }).catch(() => null);
44
+ maps.set(url, cached);
45
+ if (maps.size > 50) maps.delete(maps.keys().next().value);
46
+ return cached;
47
+ }
48
+ function servedPath(source, base, stack) {
49
+ if (source.startsWith("/") && !source.startsWith("//")) return sourceFile(source, stack, location.origin);
50
+ let url = new URL(source, base);
51
+ return url.origin === location.origin && !url.pathname.startsWith("/@") && !url.pathname.includes("/node_modules/") ? url.pathname : null;
52
+ }
53
+ async function written(stack) {
54
+ let frames = projectFrames(stack, location.origin);
55
+ for (let frame of frames) {
56
+ let map = await sourceMap(frame.url);
57
+ let position = map ? map.lookup(frame.line, frame.column) : {
58
+ source: frame.url,
59
+ line: frame.line,
60
+ column: frame.column
61
+ };
62
+ if (!position) continue;
63
+ let file = servedPath(position.source, map?.base ?? frame.url, stack);
64
+ if (file) return {
65
+ name: frame.name,
66
+ file,
67
+ line: position.line,
68
+ column: position.column
69
+ };
70
+ }
71
+ return frames[0] ? {
72
+ name: frames[0].name,
73
+ file: null,
74
+ line: null,
75
+ column: null
76
+ } : null;
77
+ }
78
+ function ownerName(element) {
79
+ let type = fiberOf(element)?._debugOwner?.type;
80
+ let name = type && typeof type === "object" ? type.displayName ?? type.name : null;
81
+ return typeof name === "string" && name ? name : null;
82
+ }
83
+ let adapter = {
84
+ async describe(element) {
85
+ let api = grab?.getGlobalApi() ?? null;
86
+ let stack = fiberOf(element)?._debugStack?.stack ?? "";
87
+ let mapped = stack ? await written(stack).catch(() => null) : null;
88
+ let found = !mapped?.file && api ? await api.getSource(element).catch(() => null) : null;
89
+ let component = mapped?.name ?? found?.componentName ?? api?.getDisplayName(element) ?? ownerName(element);
90
+ if (!mapped?.file && !found && !component) return null;
91
+ if (mapped?.file) return { source: {
92
+ component: component || null,
93
+ file: mapped.file,
94
+ line: mapped.line,
95
+ column: mapped.column
96
+ } };
97
+ let file = found?.filePath ? sourceFile(found.filePath, stack, location.origin) : null;
98
+ let line = found?.lineNumber && found.lineNumber > 0 ? found.lineNumber : null;
99
+ let column = found?.columnNumber != null && found.columnNumber >= 0 ? found.columnNumber + 1 : null;
100
+ return { source: {
101
+ component: component || null,
102
+ file,
103
+ line,
104
+ column
105
+ } };
106
+ },
107
+ block(element) {
108
+ for (let owner = fiberOf(element)?._debugOwner; owner; owner = owner._debugOwner) {
109
+ let outer = outermost(owner);
110
+ if (outer && outer !== document.body && outer.contains(element)) return outer;
111
+ }
112
+ return null;
113
+ }
114
+ };
115
+ if (!grab) return adapter;
116
+ return {
117
+ ...adapter,
118
+ pick(signal) {
119
+ let api = grab.getGlobalApi();
120
+ if (!api || signal.aborted) return Promise.resolve(null);
121
+ return new Promise((resolve) => {
122
+ let settled = false;
123
+ let tidy = () => {
124
+ api.unregisterPlugin(plugin);
125
+ if (api.isActive()) api.deactivate();
126
+ };
127
+ let finish = (element, during) => {
128
+ if (settled) return;
129
+ settled = true;
130
+ signal.removeEventListener("abort", cancel);
131
+ resolve(element);
132
+ if (during) setTimeout(tidy, 1e3);
133
+ else tidy();
134
+ };
135
+ let cancel = () => finish(null, false);
136
+ signal.addEventListener("abort", cancel, { once: true });
137
+ api.unregisterPlugin(plugin);
138
+ api.registerPlugin({
139
+ name: plugin,
140
+ theme: { grabbedBoxes: { enabled: false } },
141
+ hooks: {
142
+ onElementSelect(element) {
143
+ finish(element, true);
144
+ return true;
145
+ },
146
+ onDeactivate: () => finish(null, true)
147
+ }
148
+ });
149
+ api.activate();
150
+ });
151
+ }
152
+ };
153
+ }
154
+ //#endregion
155
+ //#region ../picker-react-grab/src/lib/source-map.ts
156
+ /**
157
+ * The frames of React's stack for an element that may have run in the project's own code, in
158
+ * order: the first one whose source is the project's is the component that rendered it.
159
+ * Dependencies the dev server serves apart, Vite's own modules and other origins are left out; a
160
+ * build bundles dependencies with the project, so their frames stay for their source maps to
161
+ * tell apart. It runs in the project's pages as module text, so it must not reference anything
162
+ * outside its own body.
163
+ * @param stack - React's stack for the element, as `Error.stack` text.
164
+ * @param origin - The page's origin.
165
+ * @returns The frames, possibly none.
166
+ */
167
+ function projectFrames(stack, origin) {
168
+ let frames = [];
169
+ for (let text of stack.split("\n")) {
170
+ let match = /^\s*at (?:(.+?) \()?(https?:\/\/[^\s()]+?):(\d+):(\d+)\)?\s*$/.exec(text);
171
+ if (!match) continue;
172
+ let url = new URL(match[2]);
173
+ if (url.origin !== origin || url.pathname.startsWith("/@") || url.pathname.includes("/node_modules/")) continue;
174
+ let name = match[1]?.replace(/^Object\./, "") ?? null;
175
+ frames.push({
176
+ name,
177
+ url: url.href,
178
+ line: Number(match[3]),
179
+ column: Number(match[4])
180
+ });
181
+ }
182
+ return frames;
183
+ }
184
+ /**
185
+ * Decodes a module's source map once, for looking up many positions in it. It runs in the
186
+ * project's pages as module text, so it must not reference anything outside its own body.
187
+ * @param map - The source map, as parsed JSON.
188
+ * @returns Maps a generated line and column, counted from one, to the original position; null
189
+ * for a map that can't be read.
190
+ */
191
+ function sourceMapLookup(map) {
192
+ if (typeof map.mappings !== "string" || !Array.isArray(map.sources)) return null;
193
+ let sources = map.sources;
194
+ let root = typeof map.sourceRoot === "string" && map.sourceRoot ? map.sourceRoot : "";
195
+ let digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
196
+ let lines = [];
197
+ let source = 0;
198
+ let sourceLine = 0;
199
+ let sourceColumn = 0;
200
+ for (let text of map.mappings.split(";")) {
201
+ let generated = 0;
202
+ let segments = [];
203
+ for (let segment of text.split(",")) {
204
+ if (!segment) continue;
205
+ let values = [];
206
+ let value = 0;
207
+ let shift = 0;
208
+ for (let character of segment) {
209
+ let digit = digits.indexOf(character);
210
+ if (digit < 0) return null;
211
+ value += (digit & 31) << shift;
212
+ if (digit & 32) shift += 5;
213
+ else {
214
+ values.push(value & 1 ? -(value >>> 1) : value >>> 1);
215
+ value = 0;
216
+ shift = 0;
217
+ }
218
+ }
219
+ generated += values[0] ?? 0;
220
+ if (values.length < 4) continue;
221
+ source += values[1];
222
+ sourceLine += values[2];
223
+ sourceColumn += values[3];
224
+ segments.push([
225
+ generated,
226
+ source,
227
+ sourceLine,
228
+ sourceColumn
229
+ ]);
230
+ }
231
+ lines.push(segments);
232
+ }
233
+ return (line, column) => {
234
+ let found = null;
235
+ for (let segment of lines[line - 1] ?? []) if (segment[0] <= column - 1) found = segment;
236
+ let name = found ? sources[found[1]] : null;
237
+ if (!found || typeof name !== "string") return null;
238
+ return {
239
+ source: root ? `${root.replace(/\/$/, "")}/${name}` : name,
240
+ line: found[2] + 1,
241
+ column: found[3] + 1
242
+ };
243
+ };
244
+ }
245
+ //#endregion
246
+ //#region ../picker-react-grab/src/lib/source.ts
247
+ /**
248
+ * The project path of a file React Grab names. React Grab maps React's stack through the dev
249
+ * server's source maps, whose sources are relative to the module that names them (Vite writes
250
+ * `card.tsx` for `/src/components/card.tsx`). The module's address is still in React's own stack,
251
+ * so the file resolves against the first frame from the page's origin that shares its name. It runs
252
+ * in the project's pages as module text, so it must not reference anything outside its own body.
253
+ * @param file - The file React Grab reported: a name, a relative or absolute path, or a URL.
254
+ * @param stack - React's stack for the element, as `Error.stack` text.
255
+ * @param origin - The page's origin; frames from elsewhere are never the project's.
256
+ * @returns A path as the dev server serves it, such as `/src/components/card.tsx`, or null.
257
+ */
258
+ function sourceFile(file, stack, origin) {
259
+ let served = (url) => url.origin === origin && !url.pathname.startsWith("/@") && !url.pathname.includes("/node_modules/") && !/[\\\u0000-\u001f\u007f]/.test(url.pathname);
260
+ if (/^https?:\/\//.test(file)) {
261
+ let url = new URL(file);
262
+ return served(url) ? url.pathname : null;
263
+ }
264
+ let name = file.split("/").pop();
265
+ for (let line of stack.split("\n")) {
266
+ let match = /(https?:\/\/[^\s()]+?)(?::\d+){1,2}\)?\s*$/.exec(line);
267
+ if (!match) continue;
268
+ let frame = new URL(match[1]);
269
+ if (!served(frame) || frame.pathname.split("/").pop() !== name) continue;
270
+ if (file.startsWith("/")) return file.endsWith(frame.pathname) ? frame.pathname : null;
271
+ let resolved = new URL(file, frame);
272
+ return served(resolved) ? resolved.pathname : null;
273
+ }
274
+ return null;
275
+ }
276
+ //#endregion
277
+ //#region ../picker-react-grab/src/lib/module.ts
278
+ /** The React Grab picker's name in `bud.config`. */
279
+ var REACT_GRAB_PICKER = "bud:react-grab";
280
+ /** The picker that reads React alone, without React Grab, in `bud.config`. */
281
+ var REACT_PICKER = "bud:react";
282
+ function helpers() {
283
+ return [
284
+ "{",
285
+ ` sourceFile: ${sourceFile.toString()},`,
286
+ ` projectFrames: ${projectFrames.toString()},`,
287
+ ` sourceMapLookup: ${sourceMapLookup.toString()},`,
288
+ "}"
289
+ ].join("\n");
290
+ }
291
+ /**
292
+ * The adapter's page module text. It imports `react-grab` from the project, so React Grab must be
293
+ * installed there; the dev server serves the same instance the project's pages use.
294
+ * @returns ES module text whose default export is the picker adapter.
295
+ */
296
+ function reactGrabAdapterModule() {
297
+ return ["import * as grab from 'react-grab'", `export default (${reactGrabAdapter.toString()})(grab, ${helpers()})`].join("\n");
298
+ }
299
+ /**
300
+ * An expression that builds the React adapter without React Grab, for module or script text.
301
+ * It needs nothing from the project, so pages without a dev server can run it too.
302
+ * @returns JavaScript expression text evaluating to the picker adapter.
303
+ */
304
+ function reactAdapterExpression() {
305
+ return `(${reactGrabAdapter.toString()})(null, ${helpers()})`;
306
+ }
307
+ //#endregion
308
+ export { reactGrabAdapterModule as i, REACT_PICKER as n, reactAdapterExpression as r, REACT_GRAB_PICKER as t };