rastack 0.0.57 → 0.0.59

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 (86) hide show
  1. package/CHANGELOG.md +11 -0
  2. package/README.md +190 -0
  3. package/admin/index.tsx +19 -13
  4. package/admin/ui/BootScreen.tsx +201 -0
  5. package/dist/admin.js +156 -18
  6. package/dist/deploy/ci.js +2 -2
  7. package/dist/deploy/io.js +2 -2
  8. package/dist/dev/harness.d.ts +1 -1
  9. package/dist/dev/harness.js +21 -5
  10. package/dist/external/cache.d.ts +28 -0
  11. package/dist/external/cache.js +35 -0
  12. package/dist/external/envelope.d.ts +35 -0
  13. package/dist/external/envelope.js +48 -0
  14. package/dist/external/graphql.d.ts +25 -0
  15. package/dist/external/graphql.js +78 -0
  16. package/dist/external/handler.d.ts +52 -0
  17. package/dist/external/handler.js +139 -0
  18. package/dist/external/index.d.ts +19 -0
  19. package/dist/external/index.js +38 -0
  20. package/dist/external/lambda.d.ts +49 -0
  21. package/dist/external/lambda.js +86 -0
  22. package/dist/external/rest.d.ts +17 -0
  23. package/dist/external/rest.js +46 -0
  24. package/dist/external/route.d.ts +12 -0
  25. package/dist/external/route.js +33 -0
  26. package/dist/external/service.d.ts +50 -0
  27. package/dist/external/service.js +59 -0
  28. package/dist/external/types.d.ts +107 -0
  29. package/dist/external/types.js +22 -0
  30. package/dist/external/util.d.ts +16 -0
  31. package/dist/external/util.js +58 -0
  32. package/dist/rastack-dev.js +200 -4
  33. package/dist/rastack-wasm-build.d.ts +1 -1
  34. package/dist/rastack-wasm-build.js +6 -6
  35. package/dist/wasm/rastack_wasm_bg.wasm +0 -0
  36. package/external.ts +10 -0
  37. package/hooks/query/delete.ts +12 -11
  38. package/hooks/query/fetch.ts +6 -8
  39. package/hooks/query/interfaces.ts +1 -4
  40. package/hooks/query/list.ts +16 -9
  41. package/hooks/query/update.ts +8 -6
  42. package/package.json +25 -2
  43. package/scripts/copy-templates.js +1 -1
  44. package/scripts/copy-wasm.js +1 -1
  45. package/scripts/dev-install.mjs +63 -0
  46. package/src/deploy/ci.ts +2 -2
  47. package/src/deploy/io.ts +2 -2
  48. package/src/dev/harness.ts +21 -5
  49. package/src/external/cache.ts +53 -0
  50. package/src/external/envelope.ts +78 -0
  51. package/src/external/graphql.ts +98 -0
  52. package/src/external/handler.ts +207 -0
  53. package/src/external/index.ts +25 -0
  54. package/src/external/lambda.ts +108 -0
  55. package/src/external/rest.ts +60 -0
  56. package/src/external/route.ts +33 -0
  57. package/src/external/service.ts +86 -0
  58. package/src/external/types.ts +121 -0
  59. package/src/external/util.ts +57 -0
  60. package/src/rastack-dev.ts +233 -6
  61. package/src/rastack-wasm-build.ts +6 -6
  62. package/jest.config.cjs +0 -12
  63. package/test/auth.spec.ts +0 -207
  64. package/test/cache.spec.ts +0 -263
  65. package/test/cognito.spec.ts +0 -281
  66. package/test/compile.spec.ts +0 -240
  67. package/test/components.spec.ts +0 -524
  68. package/test/csv-schema.spec.ts +0 -143
  69. package/test/deploy.spec.ts +0 -571
  70. package/test/dev.spec.ts +0 -414
  71. package/test/entities.spec.ts +0 -597
  72. package/test/import.spec.ts +0 -241
  73. package/test/plugin.spec.ts +0 -315
  74. package/test/runtime-manifest.spec.ts +0 -309
  75. package/test/schema-entities.spec.ts +0 -688
  76. package/test/tokens.spec.ts +0 -302
  77. package/test/transitions.spec.ts +0 -372
  78. package/test/typed-hooks.spec.ts +0 -412
  79. package/test/update.spec.ts +0 -152
  80. package/test/validate.spec.ts +0 -319
  81. package/tsconfig.json +0 -27
  82. package/wasm/package.json +0 -4
  83. package/wasm/rastack_wasm.d.ts +0 -100
  84. package/wasm/rastack_wasm.js +0 -745
  85. package/wasm/rastack_wasm_bg.wasm +0 -0
  86. package/wasm/rastack_wasm_bg.wasm.d.ts +0 -28
