@usefillo/cli 0.5.1 → 0.9.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 +95 -3
- package/dist/index.js +2491 -86
- package/dist/skill/build-with-fillo/.fillo-managed.json +6 -0
- package/dist/skill/build-with-fillo/SKILL.md +101 -0
- package/dist/skill/build-with-fillo/agents/openai.yaml +4 -0
- package/dist/skill/build-with-fillo/references/auth-and-lifecycle.md +72 -0
- package/dist/skill/build-with-fillo/references/frameworks.md +97 -0
- package/dist/skill/build-with-fillo/references/operations.md +114 -0
- package/dist/skill/build-with-fillo/references/schema-and-ux.md +58 -0
- package/dist/skill/build-with-fillo/references/source-map.md +46 -0
- package/dist/skill/build-with-fillo/references/troubleshooting.md +21 -0
- package/package.json +6 -4
package/dist/index.js
CHANGED
|
@@ -1,52 +1,1941 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
chmodSync,
|
|
6
|
+
cpSync,
|
|
7
|
+
existsSync,
|
|
8
|
+
lstatSync,
|
|
9
|
+
mkdirSync,
|
|
10
|
+
realpathSync,
|
|
11
|
+
readdirSync,
|
|
12
|
+
readFileSync,
|
|
13
|
+
renameSync,
|
|
14
|
+
rmSync,
|
|
15
|
+
writeFileSync
|
|
16
|
+
} from "fs";
|
|
17
|
+
import { randomUUID } from "crypto";
|
|
5
18
|
import { homedir } from "os";
|
|
6
|
-
import { isAbsolute, join, resolve } from "path";
|
|
19
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from "path";
|
|
7
20
|
import { spawn } from "child_process";
|
|
8
|
-
import { pathToFileURL } from "url";
|
|
21
|
+
import { fileURLToPath, pathToFileURL } from "url";
|
|
22
|
+
|
|
23
|
+
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/core.js
|
|
24
|
+
var _a;
|
|
25
|
+
// @__NO_SIDE_EFFECTS__
|
|
26
|
+
function $constructor(name, initializer2, params) {
|
|
27
|
+
function init2(inst, def) {
|
|
28
|
+
if (!inst._zod) {
|
|
29
|
+
Object.defineProperty(inst, "_zod", {
|
|
30
|
+
value: {
|
|
31
|
+
def,
|
|
32
|
+
constr: _,
|
|
33
|
+
traits: /* @__PURE__ */ new Set()
|
|
34
|
+
},
|
|
35
|
+
enumerable: false
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
if (inst._zod.traits.has(name)) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
inst._zod.traits.add(name);
|
|
42
|
+
initializer2(inst, def);
|
|
43
|
+
const proto = _.prototype;
|
|
44
|
+
const keys = Object.keys(proto);
|
|
45
|
+
for (let i = 0; i < keys.length; i++) {
|
|
46
|
+
const k = keys[i];
|
|
47
|
+
if (!(k in inst)) {
|
|
48
|
+
inst[k] = proto[k].bind(inst);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
const Parent = params?.Parent ?? Object;
|
|
53
|
+
class Definition extends Parent {
|
|
54
|
+
}
|
|
55
|
+
Object.defineProperty(Definition, "name", { value: name });
|
|
56
|
+
function _(def) {
|
|
57
|
+
var _a2;
|
|
58
|
+
const inst = params?.Parent ? new Definition() : this;
|
|
59
|
+
init2(inst, def);
|
|
60
|
+
(_a2 = inst._zod).deferred ?? (_a2.deferred = []);
|
|
61
|
+
for (const fn of inst._zod.deferred) {
|
|
62
|
+
fn();
|
|
63
|
+
}
|
|
64
|
+
return inst;
|
|
65
|
+
}
|
|
66
|
+
Object.defineProperty(_, "init", { value: init2 });
|
|
67
|
+
Object.defineProperty(_, Symbol.hasInstance, {
|
|
68
|
+
value: (inst) => {
|
|
69
|
+
if (params?.Parent && inst instanceof params.Parent)
|
|
70
|
+
return true;
|
|
71
|
+
return inst?._zod?.traits?.has(name);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
Object.defineProperty(_, "name", { value: name });
|
|
75
|
+
return _;
|
|
76
|
+
}
|
|
77
|
+
var $ZodAsyncError = class extends Error {
|
|
78
|
+
constructor() {
|
|
79
|
+
super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`);
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
(_a = globalThis).__zod_globalConfig ?? (_a.__zod_globalConfig = {});
|
|
83
|
+
var globalConfig = globalThis.__zod_globalConfig;
|
|
84
|
+
function config(newConfig) {
|
|
85
|
+
if (newConfig)
|
|
86
|
+
Object.assign(globalConfig, newConfig);
|
|
87
|
+
return globalConfig;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/util.js
|
|
91
|
+
function getEnumValues(entries) {
|
|
92
|
+
const numericValues = Object.values(entries).filter((v) => typeof v === "number");
|
|
93
|
+
const values = Object.entries(entries).filter(([k, _]) => numericValues.indexOf(+k) === -1).map(([_, v]) => v);
|
|
94
|
+
return values;
|
|
95
|
+
}
|
|
96
|
+
function jsonStringifyReplacer(_, value) {
|
|
97
|
+
if (typeof value === "bigint")
|
|
98
|
+
return value.toString();
|
|
99
|
+
return value;
|
|
100
|
+
}
|
|
101
|
+
function cached(getter) {
|
|
102
|
+
const set = false;
|
|
103
|
+
return {
|
|
104
|
+
get value() {
|
|
105
|
+
if (!set) {
|
|
106
|
+
const value = getter();
|
|
107
|
+
Object.defineProperty(this, "value", { value });
|
|
108
|
+
return value;
|
|
109
|
+
}
|
|
110
|
+
throw new Error("cached value already set");
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function nullish(input) {
|
|
115
|
+
return input === null || input === void 0;
|
|
116
|
+
}
|
|
117
|
+
function cleanRegex(source) {
|
|
118
|
+
const start = source.startsWith("^") ? 1 : 0;
|
|
119
|
+
const end = source.endsWith("$") ? source.length - 1 : source.length;
|
|
120
|
+
return source.slice(start, end);
|
|
121
|
+
}
|
|
122
|
+
var EVALUATING = /* @__PURE__ */ Symbol("evaluating");
|
|
123
|
+
function defineLazy(object2, key, getter) {
|
|
124
|
+
let value = void 0;
|
|
125
|
+
Object.defineProperty(object2, key, {
|
|
126
|
+
get() {
|
|
127
|
+
if (value === EVALUATING) {
|
|
128
|
+
return void 0;
|
|
129
|
+
}
|
|
130
|
+
if (value === void 0) {
|
|
131
|
+
value = EVALUATING;
|
|
132
|
+
value = getter();
|
|
133
|
+
}
|
|
134
|
+
return value;
|
|
135
|
+
},
|
|
136
|
+
set(v) {
|
|
137
|
+
Object.defineProperty(object2, key, {
|
|
138
|
+
value: v
|
|
139
|
+
// configurable: true,
|
|
140
|
+
});
|
|
141
|
+
},
|
|
142
|
+
configurable: true
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
var captureStackTrace = "captureStackTrace" in Error ? Error.captureStackTrace : (..._args) => {
|
|
146
|
+
};
|
|
147
|
+
function isObject(data) {
|
|
148
|
+
return typeof data === "object" && data !== null && !Array.isArray(data);
|
|
149
|
+
}
|
|
150
|
+
function isPlainObject(o) {
|
|
151
|
+
if (isObject(o) === false)
|
|
152
|
+
return false;
|
|
153
|
+
const ctor = o.constructor;
|
|
154
|
+
if (ctor === void 0)
|
|
155
|
+
return true;
|
|
156
|
+
if (typeof ctor !== "function")
|
|
157
|
+
return true;
|
|
158
|
+
const prot = ctor.prototype;
|
|
159
|
+
if (isObject(prot) === false)
|
|
160
|
+
return false;
|
|
161
|
+
if (Object.prototype.hasOwnProperty.call(prot, "isPrototypeOf") === false) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
return true;
|
|
165
|
+
}
|
|
166
|
+
function shallowClone(o) {
|
|
167
|
+
if (isPlainObject(o))
|
|
168
|
+
return { ...o };
|
|
169
|
+
if (Array.isArray(o))
|
|
170
|
+
return [...o];
|
|
171
|
+
if (o instanceof Map)
|
|
172
|
+
return new Map(o);
|
|
173
|
+
if (o instanceof Set)
|
|
174
|
+
return new Set(o);
|
|
175
|
+
return o;
|
|
176
|
+
}
|
|
177
|
+
var propertyKeyTypes = /* @__PURE__ */ new Set(["string", "number", "symbol"]);
|
|
178
|
+
function escapeRegex(str2) {
|
|
179
|
+
return str2.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
180
|
+
}
|
|
181
|
+
function clone(inst, def, params) {
|
|
182
|
+
const cl = new inst._zod.constr(def ?? inst._zod.def);
|
|
183
|
+
if (!def || params?.parent)
|
|
184
|
+
cl._zod.parent = inst;
|
|
185
|
+
return cl;
|
|
186
|
+
}
|
|
187
|
+
function normalizeParams(_params) {
|
|
188
|
+
const params = _params;
|
|
189
|
+
if (!params)
|
|
190
|
+
return {};
|
|
191
|
+
if (typeof params === "string")
|
|
192
|
+
return { error: () => params };
|
|
193
|
+
if (params?.message !== void 0) {
|
|
194
|
+
if (params?.error !== void 0)
|
|
195
|
+
throw new Error("Cannot specify both `message` and `error` params");
|
|
196
|
+
params.error = params.message;
|
|
197
|
+
}
|
|
198
|
+
delete params.message;
|
|
199
|
+
if (typeof params.error === "string")
|
|
200
|
+
return { ...params, error: () => params.error };
|
|
201
|
+
return params;
|
|
202
|
+
}
|
|
203
|
+
function optionalKeys(shape) {
|
|
204
|
+
return Object.keys(shape).filter((k) => {
|
|
205
|
+
return shape[k]._zod.optin === "optional" && shape[k]._zod.optout === "optional";
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
var NUMBER_FORMAT_RANGES = {
|
|
209
|
+
safeint: [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER],
|
|
210
|
+
int32: [-2147483648, 2147483647],
|
|
211
|
+
uint32: [0, 4294967295],
|
|
212
|
+
float32: [-34028234663852886e22, 34028234663852886e22],
|
|
213
|
+
float64: [-Number.MAX_VALUE, Number.MAX_VALUE]
|
|
214
|
+
};
|
|
215
|
+
function aborted(x, startIndex = 0) {
|
|
216
|
+
if (x.aborted === true)
|
|
217
|
+
return true;
|
|
218
|
+
for (let i = startIndex; i < x.issues.length; i++) {
|
|
219
|
+
if (x.issues[i]?.continue !== true) {
|
|
220
|
+
return true;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
function explicitlyAborted(x, startIndex = 0) {
|
|
226
|
+
if (x.aborted === true)
|
|
227
|
+
return true;
|
|
228
|
+
for (let i = startIndex; i < x.issues.length; i++) {
|
|
229
|
+
if (x.issues[i]?.continue === false) {
|
|
230
|
+
return true;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return false;
|
|
234
|
+
}
|
|
235
|
+
function prefixIssues(path, issues) {
|
|
236
|
+
return issues.map((iss) => {
|
|
237
|
+
var _a2;
|
|
238
|
+
(_a2 = iss).path ?? (_a2.path = []);
|
|
239
|
+
iss.path.unshift(path);
|
|
240
|
+
return iss;
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
function unwrapMessage(message) {
|
|
244
|
+
return typeof message === "string" ? message : message?.message;
|
|
245
|
+
}
|
|
246
|
+
function finalizeIssue(iss, ctx, config2) {
|
|
247
|
+
const message = iss.message ? iss.message : unwrapMessage(iss.inst?._zod.def?.error?.(iss)) ?? unwrapMessage(ctx?.error?.(iss)) ?? unwrapMessage(config2.customError?.(iss)) ?? unwrapMessage(config2.localeError?.(iss)) ?? "Invalid input";
|
|
248
|
+
const { inst: _inst, continue: _continue, input: _input, ...rest } = iss;
|
|
249
|
+
rest.path ?? (rest.path = []);
|
|
250
|
+
rest.message = message;
|
|
251
|
+
if (ctx?.reportInput) {
|
|
252
|
+
rest.input = _input;
|
|
253
|
+
}
|
|
254
|
+
return rest;
|
|
255
|
+
}
|
|
256
|
+
function getLengthableOrigin(input) {
|
|
257
|
+
if (Array.isArray(input))
|
|
258
|
+
return "array";
|
|
259
|
+
if (typeof input === "string")
|
|
260
|
+
return "string";
|
|
261
|
+
return "unknown";
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/errors.js
|
|
265
|
+
var initializer = (inst, def) => {
|
|
266
|
+
inst.name = "$ZodError";
|
|
267
|
+
Object.defineProperty(inst, "_zod", {
|
|
268
|
+
value: inst._zod,
|
|
269
|
+
enumerable: false
|
|
270
|
+
});
|
|
271
|
+
Object.defineProperty(inst, "issues", {
|
|
272
|
+
value: def,
|
|
273
|
+
enumerable: false
|
|
274
|
+
});
|
|
275
|
+
inst.message = JSON.stringify(def, jsonStringifyReplacer, 2);
|
|
276
|
+
Object.defineProperty(inst, "toString", {
|
|
277
|
+
value: () => inst.message,
|
|
278
|
+
enumerable: false
|
|
279
|
+
});
|
|
280
|
+
};
|
|
281
|
+
var $ZodError = $constructor("$ZodError", initializer);
|
|
282
|
+
var $ZodRealError = $constructor("$ZodError", initializer, { Parent: Error });
|
|
283
|
+
|
|
284
|
+
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/parse.js
|
|
285
|
+
var _parse = (_Err) => (schema, value, _ctx, _params) => {
|
|
286
|
+
const ctx = _ctx ? { ..._ctx, async: false } : { async: false };
|
|
287
|
+
const result = schema._zod.run({ value, issues: [] }, ctx);
|
|
288
|
+
if (result instanceof Promise) {
|
|
289
|
+
throw new $ZodAsyncError();
|
|
290
|
+
}
|
|
291
|
+
if (result.issues.length) {
|
|
292
|
+
const e = new (_params?.Err ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));
|
|
293
|
+
captureStackTrace(e, _params?.callee);
|
|
294
|
+
throw e;
|
|
295
|
+
}
|
|
296
|
+
return result.value;
|
|
297
|
+
};
|
|
298
|
+
var parse = /* @__PURE__ */ _parse($ZodRealError);
|
|
299
|
+
var _parseAsync = (_Err) => async (schema, value, _ctx, params) => {
|
|
300
|
+
const ctx = _ctx ? { ..._ctx, async: true } : { async: true };
|
|
301
|
+
let result = schema._zod.run({ value, issues: [] }, ctx);
|
|
302
|
+
if (result instanceof Promise)
|
|
303
|
+
result = await result;
|
|
304
|
+
if (result.issues.length) {
|
|
305
|
+
const e = new (params?.Err ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));
|
|
306
|
+
captureStackTrace(e, params?.callee);
|
|
307
|
+
throw e;
|
|
308
|
+
}
|
|
309
|
+
return result.value;
|
|
310
|
+
};
|
|
311
|
+
var parseAsync = /* @__PURE__ */ _parseAsync($ZodRealError);
|
|
312
|
+
var _safeParse = (_Err) => (schema, value, _ctx) => {
|
|
313
|
+
const ctx = _ctx ? { ..._ctx, async: false } : { async: false };
|
|
314
|
+
const result = schema._zod.run({ value, issues: [] }, ctx);
|
|
315
|
+
if (result instanceof Promise) {
|
|
316
|
+
throw new $ZodAsyncError();
|
|
317
|
+
}
|
|
318
|
+
return result.issues.length ? {
|
|
319
|
+
success: false,
|
|
320
|
+
error: new (_Err ?? $ZodError)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())))
|
|
321
|
+
} : { success: true, data: result.value };
|
|
322
|
+
};
|
|
323
|
+
var safeParse = /* @__PURE__ */ _safeParse($ZodRealError);
|
|
324
|
+
var _safeParseAsync = (_Err) => async (schema, value, _ctx) => {
|
|
325
|
+
const ctx = _ctx ? { ..._ctx, async: true } : { async: true };
|
|
326
|
+
let result = schema._zod.run({ value, issues: [] }, ctx);
|
|
327
|
+
if (result instanceof Promise)
|
|
328
|
+
result = await result;
|
|
329
|
+
return result.issues.length ? {
|
|
330
|
+
success: false,
|
|
331
|
+
error: new _Err(result.issues.map((iss) => finalizeIssue(iss, ctx, config())))
|
|
332
|
+
} : { success: true, data: result.value };
|
|
333
|
+
};
|
|
334
|
+
var safeParseAsync = /* @__PURE__ */ _safeParseAsync($ZodRealError);
|
|
335
|
+
|
|
336
|
+
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/regexes.js
|
|
337
|
+
var email = /^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/;
|
|
338
|
+
var dateSource = `(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))`;
|
|
339
|
+
var date = /* @__PURE__ */ new RegExp(`^${dateSource}$`);
|
|
340
|
+
var string = (params) => {
|
|
341
|
+
const regex = params ? `[\\s\\S]{${params?.minimum ?? 0},${params?.maximum ?? ""}}` : `[\\s\\S]*`;
|
|
342
|
+
return new RegExp(`^${regex}$`);
|
|
343
|
+
};
|
|
344
|
+
var number = /^-?\d+(?:\.\d+)?$/;
|
|
345
|
+
|
|
346
|
+
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/checks.js
|
|
347
|
+
var $ZodCheck = /* @__PURE__ */ $constructor("$ZodCheck", (inst, def) => {
|
|
348
|
+
var _a2;
|
|
349
|
+
inst._zod ?? (inst._zod = {});
|
|
350
|
+
inst._zod.def = def;
|
|
351
|
+
(_a2 = inst._zod).onattach ?? (_a2.onattach = []);
|
|
352
|
+
});
|
|
353
|
+
var numericOriginMap = {
|
|
354
|
+
number: "number",
|
|
355
|
+
bigint: "bigint",
|
|
356
|
+
object: "date"
|
|
357
|
+
};
|
|
358
|
+
var $ZodCheckGreaterThan = /* @__PURE__ */ $constructor("$ZodCheckGreaterThan", (inst, def) => {
|
|
359
|
+
$ZodCheck.init(inst, def);
|
|
360
|
+
const origin = numericOriginMap[typeof def.value];
|
|
361
|
+
inst._zod.onattach.push((inst2) => {
|
|
362
|
+
const bag = inst2._zod.bag;
|
|
363
|
+
const curr = (def.inclusive ? bag.minimum : bag.exclusiveMinimum) ?? Number.NEGATIVE_INFINITY;
|
|
364
|
+
if (def.value > curr) {
|
|
365
|
+
if (def.inclusive)
|
|
366
|
+
bag.minimum = def.value;
|
|
367
|
+
else
|
|
368
|
+
bag.exclusiveMinimum = def.value;
|
|
369
|
+
}
|
|
370
|
+
});
|
|
371
|
+
inst._zod.check = (payload) => {
|
|
372
|
+
if (def.inclusive ? payload.value >= def.value : payload.value > def.value) {
|
|
373
|
+
return;
|
|
374
|
+
}
|
|
375
|
+
payload.issues.push({
|
|
376
|
+
origin,
|
|
377
|
+
code: "too_small",
|
|
378
|
+
minimum: typeof def.value === "object" ? def.value.getTime() : def.value,
|
|
379
|
+
input: payload.value,
|
|
380
|
+
inclusive: def.inclusive,
|
|
381
|
+
inst,
|
|
382
|
+
continue: !def.abort
|
|
383
|
+
});
|
|
384
|
+
};
|
|
385
|
+
});
|
|
386
|
+
var $ZodCheckMaxLength = /* @__PURE__ */ $constructor("$ZodCheckMaxLength", (inst, def) => {
|
|
387
|
+
var _a2;
|
|
388
|
+
$ZodCheck.init(inst, def);
|
|
389
|
+
(_a2 = inst._zod.def).when ?? (_a2.when = (payload) => {
|
|
390
|
+
const val = payload.value;
|
|
391
|
+
return !nullish(val) && val.length !== void 0;
|
|
392
|
+
});
|
|
393
|
+
inst._zod.onattach.push((inst2) => {
|
|
394
|
+
const curr = inst2._zod.bag.maximum ?? Number.POSITIVE_INFINITY;
|
|
395
|
+
if (def.maximum < curr)
|
|
396
|
+
inst2._zod.bag.maximum = def.maximum;
|
|
397
|
+
});
|
|
398
|
+
inst._zod.check = (payload) => {
|
|
399
|
+
const input = payload.value;
|
|
400
|
+
const length = input.length;
|
|
401
|
+
if (length <= def.maximum)
|
|
402
|
+
return;
|
|
403
|
+
const origin = getLengthableOrigin(input);
|
|
404
|
+
payload.issues.push({
|
|
405
|
+
origin,
|
|
406
|
+
code: "too_big",
|
|
407
|
+
maximum: def.maximum,
|
|
408
|
+
inclusive: true,
|
|
409
|
+
input,
|
|
410
|
+
inst,
|
|
411
|
+
continue: !def.abort
|
|
412
|
+
});
|
|
413
|
+
};
|
|
414
|
+
});
|
|
415
|
+
var $ZodCheckMinLength = /* @__PURE__ */ $constructor("$ZodCheckMinLength", (inst, def) => {
|
|
416
|
+
var _a2;
|
|
417
|
+
$ZodCheck.init(inst, def);
|
|
418
|
+
(_a2 = inst._zod.def).when ?? (_a2.when = (payload) => {
|
|
419
|
+
const val = payload.value;
|
|
420
|
+
return !nullish(val) && val.length !== void 0;
|
|
421
|
+
});
|
|
422
|
+
inst._zod.onattach.push((inst2) => {
|
|
423
|
+
const curr = inst2._zod.bag.minimum ?? Number.NEGATIVE_INFINITY;
|
|
424
|
+
if (def.minimum > curr)
|
|
425
|
+
inst2._zod.bag.minimum = def.minimum;
|
|
426
|
+
});
|
|
427
|
+
inst._zod.check = (payload) => {
|
|
428
|
+
const input = payload.value;
|
|
429
|
+
const length = input.length;
|
|
430
|
+
if (length >= def.minimum)
|
|
431
|
+
return;
|
|
432
|
+
const origin = getLengthableOrigin(input);
|
|
433
|
+
payload.issues.push({
|
|
434
|
+
origin,
|
|
435
|
+
code: "too_small",
|
|
436
|
+
minimum: def.minimum,
|
|
437
|
+
inclusive: true,
|
|
438
|
+
input,
|
|
439
|
+
inst,
|
|
440
|
+
continue: !def.abort
|
|
441
|
+
});
|
|
442
|
+
};
|
|
443
|
+
});
|
|
444
|
+
var $ZodCheckStringFormat = /* @__PURE__ */ $constructor("$ZodCheckStringFormat", (inst, def) => {
|
|
445
|
+
var _a2, _b;
|
|
446
|
+
$ZodCheck.init(inst, def);
|
|
447
|
+
inst._zod.onattach.push((inst2) => {
|
|
448
|
+
const bag = inst2._zod.bag;
|
|
449
|
+
bag.format = def.format;
|
|
450
|
+
if (def.pattern) {
|
|
451
|
+
bag.patterns ?? (bag.patterns = /* @__PURE__ */ new Set());
|
|
452
|
+
bag.patterns.add(def.pattern);
|
|
453
|
+
}
|
|
454
|
+
});
|
|
455
|
+
if (def.pattern)
|
|
456
|
+
(_a2 = inst._zod).check ?? (_a2.check = (payload) => {
|
|
457
|
+
def.pattern.lastIndex = 0;
|
|
458
|
+
if (def.pattern.test(payload.value))
|
|
459
|
+
return;
|
|
460
|
+
payload.issues.push({
|
|
461
|
+
origin: "string",
|
|
462
|
+
code: "invalid_format",
|
|
463
|
+
format: def.format,
|
|
464
|
+
input: payload.value,
|
|
465
|
+
...def.pattern ? { pattern: def.pattern.toString() } : {},
|
|
466
|
+
inst,
|
|
467
|
+
continue: !def.abort
|
|
468
|
+
});
|
|
469
|
+
});
|
|
470
|
+
else
|
|
471
|
+
(_b = inst._zod).check ?? (_b.check = () => {
|
|
472
|
+
});
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/versions.js
|
|
476
|
+
var version = {
|
|
477
|
+
major: 4,
|
|
478
|
+
minor: 4,
|
|
479
|
+
patch: 3
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/schemas.js
|
|
483
|
+
var $ZodType = /* @__PURE__ */ $constructor("$ZodType", (inst, def) => {
|
|
484
|
+
var _a2;
|
|
485
|
+
inst ?? (inst = {});
|
|
486
|
+
inst._zod.def = def;
|
|
487
|
+
inst._zod.bag = inst._zod.bag || {};
|
|
488
|
+
inst._zod.version = version;
|
|
489
|
+
const checks = [...inst._zod.def.checks ?? []];
|
|
490
|
+
if (inst._zod.traits.has("$ZodCheck")) {
|
|
491
|
+
checks.unshift(inst);
|
|
492
|
+
}
|
|
493
|
+
for (const ch of checks) {
|
|
494
|
+
for (const fn of ch._zod.onattach) {
|
|
495
|
+
fn(inst);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
if (checks.length === 0) {
|
|
499
|
+
(_a2 = inst._zod).deferred ?? (_a2.deferred = []);
|
|
500
|
+
inst._zod.deferred?.push(() => {
|
|
501
|
+
inst._zod.run = inst._zod.parse;
|
|
502
|
+
});
|
|
503
|
+
} else {
|
|
504
|
+
const runChecks = (payload, checks2, ctx) => {
|
|
505
|
+
let isAborted = aborted(payload);
|
|
506
|
+
let asyncResult;
|
|
507
|
+
for (const ch of checks2) {
|
|
508
|
+
if (ch._zod.def.when) {
|
|
509
|
+
if (explicitlyAborted(payload))
|
|
510
|
+
continue;
|
|
511
|
+
const shouldRun = ch._zod.def.when(payload);
|
|
512
|
+
if (!shouldRun)
|
|
513
|
+
continue;
|
|
514
|
+
} else if (isAborted) {
|
|
515
|
+
continue;
|
|
516
|
+
}
|
|
517
|
+
const currLen = payload.issues.length;
|
|
518
|
+
const _ = ch._zod.check(payload);
|
|
519
|
+
if (_ instanceof Promise && ctx?.async === false) {
|
|
520
|
+
throw new $ZodAsyncError();
|
|
521
|
+
}
|
|
522
|
+
if (asyncResult || _ instanceof Promise) {
|
|
523
|
+
asyncResult = (asyncResult ?? Promise.resolve()).then(async () => {
|
|
524
|
+
await _;
|
|
525
|
+
const nextLen = payload.issues.length;
|
|
526
|
+
if (nextLen === currLen)
|
|
527
|
+
return;
|
|
528
|
+
if (!isAborted)
|
|
529
|
+
isAborted = aborted(payload, currLen);
|
|
530
|
+
});
|
|
531
|
+
} else {
|
|
532
|
+
const nextLen = payload.issues.length;
|
|
533
|
+
if (nextLen === currLen)
|
|
534
|
+
continue;
|
|
535
|
+
if (!isAborted)
|
|
536
|
+
isAborted = aborted(payload, currLen);
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
if (asyncResult) {
|
|
540
|
+
return asyncResult.then(() => {
|
|
541
|
+
return payload;
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
return payload;
|
|
545
|
+
};
|
|
546
|
+
const handleCanaryResult = (canary, payload, ctx) => {
|
|
547
|
+
if (aborted(canary)) {
|
|
548
|
+
canary.aborted = true;
|
|
549
|
+
return canary;
|
|
550
|
+
}
|
|
551
|
+
const checkResult = runChecks(payload, checks, ctx);
|
|
552
|
+
if (checkResult instanceof Promise) {
|
|
553
|
+
if (ctx.async === false)
|
|
554
|
+
throw new $ZodAsyncError();
|
|
555
|
+
return checkResult.then((checkResult2) => inst._zod.parse(checkResult2, ctx));
|
|
556
|
+
}
|
|
557
|
+
return inst._zod.parse(checkResult, ctx);
|
|
558
|
+
};
|
|
559
|
+
inst._zod.run = (payload, ctx) => {
|
|
560
|
+
if (ctx.skipChecks) {
|
|
561
|
+
return inst._zod.parse(payload, ctx);
|
|
562
|
+
}
|
|
563
|
+
if (ctx.direction === "backward") {
|
|
564
|
+
const canary = inst._zod.parse({ value: payload.value, issues: [] }, { ...ctx, skipChecks: true });
|
|
565
|
+
if (canary instanceof Promise) {
|
|
566
|
+
return canary.then((canary2) => {
|
|
567
|
+
return handleCanaryResult(canary2, payload, ctx);
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
return handleCanaryResult(canary, payload, ctx);
|
|
571
|
+
}
|
|
572
|
+
const result = inst._zod.parse(payload, ctx);
|
|
573
|
+
if (result instanceof Promise) {
|
|
574
|
+
if (ctx.async === false)
|
|
575
|
+
throw new $ZodAsyncError();
|
|
576
|
+
return result.then((result2) => runChecks(result2, checks, ctx));
|
|
577
|
+
}
|
|
578
|
+
return runChecks(result, checks, ctx);
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
defineLazy(inst, "~standard", () => ({
|
|
582
|
+
validate: (value) => {
|
|
583
|
+
try {
|
|
584
|
+
const r = safeParse(inst, value);
|
|
585
|
+
return r.success ? { value: r.data } : { issues: r.error?.issues };
|
|
586
|
+
} catch (_) {
|
|
587
|
+
return safeParseAsync(inst, value).then((r) => r.success ? { value: r.data } : { issues: r.error?.issues });
|
|
588
|
+
}
|
|
589
|
+
},
|
|
590
|
+
vendor: "zod",
|
|
591
|
+
version: 1
|
|
592
|
+
}));
|
|
593
|
+
});
|
|
594
|
+
var $ZodString = /* @__PURE__ */ $constructor("$ZodString", (inst, def) => {
|
|
595
|
+
$ZodType.init(inst, def);
|
|
596
|
+
inst._zod.pattern = [...inst?._zod.bag?.patterns ?? []].pop() ?? string(inst._zod.bag);
|
|
597
|
+
inst._zod.parse = (payload, _) => {
|
|
598
|
+
if (def.coerce)
|
|
599
|
+
try {
|
|
600
|
+
payload.value = String(payload.value);
|
|
601
|
+
} catch (_2) {
|
|
602
|
+
}
|
|
603
|
+
if (typeof payload.value === "string")
|
|
604
|
+
return payload;
|
|
605
|
+
payload.issues.push({
|
|
606
|
+
expected: "string",
|
|
607
|
+
code: "invalid_type",
|
|
608
|
+
input: payload.value,
|
|
609
|
+
inst
|
|
610
|
+
});
|
|
611
|
+
return payload;
|
|
612
|
+
};
|
|
613
|
+
});
|
|
614
|
+
var $ZodStringFormat = /* @__PURE__ */ $constructor("$ZodStringFormat", (inst, def) => {
|
|
615
|
+
$ZodCheckStringFormat.init(inst, def);
|
|
616
|
+
$ZodString.init(inst, def);
|
|
617
|
+
});
|
|
618
|
+
var $ZodEmail = /* @__PURE__ */ $constructor("$ZodEmail", (inst, def) => {
|
|
619
|
+
def.pattern ?? (def.pattern = email);
|
|
620
|
+
$ZodStringFormat.init(inst, def);
|
|
621
|
+
});
|
|
622
|
+
var $ZodNumber = /* @__PURE__ */ $constructor("$ZodNumber", (inst, def) => {
|
|
623
|
+
$ZodType.init(inst, def);
|
|
624
|
+
inst._zod.pattern = inst._zod.bag.pattern ?? number;
|
|
625
|
+
inst._zod.parse = (payload, _ctx) => {
|
|
626
|
+
if (def.coerce)
|
|
627
|
+
try {
|
|
628
|
+
payload.value = Number(payload.value);
|
|
629
|
+
} catch (_) {
|
|
630
|
+
}
|
|
631
|
+
const input = payload.value;
|
|
632
|
+
if (typeof input === "number" && !Number.isNaN(input) && Number.isFinite(input)) {
|
|
633
|
+
return payload;
|
|
634
|
+
}
|
|
635
|
+
const received = typeof input === "number" ? Number.isNaN(input) ? "NaN" : !Number.isFinite(input) ? "Infinity" : void 0 : void 0;
|
|
636
|
+
payload.issues.push({
|
|
637
|
+
expected: "number",
|
|
638
|
+
code: "invalid_type",
|
|
639
|
+
input,
|
|
640
|
+
inst,
|
|
641
|
+
...received ? { received } : {}
|
|
642
|
+
});
|
|
643
|
+
return payload;
|
|
644
|
+
};
|
|
645
|
+
});
|
|
646
|
+
var $ZodUnknown = /* @__PURE__ */ $constructor("$ZodUnknown", (inst, def) => {
|
|
647
|
+
$ZodType.init(inst, def);
|
|
648
|
+
inst._zod.parse = (payload) => payload;
|
|
649
|
+
});
|
|
650
|
+
function handleArrayResult(result, final, index) {
|
|
651
|
+
if (result.issues.length) {
|
|
652
|
+
final.issues.push(...prefixIssues(index, result.issues));
|
|
653
|
+
}
|
|
654
|
+
final.value[index] = result.value;
|
|
655
|
+
}
|
|
656
|
+
var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
|
|
657
|
+
$ZodType.init(inst, def);
|
|
658
|
+
inst._zod.parse = (payload, ctx) => {
|
|
659
|
+
const input = payload.value;
|
|
660
|
+
if (!Array.isArray(input)) {
|
|
661
|
+
payload.issues.push({
|
|
662
|
+
expected: "array",
|
|
663
|
+
code: "invalid_type",
|
|
664
|
+
input,
|
|
665
|
+
inst
|
|
666
|
+
});
|
|
667
|
+
return payload;
|
|
668
|
+
}
|
|
669
|
+
payload.value = Array(input.length);
|
|
670
|
+
const proms = [];
|
|
671
|
+
for (let i = 0; i < input.length; i++) {
|
|
672
|
+
const item = input[i];
|
|
673
|
+
const result = def.element._zod.run({
|
|
674
|
+
value: item,
|
|
675
|
+
issues: []
|
|
676
|
+
}, ctx);
|
|
677
|
+
if (result instanceof Promise) {
|
|
678
|
+
proms.push(result.then((result2) => handleArrayResult(result2, payload, i)));
|
|
679
|
+
} else {
|
|
680
|
+
handleArrayResult(result, payload, i);
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
if (proms.length) {
|
|
684
|
+
return Promise.all(proms).then(() => payload);
|
|
685
|
+
}
|
|
686
|
+
return payload;
|
|
687
|
+
};
|
|
688
|
+
});
|
|
689
|
+
function handlePropertyResult(result, final, key, input, isOptionalIn, isOptionalOut) {
|
|
690
|
+
const isPresent = key in input;
|
|
691
|
+
if (result.issues.length) {
|
|
692
|
+
if (isOptionalIn && isOptionalOut && !isPresent) {
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
final.issues.push(...prefixIssues(key, result.issues));
|
|
696
|
+
}
|
|
697
|
+
if (!isPresent && !isOptionalIn) {
|
|
698
|
+
if (!result.issues.length) {
|
|
699
|
+
final.issues.push({
|
|
700
|
+
code: "invalid_type",
|
|
701
|
+
expected: "nonoptional",
|
|
702
|
+
input: void 0,
|
|
703
|
+
path: [key]
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
if (result.value === void 0) {
|
|
709
|
+
if (isPresent) {
|
|
710
|
+
final.value[key] = void 0;
|
|
711
|
+
}
|
|
712
|
+
} else {
|
|
713
|
+
final.value[key] = result.value;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
function normalizeDef(def) {
|
|
717
|
+
const keys = Object.keys(def.shape);
|
|
718
|
+
for (const k of keys) {
|
|
719
|
+
if (!def.shape?.[k]?._zod?.traits?.has("$ZodType")) {
|
|
720
|
+
throw new Error(`Invalid element at key "${k}": expected a Zod schema`);
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
const okeys = optionalKeys(def.shape);
|
|
724
|
+
return {
|
|
725
|
+
...def,
|
|
726
|
+
keys,
|
|
727
|
+
keySet: new Set(keys),
|
|
728
|
+
numKeys: keys.length,
|
|
729
|
+
optionalKeys: new Set(okeys)
|
|
730
|
+
};
|
|
731
|
+
}
|
|
732
|
+
function handleCatchall(proms, input, payload, ctx, def, inst) {
|
|
733
|
+
const unrecognized = [];
|
|
734
|
+
const keySet = def.keySet;
|
|
735
|
+
const _catchall = def.catchall._zod;
|
|
736
|
+
const t = _catchall.def.type;
|
|
737
|
+
const isOptionalIn = _catchall.optin === "optional";
|
|
738
|
+
const isOptionalOut = _catchall.optout === "optional";
|
|
739
|
+
for (const key in input) {
|
|
740
|
+
if (key === "__proto__")
|
|
741
|
+
continue;
|
|
742
|
+
if (keySet.has(key))
|
|
743
|
+
continue;
|
|
744
|
+
if (t === "never") {
|
|
745
|
+
unrecognized.push(key);
|
|
746
|
+
continue;
|
|
747
|
+
}
|
|
748
|
+
const r = _catchall.run({ value: input[key], issues: [] }, ctx);
|
|
749
|
+
if (r instanceof Promise) {
|
|
750
|
+
proms.push(r.then((r2) => handlePropertyResult(r2, payload, key, input, isOptionalIn, isOptionalOut)));
|
|
751
|
+
} else {
|
|
752
|
+
handlePropertyResult(r, payload, key, input, isOptionalIn, isOptionalOut);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
if (unrecognized.length) {
|
|
756
|
+
payload.issues.push({
|
|
757
|
+
code: "unrecognized_keys",
|
|
758
|
+
keys: unrecognized,
|
|
759
|
+
input,
|
|
760
|
+
inst
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
if (!proms.length)
|
|
764
|
+
return payload;
|
|
765
|
+
return Promise.all(proms).then(() => {
|
|
766
|
+
return payload;
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
770
|
+
$ZodType.init(inst, def);
|
|
771
|
+
const desc = Object.getOwnPropertyDescriptor(def, "shape");
|
|
772
|
+
if (!desc?.get) {
|
|
773
|
+
const sh = def.shape;
|
|
774
|
+
Object.defineProperty(def, "shape", {
|
|
775
|
+
get: () => {
|
|
776
|
+
const newSh = { ...sh };
|
|
777
|
+
Object.defineProperty(def, "shape", {
|
|
778
|
+
value: newSh
|
|
779
|
+
});
|
|
780
|
+
return newSh;
|
|
781
|
+
}
|
|
782
|
+
});
|
|
783
|
+
}
|
|
784
|
+
const _normalized = cached(() => normalizeDef(def));
|
|
785
|
+
defineLazy(inst._zod, "propValues", () => {
|
|
786
|
+
const shape = def.shape;
|
|
787
|
+
const propValues = {};
|
|
788
|
+
for (const key in shape) {
|
|
789
|
+
const field2 = shape[key]._zod;
|
|
790
|
+
if (field2.values) {
|
|
791
|
+
propValues[key] ?? (propValues[key] = /* @__PURE__ */ new Set());
|
|
792
|
+
for (const v of field2.values)
|
|
793
|
+
propValues[key].add(v);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
return propValues;
|
|
797
|
+
});
|
|
798
|
+
const isObject2 = isObject;
|
|
799
|
+
const catchall = def.catchall;
|
|
800
|
+
let value;
|
|
801
|
+
inst._zod.parse = (payload, ctx) => {
|
|
802
|
+
value ?? (value = _normalized.value);
|
|
803
|
+
const input = payload.value;
|
|
804
|
+
if (!isObject2(input)) {
|
|
805
|
+
payload.issues.push({
|
|
806
|
+
expected: "object",
|
|
807
|
+
code: "invalid_type",
|
|
808
|
+
input,
|
|
809
|
+
inst
|
|
810
|
+
});
|
|
811
|
+
return payload;
|
|
812
|
+
}
|
|
813
|
+
payload.value = {};
|
|
814
|
+
const proms = [];
|
|
815
|
+
const shape = value.shape;
|
|
816
|
+
for (const key of value.keys) {
|
|
817
|
+
const el = shape[key];
|
|
818
|
+
const isOptionalIn = el._zod.optin === "optional";
|
|
819
|
+
const isOptionalOut = el._zod.optout === "optional";
|
|
820
|
+
const r = el._zod.run({ value: input[key], issues: [] }, ctx);
|
|
821
|
+
if (r instanceof Promise) {
|
|
822
|
+
proms.push(r.then((r2) => handlePropertyResult(r2, payload, key, input, isOptionalIn, isOptionalOut)));
|
|
823
|
+
} else {
|
|
824
|
+
handlePropertyResult(r, payload, key, input, isOptionalIn, isOptionalOut);
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
if (!catchall) {
|
|
828
|
+
return proms.length ? Promise.all(proms).then(() => payload) : payload;
|
|
829
|
+
}
|
|
830
|
+
return handleCatchall(proms, input, payload, ctx, _normalized.value, inst);
|
|
831
|
+
};
|
|
832
|
+
});
|
|
833
|
+
var $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
|
|
834
|
+
$ZodType.init(inst, def);
|
|
835
|
+
inst._zod.parse = (payload, ctx) => {
|
|
836
|
+
const input = payload.value;
|
|
837
|
+
if (!isPlainObject(input)) {
|
|
838
|
+
payload.issues.push({
|
|
839
|
+
expected: "record",
|
|
840
|
+
code: "invalid_type",
|
|
841
|
+
input,
|
|
842
|
+
inst
|
|
843
|
+
});
|
|
844
|
+
return payload;
|
|
845
|
+
}
|
|
846
|
+
const proms = [];
|
|
847
|
+
const values = def.keyType._zod.values;
|
|
848
|
+
if (values) {
|
|
849
|
+
payload.value = {};
|
|
850
|
+
const recordKeys = /* @__PURE__ */ new Set();
|
|
851
|
+
for (const key of values) {
|
|
852
|
+
if (typeof key === "string" || typeof key === "number" || typeof key === "symbol") {
|
|
853
|
+
recordKeys.add(typeof key === "number" ? key.toString() : key);
|
|
854
|
+
const keyResult = def.keyType._zod.run({ value: key, issues: [] }, ctx);
|
|
855
|
+
if (keyResult instanceof Promise) {
|
|
856
|
+
throw new Error("Async schemas not supported in object keys currently");
|
|
857
|
+
}
|
|
858
|
+
if (keyResult.issues.length) {
|
|
859
|
+
payload.issues.push({
|
|
860
|
+
code: "invalid_key",
|
|
861
|
+
origin: "record",
|
|
862
|
+
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
|
|
863
|
+
input: key,
|
|
864
|
+
path: [key],
|
|
865
|
+
inst
|
|
866
|
+
});
|
|
867
|
+
continue;
|
|
868
|
+
}
|
|
869
|
+
const outKey = keyResult.value;
|
|
870
|
+
const result = def.valueType._zod.run({ value: input[key], issues: [] }, ctx);
|
|
871
|
+
if (result instanceof Promise) {
|
|
872
|
+
proms.push(result.then((result2) => {
|
|
873
|
+
if (result2.issues.length) {
|
|
874
|
+
payload.issues.push(...prefixIssues(key, result2.issues));
|
|
875
|
+
}
|
|
876
|
+
payload.value[outKey] = result2.value;
|
|
877
|
+
}));
|
|
878
|
+
} else {
|
|
879
|
+
if (result.issues.length) {
|
|
880
|
+
payload.issues.push(...prefixIssues(key, result.issues));
|
|
881
|
+
}
|
|
882
|
+
payload.value[outKey] = result.value;
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
let unrecognized;
|
|
887
|
+
for (const key in input) {
|
|
888
|
+
if (!recordKeys.has(key)) {
|
|
889
|
+
unrecognized = unrecognized ?? [];
|
|
890
|
+
unrecognized.push(key);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
if (unrecognized && unrecognized.length > 0) {
|
|
894
|
+
payload.issues.push({
|
|
895
|
+
code: "unrecognized_keys",
|
|
896
|
+
input,
|
|
897
|
+
inst,
|
|
898
|
+
keys: unrecognized
|
|
899
|
+
});
|
|
900
|
+
}
|
|
901
|
+
} else {
|
|
902
|
+
payload.value = {};
|
|
903
|
+
for (const key of Reflect.ownKeys(input)) {
|
|
904
|
+
if (key === "__proto__")
|
|
905
|
+
continue;
|
|
906
|
+
if (!Object.prototype.propertyIsEnumerable.call(input, key))
|
|
907
|
+
continue;
|
|
908
|
+
let keyResult = def.keyType._zod.run({ value: key, issues: [] }, ctx);
|
|
909
|
+
if (keyResult instanceof Promise) {
|
|
910
|
+
throw new Error("Async schemas not supported in object keys currently");
|
|
911
|
+
}
|
|
912
|
+
const checkNumericKey = typeof key === "string" && number.test(key) && keyResult.issues.length;
|
|
913
|
+
if (checkNumericKey) {
|
|
914
|
+
const retryResult = def.keyType._zod.run({ value: Number(key), issues: [] }, ctx);
|
|
915
|
+
if (retryResult instanceof Promise) {
|
|
916
|
+
throw new Error("Async schemas not supported in object keys currently");
|
|
917
|
+
}
|
|
918
|
+
if (retryResult.issues.length === 0) {
|
|
919
|
+
keyResult = retryResult;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
if (keyResult.issues.length) {
|
|
923
|
+
if (def.mode === "loose") {
|
|
924
|
+
payload.value[key] = input[key];
|
|
925
|
+
} else {
|
|
926
|
+
payload.issues.push({
|
|
927
|
+
code: "invalid_key",
|
|
928
|
+
origin: "record",
|
|
929
|
+
issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),
|
|
930
|
+
input: key,
|
|
931
|
+
path: [key],
|
|
932
|
+
inst
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
continue;
|
|
936
|
+
}
|
|
937
|
+
const result = def.valueType._zod.run({ value: input[key], issues: [] }, ctx);
|
|
938
|
+
if (result instanceof Promise) {
|
|
939
|
+
proms.push(result.then((result2) => {
|
|
940
|
+
if (result2.issues.length) {
|
|
941
|
+
payload.issues.push(...prefixIssues(key, result2.issues));
|
|
942
|
+
}
|
|
943
|
+
payload.value[keyResult.value] = result2.value;
|
|
944
|
+
}));
|
|
945
|
+
} else {
|
|
946
|
+
if (result.issues.length) {
|
|
947
|
+
payload.issues.push(...prefixIssues(key, result.issues));
|
|
948
|
+
}
|
|
949
|
+
payload.value[keyResult.value] = result.value;
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
if (proms.length) {
|
|
954
|
+
return Promise.all(proms).then(() => payload);
|
|
955
|
+
}
|
|
956
|
+
return payload;
|
|
957
|
+
};
|
|
958
|
+
});
|
|
959
|
+
var $ZodEnum = /* @__PURE__ */ $constructor("$ZodEnum", (inst, def) => {
|
|
960
|
+
$ZodType.init(inst, def);
|
|
961
|
+
const values = getEnumValues(def.entries);
|
|
962
|
+
const valuesSet = new Set(values);
|
|
963
|
+
inst._zod.values = valuesSet;
|
|
964
|
+
inst._zod.pattern = new RegExp(`^(${values.filter((k) => propertyKeyTypes.has(typeof k)).map((o) => typeof o === "string" ? escapeRegex(o) : o.toString()).join("|")})$`);
|
|
965
|
+
inst._zod.parse = (payload, _ctx) => {
|
|
966
|
+
const input = payload.value;
|
|
967
|
+
if (valuesSet.has(input)) {
|
|
968
|
+
return payload;
|
|
969
|
+
}
|
|
970
|
+
payload.issues.push({
|
|
971
|
+
code: "invalid_value",
|
|
972
|
+
values,
|
|
973
|
+
input,
|
|
974
|
+
inst
|
|
975
|
+
});
|
|
976
|
+
return payload;
|
|
977
|
+
};
|
|
978
|
+
});
|
|
979
|
+
var $ZodLiteral = /* @__PURE__ */ $constructor("$ZodLiteral", (inst, def) => {
|
|
980
|
+
$ZodType.init(inst, def);
|
|
981
|
+
if (def.values.length === 0) {
|
|
982
|
+
throw new Error("Cannot create literal schema with no valid values");
|
|
983
|
+
}
|
|
984
|
+
const values = new Set(def.values);
|
|
985
|
+
inst._zod.values = values;
|
|
986
|
+
inst._zod.pattern = new RegExp(`^(${def.values.map((o) => typeof o === "string" ? escapeRegex(o) : o ? escapeRegex(o.toString()) : String(o)).join("|")})$`);
|
|
987
|
+
inst._zod.parse = (payload, _ctx) => {
|
|
988
|
+
const input = payload.value;
|
|
989
|
+
if (values.has(input)) {
|
|
990
|
+
return payload;
|
|
991
|
+
}
|
|
992
|
+
payload.issues.push({
|
|
993
|
+
code: "invalid_value",
|
|
994
|
+
values: def.values,
|
|
995
|
+
input,
|
|
996
|
+
inst
|
|
997
|
+
});
|
|
998
|
+
return payload;
|
|
999
|
+
};
|
|
1000
|
+
});
|
|
1001
|
+
function handleOptionalResult(result, input) {
|
|
1002
|
+
if (input === void 0 && (result.issues.length || result.fallback)) {
|
|
1003
|
+
return { issues: [], value: void 0 };
|
|
1004
|
+
}
|
|
1005
|
+
return result;
|
|
1006
|
+
}
|
|
1007
|
+
var $ZodOptional = /* @__PURE__ */ $constructor("$ZodOptional", (inst, def) => {
|
|
1008
|
+
$ZodType.init(inst, def);
|
|
1009
|
+
inst._zod.optin = "optional";
|
|
1010
|
+
inst._zod.optout = "optional";
|
|
1011
|
+
defineLazy(inst._zod, "values", () => {
|
|
1012
|
+
return def.innerType._zod.values ? /* @__PURE__ */ new Set([...def.innerType._zod.values, void 0]) : void 0;
|
|
1013
|
+
});
|
|
1014
|
+
defineLazy(inst._zod, "pattern", () => {
|
|
1015
|
+
const pattern = def.innerType._zod.pattern;
|
|
1016
|
+
return pattern ? new RegExp(`^(${cleanRegex(pattern.source)})?$`) : void 0;
|
|
1017
|
+
});
|
|
1018
|
+
inst._zod.parse = (payload, ctx) => {
|
|
1019
|
+
if (def.innerType._zod.optin === "optional") {
|
|
1020
|
+
const input = payload.value;
|
|
1021
|
+
const result = def.innerType._zod.run(payload, ctx);
|
|
1022
|
+
if (result instanceof Promise)
|
|
1023
|
+
return result.then((r) => handleOptionalResult(r, input));
|
|
1024
|
+
return handleOptionalResult(result, input);
|
|
1025
|
+
}
|
|
1026
|
+
if (payload.value === void 0) {
|
|
1027
|
+
return payload;
|
|
1028
|
+
}
|
|
1029
|
+
return def.innerType._zod.run(payload, ctx);
|
|
1030
|
+
};
|
|
1031
|
+
});
|
|
1032
|
+
var $ZodDefault = /* @__PURE__ */ $constructor("$ZodDefault", (inst, def) => {
|
|
1033
|
+
$ZodType.init(inst, def);
|
|
1034
|
+
inst._zod.optin = "optional";
|
|
1035
|
+
defineLazy(inst._zod, "values", () => def.innerType._zod.values);
|
|
1036
|
+
inst._zod.parse = (payload, ctx) => {
|
|
1037
|
+
if (ctx.direction === "backward") {
|
|
1038
|
+
return def.innerType._zod.run(payload, ctx);
|
|
1039
|
+
}
|
|
1040
|
+
if (payload.value === void 0) {
|
|
1041
|
+
payload.value = def.defaultValue;
|
|
1042
|
+
return payload;
|
|
1043
|
+
}
|
|
1044
|
+
const result = def.innerType._zod.run(payload, ctx);
|
|
1045
|
+
if (result instanceof Promise) {
|
|
1046
|
+
return result.then((result2) => handleDefaultResult(result2, def));
|
|
1047
|
+
}
|
|
1048
|
+
return handleDefaultResult(result, def);
|
|
1049
|
+
};
|
|
1050
|
+
});
|
|
1051
|
+
function handleDefaultResult(payload, def) {
|
|
1052
|
+
if (payload.value === void 0) {
|
|
1053
|
+
payload.value = def.defaultValue;
|
|
1054
|
+
}
|
|
1055
|
+
return payload;
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/core/api.js
|
|
1059
|
+
// @__NO_SIDE_EFFECTS__
|
|
1060
|
+
function _string(Class, params) {
|
|
1061
|
+
return new Class({
|
|
1062
|
+
type: "string",
|
|
1063
|
+
...normalizeParams(params)
|
|
1064
|
+
});
|
|
1065
|
+
}
|
|
1066
|
+
// @__NO_SIDE_EFFECTS__
|
|
1067
|
+
function _email(Class, params) {
|
|
1068
|
+
return new Class({
|
|
1069
|
+
type: "string",
|
|
1070
|
+
format: "email",
|
|
1071
|
+
check: "string_format",
|
|
1072
|
+
abort: false,
|
|
1073
|
+
...normalizeParams(params)
|
|
1074
|
+
});
|
|
1075
|
+
}
|
|
1076
|
+
// @__NO_SIDE_EFFECTS__
|
|
1077
|
+
function _number(Class, params) {
|
|
1078
|
+
return new Class({
|
|
1079
|
+
type: "number",
|
|
1080
|
+
checks: [],
|
|
1081
|
+
...normalizeParams(params)
|
|
1082
|
+
});
|
|
1083
|
+
}
|
|
1084
|
+
// @__NO_SIDE_EFFECTS__
|
|
1085
|
+
function _unknown(Class) {
|
|
1086
|
+
return new Class({
|
|
1087
|
+
type: "unknown"
|
|
1088
|
+
});
|
|
1089
|
+
}
|
|
1090
|
+
// @__NO_SIDE_EFFECTS__
|
|
1091
|
+
function _gte(value, params) {
|
|
1092
|
+
return new $ZodCheckGreaterThan({
|
|
1093
|
+
check: "greater_than",
|
|
1094
|
+
...normalizeParams(params),
|
|
1095
|
+
value,
|
|
1096
|
+
inclusive: true
|
|
1097
|
+
});
|
|
1098
|
+
}
|
|
1099
|
+
// @__NO_SIDE_EFFECTS__
|
|
1100
|
+
function _nonnegative(params) {
|
|
1101
|
+
return /* @__PURE__ */ _gte(0, params);
|
|
1102
|
+
}
|
|
1103
|
+
// @__NO_SIDE_EFFECTS__
|
|
1104
|
+
function _maxLength(maximum, params) {
|
|
1105
|
+
const ch = new $ZodCheckMaxLength({
|
|
1106
|
+
check: "max_length",
|
|
1107
|
+
...normalizeParams(params),
|
|
1108
|
+
maximum
|
|
1109
|
+
});
|
|
1110
|
+
return ch;
|
|
1111
|
+
}
|
|
1112
|
+
// @__NO_SIDE_EFFECTS__
|
|
1113
|
+
function _minLength(minimum, params) {
|
|
1114
|
+
return new $ZodCheckMinLength({
|
|
1115
|
+
check: "min_length",
|
|
1116
|
+
...normalizeParams(params),
|
|
1117
|
+
minimum
|
|
1118
|
+
});
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/mini/schemas.js
|
|
1122
|
+
var ZodMiniType = /* @__PURE__ */ $constructor("ZodMiniType", (inst, def) => {
|
|
1123
|
+
if (!inst._zod)
|
|
1124
|
+
throw new Error("Uninitialized schema in ZodMiniType.");
|
|
1125
|
+
$ZodType.init(inst, def);
|
|
1126
|
+
inst.def = def;
|
|
1127
|
+
inst.type = def.type;
|
|
1128
|
+
inst.parse = (data, params) => parse(inst, data, params, { callee: inst.parse });
|
|
1129
|
+
inst.safeParse = (data, params) => safeParse(inst, data, params);
|
|
1130
|
+
inst.parseAsync = async (data, params) => parseAsync(inst, data, params, { callee: inst.parseAsync });
|
|
1131
|
+
inst.safeParseAsync = async (data, params) => safeParseAsync(inst, data, params);
|
|
1132
|
+
inst.check = (...checks) => {
|
|
1133
|
+
return inst.clone({
|
|
1134
|
+
...def,
|
|
1135
|
+
checks: [
|
|
1136
|
+
...def.checks ?? [],
|
|
1137
|
+
...checks.map((ch) => typeof ch === "function" ? {
|
|
1138
|
+
_zod: { check: ch, def: { check: "custom" }, onattach: [] }
|
|
1139
|
+
} : ch)
|
|
1140
|
+
]
|
|
1141
|
+
}, { parent: true });
|
|
1142
|
+
};
|
|
1143
|
+
inst.with = inst.check;
|
|
1144
|
+
inst.clone = (_def, params) => clone(inst, _def, params);
|
|
1145
|
+
inst.brand = () => inst;
|
|
1146
|
+
inst.register = ((reg, meta2) => {
|
|
1147
|
+
reg.add(inst, meta2);
|
|
1148
|
+
return inst;
|
|
1149
|
+
});
|
|
1150
|
+
inst.apply = (fn) => fn(inst);
|
|
1151
|
+
});
|
|
1152
|
+
var ZodMiniString = /* @__PURE__ */ $constructor("ZodMiniString", (inst, def) => {
|
|
1153
|
+
$ZodString.init(inst, def);
|
|
1154
|
+
ZodMiniType.init(inst, def);
|
|
1155
|
+
});
|
|
1156
|
+
// @__NO_SIDE_EFFECTS__
|
|
1157
|
+
function string2(params) {
|
|
1158
|
+
return _string(ZodMiniString, params);
|
|
1159
|
+
}
|
|
1160
|
+
var ZodMiniStringFormat = /* @__PURE__ */ $constructor("ZodMiniStringFormat", (inst, def) => {
|
|
1161
|
+
$ZodStringFormat.init(inst, def);
|
|
1162
|
+
ZodMiniString.init(inst, def);
|
|
1163
|
+
});
|
|
1164
|
+
var ZodMiniEmail = /* @__PURE__ */ $constructor("ZodMiniEmail", (inst, def) => {
|
|
1165
|
+
$ZodEmail.init(inst, def);
|
|
1166
|
+
ZodMiniStringFormat.init(inst, def);
|
|
1167
|
+
});
|
|
1168
|
+
// @__NO_SIDE_EFFECTS__
|
|
1169
|
+
function email2(params) {
|
|
1170
|
+
return _email(ZodMiniEmail, params);
|
|
1171
|
+
}
|
|
1172
|
+
var ZodMiniNumber = /* @__PURE__ */ $constructor("ZodMiniNumber", (inst, def) => {
|
|
1173
|
+
$ZodNumber.init(inst, def);
|
|
1174
|
+
ZodMiniType.init(inst, def);
|
|
1175
|
+
});
|
|
1176
|
+
// @__NO_SIDE_EFFECTS__
|
|
1177
|
+
function number2(params) {
|
|
1178
|
+
return _number(ZodMiniNumber, params);
|
|
1179
|
+
}
|
|
1180
|
+
var ZodMiniUnknown = /* @__PURE__ */ $constructor("ZodMiniUnknown", (inst, def) => {
|
|
1181
|
+
$ZodUnknown.init(inst, def);
|
|
1182
|
+
ZodMiniType.init(inst, def);
|
|
1183
|
+
});
|
|
1184
|
+
// @__NO_SIDE_EFFECTS__
|
|
1185
|
+
function unknown() {
|
|
1186
|
+
return _unknown(ZodMiniUnknown);
|
|
1187
|
+
}
|
|
1188
|
+
var ZodMiniArray = /* @__PURE__ */ $constructor("ZodMiniArray", (inst, def) => {
|
|
1189
|
+
$ZodArray.init(inst, def);
|
|
1190
|
+
ZodMiniType.init(inst, def);
|
|
1191
|
+
});
|
|
1192
|
+
// @__NO_SIDE_EFFECTS__
|
|
1193
|
+
function array(element, params) {
|
|
1194
|
+
return new ZodMiniArray({
|
|
1195
|
+
type: "array",
|
|
1196
|
+
element,
|
|
1197
|
+
...normalizeParams(params)
|
|
1198
|
+
});
|
|
1199
|
+
}
|
|
1200
|
+
var ZodMiniObject = /* @__PURE__ */ $constructor("ZodMiniObject", (inst, def) => {
|
|
1201
|
+
$ZodObject.init(inst, def);
|
|
1202
|
+
ZodMiniType.init(inst, def);
|
|
1203
|
+
defineLazy(inst, "shape", () => def.shape);
|
|
1204
|
+
});
|
|
1205
|
+
// @__NO_SIDE_EFFECTS__
|
|
1206
|
+
function object(shape, params) {
|
|
1207
|
+
const def = {
|
|
1208
|
+
type: "object",
|
|
1209
|
+
shape: shape ?? {},
|
|
1210
|
+
...normalizeParams(params)
|
|
1211
|
+
};
|
|
1212
|
+
return new ZodMiniObject(def);
|
|
1213
|
+
}
|
|
1214
|
+
// @__NO_SIDE_EFFECTS__
|
|
1215
|
+
function looseObject(shape, params) {
|
|
1216
|
+
return new ZodMiniObject({
|
|
1217
|
+
type: "object",
|
|
1218
|
+
shape,
|
|
1219
|
+
catchall: /* @__PURE__ */ unknown(),
|
|
1220
|
+
...normalizeParams(params)
|
|
1221
|
+
});
|
|
1222
|
+
}
|
|
1223
|
+
var ZodMiniRecord = /* @__PURE__ */ $constructor("ZodMiniRecord", (inst, def) => {
|
|
1224
|
+
$ZodRecord.init(inst, def);
|
|
1225
|
+
ZodMiniType.init(inst, def);
|
|
1226
|
+
});
|
|
1227
|
+
// @__NO_SIDE_EFFECTS__
|
|
1228
|
+
function record(keyType, valueType, params) {
|
|
1229
|
+
if (!valueType || !valueType._zod) {
|
|
1230
|
+
return new ZodMiniRecord({
|
|
1231
|
+
type: "record",
|
|
1232
|
+
keyType: /* @__PURE__ */ string2(),
|
|
1233
|
+
valueType: keyType,
|
|
1234
|
+
...normalizeParams(valueType)
|
|
1235
|
+
});
|
|
1236
|
+
}
|
|
1237
|
+
return new ZodMiniRecord({
|
|
1238
|
+
type: "record",
|
|
1239
|
+
keyType,
|
|
1240
|
+
valueType,
|
|
1241
|
+
...normalizeParams(params)
|
|
1242
|
+
});
|
|
1243
|
+
}
|
|
1244
|
+
var ZodMiniEnum = /* @__PURE__ */ $constructor("ZodMiniEnum", (inst, def) => {
|
|
1245
|
+
$ZodEnum.init(inst, def);
|
|
1246
|
+
ZodMiniType.init(inst, def);
|
|
1247
|
+
inst.options = Object.values(def.entries);
|
|
1248
|
+
});
|
|
1249
|
+
// @__NO_SIDE_EFFECTS__
|
|
1250
|
+
function _enum(values, params) {
|
|
1251
|
+
const entries = Array.isArray(values) ? Object.fromEntries(values.map((v) => [v, v])) : values;
|
|
1252
|
+
return new ZodMiniEnum({
|
|
1253
|
+
type: "enum",
|
|
1254
|
+
entries,
|
|
1255
|
+
...normalizeParams(params)
|
|
1256
|
+
});
|
|
1257
|
+
}
|
|
1258
|
+
var ZodMiniLiteral = /* @__PURE__ */ $constructor("ZodMiniLiteral", (inst, def) => {
|
|
1259
|
+
$ZodLiteral.init(inst, def);
|
|
1260
|
+
ZodMiniType.init(inst, def);
|
|
1261
|
+
});
|
|
1262
|
+
// @__NO_SIDE_EFFECTS__
|
|
1263
|
+
function literal(value, params) {
|
|
1264
|
+
return new ZodMiniLiteral({
|
|
1265
|
+
type: "literal",
|
|
1266
|
+
values: Array.isArray(value) ? value : [value],
|
|
1267
|
+
...normalizeParams(params)
|
|
1268
|
+
});
|
|
1269
|
+
}
|
|
1270
|
+
var ZodMiniOptional = /* @__PURE__ */ $constructor("ZodMiniOptional", (inst, def) => {
|
|
1271
|
+
$ZodOptional.init(inst, def);
|
|
1272
|
+
ZodMiniType.init(inst, def);
|
|
1273
|
+
});
|
|
1274
|
+
// @__NO_SIDE_EFFECTS__
|
|
1275
|
+
function optional(innerType) {
|
|
1276
|
+
return new ZodMiniOptional({
|
|
1277
|
+
type: "optional",
|
|
1278
|
+
innerType
|
|
1279
|
+
});
|
|
1280
|
+
}
|
|
1281
|
+
var ZodMiniDefault = /* @__PURE__ */ $constructor("ZodMiniDefault", (inst, def) => {
|
|
1282
|
+
$ZodDefault.init(inst, def);
|
|
1283
|
+
ZodMiniType.init(inst, def);
|
|
1284
|
+
});
|
|
1285
|
+
// @__NO_SIDE_EFFECTS__
|
|
1286
|
+
function _default(innerType, defaultValue) {
|
|
1287
|
+
return new ZodMiniDefault({
|
|
1288
|
+
type: "default",
|
|
1289
|
+
innerType,
|
|
1290
|
+
get defaultValue() {
|
|
1291
|
+
return typeof defaultValue === "function" ? defaultValue() : shallowClone(defaultValue);
|
|
1292
|
+
}
|
|
1293
|
+
});
|
|
1294
|
+
}
|
|
1295
|
+
|
|
1296
|
+
// ../core/dist/index.js
|
|
1297
|
+
var CONTENT_KINDS = ["heading", "paragraph", "divider"];
|
|
1298
|
+
function isField(block) {
|
|
1299
|
+
return !CONTENT_KINDS.includes(block.kind);
|
|
1300
|
+
}
|
|
1301
|
+
var C = (iso2, name, dialCode, lengths = [], groups = [], example = "") => ({ iso2, name, dialCode, lengths, groups, example });
|
|
1302
|
+
var PHONE_COUNTRIES = [
|
|
1303
|
+
C("US", "United States", "1", [10], [3, 3, 4], "2015550123"),
|
|
1304
|
+
C("CA", "Canada", "1", [10], [3, 3, 4], "5145550123"),
|
|
1305
|
+
C("GB", "United Kingdom", "44", [10], [4, 6], "7400123456"),
|
|
1306
|
+
C("AU", "Australia", "61", [9], [3, 3, 3], "412345678"),
|
|
1307
|
+
C("DE", "Germany", "49", [10, 11], [4, 7], "15123456789"),
|
|
1308
|
+
C("FR", "France", "33", [9], [1, 2, 2, 2, 2], "612345678"),
|
|
1309
|
+
C("IN", "India", "91", [10], [5, 5], "8123456789"),
|
|
1310
|
+
C("DK", "Denmark", "45", [8], [2, 2, 2, 2], "32123456"),
|
|
1311
|
+
C("SE", "Sweden", "46", [9], [2, 3, 4], "701234567"),
|
|
1312
|
+
C("NO", "Norway", "47", [8], [3, 2, 3], "40612345"),
|
|
1313
|
+
C("FI", "Finland", "358", [9, 10], [2, 3, 4], "412345678"),
|
|
1314
|
+
C("NL", "Netherlands", "31", [9], [1, 4, 4], "612345678"),
|
|
1315
|
+
C("BE", "Belgium", "32", [9], [3, 2, 2, 2], "470123456"),
|
|
1316
|
+
C("ES", "Spain", "34", [9], [3, 3, 3], "612345678"),
|
|
1317
|
+
C("IT", "Italy", "39", [9, 10], [3, 3, 4], "3123456789"),
|
|
1318
|
+
C("PT", "Portugal", "351", [9], [3, 3, 3], "912345678"),
|
|
1319
|
+
C("IE", "Ireland", "353", [9], [2, 3, 4], "851234567"),
|
|
1320
|
+
C("CH", "Switzerland", "41", [9], [2, 3, 2, 2], "781234567"),
|
|
1321
|
+
C("AT", "Austria", "43", [10, 11], [3, 7], "6641234567"),
|
|
1322
|
+
C("PL", "Poland", "48", [9], [3, 3, 3], "512345678"),
|
|
1323
|
+
C("CZ", "Czechia", "420", [9], [3, 3, 3], "601123456"),
|
|
1324
|
+
C("GR", "Greece", "30", [10], [3, 3, 4], "6912345678"),
|
|
1325
|
+
C("RO", "Romania", "40", [9], [3, 3, 3], "712345678"),
|
|
1326
|
+
C("HU", "Hungary", "36", [9], [2, 3, 4], "201234567"),
|
|
1327
|
+
C("UA", "Ukraine", "380", [9], [2, 3, 2, 2], "501234567"),
|
|
1328
|
+
C("RU", "Russia", "7", [10], [3, 3, 2, 2], "9123456789"),
|
|
1329
|
+
C("TR", "Turkey", "90", [10], [3, 3, 2, 2], "5012345678"),
|
|
1330
|
+
C("IL", "Israel", "972", [9], [2, 3, 4], "501234567"),
|
|
1331
|
+
C("AE", "United Arab Emirates", "971", [9], [2, 3, 4], "501234567"),
|
|
1332
|
+
C("SA", "Saudi Arabia", "966", [9], [2, 3, 4], "512345678"),
|
|
1333
|
+
C("ZA", "South Africa", "27", [9], [2, 3, 4], "711234567"),
|
|
1334
|
+
C("NG", "Nigeria", "234", [10], [3, 3, 4], "8021234567"),
|
|
1335
|
+
C("KE", "Kenya", "254", [9], [3, 3, 3], "712123456"),
|
|
1336
|
+
C("EG", "Egypt", "20", [10], [3, 3, 4], "1001234567"),
|
|
1337
|
+
C("BR", "Brazil", "55", [10, 11], [2, 5, 4], "11961234567"),
|
|
1338
|
+
C("MX", "Mexico", "52", [10], [3, 3, 4], "2221234567"),
|
|
1339
|
+
C("AR", "Argentina", "54", [10], [4, 6], "1123456789"),
|
|
1340
|
+
C("CL", "Chile", "56", [9], [1, 4, 4], "221234567"),
|
|
1341
|
+
C("CO", "Colombia", "57", [10], [3, 3, 4], "3211234567"),
|
|
1342
|
+
C("PE", "Peru", "51", [9], [3, 3, 3], "912345678"),
|
|
1343
|
+
C("CN", "China", "86", [11], [3, 4, 4], "13123456789"),
|
|
1344
|
+
C("JP", "Japan", "81", [10], [2, 4, 4], "9012345678"),
|
|
1345
|
+
C("KR", "South Korea", "82", [9, 10], [2, 4, 4], "1023456789"),
|
|
1346
|
+
C("SG", "Singapore", "65", [8], [4, 4], "81234567"),
|
|
1347
|
+
C("HK", "Hong Kong", "852", [8], [4, 4], "51234567"),
|
|
1348
|
+
C("TW", "Taiwan", "886", [9], [3, 3, 3], "912345678"),
|
|
1349
|
+
C("MY", "Malaysia", "60", [9, 10], [2, 3, 4], "123456789"),
|
|
1350
|
+
C("ID", "Indonesia", "62", [10, 11], [3, 4, 4], "81234567890"),
|
|
1351
|
+
C("TH", "Thailand", "66", [9], [2, 3, 4], "812345678"),
|
|
1352
|
+
C("PH", "Philippines", "63", [10], [3, 3, 4], "9171234567"),
|
|
1353
|
+
C("VN", "Vietnam", "84", [9], [3, 3, 3], "912345678"),
|
|
1354
|
+
C("PK", "Pakistan", "92", [10], [3, 3, 4], "3012345678"),
|
|
1355
|
+
C("BD", "Bangladesh", "880", [10], [2, 4, 4], "1812345678"),
|
|
1356
|
+
C("NZ", "New Zealand", "64", [9, 10], [2, 3, 4], "211234567"),
|
|
1357
|
+
C("SK", "Slovakia", "421", [9], [3, 3, 3], "912123456"),
|
|
1358
|
+
C("BG", "Bulgaria", "359", [9], [2, 3, 4], "481234567"),
|
|
1359
|
+
C("HR", "Croatia", "385", [8, 9], [2, 3, 4], "921234567"),
|
|
1360
|
+
C("RS", "Serbia", "381", [8, 9], [2, 3, 4], "601234567"),
|
|
1361
|
+
C("SI", "Slovenia", "386", [8], [2, 3, 3], "31234567"),
|
|
1362
|
+
C("LT", "Lithuania", "370", [8], [3, 2, 3], "61234567"),
|
|
1363
|
+
C("LV", "Latvia", "371", [8], [2, 3, 3], "21234567"),
|
|
1364
|
+
C("EE", "Estonia", "372", [7, 8], [3, 4], "51234567"),
|
|
1365
|
+
C("IS", "Iceland", "354", [7], [3, 4], "6111234"),
|
|
1366
|
+
C("LU", "Luxembourg", "352", [9], [3, 3, 3], "628123456"),
|
|
1367
|
+
C("MA", "Morocco", "212", [9], [3, 3, 3], "650123456"),
|
|
1368
|
+
C("CR", "Costa Rica", "506", [8], [4, 4], "83123456"),
|
|
1369
|
+
C("EC", "Ecuador", "593", [9], [2, 3, 4], "991234567"),
|
|
1370
|
+
C("UY", "Uruguay", "598", [8], [1, 3, 4], "94231234"),
|
|
1371
|
+
C("QA", "Qatar", "974", [8], [4, 4], "33123456"),
|
|
1372
|
+
C("KW", "Kuwait", "965", [8], [4, 4], "50012345")
|
|
1373
|
+
];
|
|
1374
|
+
var byIso = new Map(PHONE_COUNTRIES.map((c) => [c.iso2, c]));
|
|
1375
|
+
var fileValueSchema = object({
|
|
1376
|
+
fileId: string2().check(_minLength(1)),
|
|
1377
|
+
name: string2(),
|
|
1378
|
+
size: number2().check(_nonnegative()),
|
|
1379
|
+
mime: string2(),
|
|
1380
|
+
url: optional(string2())
|
|
1381
|
+
});
|
|
1382
|
+
var FIELD_KINDS = [
|
|
1383
|
+
"short_text",
|
|
1384
|
+
"long_text",
|
|
1385
|
+
"email",
|
|
1386
|
+
"url",
|
|
1387
|
+
"phone",
|
|
1388
|
+
"number",
|
|
1389
|
+
"select",
|
|
1390
|
+
"multi_select",
|
|
1391
|
+
"dropdown",
|
|
1392
|
+
"checkbox",
|
|
1393
|
+
"rating",
|
|
1394
|
+
"linear_scale",
|
|
1395
|
+
"ranking",
|
|
1396
|
+
"matrix",
|
|
1397
|
+
"signature",
|
|
1398
|
+
"date",
|
|
1399
|
+
"file_upload",
|
|
1400
|
+
"hidden",
|
|
1401
|
+
"custom"
|
|
1402
|
+
];
|
|
1403
|
+
var CONTENT_KINDS2 = ["heading", "paragraph", "divider"];
|
|
1404
|
+
var ALL_KINDS = [...FIELD_KINDS, ...CONTENT_KINDS2];
|
|
1405
|
+
var idSchema = string2().check(_minLength(1), _maxLength(128));
|
|
1406
|
+
var optionSchema = looseObject({
|
|
1407
|
+
id: idSchema,
|
|
1408
|
+
label: string2().check(_maxLength(1e3)),
|
|
1409
|
+
icon: optional(unknown())
|
|
1410
|
+
});
|
|
1411
|
+
var blockSchema = looseObject({
|
|
1412
|
+
id: idSchema,
|
|
1413
|
+
kind: _enum(ALL_KINDS),
|
|
1414
|
+
label: optional(string2().check(_maxLength(2e3))),
|
|
1415
|
+
options: optional(array(optionSchema).check(_maxLength(200))),
|
|
1416
|
+
rows: optional(array(optionSchema).check(_maxLength(200))),
|
|
1417
|
+
columns: optional(array(optionSchema).check(_maxLength(200)))
|
|
1418
|
+
});
|
|
1419
|
+
var pageSchema = object({
|
|
1420
|
+
id: idSchema,
|
|
1421
|
+
title: optional(string2().check(_maxLength(500))),
|
|
1422
|
+
blocks: array(blockSchema).check(_maxLength(500)),
|
|
1423
|
+
// Optional conditional page flow. Kept as unknown here (this schema is strict,
|
|
1424
|
+
// so it would otherwise be dropped at parse) and normalized by hand below once
|
|
1425
|
+
// the page-id set is known — a jump to a missing page is dropped, never kept.
|
|
1426
|
+
next: optional(unknown())
|
|
1427
|
+
});
|
|
1428
|
+
var schemaShape = object({
|
|
1429
|
+
version: literal(1),
|
|
1430
|
+
title: _default(optional(string2().check(_maxLength(2e3))), ""),
|
|
1431
|
+
description: optional(string2().check(_maxLength(5e3))),
|
|
1432
|
+
pages: array(pageSchema).check(_minLength(1), _maxLength(50)),
|
|
1433
|
+
settings: _default(optional(record(string2(), unknown())), {})
|
|
1434
|
+
});
|
|
1435
|
+
var MAX_SCHEMA_VERSION = 1;
|
|
1436
|
+
var FILLO_SCHEMA_VERSION = 1;
|
|
1437
|
+
var FILLO_SDK_VERSION = true ? "0.9.0" : "0.0.0-dev";
|
|
1438
|
+
function str(value, max, fallback = "") {
|
|
1439
|
+
return typeof value === "string" ? value.trim().slice(0, max) : fallback;
|
|
1440
|
+
}
|
|
1441
|
+
function optionalStr(value, max) {
|
|
1442
|
+
const s = str(value, max);
|
|
1443
|
+
return s === "" ? void 0 : s;
|
|
1444
|
+
}
|
|
1445
|
+
function bool(value) {
|
|
1446
|
+
return typeof value === "boolean" ? value : void 0;
|
|
1447
|
+
}
|
|
1448
|
+
function finite(value) {
|
|
1449
|
+
return typeof value === "number" && Number.isFinite(value) ? value : void 0;
|
|
1450
|
+
}
|
|
1451
|
+
function int(value, min, max, fallback) {
|
|
1452
|
+
const n = finite(value);
|
|
1453
|
+
if (n === void 0) return fallback;
|
|
1454
|
+
return Math.max(min, Math.min(max, Math.round(n)));
|
|
1455
|
+
}
|
|
1456
|
+
function options(value, max = 200) {
|
|
1457
|
+
if (!Array.isArray(value)) return [];
|
|
1458
|
+
return value.slice(0, max).flatMap((item) => {
|
|
1459
|
+
if (!item || typeof item !== "object") return [];
|
|
1460
|
+
const rec = item;
|
|
1461
|
+
const id = str(rec.id, 128);
|
|
1462
|
+
const label = str(rec.label, 1e3);
|
|
1463
|
+
const icon = rec.icon === "thumbs_up" || rec.icon === "thumbs_down" ? rec.icon : void 0;
|
|
1464
|
+
return id && label ? [cleanObject({ id, label, icon })] : [];
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1467
|
+
function duplicateOptionId(items) {
|
|
1468
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1469
|
+
for (const { id } of items) {
|
|
1470
|
+
if (ids.has(id)) return id;
|
|
1471
|
+
ids.add(id);
|
|
1472
|
+
}
|
|
1473
|
+
return void 0;
|
|
1474
|
+
}
|
|
1475
|
+
function conditions(value) {
|
|
1476
|
+
if (!Array.isArray(value)) return void 0;
|
|
1477
|
+
const normalized = value.slice(0, 20).flatMap((item) => {
|
|
1478
|
+
if (!item || typeof item !== "object") return [];
|
|
1479
|
+
const rec = item;
|
|
1480
|
+
const op = rec.op;
|
|
1481
|
+
if (op !== "eq" && op !== "neq" && op !== "contains" && op !== "gt" && op !== "lt" && op !== "answered" && op !== "not_answered") {
|
|
1482
|
+
return [];
|
|
1483
|
+
}
|
|
1484
|
+
const fieldId = str(rec.fieldId, 128);
|
|
1485
|
+
if (!fieldId) return [];
|
|
1486
|
+
const raw = rec.value;
|
|
1487
|
+
const value2 = typeof raw === "string" || typeof raw === "number" || typeof raw === "boolean" ? raw : void 0;
|
|
1488
|
+
return [{ fieldId, op, ...value2 !== void 0 ? { value: value2 } : {} }];
|
|
1489
|
+
});
|
|
1490
|
+
return normalized.length ? normalized : void 0;
|
|
1491
|
+
}
|
|
1492
|
+
function jumpRules(value, pageIds, sourceId, allowedFieldIds) {
|
|
1493
|
+
if (!Array.isArray(value)) return void 0;
|
|
1494
|
+
const rules = value.slice(0, 50).flatMap((item) => {
|
|
1495
|
+
if (!item || typeof item !== "object") return [];
|
|
1496
|
+
const rec = item;
|
|
1497
|
+
const to = typeof rec.to === "string" ? rec.to : void 0;
|
|
1498
|
+
if (!to || to !== "end" && !pageIds.has(to)) return [];
|
|
1499
|
+
if (to === sourceId) return [];
|
|
1500
|
+
const rawWhen = rec.when;
|
|
1501
|
+
if (rawWhen !== void 0 && !Array.isArray(rawWhen)) return [];
|
|
1502
|
+
const when2 = conditions(rawWhen);
|
|
1503
|
+
if (Array.isArray(rawWhen) && rawWhen.length > 0 && when2 === void 0) return [];
|
|
1504
|
+
if (when2 && when2.some((c) => !allowedFieldIds.has(c.fieldId))) return [];
|
|
1505
|
+
return [{ when: when2 ?? [], to }];
|
|
1506
|
+
});
|
|
1507
|
+
return rules.length ? rules : void 0;
|
|
1508
|
+
}
|
|
1509
|
+
function baseBlock(rec) {
|
|
1510
|
+
return {
|
|
1511
|
+
id: str(rec.id, 128),
|
|
1512
|
+
visibleIf: conditions(rec.visibleIf)
|
|
1513
|
+
};
|
|
1514
|
+
}
|
|
1515
|
+
function baseField(rec, kind) {
|
|
1516
|
+
const base = baseBlock(rec);
|
|
1517
|
+
return {
|
|
1518
|
+
...base,
|
|
1519
|
+
kind,
|
|
1520
|
+
label: str(rec.label, 2e3, "Untitled field"),
|
|
1521
|
+
description: optionalStr(rec.description, 5e3),
|
|
1522
|
+
required: bool(rec.required),
|
|
1523
|
+
placeholder: optionalStr(rec.placeholder, 500)
|
|
1524
|
+
};
|
|
1525
|
+
}
|
|
1526
|
+
function normalizeUrl(value) {
|
|
1527
|
+
const raw = optionalStr(value, 2e3);
|
|
1528
|
+
if (!raw) return void 0;
|
|
1529
|
+
try {
|
|
1530
|
+
const url = new URL(raw);
|
|
1531
|
+
return url.protocol === "http:" || url.protocol === "https:" ? raw : void 0;
|
|
1532
|
+
} catch {
|
|
1533
|
+
return void 0;
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
function normalizeResponseLimit(value) {
|
|
1537
|
+
if (!value || typeof value !== "object") return void 0;
|
|
1538
|
+
const rec = value;
|
|
1539
|
+
const by = rec.by === "browser" || rec.by === "field" || rec.by === "identify" ? rec.by : void 0;
|
|
1540
|
+
if (!by) return void 0;
|
|
1541
|
+
const field2 = by === "field" ? optionalStr(rec.field, 128) : void 0;
|
|
1542
|
+
if (by === "field" && !field2) return void 0;
|
|
1543
|
+
const scopeField = optionalStr(rec.scopeField, 128);
|
|
1544
|
+
const onRepeat = rec.onRepeat === "update" && by === "identify" ? "update" : "keep";
|
|
1545
|
+
return {
|
|
1546
|
+
by,
|
|
1547
|
+
...field2 ? { field: field2 } : {},
|
|
1548
|
+
...scopeField ? { scopeField } : {},
|
|
1549
|
+
onRepeat
|
|
1550
|
+
};
|
|
1551
|
+
}
|
|
1552
|
+
function normalizeTrust(value) {
|
|
1553
|
+
if (!value || typeof value !== "object") return void 0;
|
|
1554
|
+
const rec = value;
|
|
1555
|
+
const unverified = rec.unverified === "allow" || rec.unverified === "quarantine" ? rec.unverified : void 0;
|
|
1556
|
+
const challenge = rec.challenge === "turnstile" ? "turnstile" : void 0;
|
|
1557
|
+
if (!unverified && !challenge) return void 0;
|
|
1558
|
+
return {
|
|
1559
|
+
...unverified ? { unverified } : {},
|
|
1560
|
+
...challenge ? { challenge } : {}
|
|
1561
|
+
};
|
|
1562
|
+
}
|
|
1563
|
+
function normalizeSettings(value) {
|
|
1564
|
+
const rec = value && typeof value === "object" ? value : {};
|
|
1565
|
+
const submitMode = rec.submitMode === "button" || rec.submitMode === "auto" ? rec.submitMode : void 0;
|
|
1566
|
+
return {
|
|
1567
|
+
submitMode,
|
|
1568
|
+
submitLabel: optionalStr(rec.submitLabel, 100),
|
|
1569
|
+
successTitle: optionalStr(rec.successTitle, 200),
|
|
1570
|
+
successMessage: optionalStr(rec.successMessage, 5e3),
|
|
1571
|
+
redirectUrl: normalizeUrl(rec.redirectUrl),
|
|
1572
|
+
showProgress: bool(rec.showProgress),
|
|
1573
|
+
responseLimit: normalizeResponseLimit(rec.responseLimit),
|
|
1574
|
+
trust: normalizeTrust(rec.trust),
|
|
1575
|
+
notifyEmail: email2().check(_maxLength(254)).safeParse(rec.notifyEmail).success ? rec.notifyEmail : void 0,
|
|
1576
|
+
sendReceipt: bool(rec.sendReceipt),
|
|
1577
|
+
saveProgress: bool(rec.saveProgress),
|
|
1578
|
+
draftAnswersVisible: bool(rec.draftAnswersVisible),
|
|
1579
|
+
resumeEmails: bool(rec.resumeEmails),
|
|
1580
|
+
resumeUrl: normalizeUrl(rec.resumeUrl),
|
|
1581
|
+
draftDigest: bool(rec.draftDigest)
|
|
1582
|
+
};
|
|
1583
|
+
}
|
|
1584
|
+
function cleanObject(obj) {
|
|
1585
|
+
return Object.fromEntries(Object.entries(obj).filter(([, value]) => value !== void 0));
|
|
1586
|
+
}
|
|
1587
|
+
function normalizeBlock(input) {
|
|
1588
|
+
if (!input || typeof input !== "object") return null;
|
|
1589
|
+
const rec = input;
|
|
1590
|
+
const kind = rec.kind;
|
|
1591
|
+
const base = baseBlock(rec);
|
|
1592
|
+
if (!base.id || typeof kind !== "string") return null;
|
|
1593
|
+
switch (kind) {
|
|
1594
|
+
case "heading":
|
|
1595
|
+
return cleanObject({ ...base, kind, text: str(rec.text, 2e3, "Section") });
|
|
1596
|
+
case "paragraph":
|
|
1597
|
+
return cleanObject({ ...base, kind, text: str(rec.text, 5e3) });
|
|
1598
|
+
case "divider":
|
|
1599
|
+
return cleanObject({ ...base, kind });
|
|
1600
|
+
case "short_text":
|
|
1601
|
+
case "email":
|
|
1602
|
+
case "url":
|
|
1603
|
+
return cleanObject({
|
|
1604
|
+
...baseField(rec, kind),
|
|
1605
|
+
maxLength: finite(rec.maxLength) === void 0 ? void 0 : int(rec.maxLength, 1, 2e3, 2e3)
|
|
1606
|
+
});
|
|
1607
|
+
case "phone": {
|
|
1608
|
+
const cc = optionalStr(rec.defaultCountry, 2)?.toUpperCase();
|
|
1609
|
+
return cleanObject({
|
|
1610
|
+
...baseField(rec, kind),
|
|
1611
|
+
defaultCountry: cc && /^[A-Z]{2}$/.test(cc) ? cc : void 0
|
|
1612
|
+
});
|
|
1613
|
+
}
|
|
1614
|
+
case "long_text":
|
|
1615
|
+
return cleanObject({
|
|
1616
|
+
...baseField(rec, kind),
|
|
1617
|
+
maxLength: finite(rec.maxLength) === void 0 ? void 0 : int(rec.maxLength, 1, 2e4, 2e4)
|
|
1618
|
+
});
|
|
1619
|
+
case "number":
|
|
1620
|
+
return cleanObject({ ...baseField(rec, kind), min: finite(rec.min), max: finite(rec.max) });
|
|
1621
|
+
case "select":
|
|
1622
|
+
case "multi_select":
|
|
1623
|
+
case "dropdown": {
|
|
1624
|
+
const opts = options(rec.options);
|
|
1625
|
+
if (opts.length === 0) return null;
|
|
1626
|
+
return cleanObject({
|
|
1627
|
+
...baseField(rec, kind),
|
|
1628
|
+
options: opts,
|
|
1629
|
+
allowOther: bool(rec.allowOther),
|
|
1630
|
+
shuffleOptions: bool(rec.shuffleOptions)
|
|
1631
|
+
});
|
|
1632
|
+
}
|
|
1633
|
+
case "checkbox": {
|
|
1634
|
+
const appearance = rec.appearance === "toggle" ? "toggle" : void 0;
|
|
1635
|
+
return cleanObject({
|
|
1636
|
+
...baseField(rec, kind),
|
|
1637
|
+
appearance
|
|
1638
|
+
});
|
|
1639
|
+
}
|
|
1640
|
+
case "signature":
|
|
1641
|
+
case "date":
|
|
1642
|
+
return cleanObject(baseField(rec, kind));
|
|
1643
|
+
case "rating": {
|
|
1644
|
+
const max = int(rec.max, 1, 10, 5);
|
|
1645
|
+
return cleanObject({
|
|
1646
|
+
...baseField(rec, kind),
|
|
1647
|
+
max,
|
|
1648
|
+
insightsMetric: rec.insightsMetric === "csat" && max === 5 ? "csat" : void 0
|
|
1649
|
+
});
|
|
1650
|
+
}
|
|
1651
|
+
case "linear_scale": {
|
|
1652
|
+
const min = int(rec.min, 0, 9, 1);
|
|
1653
|
+
const max = int(rec.max, min + 1, 10, 10);
|
|
1654
|
+
const insightsMetric = rec.insightsMetric === "nps" && min === 0 && max === 10 ? "nps" : rec.insightsMetric === "csat" && min === 1 && max === 5 ? "csat" : void 0;
|
|
1655
|
+
return cleanObject({
|
|
1656
|
+
...baseField(rec, kind),
|
|
1657
|
+
min,
|
|
1658
|
+
max,
|
|
1659
|
+
minLabel: optionalStr(rec.minLabel, 100),
|
|
1660
|
+
maxLabel: optionalStr(rec.maxLabel, 100),
|
|
1661
|
+
insightsMetric
|
|
1662
|
+
});
|
|
1663
|
+
}
|
|
1664
|
+
case "ranking": {
|
|
1665
|
+
const opts = options(rec.options);
|
|
1666
|
+
if (opts.length < 2) return null;
|
|
1667
|
+
return cleanObject({ ...baseField(rec, kind), options: opts });
|
|
1668
|
+
}
|
|
1669
|
+
case "matrix": {
|
|
1670
|
+
const rows = options(rec.rows);
|
|
1671
|
+
const columns = options(rec.columns);
|
|
1672
|
+
if (rows.length === 0 || columns.length === 0) return null;
|
|
1673
|
+
return cleanObject({ ...baseField(rec, kind), rows, columns });
|
|
1674
|
+
}
|
|
1675
|
+
case "hidden":
|
|
1676
|
+
return cleanObject({
|
|
1677
|
+
...baseField(rec, kind),
|
|
1678
|
+
// Hidden fields render nothing, so a required one with no matching URL
|
|
1679
|
+
// param / default would be permanently unsubmittable — never required.
|
|
1680
|
+
required: false,
|
|
1681
|
+
paramName: optionalStr(rec.paramName, 128),
|
|
1682
|
+
defaultValue: optionalStr(rec.defaultValue, 1e3)
|
|
1683
|
+
});
|
|
1684
|
+
case "file_upload":
|
|
1685
|
+
return cleanObject({
|
|
1686
|
+
...baseField(rec, kind),
|
|
1687
|
+
maxFiles: int(rec.maxFiles, 1, 20, 1),
|
|
1688
|
+
maxFileSizeMb: int(rec.maxFileSizeMb, 1, 5e3, 500),
|
|
1689
|
+
accept: Array.isArray(rec.accept) ? rec.accept.flatMap((v) => {
|
|
1690
|
+
const item = optionalStr(v, 100);
|
|
1691
|
+
return item ? [item] : [];
|
|
1692
|
+
}).slice(0, 50) : void 0
|
|
1693
|
+
});
|
|
1694
|
+
case "custom":
|
|
1695
|
+
return cleanObject({
|
|
1696
|
+
...baseField(rec, kind),
|
|
1697
|
+
component: str(rec.component, 128),
|
|
1698
|
+
config: rec.config && typeof rec.config === "object" && !Array.isArray(rec.config) ? rec.config : void 0
|
|
1699
|
+
});
|
|
1700
|
+
default:
|
|
1701
|
+
return null;
|
|
1702
|
+
}
|
|
1703
|
+
}
|
|
1704
|
+
function normalizeFormSchema(input) {
|
|
1705
|
+
const parsed = schemaShape.safeParse(input);
|
|
1706
|
+
if (!parsed.success) {
|
|
1707
|
+
const first = parsed.error.issues[0];
|
|
1708
|
+
const path = first?.path.join(".");
|
|
1709
|
+
return { ok: false, error: first ? `${path ? `${path}: ` : ""}${first.message}` : "Invalid schema" };
|
|
1710
|
+
}
|
|
1711
|
+
if (parsed.data.version > MAX_SCHEMA_VERSION) {
|
|
1712
|
+
return { ok: false, error: `Unsupported schema version: ${parsed.data.version}` };
|
|
1713
|
+
}
|
|
1714
|
+
const rebuilt = parsed.data.pages.map((page) => {
|
|
1715
|
+
const blocks = page.blocks.flatMap((raw) => {
|
|
1716
|
+
const block = normalizeBlock(raw);
|
|
1717
|
+
return block ? [block] : [];
|
|
1718
|
+
});
|
|
1719
|
+
return { id: str(page.id, 128), title: optionalStr(page.title, 500), blocks, next: page.next };
|
|
1720
|
+
});
|
|
1721
|
+
const targetIds = new Set(rebuilt.map((p) => p.id));
|
|
1722
|
+
const priorFieldIds = /* @__PURE__ */ new Set();
|
|
1723
|
+
const pages = rebuilt.map((page) => {
|
|
1724
|
+
for (const block of page.blocks) {
|
|
1725
|
+
if (isField(block)) priorFieldIds.add(block.id);
|
|
1726
|
+
}
|
|
1727
|
+
return cleanObject({
|
|
1728
|
+
id: page.id,
|
|
1729
|
+
title: page.title,
|
|
1730
|
+
blocks: page.blocks,
|
|
1731
|
+
next: jumpRules(page.next, targetIds, page.id, new Set(priorFieldIds))
|
|
1732
|
+
});
|
|
1733
|
+
});
|
|
1734
|
+
const pageIds = /* @__PURE__ */ new Set();
|
|
1735
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1736
|
+
for (const page of pages) {
|
|
1737
|
+
if (!page.id) return { ok: false, error: "Page ids cannot be blank" };
|
|
1738
|
+
if (pageIds.has(page.id)) return { ok: false, error: `Duplicate page id: ${page.id}` };
|
|
1739
|
+
pageIds.add(page.id);
|
|
1740
|
+
for (const block of page.blocks) {
|
|
1741
|
+
if (seen.has(block.id)) return { ok: false, error: `Duplicate block id: ${block.id}` };
|
|
1742
|
+
seen.add(block.id);
|
|
1743
|
+
if (block.kind === "number" && block.min !== void 0 && block.max !== void 0 && block.min > block.max) {
|
|
1744
|
+
return { ok: false, error: `Field ${block.id} has min greater than max` };
|
|
1745
|
+
}
|
|
1746
|
+
if (block.kind === "select" || block.kind === "multi_select" || block.kind === "dropdown" || block.kind === "ranking") {
|
|
1747
|
+
const duplicate = duplicateOptionId(block.options);
|
|
1748
|
+
if (duplicate) {
|
|
1749
|
+
return { ok: false, error: `Duplicate option id in field ${block.id}: ${duplicate}` };
|
|
1750
|
+
}
|
|
1751
|
+
} else if (block.kind === "matrix") {
|
|
1752
|
+
const duplicateRow = duplicateOptionId(block.rows);
|
|
1753
|
+
if (duplicateRow) {
|
|
1754
|
+
return { ok: false, error: `Duplicate matrix row id in field ${block.id}: ${duplicateRow}` };
|
|
1755
|
+
}
|
|
1756
|
+
const duplicateColumn = duplicateOptionId(block.columns);
|
|
1757
|
+
if (duplicateColumn) {
|
|
1758
|
+
return {
|
|
1759
|
+
ok: false,
|
|
1760
|
+
error: `Duplicate matrix column id in field ${block.id}: ${duplicateColumn}`
|
|
1761
|
+
};
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
if (pages.every((page) => page.blocks.length === 0)) {
|
|
1767
|
+
return { ok: false, error: "Schema must contain at least one valid block" };
|
|
1768
|
+
}
|
|
1769
|
+
const schema = {
|
|
1770
|
+
version: FILLO_SCHEMA_VERSION,
|
|
1771
|
+
title: str(parsed.data.title, 2e3),
|
|
1772
|
+
pages,
|
|
1773
|
+
settings: normalizeSettings(parsed.data.settings)
|
|
1774
|
+
};
|
|
1775
|
+
const description = optionalStr(parsed.data.description, 5e3);
|
|
1776
|
+
if (description) schema.description = description;
|
|
1777
|
+
return { ok: true, schema };
|
|
1778
|
+
}
|
|
1779
|
+
function validateFormSchema(input) {
|
|
1780
|
+
try {
|
|
1781
|
+
return normalizeFormSchema(input);
|
|
1782
|
+
} catch (err) {
|
|
1783
|
+
return { ok: false, error: err instanceof Error ? err.message : "Invalid schema" };
|
|
1784
|
+
}
|
|
1785
|
+
}
|
|
1786
|
+
var ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
|
1787
|
+
var MASK = 256 - 256 % ALPHABET.length;
|
|
1788
|
+
var S3_PART_TIMEOUT_MS = 5 * 6e4;
|
|
1789
|
+
var UPLOAD_CONTROL_TIMEOUT_MS = 10 * 6e4;
|
|
1790
|
+
var CLIENT_HEADER = { "X-Fillo-Client": `@usefillo/core@${FILLO_SDK_VERSION}` };
|
|
1791
|
+
var FilloJsxError = class extends Error {
|
|
1792
|
+
constructor(code, message) {
|
|
1793
|
+
super(`[fillo] ${message} \u2014 https://fillo.so/docs/troubleshooting#jsx-${code.toLowerCase()}`);
|
|
1794
|
+
this.code = code;
|
|
1795
|
+
this.name = "FilloJsxError";
|
|
1796
|
+
}
|
|
1797
|
+
code;
|
|
1798
|
+
};
|
|
1799
|
+
var BRAND = /* @__PURE__ */ Symbol.for("fillo.block");
|
|
1800
|
+
var FIELD_BASE = ["label", "description", "required", "placeholder"];
|
|
1801
|
+
var field = (name, kind, extra, opts = {}) => ({
|
|
1802
|
+
name,
|
|
1803
|
+
kind,
|
|
1804
|
+
props: [...FIELD_BASE, ...extra],
|
|
1805
|
+
...opts
|
|
1806
|
+
});
|
|
1807
|
+
var content = (name, kind, textChildren) => ({
|
|
1808
|
+
name,
|
|
1809
|
+
kind,
|
|
1810
|
+
props: textChildren ? ["text"] : [],
|
|
1811
|
+
textChildren,
|
|
1812
|
+
content: true
|
|
1813
|
+
});
|
|
1814
|
+
var CHOICE_EXTRA = ["options", "allowOther", "shuffleOptions"];
|
|
1815
|
+
var JSX_BLOCK_SPECS = [
|
|
1816
|
+
field("Text", "short_text", ["maxLength"]),
|
|
1817
|
+
field("LongText", "long_text", ["maxLength"]),
|
|
1818
|
+
field("Email", "email", ["maxLength"]),
|
|
1819
|
+
field("Url", "url", ["maxLength"]),
|
|
1820
|
+
field("Phone", "phone", ["defaultCountry"]),
|
|
1821
|
+
field("Number", "number", ["min", "max"]),
|
|
1822
|
+
field("Select", "select", CHOICE_EXTRA, { optionChildren: true }),
|
|
1823
|
+
field("MultiSelect", "multi_select", CHOICE_EXTRA, { optionChildren: true }),
|
|
1824
|
+
field("Dropdown", "dropdown", CHOICE_EXTRA, { optionChildren: true }),
|
|
1825
|
+
field("Checkbox", "checkbox", ["appearance"]),
|
|
1826
|
+
field("Rating", "rating", ["max", "insightsMetric"]),
|
|
1827
|
+
field("Scale", "linear_scale", ["min", "max", "minLabel", "maxLabel", "insightsMetric"]),
|
|
1828
|
+
field("Ranking", "ranking", ["options"], { optionChildren: true }),
|
|
1829
|
+
field("Matrix", "matrix", ["rows", "columns"]),
|
|
1830
|
+
field("Signature", "signature", []),
|
|
1831
|
+
field("Date", "date", []),
|
|
1832
|
+
field("FileUpload", "file_upload", ["maxFiles", "maxFileSizeMb", "accept"]),
|
|
1833
|
+
field("Hidden", "hidden", ["paramName", "defaultValue"]),
|
|
1834
|
+
field("Custom", "custom", ["component", "config"]),
|
|
1835
|
+
content("Heading", "heading", true),
|
|
1836
|
+
content("Paragraph", "paragraph", true),
|
|
1837
|
+
{ name: "Divider", kind: "divider", props: [], content: true }
|
|
1838
|
+
];
|
|
1839
|
+
var PAGE_SPEC = { name: "Page", kind: "__page", props: ["title"] };
|
|
1840
|
+
var OPTION_SPEC = { name: "Option", kind: "__option", props: ["label", "icon"] };
|
|
1841
|
+
function makeInert(spec) {
|
|
1842
|
+
const component = () => {
|
|
1843
|
+
throw new FilloJsxError(
|
|
1844
|
+
"RENDERED_INERT",
|
|
1845
|
+
`<Fillo.${spec.name}> was rendered by React. Fillo fields are schema declarations, valid only inside <Fillo.Form> or Fillo.defineForm(). If this form lives in a server component, move it to a client module ("use client")`
|
|
1846
|
+
);
|
|
1847
|
+
};
|
|
1848
|
+
component[BRAND] = spec;
|
|
1849
|
+
return component;
|
|
1850
|
+
}
|
|
1851
|
+
var JSX_BLOCK_COMPONENTS = Object.fromEntries([
|
|
1852
|
+
...JSX_BLOCK_SPECS.map((spec) => [spec.name, makeInert(spec)]),
|
|
1853
|
+
["Page", makeInert(PAGE_SPEC)],
|
|
1854
|
+
["Option", makeInert(OPTION_SPEC)]
|
|
1855
|
+
]);
|
|
1856
|
+
|
|
1857
|
+
// src/index.ts
|
|
9
1858
|
var API = (process.env.FILLO_API ?? "https://fillo.so").replace(/\/$/, "");
|
|
10
1859
|
var CONFIG_DIR = join(homedir(), ".fillo");
|
|
11
1860
|
var CONFIG_PATH = join(CONFIG_DIR, "config.json");
|
|
12
|
-
var
|
|
13
|
-
var
|
|
1861
|
+
var BUNDLED_SKILL_DIR = fileURLToPath(new URL("./skill/build-with-fillo", import.meta.url));
|
|
1862
|
+
var REQUEST_TIMEOUT_MS = 3e4;
|
|
1863
|
+
var MAX_STDIN_SCHEMA_BYTES = 1024 * 1024;
|
|
1864
|
+
var SYNC_TOKEN_ENV = "FILLO_SYNC_TOKEN";
|
|
1865
|
+
function terminalText(value) {
|
|
1866
|
+
return value.replace(/\b(?:fcli|fsync)_[A-Za-z0-9._~-]+\b/g, "[redacted]").replace(/[\u0000-\u001f\u007f-\u009f]/g, " ").replace(/\s+/g, " ").trim();
|
|
1867
|
+
}
|
|
1868
|
+
var bold = (s) => `\x1B[1m${terminalText(s)}\x1B[0m`;
|
|
1869
|
+
var dim = (s) => `\x1B[2m${terminalText(s)}\x1B[0m`;
|
|
14
1870
|
var sleep = (ms) => new Promise((r) => setTimeout(r, ms));
|
|
15
1871
|
function die(msg) {
|
|
16
|
-
console.error(`\x1B[31m\u2717\x1B[0m ${msg}`);
|
|
1872
|
+
console.error(`\x1B[31m\u2717\x1B[0m ${terminalText(msg)}`);
|
|
17
1873
|
process.exit(1);
|
|
18
1874
|
}
|
|
19
1875
|
function readConfig() {
|
|
20
1876
|
try {
|
|
21
|
-
|
|
1877
|
+
const parsed = JSON.parse(readFileSync(CONFIG_PATH, "utf8"));
|
|
1878
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) return {};
|
|
1879
|
+
const record2 = parsed;
|
|
1880
|
+
return {
|
|
1881
|
+
...typeof record2.token === "string" ? { token: record2.token } : {},
|
|
1882
|
+
...typeof record2.tokenApi === "string" ? { tokenApi: record2.tokenApi } : {},
|
|
1883
|
+
...typeof record2.pk === "string" ? { pk: record2.pk } : {},
|
|
1884
|
+
...typeof record2.claimUrl === "string" ? { claimUrl: record2.claimUrl } : {}
|
|
1885
|
+
};
|
|
22
1886
|
} catch {
|
|
23
1887
|
return {};
|
|
24
1888
|
}
|
|
25
1889
|
}
|
|
26
1890
|
function writeConfig(c) {
|
|
27
1891
|
mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
1892
|
+
try {
|
|
1893
|
+
chmodSync(CONFIG_DIR, 448);
|
|
1894
|
+
} catch {
|
|
1895
|
+
}
|
|
28
1896
|
writeFileSync(CONFIG_PATH, JSON.stringify(c, null, 2), { mode: 384 });
|
|
29
1897
|
try {
|
|
30
1898
|
chmodSync(CONFIG_PATH, 384);
|
|
31
1899
|
} catch {
|
|
32
1900
|
}
|
|
33
1901
|
}
|
|
1902
|
+
function requireTokenFor(apiBase) {
|
|
1903
|
+
const config2 = readConfig();
|
|
1904
|
+
if (typeof config2.token !== "string" || !config2.token) {
|
|
1905
|
+
die("Not logged in. Run `fillo login` first.");
|
|
1906
|
+
}
|
|
1907
|
+
if (typeof config2.tokenApi !== "string" || !config2.tokenApi) {
|
|
1908
|
+
die("This login cannot be used safely. Run `fillo login` again, then retry.");
|
|
1909
|
+
}
|
|
1910
|
+
const tokenApi = config2.tokenApi.replace(/\/$/, "");
|
|
1911
|
+
if (apiBase.replace(/\/$/, "") !== tokenApi) {
|
|
1912
|
+
die(
|
|
1913
|
+
`This login belongs to ${terminalText(tokenApi)}. Log in to the requested Fillo deployment, then try again.`
|
|
1914
|
+
);
|
|
1915
|
+
}
|
|
1916
|
+
return config2.token;
|
|
1917
|
+
}
|
|
34
1918
|
function requireToken() {
|
|
35
|
-
|
|
36
|
-
if (!t) die("Not logged in. Run `fillo login` first.");
|
|
37
|
-
return t;
|
|
1919
|
+
return requireTokenFor(API);
|
|
38
1920
|
}
|
|
39
1921
|
function openBrowser(url) {
|
|
40
|
-
|
|
1922
|
+
let safeUrl;
|
|
1923
|
+
try {
|
|
1924
|
+
const parsed = new URL(url);
|
|
1925
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") return;
|
|
1926
|
+
safeUrl = parsed.toString();
|
|
1927
|
+
} catch {
|
|
1928
|
+
return;
|
|
1929
|
+
}
|
|
41
1930
|
try {
|
|
42
1931
|
if (process.platform === "win32") {
|
|
43
|
-
const child = spawn("cmd", ["/c", "start", "",
|
|
1932
|
+
const child = spawn("cmd", ["/c", "start", "", safeUrl], { stdio: "ignore", detached: true });
|
|
44
1933
|
child.on("error", () => {
|
|
45
1934
|
});
|
|
46
1935
|
child.unref();
|
|
47
1936
|
} else {
|
|
48
1937
|
const cmd = process.platform === "darwin" ? "open" : "xdg-open";
|
|
49
|
-
const child = spawn(cmd, [
|
|
1938
|
+
const child = spawn(cmd, [safeUrl], { stdio: "ignore", detached: true });
|
|
50
1939
|
child.on("error", () => {
|
|
51
1940
|
});
|
|
52
1941
|
child.unref();
|
|
@@ -54,10 +1943,11 @@ function openBrowser(url) {
|
|
|
54
1943
|
} catch {
|
|
55
1944
|
}
|
|
56
1945
|
}
|
|
57
|
-
async function api(path, init2 = {}) {
|
|
1946
|
+
async function api(path, init2 = {}, apiBase = API) {
|
|
58
1947
|
const { token, ...rest } = init2;
|
|
59
|
-
return fetch(`${
|
|
1948
|
+
return fetch(`${apiBase}/api/v1${path}`, {
|
|
60
1949
|
...rest,
|
|
1950
|
+
signal: rest.signal ?? AbortSignal.timeout(REQUEST_TIMEOUT_MS),
|
|
61
1951
|
headers: {
|
|
62
1952
|
"Content-Type": "application/json",
|
|
63
1953
|
...token ? { Authorization: `Bearer ${token}` } : {},
|
|
@@ -73,13 +1963,31 @@ async function readJson(res) {
|
|
|
73
1963
|
die(`Unexpected non-JSON response from ${API} (${res.status}).`);
|
|
74
1964
|
}
|
|
75
1965
|
}
|
|
76
|
-
async function login() {
|
|
77
|
-
const
|
|
1966
|
+
async function login(flags) {
|
|
1967
|
+
const apiBase = flagString(flags, "api")?.replace(/\/$/, "") ?? API;
|
|
1968
|
+
const run = flagString(flags, "run");
|
|
1969
|
+
const progressToken = flagString(flags, "token");
|
|
1970
|
+
if (Boolean(run) !== Boolean(progressToken)) {
|
|
1971
|
+
die("--run and --token must be provided together for an agent handoff login.");
|
|
1972
|
+
}
|
|
1973
|
+
const res = await api(
|
|
1974
|
+
"/device/code",
|
|
1975
|
+
{
|
|
1976
|
+
method: "POST",
|
|
1977
|
+
...run ? {
|
|
1978
|
+
body: JSON.stringify({
|
|
1979
|
+
agent_run_id: run,
|
|
1980
|
+
agent_run_token: progressToken
|
|
1981
|
+
})
|
|
1982
|
+
} : {}
|
|
1983
|
+
},
|
|
1984
|
+
apiBase
|
|
1985
|
+
);
|
|
78
1986
|
if (!res.ok) die(`Couldn't start login (${res.status}).`);
|
|
79
|
-
const d = await res
|
|
1987
|
+
const d = await readJson(res);
|
|
80
1988
|
console.log(`
|
|
81
1989
|
Your code: ${bold(d.user_code)}`);
|
|
82
|
-
console.log(` Approve it at ${d.verification_uri} \u2014 opening your browser\u2026
|
|
1990
|
+
console.log(` Approve it at ${terminalText(d.verification_uri)} \u2014 opening your browser\u2026
|
|
83
1991
|
`);
|
|
84
1992
|
openBrowser(d.verification_uri_complete);
|
|
85
1993
|
const deadline = Date.now() + d.expires_in * 1e3;
|
|
@@ -88,18 +1996,28 @@ async function login() {
|
|
|
88
1996
|
while (Date.now() < deadline) {
|
|
89
1997
|
await sleep(interval);
|
|
90
1998
|
process.stdout.write(".");
|
|
91
|
-
const r = await api(
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
1999
|
+
const r = await api(
|
|
2000
|
+
"/device/token",
|
|
2001
|
+
{
|
|
2002
|
+
method: "POST",
|
|
2003
|
+
body: JSON.stringify({ device_code: d.device_code })
|
|
2004
|
+
},
|
|
2005
|
+
apiBase
|
|
2006
|
+
);
|
|
2007
|
+
const body = await readJson(r);
|
|
2008
|
+
if (!r.ok && !body.error) die(`
|
|
2009
|
+
Login failed (${r.status}).`);
|
|
96
2010
|
if (body.access_token) {
|
|
97
|
-
writeConfig({ ...readConfig(), token: body.access_token });
|
|
2011
|
+
writeConfig({ ...readConfig(), token: body.access_token, tokenApi: apiBase });
|
|
98
2012
|
console.log("\n");
|
|
99
|
-
await whoami();
|
|
100
|
-
console.log(
|
|
2013
|
+
await whoami(apiBase);
|
|
2014
|
+
console.log(
|
|
2015
|
+
run ? `
|
|
2016
|
+
${dim("Return to the Fillo setup prompt and run its next command.")}
|
|
2017
|
+
` : `
|
|
101
2018
|
${dim("Now run:")} fillo push form.json
|
|
102
|
-
`
|
|
2019
|
+
`
|
|
2020
|
+
);
|
|
103
2021
|
return;
|
|
104
2022
|
}
|
|
105
2023
|
if (body.error === "slow_down") interval += 2e3;
|
|
@@ -108,12 +2026,15 @@ Login failed: ${body.error}`);
|
|
|
108
2026
|
}
|
|
109
2027
|
die("\nLogin timed out \u2014 run `fillo login` again.");
|
|
110
2028
|
}
|
|
111
|
-
async function whoami() {
|
|
112
|
-
const res = await api("/cli/whoami", { token:
|
|
2029
|
+
async function whoami(apiBase = API) {
|
|
2030
|
+
const res = await api("/cli/whoami", { token: requireTokenFor(apiBase) }, apiBase);
|
|
113
2031
|
if (res.status === 401) die("Token invalid \u2014 run `fillo login` again.");
|
|
114
2032
|
if (!res.ok) die(`whoami failed (${res.status}).`);
|
|
115
2033
|
const me = await readJson(res);
|
|
116
|
-
|
|
2034
|
+
if (typeof me.workspace !== "string" || !terminalText(me.workspace)) {
|
|
2035
|
+
die("Fillo returned an invalid workspace identity.");
|
|
2036
|
+
}
|
|
2037
|
+
console.log(` \x1B[32m\u2713\x1B[0m Connected to ${bold(terminalText(me.workspace))}`);
|
|
117
2038
|
}
|
|
118
2039
|
async function list() {
|
|
119
2040
|
const res = await api("/cli/forms", { token: requireToken() });
|
|
@@ -121,10 +2042,33 @@ async function list() {
|
|
|
121
2042
|
const { forms } = await readJson(res);
|
|
122
2043
|
if (!forms.length) return console.log(" No forms yet.");
|
|
123
2044
|
for (const f of forms) {
|
|
124
|
-
console.log(
|
|
2045
|
+
console.log(
|
|
2046
|
+
` ${f.status === "published" ? "\x1B[32m\u25CF\x1B[0m" : "\u25CB"} ${terminalText(f.name)} ${dim(f.id)}`
|
|
2047
|
+
);
|
|
125
2048
|
}
|
|
126
2049
|
}
|
|
127
2050
|
async function loadSchema(file, allowCode) {
|
|
2051
|
+
if (file === "-") {
|
|
2052
|
+
try {
|
|
2053
|
+
const chunks = [];
|
|
2054
|
+
let bytes = 0;
|
|
2055
|
+
for await (const chunk of process.stdin) {
|
|
2056
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
2057
|
+
bytes += buffer.byteLength;
|
|
2058
|
+
if (bytes > MAX_STDIN_SCHEMA_BYTES) {
|
|
2059
|
+
die("The schema on stdin is too large (maximum 1 MB).");
|
|
2060
|
+
}
|
|
2061
|
+
chunks.push(buffer);
|
|
2062
|
+
}
|
|
2063
|
+
const input = Buffer.concat(chunks).toString("utf8");
|
|
2064
|
+
if (!input.trim()) die("stdin is empty - pipe one JSON form schema to `fillo push -`.");
|
|
2065
|
+
const parsed = JSON.parse(input);
|
|
2066
|
+
if (parsed == null) die("stdin must contain a form schema.");
|
|
2067
|
+
return parsed;
|
|
2068
|
+
} catch (error) {
|
|
2069
|
+
die(`Couldn't read the schema from stdin: ${error.message}`);
|
|
2070
|
+
}
|
|
2071
|
+
}
|
|
128
2072
|
const abs = isAbsolute(file) ? file : resolve(process.cwd(), file);
|
|
129
2073
|
if (!abs.endsWith(".json") && !allowCode) {
|
|
130
2074
|
die(
|
|
@@ -154,6 +2098,7 @@ function isRecord(value) {
|
|
|
154
2098
|
}
|
|
155
2099
|
function toPushItems(value, handle) {
|
|
156
2100
|
const values = Array.isArray(value) ? value : [value];
|
|
2101
|
+
if (values.length === 0) die("The schema file contains no forms to push.");
|
|
157
2102
|
return values.map((item, index) => {
|
|
158
2103
|
if (isRecord(item) && "schema" in item) {
|
|
159
2104
|
const ownHandle = typeof item.id === "string" ? item.id : void 0;
|
|
@@ -165,81 +2110,198 @@ function toPushItems(value, handle) {
|
|
|
165
2110
|
return { handle, schema: item };
|
|
166
2111
|
});
|
|
167
2112
|
}
|
|
168
|
-
function printPushed(formId, url, updated,
|
|
2113
|
+
function printPushed(formId, url, updated, draft = false) {
|
|
2114
|
+
const label = draft ? "Created draft" : updated ? "Updated" : "Created";
|
|
169
2115
|
console.log(`
|
|
170
|
-
\x1B[32m\u2713\x1B[0m ${
|
|
171
|
-
if (
|
|
172
|
-
else if (url) console.log(` Live at ${url}`);
|
|
173
|
-
console.log(` Embed: <FilloForm formId="${formId}" />
|
|
2116
|
+
\x1B[32m\u2713\x1B[0m ${label} ${bold(formId)}`);
|
|
2117
|
+
if (draft) console.log(` ${dim("Review and publish it from the Fillo dashboard.")}`);
|
|
2118
|
+
else if (url) console.log(` Live at ${terminalText(url)}`);
|
|
2119
|
+
console.log(` Embed: <FilloForm formId="${terminalText(formId)}" />
|
|
174
2120
|
`);
|
|
175
2121
|
}
|
|
2122
|
+
function syncError(response, body, credential) {
|
|
2123
|
+
const code = body.syncError?.code ?? body.code;
|
|
2124
|
+
const serverMessage = body.syncError?.message ?? body.error;
|
|
2125
|
+
if (code === "trusted_sync_required") {
|
|
2126
|
+
return `This workspace accepts schema changes only from an authenticated CLI or sync token. Run \`fillo login\`, then retry with \`fillo push <file> --handle <id> --stage\`, or set ${SYNC_TOKEN_ENV} from Settings > Developers.`;
|
|
2127
|
+
}
|
|
2128
|
+
if (response.status === 401 && credential === "sync_token") {
|
|
2129
|
+
return `${SYNC_TOKEN_ENV} was rejected. Create a replacement in Settings > Developers, update the CI secret, and retry.`;
|
|
2130
|
+
}
|
|
2131
|
+
if (response.status === 401 && credential === "account") {
|
|
2132
|
+
return "Your CLI login was rejected. Run `fillo login` again, then retry the staged push.";
|
|
2133
|
+
}
|
|
2134
|
+
return serverMessage ?? `push failed (${response.status}).`;
|
|
2135
|
+
}
|
|
2136
|
+
function readSyncToken() {
|
|
2137
|
+
const raw = process.env[SYNC_TOKEN_ENV];
|
|
2138
|
+
if (raw === void 0) return void 0;
|
|
2139
|
+
const token = raw.trim();
|
|
2140
|
+
if (!token.startsWith("fsync_") || token.length < 16 || token.length > 512 || /\s/.test(token)) {
|
|
2141
|
+
die(`${SYNC_TOKEN_ENV} must contain a valid fsync_ token from Settings > Developers.`);
|
|
2142
|
+
}
|
|
2143
|
+
return token;
|
|
2144
|
+
}
|
|
2145
|
+
function requireStableHandle(item) {
|
|
2146
|
+
if (item.handle) return item.handle;
|
|
2147
|
+
die("Staging needs a stable form id. Add --handle <name> or an id beside schema in the input.");
|
|
2148
|
+
}
|
|
2149
|
+
function printSynced(body, requestedStage) {
|
|
2150
|
+
const formId = body.formId;
|
|
2151
|
+
const changed = body.staged === true || body.status === "draft";
|
|
2152
|
+
const label = changed ? body.status === "draft" ? "Draft ready" : "Staged changes" : requestedStage ? "Checked" : "Synced";
|
|
2153
|
+
console.log(`
|
|
2154
|
+
\x1B[32m\u2713\x1B[0m ${label} for ${bold(formId)}`);
|
|
2155
|
+
if (changed) {
|
|
2156
|
+
console.log(` ${dim("Review and publish it from the Fillo dashboard.")}`);
|
|
2157
|
+
} else if (requestedStage && body.status === "published") {
|
|
2158
|
+
console.log(` ${dim("Nothing to stage - the published version already matches.")}`);
|
|
2159
|
+
} else if (body.slug) {
|
|
2160
|
+
console.log(` Live at ${terminalText(`${API}/f/${body.slug}`)}`);
|
|
2161
|
+
}
|
|
2162
|
+
if (body.warning) console.log(` ${dim(`Before publishing: ${body.warning}`)}`);
|
|
2163
|
+
console.log(` Embed: <FilloForm formId="${terminalText(formId)}" />
|
|
2164
|
+
`);
|
|
2165
|
+
}
|
|
2166
|
+
async function pushWithSync(items, credential, requestedStage) {
|
|
2167
|
+
for (const item of items) {
|
|
2168
|
+
const handle = requireStableHandle(item);
|
|
2169
|
+
const validation = validateFormSchema(item.schema);
|
|
2170
|
+
if (!validation.ok) {
|
|
2171
|
+
die(`Invalid schema for "${handle}" \u2014 ${validation.error ?? "schema is not valid"}`);
|
|
2172
|
+
}
|
|
2173
|
+
const res = await api("/forms/sync", {
|
|
2174
|
+
method: "POST",
|
|
2175
|
+
...credential.token ? { token: credential.token } : {},
|
|
2176
|
+
body: JSON.stringify({
|
|
2177
|
+
...credential.key ? { key: credential.key } : {},
|
|
2178
|
+
id: handle,
|
|
2179
|
+
schema: item.schema,
|
|
2180
|
+
theme: item.theme ?? null
|
|
2181
|
+
})
|
|
2182
|
+
});
|
|
2183
|
+
const body = await readJson(res);
|
|
2184
|
+
if (!res.ok || body.syncError || !body.formId) {
|
|
2185
|
+
die(syncError(res, body, credential.kind));
|
|
2186
|
+
}
|
|
2187
|
+
printSynced(body, requestedStage);
|
|
2188
|
+
}
|
|
2189
|
+
}
|
|
176
2190
|
async function push(file, flags) {
|
|
177
|
-
if (!file)
|
|
2191
|
+
if (!file) {
|
|
2192
|
+
die("Usage: fillo push <form.json|-> [--handle name] [--stage] [--allow-code]");
|
|
2193
|
+
}
|
|
2194
|
+
const cfg = readConfig();
|
|
2195
|
+
const explicitStage = flags.stage === true;
|
|
2196
|
+
const legacyDraft = flags.draft === true;
|
|
2197
|
+
const stage = explicitStage || legacyDraft;
|
|
2198
|
+
const syncToken = readSyncToken();
|
|
2199
|
+
if (syncToken && !stage) {
|
|
2200
|
+
die(`${SYNC_TOKEN_ENV} can only stage changes. Add --stage to this push.`);
|
|
2201
|
+
}
|
|
2202
|
+
const accountToken = !syncToken && cfg.token ? requireToken() : void 0;
|
|
2203
|
+
if (!syncToken && !accountToken && stage && cfg.pk) {
|
|
2204
|
+
die(
|
|
2205
|
+
"This local setup is an unclaimed preview, where publishable-key sync applies changes immediately. Omit --stage for the preview, or claim it and run `fillo login` before staging for review."
|
|
2206
|
+
);
|
|
2207
|
+
}
|
|
2208
|
+
if (!syncToken && !accountToken && stage) {
|
|
2209
|
+
die(`To stage changes, run \`fillo login\` or set ${SYNC_TOKEN_ENV} from Settings > Developers.`);
|
|
2210
|
+
}
|
|
178
2211
|
const handle = typeof flags.handle === "string" ? flags.handle : void 0;
|
|
179
2212
|
const items = toPushItems(await loadSchema(file, flags["allow-code"] === true), handle);
|
|
180
2213
|
if (items.length > 1 && handle) die("--handle can only be used when pushing one form.");
|
|
181
|
-
|
|
182
|
-
|
|
2214
|
+
if (syncToken) {
|
|
2215
|
+
await pushWithSync(items, { kind: "sync_token", token: syncToken }, true);
|
|
2216
|
+
return;
|
|
2217
|
+
}
|
|
2218
|
+
if (accountToken) {
|
|
2219
|
+
if (stage) {
|
|
2220
|
+
for (const item of items) {
|
|
2221
|
+
if (item.handle || explicitStage || !legacyDraft) {
|
|
2222
|
+
await pushWithSync([item], { kind: "account", token: accountToken }, true);
|
|
2223
|
+
continue;
|
|
2224
|
+
}
|
|
2225
|
+
const res = await api("/cli/forms", {
|
|
2226
|
+
method: "POST",
|
|
2227
|
+
token: accountToken,
|
|
2228
|
+
body: JSON.stringify({
|
|
2229
|
+
schema: item.schema,
|
|
2230
|
+
theme: item.theme ?? null,
|
|
2231
|
+
publish: false
|
|
2232
|
+
})
|
|
2233
|
+
});
|
|
2234
|
+
const body = await readJson(res);
|
|
2235
|
+
if (!res.ok || !body.formId) die(body.error ?? `push failed (${res.status}).`);
|
|
2236
|
+
printPushed(body.formId, body.url, !!body.updated, true);
|
|
2237
|
+
}
|
|
2238
|
+
return;
|
|
2239
|
+
}
|
|
183
2240
|
for (const item of items) {
|
|
184
2241
|
const res = await api("/cli/forms", {
|
|
185
2242
|
method: "POST",
|
|
186
|
-
token:
|
|
2243
|
+
token: accountToken,
|
|
187
2244
|
body: JSON.stringify({
|
|
188
2245
|
schema: item.schema,
|
|
189
2246
|
theme: item.theme ?? null,
|
|
190
2247
|
handle: item.handle,
|
|
191
|
-
publish:
|
|
2248
|
+
publish: true
|
|
192
2249
|
})
|
|
193
2250
|
});
|
|
194
2251
|
const body = await readJson(res);
|
|
195
2252
|
if (!res.ok || !body.formId) die(body.error ?? `push failed (${res.status}).`);
|
|
196
|
-
printPushed(body.formId, body.url, !!body.updated
|
|
2253
|
+
printPushed(body.formId, body.url, !!body.updated);
|
|
197
2254
|
}
|
|
198
2255
|
return;
|
|
199
2256
|
}
|
|
200
2257
|
if (cfg.pk) {
|
|
201
|
-
|
|
202
|
-
if (!item.handle) die("Pushing with a provisioned key needs --handle <name> or form.id.");
|
|
203
|
-
const res = await api("/forms/sync", {
|
|
204
|
-
method: "POST",
|
|
205
|
-
body: JSON.stringify({
|
|
206
|
-
key: cfg.pk,
|
|
207
|
-
id: item.handle,
|
|
208
|
-
schema: item.schema,
|
|
209
|
-
theme: item.theme ?? null
|
|
210
|
-
})
|
|
211
|
-
});
|
|
212
|
-
const body = await readJson(res);
|
|
213
|
-
if (!res.ok || !body.formId) die(body.error ?? `push failed (${res.status}).`);
|
|
214
|
-
printPushed(body.formId, body.slug ? `${API}/f/${body.slug}` : void 0, false, !!body.staged);
|
|
215
|
-
}
|
|
2258
|
+
await pushWithSync(items, { kind: "publishable_key", key: cfg.pk }, false);
|
|
216
2259
|
return;
|
|
217
2260
|
}
|
|
218
|
-
die("Not set up yet. Run `fillo init
|
|
2261
|
+
die("Not set up yet. Run `fillo init --email you@company.com` or `fillo login`.");
|
|
219
2262
|
}
|
|
220
2263
|
async function init(flags) {
|
|
221
|
-
const
|
|
2264
|
+
const email3 = typeof flags.email === "string" ? flags.email.trim() : "";
|
|
2265
|
+
if (!email3) {
|
|
2266
|
+
die("Usage: fillo init --email you@company.com (or run `fillo login` for an existing account).");
|
|
2267
|
+
}
|
|
222
2268
|
const res = await api("/workspaces/provision", {
|
|
223
2269
|
method: "POST",
|
|
224
|
-
body: JSON.stringify({ email, source: "cli" })
|
|
2270
|
+
body: JSON.stringify({ email: email3, source: "cli" })
|
|
225
2271
|
});
|
|
226
2272
|
const body = await readJson(res);
|
|
227
2273
|
if (!res.ok || !body.key) die(body.error ?? `init failed (${res.status}).`);
|
|
228
|
-
|
|
2274
|
+
const { claimUrl: _legacyWorkspaceLink, ...current } = readConfig();
|
|
2275
|
+
writeConfig({ ...current, pk: body.key });
|
|
229
2276
|
console.log(`
|
|
230
|
-
\x1B[32m\u2713\x1B[0m Workspace ready
|
|
2277
|
+
\x1B[32m\u2713\x1B[0m Workspace ready. A workspace link was sent to ${bold(terminalText(email3))}.`);
|
|
231
2278
|
if (body.limits) {
|
|
232
|
-
const
|
|
233
|
-
|
|
2279
|
+
const expiry = Date.parse(body.limits.expiresAt);
|
|
2280
|
+
if (Number.isFinite(expiry)) {
|
|
2281
|
+
const days = Math.max(1, Math.round((expiry - Date.now()) / 864e5));
|
|
2282
|
+
console.log(` ${dim(`Preview: up to ${body.limits.responses} responses for ~${days} days.`)}`);
|
|
2283
|
+
}
|
|
234
2284
|
}
|
|
235
2285
|
console.log(`
|
|
236
2286
|
${bold("Next:")} fillo push form.json --handle my-form`);
|
|
237
|
-
|
|
238
|
-
console.log(`
|
|
239
|
-
${dim("Keep your responses \u2014 claim it (signup, one click):")}`);
|
|
240
|
-
console.log(` ${body.claim.url}
|
|
2287
|
+
console.log(` ${dim("Open the emailed link whenever you want to save it to an account.")}
|
|
241
2288
|
`);
|
|
2289
|
+
}
|
|
2290
|
+
var AGENT_ACTIONS = ["claim_required", "storage_required", "publish_required"];
|
|
2291
|
+
var FORM_STATUSES = ["draft", "published"];
|
|
2292
|
+
function enumFlag(flags, key, allowed) {
|
|
2293
|
+
const value = flags[key];
|
|
2294
|
+
if (value === void 0) return void 0;
|
|
2295
|
+
if (typeof value !== "string" || !allowed.includes(value)) {
|
|
2296
|
+
die(`--${key} must be one of: ${allowed.join(", ")}`);
|
|
242
2297
|
}
|
|
2298
|
+
return value;
|
|
2299
|
+
}
|
|
2300
|
+
function optionalStringFlag(flags, key) {
|
|
2301
|
+
const value = flags[key];
|
|
2302
|
+
if (value === void 0) return void 0;
|
|
2303
|
+
if (typeof value !== "string" || !value.trim()) die(`--${key} requires a value.`);
|
|
2304
|
+
return value;
|
|
243
2305
|
}
|
|
244
2306
|
async function agent(subcommand, flags) {
|
|
245
2307
|
const apiBase = flagString(flags, "api")?.replace(/\/$/, "") ?? API;
|
|
@@ -251,36 +2313,263 @@ async function agent(subcommand, flags) {
|
|
|
251
2313
|
if (!run || !token) {
|
|
252
2314
|
die("Usage: fillo agent <connect|event> --run <id> --token <token> [--api <url>]");
|
|
253
2315
|
}
|
|
2316
|
+
if (flags.account !== void 0 && flags.account !== true) {
|
|
2317
|
+
die("--account does not take a value.");
|
|
2318
|
+
}
|
|
254
2319
|
if (subcommand === "connect") {
|
|
2320
|
+
const account = flags.account === true ? await attachAgentAccount(apiBase, run, token) : void 0;
|
|
255
2321
|
await postAgentEvent(apiBase, run, token, {
|
|
256
2322
|
status: "connected",
|
|
257
2323
|
message: "Agent connected. Reading the app now."
|
|
258
2324
|
});
|
|
259
2325
|
console.log(` \x1B[32m\u2713\x1B[0m Live progress connected.`);
|
|
2326
|
+
if (account) {
|
|
2327
|
+
console.log(` \x1B[32m\u2713\x1B[0m ${bold(account.workspace)}`);
|
|
2328
|
+
console.log(` ${dim("Publishable key:")} ${account.publishableKey}`);
|
|
2329
|
+
}
|
|
260
2330
|
console.log(` ${dim("Report next steps with:")}`);
|
|
261
2331
|
console.log(
|
|
262
|
-
` fillo agent event --api ${apiBase} --run ${run} --token <same-token> --status editing --message "Editing the form screen"`
|
|
2332
|
+
` fillo agent event --api ${terminalText(apiBase)} --run ${terminalText(run)} --token <same-token> --status editing --message "Editing the form screen"`
|
|
263
2333
|
);
|
|
264
2334
|
return;
|
|
265
2335
|
}
|
|
2336
|
+
if (flags.account === true) {
|
|
2337
|
+
die("--account can only be used with `fillo agent connect`.");
|
|
2338
|
+
}
|
|
266
2339
|
if (subcommand === "event") {
|
|
267
2340
|
const status = flagString(flags, "status");
|
|
268
2341
|
const message = flagString(flags, "message");
|
|
269
2342
|
if (!status) die("Usage: fillo agent event --status <status> --message <short update>");
|
|
2343
|
+
const action = enumFlag(flags, "action", AGENT_ACTIONS);
|
|
2344
|
+
const formStatus = enumFlag(flags, "form-status", FORM_STATUSES);
|
|
2345
|
+
const formId = optionalStringFlag(flags, "form-id");
|
|
2346
|
+
if ((status === "done" || status === "needs_action") && !formId) {
|
|
2347
|
+
die(`--form-id is required when --status is ${status}.`);
|
|
2348
|
+
}
|
|
2349
|
+
if (status === "needs_action" && !action) {
|
|
2350
|
+
die("--action is required when --status is needs_action.");
|
|
2351
|
+
}
|
|
270
2352
|
await postAgentEvent(apiBase, run, token, {
|
|
271
2353
|
status,
|
|
272
2354
|
message,
|
|
273
|
-
claimUrl: flagString(flags, "claim-url"),
|
|
274
|
-
dashboardUrl: flagString(flags, "dashboard-url"),
|
|
275
2355
|
appUrl: flagString(flags, "app-url"),
|
|
276
|
-
|
|
277
|
-
|
|
2356
|
+
action,
|
|
2357
|
+
formId,
|
|
2358
|
+
formName: flagString(flags, "form-name"),
|
|
2359
|
+
formStatus
|
|
278
2360
|
});
|
|
279
2361
|
console.log(` \x1B[32m\u2713\x1B[0m Progress sent.`);
|
|
280
2362
|
return;
|
|
281
2363
|
}
|
|
282
2364
|
die(`Unknown agent command: ${subcommand}`);
|
|
283
2365
|
}
|
|
2366
|
+
var SKILL_AGENT_DIRECTORIES = {
|
|
2367
|
+
shared: ".agents/skills",
|
|
2368
|
+
universal: ".agents/skills",
|
|
2369
|
+
agents: ".agents/skills",
|
|
2370
|
+
codex: ".agents/skills",
|
|
2371
|
+
cursor: ".agents/skills",
|
|
2372
|
+
copilot: ".agents/skills",
|
|
2373
|
+
"github-copilot": ".agents/skills",
|
|
2374
|
+
gemini: ".agents/skills",
|
|
2375
|
+
"gemini-cli": ".agents/skills",
|
|
2376
|
+
amp: ".agents/skills",
|
|
2377
|
+
cline: ".agents/skills",
|
|
2378
|
+
opencode: ".agents/skills",
|
|
2379
|
+
warp: ".agents/skills",
|
|
2380
|
+
claude: ".claude/skills",
|
|
2381
|
+
"claude-code": ".claude/skills"
|
|
2382
|
+
};
|
|
2383
|
+
function isSkillAgent(value) {
|
|
2384
|
+
return Object.prototype.hasOwnProperty.call(SKILL_AGENT_DIRECTORIES, value);
|
|
2385
|
+
}
|
|
2386
|
+
function findProjectRoot(start) {
|
|
2387
|
+
let current = resolve(start);
|
|
2388
|
+
while (true) {
|
|
2389
|
+
if (existsSync(join(current, ".git"))) return current;
|
|
2390
|
+
const parent = dirname(current);
|
|
2391
|
+
if (parent === current) return resolve(start);
|
|
2392
|
+
current = parent;
|
|
2393
|
+
}
|
|
2394
|
+
}
|
|
2395
|
+
function parseSkillDirectories(flags) {
|
|
2396
|
+
const agent2 = flagString(flags, "agent");
|
|
2397
|
+
const customDirectory = flagString(flags, "dir");
|
|
2398
|
+
if (agent2 && customDirectory) die("Choose either --agent or --dir, not both.");
|
|
2399
|
+
if (customDirectory) {
|
|
2400
|
+
if (isAbsolute(customDirectory)) {
|
|
2401
|
+
die("--dir must be relative to the project root, or to your home directory with --global.");
|
|
2402
|
+
}
|
|
2403
|
+
const parts = customDirectory.split(/[\\/]+/).filter((part) => part && part !== ".");
|
|
2404
|
+
if (parts.length === 0 || parts.some((part) => part === "..")) {
|
|
2405
|
+
die("--dir must name a skill directory inside the selected project or home scope.");
|
|
2406
|
+
}
|
|
2407
|
+
return [join(...parts)];
|
|
2408
|
+
}
|
|
2409
|
+
if (!agent2) return [SKILL_AGENT_DIRECTORIES.shared, SKILL_AGENT_DIRECTORIES.claude];
|
|
2410
|
+
if (isSkillAgent(agent2)) return [SKILL_AGENT_DIRECTORIES[agent2]];
|
|
2411
|
+
die(
|
|
2412
|
+
`Unknown agent ${agent2}. Use --agent shared, --agent claude, or --dir <agent-skill-directory>.`
|
|
2413
|
+
);
|
|
2414
|
+
}
|
|
2415
|
+
function skillFiles(root, relative2 = "") {
|
|
2416
|
+
const directory = join(root, relative2);
|
|
2417
|
+
const files = [];
|
|
2418
|
+
for (const entry of readdirSync(directory, { withFileTypes: true })) {
|
|
2419
|
+
const next = join(relative2, entry.name);
|
|
2420
|
+
if (entry.isDirectory()) files.push(...skillFiles(root, next));
|
|
2421
|
+
else if (entry.isFile()) files.push(next);
|
|
2422
|
+
}
|
|
2423
|
+
return files.sort();
|
|
2424
|
+
}
|
|
2425
|
+
function sameSkillBundle(source, target) {
|
|
2426
|
+
try {
|
|
2427
|
+
const sourceFiles = skillFiles(source);
|
|
2428
|
+
const targetFiles = skillFiles(target);
|
|
2429
|
+
if (sourceFiles.length !== targetFiles.length) return false;
|
|
2430
|
+
return sourceFiles.every(
|
|
2431
|
+
(file, index) => file === targetFiles[index] && readFileSync(join(source, file)).equals(readFileSync(join(target, file)))
|
|
2432
|
+
);
|
|
2433
|
+
} catch {
|
|
2434
|
+
return false;
|
|
2435
|
+
}
|
|
2436
|
+
}
|
|
2437
|
+
function pathEntryExists(path) {
|
|
2438
|
+
try {
|
|
2439
|
+
lstatSync(path);
|
|
2440
|
+
return true;
|
|
2441
|
+
} catch (error) {
|
|
2442
|
+
if (error.code === "ENOENT") return false;
|
|
2443
|
+
throw error;
|
|
2444
|
+
}
|
|
2445
|
+
}
|
|
2446
|
+
var MANAGED_SKILL_MARKER = ".fillo-managed.json";
|
|
2447
|
+
function isCliManagedFilloSkill(target) {
|
|
2448
|
+
try {
|
|
2449
|
+
const marker = JSON.parse(
|
|
2450
|
+
readFileSync(join(target, MANAGED_SKILL_MARKER), "utf8")
|
|
2451
|
+
);
|
|
2452
|
+
return marker.managedBy === "@usefillo/cli" && marker.skill === "build-with-fillo" && marker.format === 1 && marker.allowAutomaticUpdates === true;
|
|
2453
|
+
} catch {
|
|
2454
|
+
return false;
|
|
2455
|
+
}
|
|
2456
|
+
}
|
|
2457
|
+
function assertSafeSkillDestination(scopeRoot, parts) {
|
|
2458
|
+
const realScopeRoot = realpathSync(scopeRoot);
|
|
2459
|
+
let current = scopeRoot;
|
|
2460
|
+
for (const part of parts) {
|
|
2461
|
+
current = join(current, part);
|
|
2462
|
+
if (!pathEntryExists(current)) return;
|
|
2463
|
+
if (lstatSync(current).isSymbolicLink()) {
|
|
2464
|
+
throw new Error(`Refusing to install through symlinked path ${current}.`);
|
|
2465
|
+
}
|
|
2466
|
+
const resolved = realpathSync(current);
|
|
2467
|
+
const fromScope = relative(realScopeRoot, resolved);
|
|
2468
|
+
if (fromScope === ".." || fromScope.startsWith(`..${sep}`) || isAbsolute(fromScope)) {
|
|
2469
|
+
throw new Error(`Refusing to install outside ${scopeRoot}.`);
|
|
2470
|
+
}
|
|
2471
|
+
}
|
|
2472
|
+
}
|
|
2473
|
+
function moveSkillIntoPlace(staging, target) {
|
|
2474
|
+
if (!pathEntryExists(target)) {
|
|
2475
|
+
renameSync(staging, target);
|
|
2476
|
+
return;
|
|
2477
|
+
}
|
|
2478
|
+
const backup = `${target}.backup-${randomUUID()}`;
|
|
2479
|
+
renameSync(target, backup);
|
|
2480
|
+
try {
|
|
2481
|
+
renameSync(staging, target);
|
|
2482
|
+
} catch (error) {
|
|
2483
|
+
try {
|
|
2484
|
+
renameSync(backup, target);
|
|
2485
|
+
} catch {
|
|
2486
|
+
throw new Error(`Skill install failed. The previous copy is preserved at ${backup}.`);
|
|
2487
|
+
}
|
|
2488
|
+
throw error;
|
|
2489
|
+
}
|
|
2490
|
+
try {
|
|
2491
|
+
rmSync(backup, { recursive: true, force: true });
|
|
2492
|
+
} catch {
|
|
2493
|
+
console.warn(` ${dim(`Previous skill copy could not be removed: ${backup}`)}`);
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
function installSkill(flags) {
|
|
2497
|
+
if (flags.global === true && flags.project === true) {
|
|
2498
|
+
die("Choose either --project or --global, not both.");
|
|
2499
|
+
}
|
|
2500
|
+
const skillDirectories = parseSkillDirectories(flags);
|
|
2501
|
+
const global = flags.global === true;
|
|
2502
|
+
const scopeRoot = global ? homedir() : findProjectRoot(process.cwd());
|
|
2503
|
+
if (!existsSync(BUNDLED_SKILL_DIR)) {
|
|
2504
|
+
die("This CLI package is missing its bundled Fillo skill. Reinstall @usefillo/cli@latest.");
|
|
2505
|
+
}
|
|
2506
|
+
const destinations = Array.from(
|
|
2507
|
+
new Set(skillDirectories)
|
|
2508
|
+
).map((skillDirectory) => {
|
|
2509
|
+
const skillsRoot = resolve(scopeRoot, skillDirectory);
|
|
2510
|
+
const target = join(skillsRoot, "build-with-fillo");
|
|
2511
|
+
const relativeSkillsRoot = relative(scopeRoot, skillsRoot);
|
|
2512
|
+
if (relativeSkillsRoot === ".." || relativeSkillsRoot.startsWith(`..${sep}`) || isAbsolute(relativeSkillsRoot)) {
|
|
2513
|
+
die("The skill destination must stay inside the selected project or home scope.");
|
|
2514
|
+
}
|
|
2515
|
+
const destinationParts = [
|
|
2516
|
+
...relativeSkillsRoot.split(sep).filter(Boolean),
|
|
2517
|
+
"build-with-fillo"
|
|
2518
|
+
];
|
|
2519
|
+
assertSafeSkillDestination(scopeRoot, destinationParts);
|
|
2520
|
+
const targetExists = pathEntryExists(target);
|
|
2521
|
+
const current = targetExists && sameSkillBundle(BUNDLED_SKILL_DIR, target);
|
|
2522
|
+
const updatingManagedSkill = targetExists && isCliManagedFilloSkill(target);
|
|
2523
|
+
if (targetExists && !current && !updatingManagedSkill && flags.force !== true) {
|
|
2524
|
+
die(`A different skill already exists at ${target}. Re-run with --force to replace it.`);
|
|
2525
|
+
}
|
|
2526
|
+
return {
|
|
2527
|
+
skillsRoot,
|
|
2528
|
+
target,
|
|
2529
|
+
destinationParts,
|
|
2530
|
+
targetExists,
|
|
2531
|
+
current,
|
|
2532
|
+
updatingManagedSkill
|
|
2533
|
+
};
|
|
2534
|
+
});
|
|
2535
|
+
for (const destination of destinations) {
|
|
2536
|
+
if (destination.current) continue;
|
|
2537
|
+
mkdirSync(destination.skillsRoot, { recursive: true });
|
|
2538
|
+
assertSafeSkillDestination(scopeRoot, destination.destinationParts.slice(0, 2));
|
|
2539
|
+
const staging = join(
|
|
2540
|
+
destination.skillsRoot,
|
|
2541
|
+
`.build-with-fillo.install-${randomUUID()}`
|
|
2542
|
+
);
|
|
2543
|
+
try {
|
|
2544
|
+
cpSync(BUNDLED_SKILL_DIR, staging, { recursive: true, errorOnExist: true });
|
|
2545
|
+
assertSafeSkillDestination(scopeRoot, destination.destinationParts);
|
|
2546
|
+
if (!destination.targetExists && pathEntryExists(destination.target)) {
|
|
2547
|
+
throw new Error(`Skill destination changed during install: ${destination.target}`);
|
|
2548
|
+
}
|
|
2549
|
+
moveSkillIntoPlace(staging, destination.target);
|
|
2550
|
+
} finally {
|
|
2551
|
+
if (pathEntryExists(staging)) rmSync(staging, { recursive: true, force: true });
|
|
2552
|
+
}
|
|
2553
|
+
}
|
|
2554
|
+
const changed = destinations.filter((destination) => !destination.current);
|
|
2555
|
+
const action = changed.length === 0 ? "Fillo skill is already installed" : changed.every((destination) => destination.updatingManagedSkill) ? `Updated ${bold("Build with Fillo")}` : `Installed ${bold("Build with Fillo")}`;
|
|
2556
|
+
console.log(`
|
|
2557
|
+
\x1B[32m\u2713\x1B[0m ${action}.`);
|
|
2558
|
+
for (const destination of destinations) console.log(` ${dim(destination.target)}`);
|
|
2559
|
+
console.log(`
|
|
2560
|
+
Ask your agent to use ${bold("build-with-fillo")}.`);
|
|
2561
|
+
console.log(
|
|
2562
|
+
` ${dim(`If it does not discover skills, point it to ${join(destinations[0].target, "SKILL.md")}.`)}
|
|
2563
|
+
`
|
|
2564
|
+
);
|
|
2565
|
+
}
|
|
2566
|
+
function skill(subcommand, flags) {
|
|
2567
|
+
if (!subcommand || subcommand === "help" || subcommand === "--help" || subcommand === "-h") {
|
|
2568
|
+
return skillHelp();
|
|
2569
|
+
}
|
|
2570
|
+
if (subcommand === "install") return installSkill(flags);
|
|
2571
|
+
die(`Unknown skill command: ${subcommand}`);
|
|
2572
|
+
}
|
|
284
2573
|
async function postAgentEvent(apiBase, run, token, body) {
|
|
285
2574
|
const res = await fetch(`${apiBase}/api/v1/agent-runs/${encodeURIComponent(run)}/events`, {
|
|
286
2575
|
method: "POST",
|
|
@@ -288,24 +2577,66 @@ async function postAgentEvent(apiBase, run, token, body) {
|
|
|
288
2577
|
Authorization: `Bearer ${token}`,
|
|
289
2578
|
"Content-Type": "application/json"
|
|
290
2579
|
},
|
|
291
|
-
body: JSON.stringify(body)
|
|
2580
|
+
body: JSON.stringify(body),
|
|
2581
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
292
2582
|
});
|
|
293
2583
|
const payload = await res.json().catch(() => ({}));
|
|
294
2584
|
if (!res.ok) die(payload.error ?? `agent progress failed (${res.status}).`);
|
|
295
2585
|
}
|
|
2586
|
+
async function attachAgentAccount(apiBase, run, progressToken) {
|
|
2587
|
+
const accountToken = requireTokenFor(apiBase);
|
|
2588
|
+
const res = await fetch(
|
|
2589
|
+
`${apiBase}/api/v1/agent-runs/${encodeURIComponent(run)}/account`,
|
|
2590
|
+
{
|
|
2591
|
+
method: "POST",
|
|
2592
|
+
redirect: "error",
|
|
2593
|
+
headers: {
|
|
2594
|
+
Authorization: `Bearer ${accountToken}`,
|
|
2595
|
+
"X-Fillo-Agent-Run-Token": progressToken
|
|
2596
|
+
},
|
|
2597
|
+
signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS)
|
|
2598
|
+
}
|
|
2599
|
+
);
|
|
2600
|
+
const payload = await res.json().catch(() => ({}));
|
|
2601
|
+
if (!res.ok) {
|
|
2602
|
+
const hint = res.status === 401 ? " Run `fillo login` and try again." : "";
|
|
2603
|
+
die(`${payload.error ?? `account connection failed (${res.status}).`}${hint}`);
|
|
2604
|
+
}
|
|
2605
|
+
if (typeof payload.workspace !== "string" || !terminalText(payload.workspace) || typeof payload.publishableKey !== "string" || !/^pk_[A-Za-z0-9_-]{1,125}$/.test(payload.publishableKey)) {
|
|
2606
|
+
die("Fillo returned an invalid workspace connection.");
|
|
2607
|
+
}
|
|
2608
|
+
return { workspace: terminalText(payload.workspace), publishableKey: payload.publishableKey };
|
|
2609
|
+
}
|
|
296
2610
|
function agentHelp() {
|
|
297
2611
|
console.log(`
|
|
298
2612
|
${bold("fillo agent")} \u2014 report live progress back to a Fillo prompt modal
|
|
299
2613
|
|
|
300
2614
|
${bold("Commands")}
|
|
301
2615
|
agent connect Connect a coding-agent run to the open browser modal
|
|
2616
|
+
${dim("--account attach the workspace from `fillo login`")}
|
|
302
2617
|
agent event Send a short progress update
|
|
303
|
-
${dim("--status <created|connected|asking|planning|installing|editing|checking|done|error>")}
|
|
2618
|
+
${dim("--status <created|connected|asking|planning|installing|editing|checking|needs_action|done|error>")}
|
|
304
2619
|
${dim('--message "Short update"')}
|
|
305
|
-
${dim("--
|
|
2620
|
+
${dim("--form-id <id> --form-status <draft|published> --form-name <name>")}
|
|
2621
|
+
${dim("--action <claim_required|storage_required|publish_required>")}
|
|
2622
|
+
${dim("--app-url <localhost-url>")}
|
|
306
2623
|
${dim("--run <id> --token <token> --api <url>")}
|
|
307
2624
|
`);
|
|
308
2625
|
}
|
|
2626
|
+
function skillHelp() {
|
|
2627
|
+
console.log(`
|
|
2628
|
+
${bold("fillo skill")} \u2014 install the Build with Fillo Agent Skill
|
|
2629
|
+
|
|
2630
|
+
${bold("Commands")}
|
|
2631
|
+
skill install Install into this project (default)
|
|
2632
|
+
${dim("--agent <shared|claude> choose a standard destination")}
|
|
2633
|
+
${dim("--dir <path> install into any agent's skill directory")}
|
|
2634
|
+
${dim("--global install for the current user")}
|
|
2635
|
+
${dim("--force replace a different existing copy")}
|
|
2636
|
+
|
|
2637
|
+
${dim("Default: open Agent Skills path (.agents/skills) plus Claude Code (.claude/skills).")}
|
|
2638
|
+
`);
|
|
2639
|
+
}
|
|
309
2640
|
function printVersion() {
|
|
310
2641
|
try {
|
|
311
2642
|
const pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
|
|
@@ -319,21 +2650,78 @@ function help() {
|
|
|
319
2650
|
${bold("fillo")} \u2014 create Fillo forms from your terminal
|
|
320
2651
|
|
|
321
2652
|
${bold("Commands")}
|
|
322
|
-
init
|
|
323
|
-
${dim("--email <addr>
|
|
2653
|
+
init Start a new workspace and email its workspace link
|
|
2654
|
+
${dim("--email <addr> required")}
|
|
324
2655
|
login Connect to an existing account (opens the browser)
|
|
2656
|
+
${dim("--run <id> --token <token> bind a fresh agent handoff login")}
|
|
325
2657
|
logout Forget the stored credentials
|
|
326
|
-
whoami Show the signed-in
|
|
327
|
-
push <file
|
|
2658
|
+
whoami Show the signed-in workspace
|
|
2659
|
+
push <file|-> Create/update a form from JSON (file or stdin)
|
|
328
2660
|
${dim("--handle <name> idempotent id for re-pushes")}
|
|
329
|
-
${dim("--
|
|
2661
|
+
${dim("--stage stage beside the live form for dashboard review")}
|
|
2662
|
+
${dim("--draft alias with a handle; legacy one-off draft without")}
|
|
330
2663
|
${dim("--allow-code allow a .mjs/.js schema (executes the file)")}
|
|
331
2664
|
list List the workspace's forms
|
|
332
2665
|
agent <cmd> Report live progress to a Fillo prompt modal
|
|
2666
|
+
skill install Install the Build with Fillo Agent Skill
|
|
333
2667
|
|
|
334
2668
|
${dim(`API: ${API} \xB7 set FILLO_API to override`)}
|
|
2669
|
+
${dim(`${SYNC_TOKEN_ENV}: stage-only server/CI credential; requires --stage`)}
|
|
335
2670
|
`);
|
|
336
2671
|
}
|
|
2672
|
+
var BOOLEAN_FLAGS = /* @__PURE__ */ new Set([
|
|
2673
|
+
"account",
|
|
2674
|
+
"allow-code",
|
|
2675
|
+
"draft",
|
|
2676
|
+
"stage",
|
|
2677
|
+
"force",
|
|
2678
|
+
"global",
|
|
2679
|
+
"help",
|
|
2680
|
+
"h",
|
|
2681
|
+
"project",
|
|
2682
|
+
"version",
|
|
2683
|
+
"v"
|
|
2684
|
+
]);
|
|
2685
|
+
var GLOBAL_FLAGS = /* @__PURE__ */ new Set(["help", "h", "version", "v"]);
|
|
2686
|
+
var FLAGS_BY_COMMAND = {
|
|
2687
|
+
init: ["email"],
|
|
2688
|
+
login: ["api", "run", "token"],
|
|
2689
|
+
logout: [],
|
|
2690
|
+
whoami: [],
|
|
2691
|
+
push: ["handle", "stage", "draft", "allow-code"],
|
|
2692
|
+
list: [],
|
|
2693
|
+
ls: [],
|
|
2694
|
+
agent: [
|
|
2695
|
+
"run",
|
|
2696
|
+
"token",
|
|
2697
|
+
"api",
|
|
2698
|
+
"account",
|
|
2699
|
+
"status",
|
|
2700
|
+
"message",
|
|
2701
|
+
"app-url",
|
|
2702
|
+
"action",
|
|
2703
|
+
"form-id",
|
|
2704
|
+
"form-name",
|
|
2705
|
+
"form-status"
|
|
2706
|
+
],
|
|
2707
|
+
skill: ["agent", "dir", "global", "project", "force"],
|
|
2708
|
+
help: [],
|
|
2709
|
+
version: []
|
|
2710
|
+
};
|
|
2711
|
+
function validateFlags(command, flags) {
|
|
2712
|
+
const allowed = /* @__PURE__ */ new Set([
|
|
2713
|
+
...GLOBAL_FLAGS,
|
|
2714
|
+
...command ? FLAGS_BY_COMMAND[command] ?? [] : []
|
|
2715
|
+
]);
|
|
2716
|
+
for (const [key, value] of Object.entries(flags)) {
|
|
2717
|
+
if (!allowed.has(key)) die(`Unknown flag for ${command ?? "fillo"}: --${key}`);
|
|
2718
|
+
if (BOOLEAN_FLAGS.has(key)) {
|
|
2719
|
+
if (value !== true) die(`--${key} does not take a value.`);
|
|
2720
|
+
} else if (typeof value !== "string" || value.length === 0) {
|
|
2721
|
+
die(`--${key} requires a value.`);
|
|
2722
|
+
}
|
|
2723
|
+
}
|
|
2724
|
+
}
|
|
337
2725
|
function flagString(flags, key) {
|
|
338
2726
|
const value = flags[key];
|
|
339
2727
|
return typeof value === "string" && value ? value : void 0;
|
|
@@ -343,6 +2731,14 @@ function parseFlags(args) {
|
|
|
343
2731
|
const positional = [];
|
|
344
2732
|
for (let i = 0; i < args.length; i++) {
|
|
345
2733
|
const a = args[i];
|
|
2734
|
+
if (a === "--") {
|
|
2735
|
+
positional.push(...args.slice(i + 1));
|
|
2736
|
+
break;
|
|
2737
|
+
}
|
|
2738
|
+
if (a === "-h" || a === "-v") {
|
|
2739
|
+
flags[a.slice(1)] = true;
|
|
2740
|
+
continue;
|
|
2741
|
+
}
|
|
346
2742
|
if (!a.startsWith("--")) {
|
|
347
2743
|
positional.push(a);
|
|
348
2744
|
continue;
|
|
@@ -353,6 +2749,10 @@ function parseFlags(args) {
|
|
|
353
2749
|
continue;
|
|
354
2750
|
}
|
|
355
2751
|
const key = a.slice(2);
|
|
2752
|
+
if (BOOLEAN_FLAGS.has(key)) {
|
|
2753
|
+
flags[key] = true;
|
|
2754
|
+
continue;
|
|
2755
|
+
}
|
|
356
2756
|
const next = args[i + 1];
|
|
357
2757
|
if (next !== void 0 && !next.startsWith("--")) {
|
|
358
2758
|
flags[key] = next;
|
|
@@ -364,19 +2764,22 @@ function parseFlags(args) {
|
|
|
364
2764
|
async function main() {
|
|
365
2765
|
const [cmd, ...rest] = process.argv.slice(2);
|
|
366
2766
|
const { positional, flags } = parseFlags(rest);
|
|
2767
|
+
validateFlags(cmd, flags);
|
|
367
2768
|
if (cmd === "version" || cmd === "--version" || cmd === "-v" || flags.version === true || flags.v === true) {
|
|
368
2769
|
return printVersion();
|
|
369
2770
|
}
|
|
370
2771
|
if (flags.help === true || flags.h === true) {
|
|
371
|
-
|
|
2772
|
+
if (cmd === "agent") return agentHelp();
|
|
2773
|
+
if (cmd === "skill") return skillHelp();
|
|
2774
|
+
return help();
|
|
372
2775
|
}
|
|
373
2776
|
switch (cmd) {
|
|
374
2777
|
case "init":
|
|
375
2778
|
return init(flags);
|
|
376
2779
|
case "login":
|
|
377
|
-
return login();
|
|
2780
|
+
return login(flags);
|
|
378
2781
|
case "logout": {
|
|
379
|
-
const { token, ...rest2 } = readConfig();
|
|
2782
|
+
const { token, tokenApi, ...rest2 } = readConfig();
|
|
380
2783
|
writeConfig(rest2);
|
|
381
2784
|
return console.log(" Logged out.");
|
|
382
2785
|
}
|
|
@@ -389,13 +2792,15 @@ async function main() {
|
|
|
389
2792
|
return list();
|
|
390
2793
|
case "agent":
|
|
391
2794
|
return agent(positional[0], flags);
|
|
2795
|
+
case "skill":
|
|
2796
|
+
return skill(positional[0], flags);
|
|
392
2797
|
case void 0:
|
|
393
2798
|
case "help":
|
|
394
2799
|
case "--help":
|
|
395
2800
|
case "-h":
|
|
396
2801
|
return help();
|
|
397
2802
|
default:
|
|
398
|
-
console.error(`Unknown command: ${cmd}`);
|
|
2803
|
+
console.error(`Unknown command: ${terminalText(cmd)}`);
|
|
399
2804
|
help();
|
|
400
2805
|
return process.exit(2);
|
|
401
2806
|
}
|