@instafy/cli 0.2.3 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/README.md +4 -0
  2. package/dist/bind/LICENSE +661 -0
  3. package/dist/bind/bin/instafy-bind.mjs +542 -0
  4. package/dist/bind/client/bind-client.js +1219 -0
  5. package/dist/bind/src/apply.mjs +293 -0
  6. package/dist/bind/src/bound.mjs +202 -0
  7. package/dist/bind/src/budget.mjs +58 -0
  8. package/dist/bind/src/check.mjs +176 -0
  9. package/dist/bind/src/config.mjs +180 -0
  10. package/dist/bind/src/controller.mjs +244 -0
  11. package/dist/bind/src/executors/agent.mjs +336 -0
  12. package/dist/bind/src/executors/script.mjs +163 -0
  13. package/dist/bind/src/handler-kit.mjs +150 -0
  14. package/dist/bind/src/init.mjs +238 -0
  15. package/dist/bind/src/jobs.mjs +316 -0
  16. package/dist/bind/src/net.mjs +281 -0
  17. package/dist/bind/src/page-fetch.mjs +43 -0
  18. package/dist/bind/src/preview-host.mjs +114 -0
  19. package/dist/bind/src/protocol.mjs +103 -0
  20. package/dist/bind/src/records-schema.mjs +580 -0
  21. package/dist/bind/src/records.mjs +161 -0
  22. package/dist/bind/src/save-owner.mjs +492 -0
  23. package/dist/bind/src/schema-lite.mjs +212 -0
  24. package/dist/bind/src/server.mjs +908 -0
  25. package/dist/bind/src/sse.mjs +119 -0
  26. package/dist/bind/src/starters/blank/app.js +17 -0
  27. package/dist/bind/src/starters/blank/index.html +22 -0
  28. package/dist/bind/src/starters/checklist/app.js +171 -0
  29. package/dist/bind/src/starters/checklist/bound.json +29 -0
  30. package/dist/bind/src/starters/checklist/data.json +26 -0
  31. package/dist/bind/src/starters/checklist/index.html +23 -0
  32. package/dist/bind/src/starters/compare/app.js +316 -0
  33. package/dist/bind/src/starters/compare/bound.json +26 -0
  34. package/dist/bind/src/starters/compare/data.json +170 -0
  35. package/dist/bind/src/starters/compare/index.html +23 -0
  36. package/dist/bind/src/starters/handlers/read_offer.mjs +55 -0
  37. package/dist/bind/src/starters/handlers/set_check.mjs +41 -0
  38. package/dist/bind/src/starters/ranked/app.js +166 -0
  39. package/dist/bind/src/starters/ranked/bound.json +26 -0
  40. package/dist/bind/src/starters/ranked/data.json +142 -0
  41. package/dist/bind/src/starters/ranked/index.html +23 -0
  42. package/dist/bind/src/starters/site.js +888 -0
  43. package/dist/bind/src/starters/theme.css +492 -0
  44. package/dist/bind/src/starters/timeline/app.js +143 -0
  45. package/dist/bind/src/starters/timeline/data.json +41 -0
  46. package/dist/bind/src/starters/timeline/index.html +22 -0
  47. package/dist/bind/src/static.mjs +141 -0
  48. package/dist/bind/src/tokens.mjs +102 -0
  49. package/dist/bind/src/try.mjs +139 -0
  50. package/dist/bind/src/web.mjs +191 -0
  51. package/dist/cli.js +2117 -365
  52. package/package.json +3 -2