@@ -1,319 +0,0 @@
1
- /**
2
- * The constraint state machine (`rastack/validate`): compilation from both
3
- * adapters (manifest field, write JSON Schema property), gate-by-gate
4
- * execution, dataset-level `unique`/`resolved` gates, record machines, and
5
- * the form-hook integration (`getFieldMachine`).
6
- */
7
-
8
- import {
9
- compileFieldMachine,
10
- compileRecordMachine,
11
- createDatasetContext,
12
- describeMachine,
13
- runFieldMachine,
14
- runRecordMachine,
15
- specFromManifestField,
16
- specFromSchemaProperty,
17
- specsFromResource,
18
- type FieldSpec,
19
- } from "../src/validate";
20
- import { getFieldMachine } from "../hooks/form/structure";
21
- import type { FieldModel } from "../src/compile/model";
22
-
23
- // The Airport.code field, as `rastack compile` writes it to the manifest.
24
- const CODE_FIELD: FieldModel = {
25
- name: "code",
26
- type: "string",
27
- maxLength: 3,
28
- unique: true,
29
- };
30
-
31
- describe("constraint state machine — compilation", () => {
32
- it("builds one gate per constraint, in canonical order", () => {
33
- const machine = compileFieldMachine(specFromManifestField(CODE_FIELD));
34
- expect(machine.states).toEqual([
35
- "pristine",
36
- "present",
37
- "typed",
38
- "bounded",
39
- "unique",
40
- "valid",
41
- ]);
42
- });
43
-
44
- it("emits no gate for an absent constraint", () => {
45
- const machine = compileFieldMachine(
46
- specFromManifestField({ name: "note", type: "string", null: true }),
47
- );
48
- expect(machine.states).toEqual(["pristine", "present", "typed", "valid"]);
49
- });
50
-
51
- it("describes the constraint chain for UI hints", () => {
52
- const machine = compileFieldMachine(specFromManifestField(CODE_FIELD));
53
- expect(describeMachine(machine)).toEqual([
54
- "required",
55
- "string",
56
- "maxLength ≤ 3",
57
- "unique",
58
- ]);
59
- });
60
- });
61
-
62
- describe("constraint state machine — execution", () => {
63
- const codeMachine = compileFieldMachine(specFromManifestField(CODE_FIELD));
64
-
65
- it("accepts a conforming value, recording the full path", () => {
66
- const run = runFieldMachine(codeMachine, "LHR");
67
- expect(run.state).toBe("valid");
68
- expect(run.value).toBe("LHR");
69
- expect(run.path).toEqual([
70
- "pristine",
71
- "present",
72
- "typed",
73
- "bounded",
74
- "unique",
75
- "valid",
76
- ]);
77
- });
78
-
79
- it("halts at `present` for a missing required value", () => {
80
- const run = runFieldMachine(codeMachine, "");
81
- expect(run.state).toBe("invalid");
82
- expect(run.failed?.gate).toBe("present");
83
- expect(run.path).toEqual(["pristine", "invalid"]);
84
- });
85
-
86
- it("halts at `bounded` when maxLength is exceeded", () => {
87
- const run = runFieldMachine(codeMachine, "LHRX");
88
- expect(run.state).toBe("invalid");
89
- expect(run.failed).toMatchObject({
90
- gate: "bounded",
91
- constraint: "maxLength ≤ 3",
92
- });
93
- // The path shows exactly how far the value got.
94
- expect(run.path).toEqual(["pristine", "present", "typed", "invalid"]);
95
- });
96
-
97
- it("short-circuits an empty optional field to valid with its default", () => {
98
- const machine = compileFieldMachine(
99
- specFromManifestField({
100
- name: "status",
101
- type: "string",
102
- maxLength: 20,
103
- default: "scheduled",
104
- }),
105
- );
106
- const run = runFieldMachine(machine, "");
107
- expect(run.state).toBe("valid");
108
- expect(run.value).toBe("scheduled");
109
- expect(run.path).toEqual(["pristine", "present", "valid"]);
110
- });
111
-
112
- it("coerces at the `typed` gate (int strings become ints)", () => {
113
- const machine = compileFieldMachine(
114
- specFromManifestField({ name: "owner_id", type: "int" }),
115
- );
116
- expect(runFieldMachine(machine, "12").value).toBe(12);
117
- expect(runFieldMachine(machine, 12).value).toBe(12);
118
-
119
- const bad = runFieldMachine(machine, "12.5");
120
- expect(bad.state).toBe("invalid");
121
- expect(bad.failed?.gate).toBe("typed");
122
- });
123
-
124
- it("coerces booleans and datetimes", () => {
125
- const bool = compileFieldMachine(
126
- specFromManifestField({ name: "active", type: "bool" }),
127
- );
128
- expect(runFieldMachine(bool, "yes").value).toBe(true);
129
- expect(runFieldMachine(bool, "0").value).toBe(false);
130
- expect(runFieldMachine(bool, "maybe").state).toBe("invalid");
131
-
132
- const dt = compileFieldMachine(
133
- specFromManifestField({ name: "departs_at", type: "datetime" }),
134
- );
135
- expect(runFieldMachine(dt, "2026-07-13T10:30:00Z").state).toBe("valid");
136
- expect(runFieldMachine(dt, "not a date").state).toBe("invalid");
137
- });
138
-
139
- it("enforces enum membership at the `member` gate", () => {
140
- const spec: FieldSpec = {
141
- name: "status",
142
- type: "string",
143
- required: true,
144
- nullable: false,
145
- options: ["scheduled", "boarding", "departed"],
146
- };
147
- const machine = compileFieldMachine(spec);
148
- expect(runFieldMachine(machine, "boarding").state).toBe("valid");
149
- const bad = runFieldMachine(machine, "cancelled");
150
- expect(bad.failed?.gate).toBe("member");
151
- });
152
-
153
- it("leaves the `unique` gate inert without a dataset context", () => {
154
- expect(runFieldMachine(codeMachine, "LHR").state).toBe("valid");
155
- expect(runFieldMachine(codeMachine, "LHR").state).toBe("valid");
156
- });
157
-
158
- it("rejects duplicates through a dataset context", () => {
159
- const record = compileRecordMachine([specFromManifestField(CODE_FIELD)]);
160
- const ctx = createDatasetContext(record);
161
- expect(runRecordMachine(record, { code: "LHR" }, ctx).state).toBe("valid");
162
- const dup = runRecordMachine(record, { code: "LHR" }, ctx);
163
- expect(dup.state).toBe("invalid");
164
- expect(dup.errors[0]).toMatchObject({ field: "code", gate: "unique" });
165
- });
166
-
167
- it("resolves foreign keys through the context, inert without one", () => {
168
- const fk: FieldModel = {
169
- name: "airport",
170
- type: "fk",
171
- relation: { app: "airports", model: "airport" },
172
- };
173
- const machine = compileFieldMachine(specFromManifestField(fk));
174
- expect(machine.states).toContain("resolved");
175
-
176
- // No resolver — the gate passes (FK existence is a dataset/server check).
177
- expect(runFieldMachine(machine, "7").state).toBe("valid");
178
-
179
- const record = compileRecordMachine([specFromManifestField(fk)]);
180
- const ctx = createDatasetContext(record, {
181
- relatedIds: { "airports.airport": new Set(["1", "2"]) },
182
- });
183
- expect(runRecordMachine(record, { airport: "2" }, ctx).state).toBe("valid");
184
- const dangling = runRecordMachine(record, { airport: "7" }, ctx);
185
- expect(dangling.errors[0]).toMatchObject({
186
- field: "airport",
187
- gate: "resolved",
188
- });
189
- });
190
- });
191
-
192
- describe("spec adapters", () => {
193
- it("manifest: required iff not nullable, no default, not a primary key", () => {
194
- expect(
195
- specFromManifestField({ name: "code", type: "string" }).required,
196
- ).toBe(true);
197
- expect(
198
- specFromManifestField({ name: "code", type: "string", null: true })
199
- .required,
200
- ).toBe(false);
201
- expect(
202
- specFromManifestField({ name: "code", type: "string", default: "x" })
203
- .required,
204
- ).toBe(false);
205
- expect(
206
- specFromManifestField({ name: "id", type: "int", primaryKey: true })
207
- .required,
208
- ).toBe(false);
209
- });
210
-
211
- it("manifest: primary keys are excluded from a resource's input specs", () => {
212
- const specs = specsFromResource({
213
- fields: [
214
- { name: "id", type: "int", primaryKey: true },
215
- { name: "code", type: "string", maxLength: 3 },
216
- ],
217
- });
218
- expect(specs.map((s) => s.name)).toEqual(["code"]);
219
- });
220
-
221
- it("JSON Schema: recovers type, nullability, maxLength, enum and the FK relation", () => {
222
- const schema = {
223
- type: "object",
224
- required: ["code", "airport"],
225
- properties: {
226
- code: { type: "string", maxLength: 3 },
227
- seats: { type: ["integer", "null"] },
228
- status: { type: "string", enum: ["scheduled", "departed"] },
229
- contact: { type: "string", format: "email" },
230
- airport: {
231
- type: "integer",
232
- "x-rastack-relation": { app: "airports", model: "airport" },
233
- },
234
- },
235
- };
236
-
237
- expect(specFromSchemaProperty(schema, "code")).toMatchObject({
238
- type: "string",
239
- required: true,
240
- maxLength: 3,
241
- });
242
- expect(specFromSchemaProperty(schema, "seats")).toMatchObject({
243
- type: "int",
244
- required: false,
245
- nullable: true,
246
- });
247
- expect(specFromSchemaProperty(schema, "status")?.options).toEqual([
248
- "scheduled",
249
- "departed",
250
- ]);
251
- expect(specFromSchemaProperty(schema, "contact")).toMatchObject({
252
- type: "string",
253
- format: "email",
254
- });
255
- expect(specFromSchemaProperty(schema, "airport")).toMatchObject({
256
- type: "fk",
257
- relation: { app: "airports", model: "airport" },
258
- });
259
- expect(specFromSchemaProperty(schema, "missing")).toBeUndefined();
260
- });
261
-
262
- it("both adapters compile machines that agree on a value", () => {
263
- const fromManifest = compileFieldMachine(specFromManifestField(CODE_FIELD));
264
- const fromSchema = compileFieldMachine(
265
- specFromSchemaProperty(
266
- {
267
- type: "object",
268
- required: ["code"],
269
- properties: { code: { type: "string", maxLength: 3 } },
270
- },
271
- "code",
272
- )!,
273
- );
274
-
275
- for (const value of ["LHR", "LHRX", "", 42]) {
276
- const a = runFieldMachine(fromManifest, value);
277
- const b = runFieldMachine(fromSchema, value);
278
- expect(b.state).toBe(a.state);
279
- expect(b.failed?.gate).toBe(a.failed?.gate);
280
- }
281
- });
282
- });
283
-
284
- describe("form hook integration — getFieldMachine", () => {
285
- const writeSchema = {
286
- type: "object",
287
- required: ["code"],
288
- properties: {
289
- code: { type: "string", maxLength: 3 },
290
- contact: { type: "string", format: "email", nullable: true },
291
- },
292
- };
293
-
294
- it("compiles a machine straight from the write schema the form validates against", () => {
295
- const machine = getFieldMachine(writeSchema, "code")!;
296
- expect(machine.states).toEqual([
297
- "pristine",
298
- "present",
299
- "typed",
300
- "bounded",
301
- "valid",
302
- ]);
303
- expect(runFieldMachine(machine, "LHRX").failed?.gate).toBe("bounded");
304
- });
305
-
306
- it("routes string formats through the `typed` gate", () => {
307
- const machine = getFieldMachine(writeSchema, "contact")!;
308
- expect(runFieldMachine(machine, "ops@example.com").state).toBe("valid");
309
- const bad = runFieldMachine(machine, "not-an-email");
310
- expect(bad.failed?.gate).toBe("typed");
311
- // Optional: empty is fine.
312
- expect(runFieldMachine(machine, "").state).toBe("valid");
313
- });
314
-
315
- it("returns undefined for a field the schema does not describe", () => {
316
- expect(getFieldMachine(writeSchema, "nope")).toBeUndefined();
317
- expect(getFieldMachine(undefined, "code")).toBeUndefined();
318
- });
319
- });
package/tsconfig.json DELETED
@@ -1,27 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es2020",
4
- "module": "commonjs",
5
- "lib": [
6
- "ES2023"
7
- ],
8
- "types": [
9
- "node",
10
- "jest"
11
- ],
12
- "outDir": "dist",
13
- "rootDir": "src",
14
- "paths": {
15
- "rastack/tokens": ["./tokens.ts"]
16
- },
17
- "declaration": true,
18
- "esModuleInterop": true,
19
- "forceConsistentCasingInFileNames": true,
20
- "strict": true,
21
- "skipLibCheck": true
22
- },
23
- "include": [
24
- "src",
25
- "src/index.ts"
26
- ]
27
- }
package/wasm/package.json DELETED
@@ -1,4 +0,0 @@
1
- {
2
- "type": "module",
3
- "sideEffects": false
4
- }
@@ -1,100 +0,0 @@
1
- /* tslint:disable */
2
- /* eslint-disable */
3
-
4
- /**
5
- * The in-browser API engine. Cheap to clone (everything behind `Arc`), which
6
- * is what lets each async call own its state without borrowing across `await`.
7
- */
8
- export class RastackApi {
9
- free(): void;
10
- [Symbol.dispose](): void;
11
- /**
12
- * Snapshot the entire warehouse to a blob for persistence (`data/` folder,
13
- * IndexedDB, or an upload to S3).
14
- */
15
- exportWarehouse(): Promise<any>;
16
- /**
17
- * Handle one request. `query` is a `{ [k]: string }` object, `body` any
18
- * JSON value (or `undefined`). Resolves to `{ status, body }`.
19
- */
20
- handle(method: string, path: string, query: any, body: any): Promise<any>;
21
- /**
22
- * Seed the warehouse from a blob previously produced by
23
- * [`export_warehouse`](Self::export_warehouse) (the `data/` folder or an
24
- * IndexedDB/OPFS snapshot).
25
- */
26
- importWarehouse(blob: Uint8Array): Promise<any>;
27
- /**
28
- * Build an engine from the compiled manifest (`schema.rastack.json`) and an
29
- * optional OpenAPI document (`openapi.json`, served at `/api/schema/`).
30
- */
31
- constructor(manifest_json: string, openapi_json?: string | null);
32
- /**
33
- * Seed one Iceberg file (metadata or data file) at its warehouse key. The
34
- * provider walks the committed `data/warehouse` Iceberg tree over HTTP and
35
- * calls this for each file, so the browser reads the *actual* Iceberg files
36
- * — no bundled blob.
37
- */
38
- seedFile(key: string, bytes: Uint8Array): Promise<any>;
39
- /**
40
- * Run subsequent requests as a signed-in identity (the Cognito `sub` and
41
- * `cognito:groups` claims). Owner fields are stamped from — and row
42
- * filters and tenant scoping keyed by — this subject, matching the server
43
- * byte-for-byte. Pass no subject to fall back to the trusted local
44
- * context.
45
- */
46
- setAuth(subject: string | null | undefined, groups: any): void;
47
- }
48
-
49
- export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
50
-
51
- export interface InitOutput {
52
- readonly memory: WebAssembly.Memory;
53
- readonly __wbg_rastackapi_free: (a: number, b: number) => void;
54
- readonly rastackapi_exportWarehouse: (a: number) => any;
55
- readonly rastackapi_handle: (a: number, b: number, c: number, d: number, e: number, f: any, g: any) => any;
56
- readonly rastackapi_importWarehouse: (a: number, b: number, c: number) => any;
57
- readonly rastackapi_new: (a: number, b: number, c: number, d: number) => [number, number, number];
58
- readonly rastackapi_seedFile: (a: number, b: number, c: number, d: number, e: number) => any;
59
- readonly rastackapi_setAuth: (a: number, b: number, c: number, d: any) => [number, number];
60
- readonly rust_zstd_wasm_shim_calloc: (a: number, b: number) => number;
61
- readonly rust_zstd_wasm_shim_free: (a: number) => void;
62
- readonly rust_zstd_wasm_shim_malloc: (a: number) => number;
63
- readonly rust_zstd_wasm_shim_memcmp: (a: number, b: number, c: number) => number;
64
- readonly rust_zstd_wasm_shim_memcpy: (a: number, b: number, c: number) => number;
65
- readonly rust_zstd_wasm_shim_memmove: (a: number, b: number, c: number) => number;
66
- readonly rust_zstd_wasm_shim_memset: (a: number, b: number, c: number) => number;
67
- readonly rust_zstd_wasm_shim_qsort: (a: number, b: number, c: number, d: number) => void;
68
- readonly wasm_bindgen_ac0f9960a408a037___convert__closures_____invoke___wasm_bindgen_ac0f9960a408a037___JsValue__core_9b3796e30d99ddb7___result__Result_____wasm_bindgen_ac0f9960a408a037___JsError___true_: (a: number, b: number, c: any) => [number, number];
69
- readonly wasm_bindgen_ac0f9960a408a037___convert__closures_____invoke___js_sys_10c47e7ecd0a94ab___Function_fn_wasm_bindgen_ac0f9960a408a037___JsValue_____wasm_bindgen_ac0f9960a408a037___sys__Undefined___js_sys_10c47e7ecd0a94ab___Function_fn_wasm_bindgen_ac0f9960a408a037___JsValue_____wasm_bindgen_ac0f9960a408a037___sys__Undefined_______true_: (a: number, b: number, c: any, d: any) => void;
70
- readonly __wbindgen_malloc: (a: number, b: number) => number;
71
- readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
72
- readonly __wbindgen_exn_store: (a: number) => void;
73
- readonly __externref_table_alloc: () => number;
74
- readonly __wbindgen_externrefs: WebAssembly.Table;
75
- readonly __wbindgen_destroy_closure: (a: number, b: number) => void;
76
- readonly __externref_table_dealloc: (a: number) => void;
77
- readonly __wbindgen_start: () => void;
78
- }
79
-
80
- export type SyncInitInput = BufferSource | WebAssembly.Module;
81
-
82
- /**
83
- * Instantiates the given `module`, which can either be bytes or
84
- * a precompiled `WebAssembly.Module`.
85
- *
86
- * @param {{ module: SyncInitInput }} module - Passing `SyncInitInput` directly is deprecated.
87
- *
88
- * @returns {InitOutput}
89
- */
90
- export function initSync(module: { module: SyncInitInput } | SyncInitInput): InitOutput;
91
-
92
- /**
93
- * If `module_or_path` is {RequestInfo} or {URL}, makes a request and
94
- * for everything else, calls `WebAssembly.instantiate` directly.
95
- *
96
- * @param {{ module_or_path: InitInput | Promise<InitInput> }} module_or_path - Passing `InitInput` directly is deprecated.
97
- *
98
- * @returns {Promise<InitOutput>}
99
- */
100
- export default function __wbg_init (module_or_path?: { module_or_path: InitInput | Promise<InitInput> } | InitInput | Promise<InitInput>): Promise<InitOutput>;