@bud.sh/app 0.5.1 → 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.
- package/README.md +41 -31
- package/dist/client/assets/bud/design.js +1 -1
- package/dist/client/assets/canvas-Bih9EdKJ.js +1 -0
- package/dist/client/assets/difference-worker-Bzg-rizy.js +8 -0
- package/dist/client/assets/dist-CdE5wBkg.js +5 -0
- package/dist/client/assets/files-1dLuoM2f.js +1 -0
- package/dist/client/assets/i18n-CkO6VFI0.js +1 -0
- package/dist/client/assets/index-Cn2mxroU.css +2 -0
- package/dist/client/assets/{index-Dn2pfmXf.js → index-DtISWZp9.js} +2 -2
- package/dist/client/assets/pages-BJ-tNJ4J.js +1 -0
- package/dist/client/assets/{project-branches-CMGRmrqr.js → project-branches-Ce3rXrkc.js} +1 -1
- package/dist/client/assets/project-comments-CPUONfs8.js +1 -0
- package/dist/client/assets/project-thread-links-C-TGkq59.js +1 -0
- package/dist/client/assets/{project-threads-ZbKDh78d.js → project-threads-Bv7IDBgi.js} +105 -105
- package/dist/client/assets/project-work-DAE9-olg.js +1 -0
- package/dist/client/assets/{task-design-BPpc4Gd7.js → task-design-CwySIAOl.js} +3 -3
- package/dist/client/assets/tasks-KWsCLi_h.js +3 -0
- package/dist/client/assets/wasm-inline-DSUyFn1L.js +1 -0
- package/dist/client/assets/workspace-CVdcfaaB.js +2 -0
- package/dist/client/index.html +3 -3
- package/dist/hosted/assets/{canvas-BYTOp1p7.js → canvas-AII16n9i.js} +97 -6
- package/dist/hosted/assets/{comment-data-Cn5y2VxV.js → comment-data-BXfMElfx.js} +1998 -381
- package/dist/hosted/assets/dist-BCSTeNf4.js +4785 -0
- package/dist/hosted/assets/{files-B1P2_24q.js → files-D_1yeAVO.js} +10 -5
- package/dist/hosted/assets/{pages-B0ZlVdci.js → pages-CN_SbKWA.js} +3 -3
- package/dist/hosted/assets/{project-branches-DlCWmfRo.js → project-branches-Bxp0DCwg.js} +1 -1
- package/dist/hosted/assets/{project-thread-links-BZXQ200n.js → project-thread-links-KqQoKBLE.js} +76 -4
- package/dist/{node-host/assets/screen-DapOVrga.js → hosted/assets/screen-DpAcDUKR.js} +25 -1
- package/dist/hosted/assets/tasks-D66LlwxM.js +1423 -0
- package/dist/hosted/assets/wasm-inline-Dl9tqabx.js +4 -0
- package/dist/hosted/hosted.js +7885 -6219
- package/dist/node/assets/Stream-CAm1eJ2n.js +16604 -0
- package/dist/{server/assets/bridge-B_Blt55E.js → node/assets/bridge-DQSBYHmw.js} +124 -290
- package/dist/node/assets/config-9_jWwNBh.js +1067 -0
- package/dist/node/assets/load-config.server-CMVtRVmO.js +261 -0
- package/dist/node/assets/module-3GgtT4Xs.js +308 -0
- package/dist/node/assets/server-DTQFuoX2.js +846 -0
- package/dist/node/assets/src-D-kG1GxB.js +2 -0
- package/dist/node/assets/{src-CerrKjID.js → src-Dwe9APUx.js} +93 -3
- package/dist/node/assets/src-DysjfbM8.js +8592 -0
- package/dist/node/bridge.js +1 -845
- package/dist/node/cli.js +206 -0
- package/dist/node/design.js +811 -8
- package/dist/node/index.js +2 -739
- package/dist/node/plugins.js +5711 -0
- package/dist/node/server.js +1 -6746
- package/dist/node/vite.js +121 -0
- package/dist/{server/assets/canvas-CkMK4hoN.js → node-host/assets/canvas-BeDoufy1.js} +97 -7
- package/dist/node-host/assets/{comment-data-yfWEdDQL.js → comment-data-DE2T9yTj.js} +1974 -355
- package/dist/node-host/assets/dist-BCSTeNf4.js +4785 -0
- package/dist/node-host/assets/{files-anHi-apm.js → files-Dl-PTS09.js} +11 -6
- package/dist/node-host/assets/{pages-CW4aF6dK.js → pages-DL2sk6_U.js} +3 -3
- package/dist/node-host/assets/{project-branches-D7rVCxQX.js → project-branches-DGp5ELct.js} +1 -1
- package/dist/{server/assets/project-thread-links-lLS_rq7c.js → node-host/assets/project-thread-links-CgBV3Jcm.js} +76 -5
- package/dist/{hosted/assets/screen-CfdC3NbR.js → node-host/assets/screen-B55yyVfb.js} +25 -1
- package/dist/node-host/assets/tasks-DZRNkoxe.js +1425 -0
- package/dist/node-host/assets/wasm-inline-Dl9tqabx.js +4 -0
- package/dist/node-host/node-host.js +6127 -4438
- package/dist/server/assets/{branch-previews-ClkoJ0lM.js → branch-previews-DedrpnVR.js} +1555 -673
- package/dist/{node-host/assets/canvas-DxmcFZCh.js → server/assets/canvas-CJWQ-jjv.js} +98 -6
- package/dist/server/assets/{comment-data-NLeHG89b.js → comment-data-Rg42ToTW.js} +1660 -26
- package/dist/server/assets/dist-BCSTeNf4.js +4785 -0
- package/dist/server/assets/{events-iHpLGr3k.js → events-BH_rAu7O.js} +155 -20
- package/dist/server/assets/{files-CRdl489E.js → files-CPJqKeMo.js} +12 -7
- package/dist/server/assets/{listener-BAYn9Q-u.js → listener-D61O6PzF.js} +708 -12
- package/dist/server/assets/{pages-DXVlJlBC.js → pages-KJY_Ba92.js} +4 -4
- package/dist/server/assets/{project-branches-CwTsf6WQ.js → project-branches-qG9ACZvo.js} +2 -2
- package/dist/{node-host/assets/project-thread-links-m-OLpsD9.js → server/assets/project-thread-links-CqK0lqCF.js} +77 -4
- package/dist/{node-host/assets/tasks-request-B0aeNocI.js → server/assets/project-work-DoIwxWMm.js} +87 -2
- package/dist/server/assets/run-BJ8r5jSh.js +572 -0
- package/dist/server/assets/{screen-B1zH_1O3.js → screen-CBrHPFug.js} +26 -2
- package/dist/server/assets/{server-DxK-UB_Z.js → server-Dkbp5stG.js} +1521 -793
- package/dist/server/assets/{services-BRrgXYlT.js → services-BTfig8A8.js} +234 -997
- package/dist/server/assets/tasks-Bgu5Lg9Y.js +1427 -0
- package/dist/server/assets/wasm-inline-Dl9tqabx.js +4 -0
- package/dist/server/capture.js +1 -2
- package/dist/server/migration.js +569 -12
- package/dist/server/runtime.js +7 -5
- package/dist/server/server.js +3 -3
- package/dist/types/assets/{config-DIC2cf_S.d.ts → config-CvcYmE2s.d.ts} +188 -50
- package/dist/types/assets/{contract-CAT-XFNq.d.ts → contract-B7yuuqSn.d.ts} +44 -2
- package/dist/types/assets/{items-CaVkByHk.d.ts → items-BQdaVksf.d.ts} +12 -1
- package/dist/types/assets/memory-state-BBW-FAVA.d.ts +236 -0
- package/dist/types/assets/picker-Be5Gx4WR.d.ts +9 -0
- package/dist/types/assets/{task-design-xJOhRNWh.d.ts → task-design-BDHKFHpp.d.ts} +3 -1
- package/dist/types/bridge.d.ts +1 -1
- package/dist/types/companion.d.ts +3 -3
- package/dist/types/design.d.ts +2 -2
- package/dist/types/hosted.d.ts +3 -3
- package/dist/types/index.d.ts +2 -2
- package/dist/types/node-host.d.ts +2 -2
- package/dist/types/plugins.d.ts +445 -0
- package/dist/types/screen.d.ts +2 -2
- package/dist/types/server.d.ts +2 -228
- package/dist/types/vite.d.ts +16 -0
- package/package.json +19 -3
- package/dist/client/assets/canvas-8GXJIuDK.js +0 -1
- package/dist/client/assets/difference-worker-C99ychYw.js +0 -8
- package/dist/client/assets/files-DkWt1l9H.js +0 -1
- package/dist/client/assets/i18n-hH_Ba5QO.js +0 -1
- package/dist/client/assets/index-tpHYVXma.css +0 -2
- package/dist/client/assets/pages-BVd6MQmu.js +0 -1
- package/dist/client/assets/project-comments-D1IIQwsW.js +0 -1
- package/dist/client/assets/project-thread-links-DKwe_SYb.js +0 -1
- package/dist/client/assets/project-work-D4DZqBCZ.js +0 -1
- package/dist/client/assets/tasks-Cn0VOZ9Z.js +0 -1
- package/dist/client/assets/tasks-request-BLyOzokZ.js +0 -1
- package/dist/client/assets/workspace-DGErsSg6.js +0 -2
- package/dist/hosted/assets/tasks-_yKh2Z6q.js +0 -649
- package/dist/hosted/assets/tasks-request-CFPLvLc7.js +0 -113
- package/dist/node-host/assets/tasks-BBK_CybR.js +0 -651
- package/dist/server/assets/project-work-CSZlCwH-.js +0 -88
- package/dist/server/assets/tasks-CGdz-uox.js +0 -652
- package/dist/server/assets/tasks-request-D2NBjCTl.js +0 -115
- package/dist/types/assets/picker-D1Bw3ndx.d.ts +0 -14
package/dist/node/index.js
CHANGED
|
@@ -1,739 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
//#region ../project/src/lib/validate.ts
|
|
4
|
-
var errors = /* @__PURE__ */ new WeakMap();
|
|
5
|
-
/**
|
|
6
|
-
* Validates config, throwing its first problem as the `Error` the config checks report.
|
|
7
|
-
* @param schema - The config schema.
|
|
8
|
-
* @param value - The project's untrusted setting.
|
|
9
|
-
* @returns The validated, normalized setting.
|
|
10
|
-
*/
|
|
11
|
-
function parseConfig(schema, value) {
|
|
12
|
-
let result = parseSafe(schema, value, { abortEarly: true });
|
|
13
|
-
if (result.success) return result.value;
|
|
14
|
-
let issue = result.issues[0];
|
|
15
|
-
throw errors.get(issue) ?? new Error(issue.message);
|
|
16
|
-
}
|
|
17
|
-
/**
|
|
18
|
-
* Reports any failure of `schema` with one message.
|
|
19
|
-
* @param schema - The schema to run.
|
|
20
|
-
* @param message - The message for any of its failures.
|
|
21
|
-
* @returns The described schema.
|
|
22
|
-
*/
|
|
23
|
-
function described(schema, message) {
|
|
24
|
-
return createSchema((value, context) => {
|
|
25
|
-
let result = schema["~run"](value, context);
|
|
26
|
-
return result.issues ? fail(message, context.path) : result;
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
/**
|
|
30
|
-
* Applies a rule after `schema` validates.
|
|
31
|
-
* @param schema - The schema to run first.
|
|
32
|
-
* @param rule - Returns a message, or undefined when the value is valid.
|
|
33
|
-
* @returns The checked schema.
|
|
34
|
-
*/
|
|
35
|
-
function check(schema, rule) {
|
|
36
|
-
return createSchema((value, context) => {
|
|
37
|
-
let result = schema["~run"](value, context);
|
|
38
|
-
if (result.issues) return result;
|
|
39
|
-
let message = rule(result.value);
|
|
40
|
-
return message === void 0 ? result : fail(message, context.path);
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
/**
|
|
44
|
-
* Validates with a function that throws, such as a URL or route map parser, keeping its error.
|
|
45
|
-
* @param schema - The schema to run first.
|
|
46
|
-
* @param parse - Turns its value into the output, or throws.
|
|
47
|
-
* @returns The delegating schema.
|
|
48
|
-
*/
|
|
49
|
-
function delegate(schema, parse) {
|
|
50
|
-
return createSchema((value, context) => {
|
|
51
|
-
let result = schema["~run"](value, context);
|
|
52
|
-
if (result.issues) return result;
|
|
53
|
-
try {
|
|
54
|
-
return { value: parse(result.value) };
|
|
55
|
-
} catch (error) {
|
|
56
|
-
if (!(error instanceof Error)) throw error;
|
|
57
|
-
let failure = fail(error.message, context.path);
|
|
58
|
-
errors.set(failure.issues[0], error);
|
|
59
|
-
return failure;
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Chooses a schema from the unvalidated value.
|
|
65
|
-
* @param choose - Picks the schema for a value.
|
|
66
|
-
* @returns The selecting schema.
|
|
67
|
-
*/
|
|
68
|
-
function select(choose) {
|
|
69
|
-
return createSchema((value, context) => choose(value)["~run"](value, context));
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Substitutes a default for null or undefined.
|
|
73
|
-
* @param schema - The schema for present values.
|
|
74
|
-
* @param value - Makes the default.
|
|
75
|
-
* @returns The schema with its default.
|
|
76
|
-
*/
|
|
77
|
-
function fallback(schema, value) {
|
|
78
|
-
return createSchema((input, context) => input == null ? { value: value() } : schema["~run"](input, context));
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* A settings object that names its unsupported keys before validating its fields.
|
|
82
|
-
* @param name - The setting's name in messages, such as `previews`.
|
|
83
|
-
* @param shape - The schema for each supported key.
|
|
84
|
-
* @returns The settings schema.
|
|
85
|
-
*/
|
|
86
|
-
function settings(name, shape) {
|
|
87
|
-
let schema = object(shape);
|
|
88
|
-
return createSchema((value, context) => {
|
|
89
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return fail(`${name} must be an object.`, context.path);
|
|
90
|
-
for (let key of Object.keys(value)) if (!Object.hasOwn(shape, key)) return fail(`${name}.${key} is not a supported setting.`, [...context.path, key]);
|
|
91
|
-
return schema["~run"](value, context);
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
/**
|
|
95
|
-
* A list whose length is checked before its entries.
|
|
96
|
-
* @param item - The schema for each entry.
|
|
97
|
-
* @param message - The message when it is not a list or is too short.
|
|
98
|
-
* @param minimum - The fewest entries it may have.
|
|
99
|
-
* @returns The list schema.
|
|
100
|
-
*/
|
|
101
|
-
function list(item, message, minimum = 0) {
|
|
102
|
-
let items = array(item);
|
|
103
|
-
return createSchema((value, context) => !Array.isArray(value) || value.length < minimum ? fail(message, context.path) : items["~run"](value, context));
|
|
104
|
-
}
|
|
105
|
-
//#endregion
|
|
106
|
-
//#region ../project/src/lib/files.ts
|
|
107
|
-
/** The Files settings, with their defaults filled in. */
|
|
108
|
-
var BudFilesSchema = defaulted(settings("files", { edit: fallback(described(boolean(), "files.edit must be true or false."), () => true) }), () => ({ edit: true }));
|
|
109
|
-
//#endregion
|
|
110
|
-
//#region ../project/src/lib/flows.ts
|
|
111
|
-
var message$1 = "flows must be [{ id, title, start, script, steps: [{ id, title }], block? }] with short ids, local paths and unique steps.";
|
|
112
|
-
var slug = (value) => typeof value === "string" && /^[a-z0-9][a-z0-9-]{0,62}$/.test(value);
|
|
113
|
-
var text = (value) => typeof value === "string" && value.trim() !== "" && value.length <= 200;
|
|
114
|
-
function flow(value) {
|
|
115
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
116
|
-
let { id, title, start, script, steps, block = [] } = value;
|
|
117
|
-
if (!slug(id) || !text(title) || !text(script) || script.includes("\0")) return null;
|
|
118
|
-
if (typeof start !== "string" || !start.startsWith("/") || start.startsWith("//")) return null;
|
|
119
|
-
if (new URL(start, "http://bud.invalid").origin !== "http://bud.invalid") return null;
|
|
120
|
-
if (!Array.isArray(steps) || !steps.length || steps.length > 50) return null;
|
|
121
|
-
let resolved = steps.map((step) => {
|
|
122
|
-
let { id: stepId, title: stepTitle } = step ?? {};
|
|
123
|
-
return slug(stepId) && text(stepTitle) ? {
|
|
124
|
-
id: stepId,
|
|
125
|
-
title: stepTitle.trim()
|
|
126
|
-
} : null;
|
|
127
|
-
});
|
|
128
|
-
if (resolved.some((step) => !step)) return null;
|
|
129
|
-
let ids = resolved.map((step) => step.id);
|
|
130
|
-
if (new Set(ids).size !== ids.length) return null;
|
|
131
|
-
if (!Array.isArray(block) || block.some((part) => !text(part))) return null;
|
|
132
|
-
return {
|
|
133
|
-
id,
|
|
134
|
-
title: title.trim(),
|
|
135
|
-
start,
|
|
136
|
-
script: script.trim(),
|
|
137
|
-
steps: resolved,
|
|
138
|
-
block
|
|
139
|
-
};
|
|
140
|
-
}
|
|
141
|
-
/** The flows, none when omitted. */
|
|
142
|
-
var BudFlowsSchema = createSchema((value, context) => {
|
|
143
|
-
if (value === void 0) return { value: [] };
|
|
144
|
-
if (!Array.isArray(value)) return fail(message$1, context.path);
|
|
145
|
-
let flows = value.map(flow);
|
|
146
|
-
if (flows.some((resolved) => !resolved)) return fail(message$1, context.path);
|
|
147
|
-
let ids = flows.map((resolved) => resolved.id);
|
|
148
|
-
if (new Set(ids).size !== ids.length) return fail(message$1, context.path);
|
|
149
|
-
return { value: flows };
|
|
150
|
-
});
|
|
151
|
-
/**
|
|
152
|
-
* Where a flow's step is pictured: a route of its own, named `<flow>/<step>`, in a group named
|
|
153
|
-
* after the flow. Its path is the start page with the step as its fragment, unique among routes.
|
|
154
|
-
* @param flow - The flow.
|
|
155
|
-
* @param step - One of its steps.
|
|
156
|
-
* @returns The step's route.
|
|
157
|
-
*/
|
|
158
|
-
function flowStepRoute(flow, step) {
|
|
159
|
-
return {
|
|
160
|
-
id: `${flow.id}/${step.id}`,
|
|
161
|
-
path: `${flow.start.replace(/#.*$/, "")}#${flow.id}-${step.id}`,
|
|
162
|
-
title: step.title,
|
|
163
|
-
group: flow.title,
|
|
164
|
-
flow: {
|
|
165
|
-
id: flow.id,
|
|
166
|
-
step: step.id
|
|
167
|
-
}
|
|
168
|
-
};
|
|
169
|
-
}
|
|
170
|
-
//#endregion
|
|
171
|
-
//#region ../project/src/lib/logo.ts
|
|
172
|
-
/** The image types a logo may be, by extension. */
|
|
173
|
-
var LOGO_TYPES = Object.freeze({
|
|
174
|
-
".svg": "image/svg+xml",
|
|
175
|
-
".png": "image/png",
|
|
176
|
-
".webp": "image/webp",
|
|
177
|
-
".jpg": "image/jpeg",
|
|
178
|
-
".jpeg": "image/jpeg",
|
|
179
|
-
".gif": "image/gif",
|
|
180
|
-
".ico": "image/x-icon"
|
|
181
|
-
});
|
|
182
|
-
var logoMessage = "logo must be an image path inside the project (.svg, .png, .webp, .jpg, .gif or .ico), or { light, dark }.";
|
|
183
|
-
function image(value) {
|
|
184
|
-
if (typeof value !== "string" || value.length > 1024 || value.includes("\0")) return null;
|
|
185
|
-
let path = value.trim().replaceAll("\\", "/");
|
|
186
|
-
if (!path || path.startsWith("/") || /^[a-z]:/i.test(path)) return null;
|
|
187
|
-
if (path.split("/").includes("..")) return null;
|
|
188
|
-
let extension = path.slice(path.lastIndexOf(".")).toLowerCase();
|
|
189
|
-
return Object.hasOwn(LOGO_TYPES, extension) ? path : null;
|
|
190
|
-
}
|
|
191
|
-
/** A logo in its one resolved form, or null for Bud's own mark. */
|
|
192
|
-
var BudLogoSchema = createSchema((value, context) => {
|
|
193
|
-
if (value === void 0) return { value: null };
|
|
194
|
-
let light = image(typeof value === "object" && value ? value.light : value);
|
|
195
|
-
let raw = typeof value === "object" && value ? value.dark : void 0;
|
|
196
|
-
let dark = raw === void 0 ? null : image(raw);
|
|
197
|
-
let keys = typeof value === "object" && value ? Object.keys(value) : [];
|
|
198
|
-
if (light && (raw === void 0 || dark) && keys.every((key) => key === "light" || key === "dark")) return { value: {
|
|
199
|
-
light,
|
|
200
|
-
dark
|
|
201
|
-
} };
|
|
202
|
-
return fail(logoMessage, context.path);
|
|
203
|
-
});
|
|
204
|
-
//#endregion
|
|
205
|
-
//#region ../project/src/lib/theme.ts
|
|
206
|
-
/**
|
|
207
|
-
* Bud's colors and shadows a theme may set, as `--bud-<name>` in its styles. Everything else
|
|
208
|
-
* Bud derives from them.
|
|
209
|
-
*/
|
|
210
|
-
var THEME_TOKENS = Object.freeze([
|
|
211
|
-
"background",
|
|
212
|
-
"shell",
|
|
213
|
-
"main",
|
|
214
|
-
"canvas",
|
|
215
|
-
"panel",
|
|
216
|
-
"board",
|
|
217
|
-
"editor",
|
|
218
|
-
"editor-tabs",
|
|
219
|
-
"foreground",
|
|
220
|
-
"muted",
|
|
221
|
-
"primary",
|
|
222
|
-
"primary-hover",
|
|
223
|
-
"primary-foreground",
|
|
224
|
-
"border",
|
|
225
|
-
"tab-divider",
|
|
226
|
-
"hover",
|
|
227
|
-
"selected",
|
|
228
|
-
"control",
|
|
229
|
-
"control-active",
|
|
230
|
-
"control-selected",
|
|
231
|
-
"card",
|
|
232
|
-
"menu",
|
|
233
|
-
"menu-hover",
|
|
234
|
-
"card-frame",
|
|
235
|
-
"card-surface",
|
|
236
|
-
"card-border",
|
|
237
|
-
"card-frame-border",
|
|
238
|
-
"card-badge",
|
|
239
|
-
"overlay-shadow",
|
|
240
|
-
"tooltip",
|
|
241
|
-
"board-control",
|
|
242
|
-
"board-control-hover",
|
|
243
|
-
"board-card",
|
|
244
|
-
"control-elevation",
|
|
245
|
-
"board-elevation",
|
|
246
|
-
"board-card-elevation",
|
|
247
|
-
"card-elevation",
|
|
248
|
-
"board-card-lift",
|
|
249
|
-
"frame-control",
|
|
250
|
-
"modal-elevation",
|
|
251
|
-
"segment-elevation",
|
|
252
|
-
"control-open-elevation",
|
|
253
|
-
"board-segment",
|
|
254
|
-
"scrollbar",
|
|
255
|
-
"focus",
|
|
256
|
-
"scrollbar-hover",
|
|
257
|
-
"tooltip-border",
|
|
258
|
-
"tooltip-shadow"
|
|
259
|
-
]);
|
|
260
|
-
var themeMessage = `theme must be { light, dark }, each mapping Bud's tokens (${THEME_TOKENS.slice(0, 3).join(", ")}, …) to CSS colors or shadows.`;
|
|
261
|
-
function cssValue(value) {
|
|
262
|
-
if (typeof value !== "string") return null;
|
|
263
|
-
let trimmed = value.trim();
|
|
264
|
-
if (!trimmed || trimmed.length > 300) return null;
|
|
265
|
-
if (!/^[#a-zA-Z0-9(),.%\s/+-]+$/.test(trimmed) || /url\s*\(/i.test(trimmed)) return null;
|
|
266
|
-
return trimmed;
|
|
267
|
-
}
|
|
268
|
-
function colors(value) {
|
|
269
|
-
if (value === void 0) return {};
|
|
270
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
271
|
-
let result = {};
|
|
272
|
-
for (let [name, raw] of Object.entries(value)) {
|
|
273
|
-
let checked = cssValue(raw);
|
|
274
|
-
if (!THEME_TOKENS.includes(name) || checked === null) return null;
|
|
275
|
-
result[name] = checked;
|
|
276
|
-
}
|
|
277
|
-
return Object.freeze(result);
|
|
278
|
-
}
|
|
279
|
-
/** A theme in its one resolved form; Bud's own colors when absent. */
|
|
280
|
-
var BudThemeSchema = createSchema((value, context) => {
|
|
281
|
-
if (value === void 0) return { value: {
|
|
282
|
-
light: {},
|
|
283
|
-
dark: {}
|
|
284
|
-
} };
|
|
285
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return fail(themeMessage, context.path);
|
|
286
|
-
let { light, dark, ...rest } = value;
|
|
287
|
-
let resolved = {
|
|
288
|
-
light: colors(light),
|
|
289
|
-
dark: colors(dark)
|
|
290
|
-
};
|
|
291
|
-
if (Object.keys(rest).length || !resolved.light || !resolved.dark) return fail(themeMessage, context.path);
|
|
292
|
-
return { value: {
|
|
293
|
-
light: resolved.light,
|
|
294
|
-
dark: resolved.dark
|
|
295
|
-
} };
|
|
296
|
-
});
|
|
297
|
-
//#endregion
|
|
298
|
-
//#region ../project/src/lib/branches.ts
|
|
299
|
-
var message = "branches must be { main?, build?: { install?, build?, serve? } } with a branch name and nonempty shell commands.";
|
|
300
|
-
function branch(value) {
|
|
301
|
-
return typeof value === "string" && value.length <= 255 && /^[A-Za-z0-9._/-]+$/.test(value) && !value.startsWith("-") && !value.startsWith("/") && !value.endsWith("/") && !value.endsWith(".lock") && !value.includes("..") && !value.includes("//") ? value : null;
|
|
302
|
-
}
|
|
303
|
-
function command(value) {
|
|
304
|
-
return typeof value === "string" && value.trim() && value.length <= 4096 && !value.includes("\0") ? value.trim() : null;
|
|
305
|
-
}
|
|
306
|
-
/** The branch settings, defaults filled in. */
|
|
307
|
-
var BudBranchesSchema = createSchema((value, context) => {
|
|
308
|
-
let empty = {
|
|
309
|
-
main: null,
|
|
310
|
-
install: null,
|
|
311
|
-
build: null,
|
|
312
|
-
serve: null
|
|
313
|
-
};
|
|
314
|
-
if (value === void 0) return { value: empty };
|
|
315
|
-
if (!value || typeof value !== "object" || Array.isArray(value)) return fail(message, context.path);
|
|
316
|
-
let input = value;
|
|
317
|
-
let build = input.build ?? {};
|
|
318
|
-
if (!build || typeof build !== "object" || Array.isArray(build) || Object.keys(input).some((key) => key !== "main" && key !== "build")) return fail(message, context.path);
|
|
319
|
-
let steps = build;
|
|
320
|
-
if (Object.keys(steps).some((key) => ![
|
|
321
|
-
"install",
|
|
322
|
-
"build",
|
|
323
|
-
"serve"
|
|
324
|
-
].includes(key))) return fail(message, context.path);
|
|
325
|
-
let resolved = {
|
|
326
|
-
main: input.main === void 0 ? null : branch(input.main),
|
|
327
|
-
install: steps.install === void 0 ? null : command(steps.install),
|
|
328
|
-
build: steps.build === void 0 ? null : command(steps.build),
|
|
329
|
-
serve: steps.serve === void 0 ? null : command(steps.serve)
|
|
330
|
-
};
|
|
331
|
-
if (input.main !== void 0 && !resolved.main || [
|
|
332
|
-
"install",
|
|
333
|
-
"build",
|
|
334
|
-
"serve"
|
|
335
|
-
].some((key) => steps[key] !== void 0 && !resolved[key])) return fail(message, context.path);
|
|
336
|
-
return { value: resolved };
|
|
337
|
-
});
|
|
338
|
-
//#endregion
|
|
339
|
-
//#region ../project/src/lib/storage.ts
|
|
340
|
-
/**
|
|
341
|
-
* A project module named in the config: a ./ path inside the project, outside node_modules.
|
|
342
|
-
* @param name - The config option, for the error message.
|
|
343
|
-
* @param server - Whether it runs on the server (.server.ts) rather than in the browser.
|
|
344
|
-
* @param message - What to say instead of the default when it is invalid.
|
|
345
|
-
* @returns A schema for the module's path.
|
|
346
|
-
*/
|
|
347
|
-
function modulePath(name, server, message) {
|
|
348
|
-
let extension = server ? /\.server\.ts$/ : /\.(?:ts|tsx|js|jsx)$/;
|
|
349
|
-
return described(string().refine((value) => value.length <= 1024 && value.startsWith("./") && !/[\u0000-\u001f\u007f\\?#%]/.test(value) && extension.test(value) && (server || !/\.server\.[cm]?[jt]sx?$/.test(value)) && !value.slice(2).split("/").some((part) => !part || part === "." || part === ".." || part === "node_modules")), message ?? (server ? `${name} must be a built-in adapter or a ./ module ending in .server.ts inside the project.` : `${name} must be bud:beads or a ./ browser module ending in .ts, .tsx, .js or .jsx inside the project.`));
|
|
350
|
-
}
|
|
351
|
-
var builtInStores = enum_([
|
|
352
|
-
false,
|
|
353
|
-
"bud:beads",
|
|
354
|
-
"bud:memory",
|
|
355
|
-
"bud:git-comments"
|
|
356
|
-
]);
|
|
357
|
-
function store(kind) {
|
|
358
|
-
let module = modulePath(`storage.${kind}`, true);
|
|
359
|
-
return defaulted(check(select((value) => value === false || value === "bud:beads" || value === "bud:memory" || value === "bud:git-comments" ? builtInStores : module), (value) => kind === "work" && value === "bud:git-comments" ? "storage.work cannot use bud:git-comments; it only stores threads." : void 0), "bud:beads");
|
|
360
|
-
}
|
|
361
|
-
/** The selected work and discussion stores, with Beads as the default for both. */
|
|
362
|
-
var BudStorageSchema = defaulted(settings("storage", {
|
|
363
|
-
work: store("work"),
|
|
364
|
-
threads: store("threads")
|
|
365
|
-
}), () => ({
|
|
366
|
-
work: "bud:beads",
|
|
367
|
-
threads: "bud:beads"
|
|
368
|
-
}));
|
|
369
|
-
/** Task presentation, chosen separately from its storage. */
|
|
370
|
-
var BudDesignsSchema = defaulted(settings("designs", {
|
|
371
|
-
tasks: defaulted(select((value) => value === "bud:beads" ? enum_(["bud:beads"]) : modulePath("designs.tasks", false)), "bud:beads"),
|
|
372
|
-
pages: defaulted(enum_(["path", "title"]), "path")
|
|
373
|
-
}), () => ({
|
|
374
|
-
tasks: "bud:beads",
|
|
375
|
-
pages: "path"
|
|
376
|
-
}));
|
|
377
|
-
//#endregion
|
|
378
|
-
//#region ../project/src/lib/picker.ts
|
|
379
|
-
var builtIn = /* @__PURE__ */ new Set([
|
|
380
|
-
"bud:dom",
|
|
381
|
-
"bud:react",
|
|
382
|
-
"bud:react-grab"
|
|
383
|
-
]);
|
|
384
|
-
var projectPicker = modulePath("picker", false, "picker must be bud:dom, bud:react, bud:react-grab or a ./ browser module ending in .ts, .tsx, .js or .jsx inside the project.");
|
|
385
|
-
/** The picker, with Bud's DOM picker as the default. */
|
|
386
|
-
var BudPickerSchema = createSchema((value, context) => {
|
|
387
|
-
if (value === void 0) return { value: {
|
|
388
|
-
name: "bud:dom",
|
|
389
|
-
module: null
|
|
390
|
-
} };
|
|
391
|
-
if (typeof value === "string" && builtIn.has(value)) return { value: {
|
|
392
|
-
name: value,
|
|
393
|
-
module: null
|
|
394
|
-
} };
|
|
395
|
-
let result = projectPicker["~run"](value, context);
|
|
396
|
-
return result.issues ? result : { value: {
|
|
397
|
-
name: result.value,
|
|
398
|
-
module: result.value
|
|
399
|
-
} };
|
|
400
|
-
});
|
|
401
|
-
//#endregion
|
|
402
|
-
//#region ../project/src/lib/previews.ts
|
|
403
|
-
var readyMessage = "ready must be a CSS selector, { selector } or { expression }.";
|
|
404
|
-
/** A readiness condition; a string is a selector. */
|
|
405
|
-
var PreviewReadySchema = createSchema((value, context) => {
|
|
406
|
-
let ready = typeof value === "string" ? { selector: value } : value;
|
|
407
|
-
if (ready && typeof ready === "object" && !Array.isArray(ready)) {
|
|
408
|
-
let entries = Object.entries(ready);
|
|
409
|
-
let [key, text] = entries[0] ?? [];
|
|
410
|
-
if (entries.length === 1 && (key === "selector" || key === "expression") && typeof text === "string" && text.trim() && text.length <= 4096) return { value: key === "selector" ? { selector: text.trim() } : { expression: text.trim() } };
|
|
411
|
-
}
|
|
412
|
-
return fail(readyMessage, context.path);
|
|
413
|
-
});
|
|
414
|
-
var defaultThemes = () => ["light", "dark"];
|
|
415
|
-
var defaultViewports = () => [{
|
|
416
|
-
id: "desktop",
|
|
417
|
-
name: "Desktop",
|
|
418
|
-
width: 1440,
|
|
419
|
-
height: 900,
|
|
420
|
-
mobile: false
|
|
421
|
-
}];
|
|
422
|
-
var viewportsMessage = "previews.viewports must list up to 4 { name, width, height?, mobile? } with distinct names, widths from 240 to 3840 and heights from 240 to 4000.";
|
|
423
|
-
function viewportId(name) {
|
|
424
|
-
return name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 32);
|
|
425
|
-
}
|
|
426
|
-
var ViewportsSchema = createSchema((value, context) => {
|
|
427
|
-
if (!Array.isArray(value) || value.length === 0 || value.length > 4) return fail(viewportsMessage, context.path);
|
|
428
|
-
let viewports = [];
|
|
429
|
-
for (let entry of value) {
|
|
430
|
-
if (!entry || typeof entry !== "object" || Array.isArray(entry)) return fail(viewportsMessage, context.path);
|
|
431
|
-
let { name, width, height, mobile, ...rest } = entry;
|
|
432
|
-
let size = (pixels, from, to) => typeof pixels === "number" && Number.isInteger(pixels) && pixels >= from && pixels <= to;
|
|
433
|
-
if (Object.keys(rest).length || typeof name !== "string" || !name.trim() || name.length > 40 || !viewportId(name) || !size(width, 240, 3840) || height !== void 0 && !size(height, 240, 4e3) || mobile !== void 0 && typeof mobile !== "boolean") return fail(viewportsMessage, context.path);
|
|
434
|
-
let phone = mobile ?? width < 800;
|
|
435
|
-
viewports.push({
|
|
436
|
-
id: viewportId(name),
|
|
437
|
-
name: name.trim(),
|
|
438
|
-
width,
|
|
439
|
-
height: height ?? (phone ? Math.round(width * 844 / 390) : 900),
|
|
440
|
-
mobile: phone
|
|
441
|
-
});
|
|
442
|
-
}
|
|
443
|
-
if (new Set(viewports.map((viewport) => viewport.id)).size !== viewports.length) return fail(viewportsMessage, context.path);
|
|
444
|
-
return { value: viewports };
|
|
445
|
-
});
|
|
446
|
-
/** The preview settings, with their defaults filled in. */
|
|
447
|
-
var BudPreviewsSchema = defaulted(settings("previews", {
|
|
448
|
-
scale: fallback(described(number().refine((scale) => Number.isInteger(scale) && scale >= 1 && scale <= 3), "previews.scale must be 1, 2 or 3."), () => 2),
|
|
449
|
-
themes: fallback(described(array(enum_(["light", "dark"])).refine((themes) => themes.length > 0 && new Set(themes).size === themes.length), "previews.themes must list light, dark or both, once each."), defaultThemes),
|
|
450
|
-
viewports: fallback(ViewportsSchema, defaultViewports),
|
|
451
|
-
ready: fallback(PreviewReadySchema, () => null),
|
|
452
|
-
readyTimeout: fallback(described(number().refine((ms) => Number.isInteger(ms) && ms >= 1e3 && ms <= 6e5), "previews.readyTimeout must be whole milliseconds from 1000 to 600000."), () => 6e4),
|
|
453
|
-
css: fallback(described(string().refine((css) => css.length <= 2e4 && !css.includes("<")), "previews.css must be CSS text without <, up to 20000 characters."), () => "")
|
|
454
|
-
}), () => ({
|
|
455
|
-
scale: 2,
|
|
456
|
-
themes: defaultThemes(),
|
|
457
|
-
viewports: defaultViewports(),
|
|
458
|
-
ready: null,
|
|
459
|
-
readyTimeout: 6e4,
|
|
460
|
-
css: ""
|
|
461
|
-
}));
|
|
462
|
-
//#endregion
|
|
463
|
-
//#region ../project/src/lib/screen-routes.ts
|
|
464
|
-
/**
|
|
465
|
-
* Validates a screen's route map without importing its component module.
|
|
466
|
-
* @param routes - A Remix route map shared with the screen's definition.
|
|
467
|
-
* @param path - The configured screen's static path.
|
|
468
|
-
* @returns Named patterns confined to the screen's path.
|
|
469
|
-
*/
|
|
470
|
-
function resolveScreenRoutes(routes, path) {
|
|
471
|
-
let result = [];
|
|
472
|
-
let seen = /* @__PURE__ */ new Set();
|
|
473
|
-
function visit(value, prefix) {
|
|
474
|
-
if (!value || typeof value !== "object" || Array.isArray(value) || seen.has(value)) throw new Error("Screen routes must be a Remix route map.");
|
|
475
|
-
seen.add(value);
|
|
476
|
-
for (let [key, entry] of Object.entries(value)) {
|
|
477
|
-
let name = prefix ? `${prefix}.${key}` : key;
|
|
478
|
-
if (!entry || typeof entry !== "object") throw new Error(`Screen route ${name} must be a Remix route.`);
|
|
479
|
-
if (!("pattern" in entry)) {
|
|
480
|
-
visit(entry, name);
|
|
481
|
-
continue;
|
|
482
|
-
}
|
|
483
|
-
if (!["GET", "ANY"].includes(entry.method) || typeof entry.href !== "function" || typeof entry.pattern?.source !== "string") throw new Error(`Screen route ${name} must be a GET route.`);
|
|
484
|
-
let pattern = RoutePattern.parse(entry.pattern.source);
|
|
485
|
-
let parts = pattern.toJSON();
|
|
486
|
-
let pathname = `/${parts.pathname}`;
|
|
487
|
-
if (parts.protocol || parts.hostname || parts.port || parts.pathname.split("/").some((segment) => /^\.{1,2}$/.test(decodeURIComponent(segment))) || pathname !== path && !pathname.startsWith(`${path}/`) && !pathname.startsWith(`${path}(/`)) throw new Error(`Screen route ${name} must stay under ${path}.`);
|
|
488
|
-
result.push({
|
|
489
|
-
name,
|
|
490
|
-
pattern: pattern.source
|
|
491
|
-
});
|
|
492
|
-
}
|
|
493
|
-
seen.delete(value);
|
|
494
|
-
}
|
|
495
|
-
visit(routes, "");
|
|
496
|
-
if (!result.length) throw new Error("Screen routes must contain at least one route.");
|
|
497
|
-
return result;
|
|
498
|
-
}
|
|
499
|
-
//#endregion
|
|
500
|
-
//#region ../project/src/lib/screens.ts
|
|
501
|
-
/**
|
|
502
|
-
* Bud's browser of your live pages, with their comments.
|
|
503
|
-
* @returns The built-in screen, ready to relabel by spreading.
|
|
504
|
-
*/
|
|
505
|
-
function pages() {
|
|
506
|
-
return {
|
|
507
|
-
id: "pages",
|
|
508
|
-
label: "Pages",
|
|
509
|
-
icon: "browser",
|
|
510
|
-
path: "/pages",
|
|
511
|
-
module: "bud:pages"
|
|
512
|
-
};
|
|
513
|
-
}
|
|
514
|
-
/**
|
|
515
|
-
* Bud's canvas of every route's screenshot.
|
|
516
|
-
* @returns The built-in screen, ready to relabel by spreading.
|
|
517
|
-
*/
|
|
518
|
-
function canvas() {
|
|
519
|
-
return {
|
|
520
|
-
id: "canvas",
|
|
521
|
-
label: "Canvas",
|
|
522
|
-
icon: "grid",
|
|
523
|
-
path: "/canvas",
|
|
524
|
-
module: "bud:canvas"
|
|
525
|
-
};
|
|
526
|
-
}
|
|
527
|
-
/**
|
|
528
|
-
* Bud's Beads task board.
|
|
529
|
-
* @returns The built-in screen, ready to relabel by spreading.
|
|
530
|
-
*/
|
|
531
|
-
function tasks() {
|
|
532
|
-
return {
|
|
533
|
-
id: "tasks",
|
|
534
|
-
label: "Tasks",
|
|
535
|
-
icon: "tasks",
|
|
536
|
-
path: "/tasks",
|
|
537
|
-
module: "bud:tasks"
|
|
538
|
-
};
|
|
539
|
-
}
|
|
540
|
-
/**
|
|
541
|
-
* Bud's file browser and review.
|
|
542
|
-
* @returns The built-in screen, ready to relabel by spreading.
|
|
543
|
-
*/
|
|
544
|
-
function files() {
|
|
545
|
-
return {
|
|
546
|
-
id: "files",
|
|
547
|
-
label: "Files",
|
|
548
|
-
icon: "files",
|
|
549
|
-
path: "/files",
|
|
550
|
-
module: "bud:files"
|
|
551
|
-
};
|
|
552
|
-
}
|
|
553
|
-
/** The screens shown when the config doesn't list any. */
|
|
554
|
-
var defaultScreens = [
|
|
555
|
-
pages(),
|
|
556
|
-
canvas(),
|
|
557
|
-
tasks(),
|
|
558
|
-
files()
|
|
559
|
-
];
|
|
560
|
-
var builtIns = new Map(defaultScreens.map((screen) => [screen.module, screen]));
|
|
561
|
-
/** First path segments owned by Bud's routes, its development server and its public assets. */
|
|
562
|
-
var reservedScreenPaths = [
|
|
563
|
-
"/comments",
|
|
564
|
-
...defaultScreens.map((screen) => screen.path),
|
|
565
|
-
"/api",
|
|
566
|
-
"/health",
|
|
567
|
-
"/__bud",
|
|
568
|
-
"/assets",
|
|
569
|
-
"/app",
|
|
570
|
-
"/src",
|
|
571
|
-
"/node_modules",
|
|
572
|
-
"/agents",
|
|
573
|
-
"/brand",
|
|
574
|
-
"/fonts",
|
|
575
|
-
"/frameworks",
|
|
576
|
-
"/licenses"
|
|
577
|
-
];
|
|
578
|
-
var ScreenSchema = check(described(any().refine((value) => !!value && typeof value === "object"), "Each screen must be an object."), ({ id, label, icon = "layers", module, path }) => {
|
|
579
|
-
if (typeof id !== "string" || !/^[a-z][a-z0-9-]{0,31}$/.test(id)) return "Screen ids are 1-32 lowercase letters, digits and hyphens.";
|
|
580
|
-
if (typeof label !== "string" || !label.trim()) return `Screen ${id} needs a label.`;
|
|
581
|
-
if (typeof icon !== "string" || !icon) return `Screen ${id} needs an icon name.`;
|
|
582
|
-
if (typeof module !== "string") return `Screen ${id} needs a module.`;
|
|
583
|
-
let builtIn = builtIns.get(module);
|
|
584
|
-
path ??= builtIn?.path ?? `/${id}`;
|
|
585
|
-
if (builtIn) {
|
|
586
|
-
if (id !== builtIn.id || path !== builtIn.path) return `${module} keeps id "${builtIn.id}" and path "${builtIn.path}".`;
|
|
587
|
-
return;
|
|
588
|
-
}
|
|
589
|
-
if (!/^\.\/[^\0\\]+\.(?:ts|tsx|js|jsx)$/.test(module)) return `Screen ${id} must be a ./ module ending in .ts, .tsx, .js or .jsx.`;
|
|
590
|
-
if (typeof path !== "string" || !/^\/[a-z0-9][a-z0-9-]*$/.test(path)) return `Screen ${id} needs one static path segment, such as /${id}.`;
|
|
591
|
-
if (defaultScreens.some((screen) => screen.id === id)) return `Screen id "${id}" is reserved for a built-in screen.`;
|
|
592
|
-
if (reservedScreenPaths.includes(path)) return `Bud reserves the path ${path}.`;
|
|
593
|
-
});
|
|
594
|
-
/** Bud's navigation in order; file and icon checks need the app and happen at startup. */
|
|
595
|
-
var BudScreensSchema = defaulted(delegate(described(array(any()).refine((screens) => screens.length > 0), "screens must list at least one screen."), (screens) => {
|
|
596
|
-
let ids = /* @__PURE__ */ new Set();
|
|
597
|
-
let paths = /* @__PURE__ */ new Set();
|
|
598
|
-
return screens.map((value) => {
|
|
599
|
-
let input = parseConfig(ScreenSchema, value);
|
|
600
|
-
let { id, label, icon = "layers", module } = input;
|
|
601
|
-
let path = input.path ?? builtIns.get(module)?.path ?? `/${id}`;
|
|
602
|
-
if (ids.has(id) || paths.has(path)) throw new Error("Screen ids and paths must be unique.");
|
|
603
|
-
ids.add(id);
|
|
604
|
-
paths.add(path);
|
|
605
|
-
if (input.routes !== void 0) resolveScreenRoutes(input.routes, path);
|
|
606
|
-
return {
|
|
607
|
-
id,
|
|
608
|
-
label,
|
|
609
|
-
icon,
|
|
610
|
-
path,
|
|
611
|
-
module,
|
|
612
|
-
...input.routes === void 0 ? {} : { routes: input.routes }
|
|
613
|
-
};
|
|
614
|
-
});
|
|
615
|
-
}), () => defaultScreens.map((screen) => ({ ...screen })));
|
|
616
|
-
//#endregion
|
|
617
|
-
//#region ../project/src/lib/config.ts
|
|
618
|
-
/**
|
|
619
|
-
* Keeps bud.config.js and bud.config.ts typed without changing their values.
|
|
620
|
-
* @param config - The project's routes and development settings.
|
|
621
|
-
* @returns The same configuration.
|
|
622
|
-
*/
|
|
623
|
-
function defineConfig(config) {
|
|
624
|
-
return config;
|
|
625
|
-
}
|
|
626
|
-
var objectLike = (value) => !!value && typeof value === "object";
|
|
627
|
-
function section(message, shape) {
|
|
628
|
-
let schema = object(shape);
|
|
629
|
-
return createSchema((value, context) => objectLike(value) ? schema["~run"](Array.isArray(value) ? { ...value } : value, context) : fail(message, context.path));
|
|
630
|
-
}
|
|
631
|
-
var ConfigFields = check(section("Bud config must export an object.", {
|
|
632
|
-
routes: described(array(any()).refine((routes) => routes.length > 0), "bud.config must define at least one route."),
|
|
633
|
-
name: optional(described(string().refine((name) => !!name.trim()), "name must be a nonempty string.")),
|
|
634
|
-
target: optional(section("target must be an object.", {
|
|
635
|
-
origin: any(),
|
|
636
|
-
port: any()
|
|
637
|
-
})),
|
|
638
|
-
comments: optional(section("comments must be an object.", { remote: any() })),
|
|
639
|
-
port: any(),
|
|
640
|
-
screens: any(),
|
|
641
|
-
storage: any(),
|
|
642
|
-
designs: any(),
|
|
643
|
-
previews: any(),
|
|
644
|
-
files: any(),
|
|
645
|
-
logo: any(),
|
|
646
|
-
theme: any(),
|
|
647
|
-
locale: any(),
|
|
648
|
-
picker: any(),
|
|
649
|
-
branches: any(),
|
|
650
|
-
flows: any()
|
|
651
|
-
}), ({ target }) => {
|
|
652
|
-
if (target?.port === 0) return "target.port must be a listening port, not zero.";
|
|
653
|
-
if (target?.origin !== void 0 && (typeof target.origin !== "string" || !target.origin.trim())) return "target.origin must be an HTTP(S) origin.";
|
|
654
|
-
});
|
|
655
|
-
var RouteSchema = check(any().transform((input) => typeof input === "string" ? {
|
|
656
|
-
path: input,
|
|
657
|
-
title: input === "/" ? "Home" : input
|
|
658
|
-
} : input), (route) => {
|
|
659
|
-
if (!route || typeof route.path !== "string" || !route.path.startsWith("/") || route.path.startsWith("//")) return "Canvas routes must be local paths beginning with a single /.";
|
|
660
|
-
if (new URL(route.path, "http://bud.invalid").origin !== "http://bud.invalid" || route.path.includes("\\")) return "Canvas routes must stay on the target origin.";
|
|
661
|
-
let id = route.id ?? routePath(route.path);
|
|
662
|
-
if (typeof id !== "string" || !id.trim()) return "Canvas route IDs and paths must be unique.";
|
|
663
|
-
if (typeof route.title !== "string" || !route.title.trim()) return "Each route needs a title.";
|
|
664
|
-
if (route.pattern !== void 0 && (typeof route.pattern !== "string" || !route.pattern.startsWith("/"))) return "A route pattern must be a path beginning with /.";
|
|
665
|
-
if (route.group !== void 0 && (typeof route.group !== "string" || !route.group.trim() || route.group.length > 120)) return "A route group must be a short name.";
|
|
666
|
-
if (route.ready !== void 0 && route.ready !== false && !parseSafe(PreviewReadySchema, route.ready).success) return "A route ready must be false, a CSS selector, { selector } or { expression }.";
|
|
667
|
-
}).transform((route) => {
|
|
668
|
-
let path = routePath(route.path);
|
|
669
|
-
return {
|
|
670
|
-
id: route.id ?? path,
|
|
671
|
-
path,
|
|
672
|
-
title: route.title,
|
|
673
|
-
...route.pattern === void 0 ? {} : { pattern: route.pattern },
|
|
674
|
-
...route.group === void 0 ? {} : { group: route.group.trim() },
|
|
675
|
-
...route.ready === void 0 ? {} : { ready: route.ready === false ? null : parseConfig(PreviewReadySchema, route.ready) }
|
|
676
|
-
};
|
|
677
|
-
});
|
|
678
|
-
function routePath(path) {
|
|
679
|
-
let url = new URL(path, "http://bud.invalid");
|
|
680
|
-
let search = url.searchParams.toString();
|
|
681
|
-
return `${url.pathname}${search ? `?${search}` : ""}${url.hash}`;
|
|
682
|
-
}
|
|
683
|
-
/** Canvas routes with unique IDs and normalized paths. */
|
|
684
|
-
var BudRoutesSchema = check(list(RouteSchema, "bud.config must define at least one route.", 1), (routes) => new Set(routes.map((route) => route.id)).size !== routes.length || new Set(routes.map((route) => route.path)).size !== routes.length ? "Canvas route IDs and paths must be unique." : void 0);
|
|
685
|
-
var port = (value) => value === void 0 || Number.isInteger(value) && value >= 0 && value <= 65535;
|
|
686
|
-
var remote = (value) => typeof value === "string" && /^[a-zA-Z0-9][a-zA-Z0-9._-]*$/.test(value);
|
|
687
|
-
delegate(check(delegate(check(check(delegate(check(delegate(ConfigFields, (config) => ({
|
|
688
|
-
...config,
|
|
689
|
-
routes: parseConfig(BudRoutesSchema, config.routes)
|
|
690
|
-
})), ({ port: companion, target }) => port(companion ?? 0) && port(target?.port) ? void 0 : "Ports must be integers between 0 and 65535."), ({ target, ...config }) => {
|
|
691
|
-
let origin = target?.origin ?? (target?.port ? `http://127.0.0.1:${target.port}` : void 0);
|
|
692
|
-
return {
|
|
693
|
-
...config,
|
|
694
|
-
targetOrigin: origin ? normalizeOrigin(origin, "target.origin must be an HTTP(S) origin without a path or credentials.") : origin
|
|
695
|
-
};
|
|
696
|
-
}), ({ locale }) => locale === void 0 || locale === "en" || locale === "de" ? void 0 : "locale must be \"en\" or \"de\"."), ({ comments }) => remote(comments?.remote ?? "origin") ? void 0 : "comments.remote must be a Git remote name."), (config) => {
|
|
697
|
-
let flows = parseConfig(BudFlowsSchema, config.flows);
|
|
698
|
-
let steps = flows.flatMap((flow) => flow.steps.map((step) => flowStepRoute(flow, step)));
|
|
699
|
-
let home = config.routes.findIndex((route) => route.path === "/") + 1;
|
|
700
|
-
return {
|
|
701
|
-
...config,
|
|
702
|
-
flows,
|
|
703
|
-
routes: [
|
|
704
|
-
...config.routes.slice(0, home),
|
|
705
|
-
...steps,
|
|
706
|
-
...config.routes.slice(home)
|
|
707
|
-
]
|
|
708
|
-
};
|
|
709
|
-
}), ({ routes }) => new Set(routes.map((route) => route.id)).size !== routes.length || new Set(routes.map((route) => route.path)).size !== routes.length ? "A flow step must not reuse a route’s id or path." : void 0), (config) => ({
|
|
710
|
-
name: config.name ?? "Your project",
|
|
711
|
-
routes: config.routes,
|
|
712
|
-
flows: config.flows,
|
|
713
|
-
port: config.port ?? 0,
|
|
714
|
-
targetOrigin: config.targetOrigin,
|
|
715
|
-
remote: config.comments?.remote ?? "origin",
|
|
716
|
-
screens: parseConfig(BudScreensSchema, config.screens),
|
|
717
|
-
storage: parseConfig(BudStorageSchema, config.storage),
|
|
718
|
-
designs: parseConfig(BudDesignsSchema, config.designs),
|
|
719
|
-
previews: parseConfig(BudPreviewsSchema, config.previews),
|
|
720
|
-
files: parseConfig(BudFilesSchema, config.files),
|
|
721
|
-
logo: parseConfig(BudLogoSchema, config.logo),
|
|
722
|
-
theme: parseConfig(BudThemeSchema, config.theme),
|
|
723
|
-
locale: config.locale === void 0 ? "en" : config.locale,
|
|
724
|
-
picker: parseConfig(BudPickerSchema, config.picker),
|
|
725
|
-
branches: parseConfig(BudBranchesSchema, config.branches)
|
|
726
|
-
}));
|
|
727
|
-
/**
|
|
728
|
-
* Returns a bare HTTP(S) origin, rejecting credentials, paths, queries and fragments.
|
|
729
|
-
* @param origin - The URL to check.
|
|
730
|
-
* @param message - The error's message when it is not a bare origin.
|
|
731
|
-
* @returns The URL's origin.
|
|
732
|
-
*/
|
|
733
|
-
function normalizeOrigin(origin, message) {
|
|
734
|
-
let url = new URL(origin);
|
|
735
|
-
if (!["http:", "https:"].includes(url.protocol) || url.username || url.password || url.pathname !== "/" || url.search || url.hash) throw new Error(message);
|
|
736
|
-
return url.origin;
|
|
737
|
-
}
|
|
738
|
-
//#endregion
|
|
739
|
-
export { canvas, defineConfig, files, pages, tasks };
|
|
1
|
+
export { o as canvas, t as defineConfig, s as files, c as pages, i as picker, a as taskDesign, l as tasks } from "./assets/config-9_jWwNBh.js";
|
|
2
|
+
import "./assets/src-D-kG1GxB.js";
|