@@ -0,0 +1,212 @@
1
+ // JSON-Schema subset validator for intent params and records.
2
+ //
3
+ // Subset (intent params): type (also an array of types), properties, required,
4
+ // additionalProperties: false, enum, const, default, minimum, maximum, minLength,
5
+ // maxLength, pattern, items, minItems, maxItems, format (date, date-time, uri),
6
+ // title, description.
7
+ //
8
+ // Extended (records schema, bound.json): the subset plus oneOf, $ref (local
9
+ // "#/$defs/..."), $defs, maxProperties, additionalProperties as a schema, $schema, $id.
10
+ //
11
+ // checkSchema() reports unknown keywords, so a constraint is never silently ignored.
12
+
13
+ export const SUBSET_KEYWORDS = [
14
+ "type", "properties", "required", "additionalProperties", "enum", "const", "default",
15
+ "minimum", "maximum", "minLength", "maxLength", "pattern", "items", "minItems", "maxItems",
16
+ "format", "title", "description",
17
+ ];
18
+ export const EXTENDED_KEYWORDS = [...SUBSET_KEYWORDS, "oneOf", "$ref", "$defs", "maxProperties", "$schema", "$id"];
19
+ const TYPES = ["object", "string", "number", "integer", "boolean", "array", "null"];
20
+ const FORMATS = ["date", "date-time", "uri"];
21
+
22
+ /** Check a schema itself. Returns [{path, message}]. `extended: false` allows the §9.2 subset only. */
23
+ export function checkSchema(schema, { extended = false, path = "$" } = {}) {
24
+ const problems = [];
25
+ const allowed = new Set(extended ? EXTENDED_KEYWORDS : SUBSET_KEYWORDS);
26
+ const walk = (s, p) => {
27
+ if (typeof s === "boolean" && extended) return;
28
+ if (!s || typeof s !== "object" || Array.isArray(s)) {
29
+ problems.push({ path: p, message: "schema must be an object" });
30
+ return;
31
+ }
32
+ for (const k of Object.keys(s)) {
33
+ if (!allowed.has(k)) problems.push({ path: `${p}.${k}`, message: `unsupported keyword "${k}"` });
34
+ }
35
+ if (s.type !== undefined) {
36
+ for (const t of Array.isArray(s.type) ? s.type : [s.type]) {
37
+ if (!TYPES.includes(t)) problems.push({ path: `${p}.type`, message: `unknown type "${t}"` });
38
+ }
39
+ }
40
+ if (s.format !== undefined && !FORMATS.includes(s.format)) {
41
+ problems.push({ path: `${p}.format`, message: `unsupported format "${s.format}" (use ${FORMATS.join(", ")})` });
42
+ }
43
+ if (s.pattern !== undefined) {
44
+ try {
45
+ new RegExp(s.pattern);
46
+ } catch (error) {
47
+ problems.push({ path: `${p}.pattern`, message: `invalid regex: ${error.message}` });
48
+ }
49
+ }
50
+ if (s.required !== undefined && !(Array.isArray(s.required) && s.required.every((x) => typeof x === "string"))) {
51
+ problems.push({ path: `${p}.required`, message: "required must be an array of property names" });
52
+ }
53
+ if (s.enum !== undefined && !Array.isArray(s.enum)) problems.push({ path: `${p}.enum`, message: "enum must be an array" });
54
+ if (s.additionalProperties !== undefined && s.additionalProperties !== false && !extended) {
55
+ problems.push({ path: `${p}.additionalProperties`, message: "only additionalProperties: false is supported" });
56
+ }
57
+ if (s.properties !== undefined) {
58
+ if (!s.properties || typeof s.properties !== "object" || Array.isArray(s.properties)) {
59
+ problems.push({ path: `${p}.properties`, message: "properties must be an object" });
60
+ } else {
61
+ for (const [k, v] of Object.entries(s.properties)) walk(v, `${p}.properties.${k}`);
62
+ }
63
+ }
64
+ if (s.items !== undefined) walk(s.items, `${p}.items`);
65
+ if (extended && s.additionalProperties && typeof s.additionalProperties === "object") {
66
+ walk(s.additionalProperties, `${p}.additionalProperties`);
67
+ }
68
+ if (extended && Array.isArray(s.oneOf)) s.oneOf.forEach((x, i) => walk(x, `${p}.oneOf[${i}]`));
69
+ if (extended && s.$defs) for (const [k, v] of Object.entries(s.$defs)) walk(v, `${p}.$defs.${k}`);
70
+ if (Array.isArray(s.required) && s.properties && s.additionalProperties === false) {
71
+ for (const r of s.required) {
72
+ if (!(r in s.properties)) {
73
+ problems.push({ path: `${p}.required`, message: `"${r}" is required but not declared in properties` });
74
+ }
75
+ }
76
+ }
77
+ };
78
+ walk(schema, path);
79
+ return problems;
80
+ }
81
+
82
+ const typeOf = (v) =>
83
+ v === null ? "null" : Array.isArray(v) ? "array" : typeof v === "number" ? (Number.isInteger(v) ? "integer" : "number") : typeof v;
84
+ const typeOk = (t, v) => {
85
+ const actual = typeOf(v);
86
+ return t === actual || (t === "number" && actual === "integer");
87
+ };
88
+ const regexCache = new Map();
89
+ function regex(pattern) {
90
+ let compiled = regexCache.get(pattern);
91
+ if (!compiled) {
92
+ compiled = new RegExp(pattern);
93
+ regexCache.set(pattern, compiled);
94
+ }
95
+ return compiled;
96
+ }
97
+
98
+ function formatOk(format, value) {
99
+ if (typeof value !== "string") return true;
100
+ if (format === "date") return /^\d{4}-\d{2}-\d{2}$/.test(value) && !Number.isNaN(Date.parse(`${value}T00:00:00Z`));
101
+ if (format === "date-time") {
102
+ return /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}(:\d{2}(\.\d+)?)?(Z|[+-]\d{2}:?\d{2})$/.test(value) && !Number.isNaN(Date.parse(value));
103
+ }
104
+ if (format === "uri") {
105
+ try {
106
+ new URL(value);
107
+ return true;
108
+ } catch {
109
+ return false;
110
+ }
111
+ }
112
+ return true;
113
+ }
114
+
115
+ function resolveRef(root, ref) {
116
+ if (!ref.startsWith("#/")) throw new Error(`only local $ref is supported (${ref})`);
117
+ let node = root;
118
+ for (const part of ref.slice(2).split("/")) node = node?.[part.replace(/~1/g, "/").replace(/~0/g, "~")];
119
+ if (node === undefined) throw new Error(`unresolved $ref ${ref}`);
120
+ return node;
121
+ }
122
+
123
+ /** Validate a value. Returns [{path, message}]; empty means valid. Stops after `max` errors. */
124
+ export function validate(schema, value, { root = schema, path = "$", max = 50 } = {}) {
125
+ const errors = [];
126
+ const err = (p, m) => {
127
+ if (errors.length < max) errors.push({ path: p, message: m });
128
+ };
129
+ const visit = (s, x, p) => {
130
+ if (errors.length >= max) return;
131
+ if (s === true || s === undefined) return;
132
+ if (s === false) {
133
+ err(p, "not allowed");
134
+ return;
135
+ }
136
+ if (s.$ref) {
137
+ visit(resolveRef(root, s.$ref), x, p);
138
+ return;
139
+ }
140
+ if (s.oneOf) {
141
+ // Discriminate on a "type" const when every branch has one: clearer errors than "matched 0 of 3".
142
+ const branches = s.oneOf.map((b) => (b && b.$ref ? resolveRef(root, b.$ref) : b));
143
+ const consts = branches.map((b) => b?.properties?.type?.const);
144
+ if (consts.every((c) => c !== undefined) && x && typeof x === "object" && !Array.isArray(x)) {
145
+ const index = consts.indexOf(x.type);
146
+ if (index < 0) err(`${p}.type`, `must be one of ${consts.map((c) => JSON.stringify(c)).join(", ")}`);
147
+ else visit(branches[index], x, p);
148
+ } else {
149
+ const matched = branches.filter((b) => validate(b, x, { root, path: p, max: 1 }).length === 0).length;
150
+ if (matched !== 1) err(p, `must match exactly one schema in oneOf (matched ${matched})`);
151
+ }
152
+ return;
153
+ }
154
+ if (s.type !== undefined) {
155
+ const types = Array.isArray(s.type) ? s.type : [s.type];
156
+ if (!types.some((t) => typeOk(t, x))) {
157
+ err(p, `must be ${types.join(" or ")} (got ${typeOf(x)})`);
158
+ return;
159
+ }
160
+ }
161
+ if (s.const !== undefined && JSON.stringify(s.const) !== JSON.stringify(x)) err(p, `must be ${JSON.stringify(s.const)}`);
162
+ if (s.enum && !s.enum.some((e) => JSON.stringify(e) === JSON.stringify(x))) {
163
+ err(p, `must be one of ${s.enum.map((e) => JSON.stringify(e)).join(", ")}`);
164
+ }
165
+ if (typeof x === "number") {
166
+ if (!Number.isFinite(x)) err(p, "must be a finite number");
167
+ if (s.minimum !== undefined && x < s.minimum) err(p, `must be >= ${s.minimum}`);
168
+ if (s.maximum !== undefined && x > s.maximum) err(p, `must be <= ${s.maximum}`);
169
+ }
170
+ if (typeof x === "string") {
171
+ const length = [...x].length;
172
+ if (s.minLength !== undefined && length < s.minLength) err(p, `must be at least ${s.minLength} characters`);
173
+ if (s.maxLength !== undefined && length > s.maxLength) err(p, `must be at most ${s.maxLength} characters`);
174
+ if (s.pattern !== undefined && !regex(s.pattern).test(x)) err(p, `must match ${s.pattern}`);
175
+ if (s.format !== undefined && !formatOk(s.format, x)) err(p, `must be a valid ${s.format}`);
176
+ }
177
+ if (Array.isArray(x)) {
178
+ if (s.minItems !== undefined && x.length < s.minItems) err(p, `must have at least ${s.minItems} items`);
179
+ if (s.maxItems !== undefined && x.length > s.maxItems) err(p, `must have at most ${s.maxItems} items`);
180
+ if (s.items) x.forEach((item, i) => visit(s.items, item, `${p}[${i}]`));
181
+ }
182
+ if (x && typeof x === "object" && !Array.isArray(x)) {
183
+ const keys = Object.keys(x);
184
+ if (s.maxProperties !== undefined && keys.length > s.maxProperties) err(p, `must have at most ${s.maxProperties} properties`);
185
+ for (const r of s.required || []) if (x[r] === undefined) err(`${p}.${r}`, "is required");
186
+ const props = s.properties || {};
187
+ for (const k of keys) {
188
+ if (Object.prototype.hasOwnProperty.call(props, k)) visit(props[k], x[k], `${p}.${k}`);
189
+ else if (s.additionalProperties === false) err(`${p}.${k}`, "is not allowed");
190
+ else if (s.additionalProperties && typeof s.additionalProperties === "object") visit(s.additionalProperties, x[k], `${p}.${k}`);
191
+ }
192
+ }
193
+ };
194
+ visit(schema, value, path);
195
+ return errors;
196
+ }
197
+
198
+ /** Fill `default` values of an object schema's properties (one level, like the map engine's form). */
199
+ export function applyDefaults(schema, value) {
200
+ if (!schema || schema.type !== "object" || !value || typeof value !== "object" || Array.isArray(value)) return value;
201
+ const out = { ...value };
202
+ for (const [k, s] of Object.entries(schema.properties || {})) {
203
+ if (out[k] === undefined && s && s.default !== undefined) out[k] = structuredClone(s.default);
204
+ }
205
+ return out;
206
+ }
207
+
208
+ /** "path message; path message (+n more)" for logs and 400 reasons. */
209
+ export function formatErrors(errors, limit = 3) {
210
+ const head = errors.slice(0, limit).map((e) => `${e.path} ${e.message}`).join("; ");
211
+ return errors.length > limit ? `${head} (+${errors.length - limit} more)` : head;
212
+ }