rastack 0.0.48 → 0.0.50
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/CHANGELOG.md +4 -0
- package/components/auto-form/AutoForm.tsx +13 -0
- package/components/auto-form/use-auto-form.ts +28 -0
- package/components/types.ts +8 -0
- package/dist/admin.js +13 -13
- package/dist/compile/analyze.d.ts +26 -0
- package/dist/compile/analyze.js +70 -3
- package/dist/compile/entities.d.ts +19 -0
- package/dist/compile/entities.js +87 -13
- package/dist/compile/index.d.ts +23 -4
- package/dist/compile/index.js +86 -7
- package/dist/compile/model.d.ts +38 -0
- package/dist/compile/openapi.d.ts +9 -0
- package/dist/compile/openapi.js +14 -0
- package/dist/define/index.d.ts +107 -13
- package/dist/define/index.js +1 -1
- package/dist/import/tabular.d.ts +8 -2
- package/dist/import/tabular.js +1 -1
- package/dist/rastack-admin.d.ts +14 -7
- package/dist/rastack-admin.js +85 -40
- package/dist/rastack-import.js +4 -1
- package/dist/validate/adapters.js +2 -0
- package/dist/validate/index.d.ts +1 -0
- package/dist/validate/index.js +1 -0
- package/dist/validate/machine.d.ts +23 -2
- package/dist/validate/machine.js +35 -2
- package/dist/validate/transitions.d.ts +86 -0
- package/dist/validate/transitions.js +199 -0
- package/dist/wasm/rastack_wasm.js +1 -1
- package/dist/wasm/rastack_wasm_bg.wasm +0 -0
- package/hooks/data.ts +209 -0
- package/hooks/entity.ts +222 -0
- package/hooks/form/entity-form.ts +354 -0
- package/hooks/form/form.ts +8 -1
- package/hooks/form/index.ts +7 -1
- package/hooks/index.ts +4 -0
- package/hooks/manifest.ts +41 -0
- package/hooks/registry.ts +39 -0
- package/package.json +1 -1
- package/provider/provider.tsx +8 -1
- package/provider/types.ts +7 -2
- package/src/compile/analyze.ts +83 -4
- package/src/compile/entities.ts +111 -11
- package/src/compile/index.ts +108 -11
- package/src/compile/model.ts +40 -0
- package/src/compile/openapi.ts +13 -1
- package/src/define/index.ts +148 -20
- package/src/import/tabular.ts +9 -2
- package/src/rastack-admin.ts +105 -46
- package/src/rastack-import.ts +4 -1
- package/src/validate/adapters.ts +1 -0
- package/src/validate/index.ts +1 -0
- package/src/validate/machine.ts +55 -3
- package/src/validate/transitions.ts +232 -0
- package/test/components.spec.ts +22 -0
- package/test/transitions.spec.ts +372 -0
- package/test/typed-hooks.spec.ts +407 -0
- package/wasm/rastack_wasm.js +1 -1
- package/wasm/rastack_wasm_bg.wasm +0 -0
|
@@ -0,0 +1,407 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pure cores behind `useData(Entity)` / `useForm(Entity)`: resolving a
|
|
3
|
+
* plain TypeScript type to its manifest resource, deriving the write schema
|
|
4
|
+
* (and its form field structures) from the manifest at runtime, and the
|
|
5
|
+
* type-level transition names. The React shells around these are thin; the
|
|
6
|
+
* decisions all live here.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { mkdirSync, readFileSync, rmSync, writeFileSync, existsSync } from "fs";
|
|
10
|
+
import { join } from "path";
|
|
11
|
+
import {
|
|
12
|
+
entityModelName,
|
|
13
|
+
humanizeName,
|
|
14
|
+
isEntityRef,
|
|
15
|
+
resolveEntityRef,
|
|
16
|
+
} from "../hooks/entity";
|
|
17
|
+
import { useData } from "../hooks/data";
|
|
18
|
+
import type { RowForKey } from "../hooks/registry";
|
|
19
|
+
import { compile } from "../src/compile";
|
|
20
|
+
import { initialValuesFromResource } from "../hooks/form/entity-form";
|
|
21
|
+
import { getFieldMachine, getFieldStructure } from "../hooks/form/structure";
|
|
22
|
+
import { writeSchema } from "../src/compile/openapi";
|
|
23
|
+
import type { Manifest, ResourceModel } from "../src/compile/model";
|
|
24
|
+
import { resource, s, type TransitionNamesOf } from "../src/define";
|
|
25
|
+
import { runFieldMachine } from "../src/validate";
|
|
26
|
+
|
|
27
|
+
const airport: ResourceModel = {
|
|
28
|
+
app: "airports",
|
|
29
|
+
model: "airport",
|
|
30
|
+
fields: [
|
|
31
|
+
{ name: "code", type: "string", maxLength: 3, unique: true },
|
|
32
|
+
{ name: "name", type: "string", maxLength: 120 },
|
|
33
|
+
],
|
|
34
|
+
relations: [],
|
|
35
|
+
admin: { listDisplay: ["code", "name"] },
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
const flight: ResourceModel = {
|
|
39
|
+
app: "airports",
|
|
40
|
+
model: "flight",
|
|
41
|
+
fields: [
|
|
42
|
+
{ name: "number", type: "string", maxLength: 8 },
|
|
43
|
+
{
|
|
44
|
+
name: "status",
|
|
45
|
+
type: "string",
|
|
46
|
+
options: ["scheduled", "boarding", "departed"],
|
|
47
|
+
default: "scheduled",
|
|
48
|
+
},
|
|
49
|
+
{ name: "active", type: "bool" },
|
|
50
|
+
{ name: "airport", type: "fk", relation: { app: "airports", model: "airport" } },
|
|
51
|
+
],
|
|
52
|
+
relations: [{ field: "airport", target: "airports.airport", kind: "fk" }],
|
|
53
|
+
transitions: {
|
|
54
|
+
field: "status",
|
|
55
|
+
states: ["scheduled", "boarding", "departed"],
|
|
56
|
+
initial: "scheduled",
|
|
57
|
+
on: {
|
|
58
|
+
board: { from: ["scheduled"], to: "boarding" },
|
|
59
|
+
depart: { from: ["boarding"], to: "departed" },
|
|
60
|
+
},
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const manifest: Manifest = { version: 1, resources: [airport, flight] };
|
|
65
|
+
|
|
66
|
+
describe("resolveEntityRef — a type names its resource", () => {
|
|
67
|
+
it("resolves a class by its (compiler-normalised) name", () => {
|
|
68
|
+
class Airport {
|
|
69
|
+
code!: string;
|
|
70
|
+
}
|
|
71
|
+
const resolved = resolveEntityRef(Airport, manifest);
|
|
72
|
+
expect(resolved).toMatchObject({
|
|
73
|
+
app: "airports",
|
|
74
|
+
model: "airport",
|
|
75
|
+
key: "airports.airport",
|
|
76
|
+
listUrl: "/api/airports/v1/airport/",
|
|
77
|
+
});
|
|
78
|
+
expect(resolved.detailUrl(7)).toBe("/api/airports/v1/airport/7/");
|
|
79
|
+
expect(resolved.resource).toBe(airport);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("strips the generated `I` prefix, like the compiler does", () => {
|
|
83
|
+
expect(entityModelName("IFlight")).toBe("flight");
|
|
84
|
+
expect(entityModelName("Flight")).toBe("flight");
|
|
85
|
+
expect(entityModelName("Item")).toBe("item"); // `It` is not an I-prefix… but `Item` is I+tem
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
it("resolves a `resource()` value directly — manifest optional", () => {
|
|
89
|
+
const Flight = resource("airports", "flight", {
|
|
90
|
+
number: s.string({ maxLength: 8 }),
|
|
91
|
+
});
|
|
92
|
+
expect(resolveEntityRef(Flight, manifest).resource).toBe(flight);
|
|
93
|
+
// Without a manifest the URLs still resolve (the DSL value carries app/model)…
|
|
94
|
+
const bare = resolveEntityRef(Flight);
|
|
95
|
+
expect(bare.listUrl).toBe("/api/airports/v1/flight/");
|
|
96
|
+
expect(bare.resource).toBeUndefined();
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it("carries a resource()'s transitions even without a manifest", () => {
|
|
100
|
+
const Flight = resource(
|
|
101
|
+
"airports",
|
|
102
|
+
"flight",
|
|
103
|
+
{ status: s.string({ maxLength: 20 }) },
|
|
104
|
+
{
|
|
105
|
+
transitions: {
|
|
106
|
+
field: "status",
|
|
107
|
+
states: ["scheduled", "boarding"],
|
|
108
|
+
on: { board: { from: "scheduled", to: "boarding" } },
|
|
109
|
+
},
|
|
110
|
+
},
|
|
111
|
+
);
|
|
112
|
+
const resolved = resolveEntityRef(Flight);
|
|
113
|
+
expect(resolved.transitions).toMatchObject({
|
|
114
|
+
on: { board: { from: ["scheduled"], to: "boarding" } },
|
|
115
|
+
});
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
it('resolves "app.model" and bare "model" strings', () => {
|
|
119
|
+
expect(resolveEntityRef("airports.flight", manifest).resource).toBe(flight);
|
|
120
|
+
expect(resolveEntityRef("flight", manifest).model).toBe("flight");
|
|
121
|
+
expect(() => resolveEntityRef("airports.spaceship", manifest)).toThrow(
|
|
122
|
+
/no resource "airports.spaceship"/,
|
|
123
|
+
);
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
it("fails loudly on ambiguity and missing manifests", () => {
|
|
127
|
+
const two: Manifest = {
|
|
128
|
+
version: 1,
|
|
129
|
+
resources: [flight, { ...flight, app: "cargo" }],
|
|
130
|
+
};
|
|
131
|
+
expect(() => resolveEntityRef("flight", two)).toThrow(/"app.model"/);
|
|
132
|
+
class Flight {
|
|
133
|
+
number!: string;
|
|
134
|
+
}
|
|
135
|
+
expect(() => resolveEntityRef(Flight, two)).toThrow(/airports\.flight, cargo\.flight/);
|
|
136
|
+
expect(() => resolveEntityRef(Flight)).toThrow(/manifest/);
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it("classifies entity refs vs. legacy form props", () => {
|
|
140
|
+
expect(isEntityRef("airports.flight")).toBe(true);
|
|
141
|
+
expect(isEntityRef(class A {})).toBe(true);
|
|
142
|
+
expect(isEntityRef({ app: "a", model: "b" })).toBe(true);
|
|
143
|
+
expect(isEntityRef({ formValues: {}, mutations: {} })).toBe(false);
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
describe("useForm(Entity) — the manifest-derived form core", () => {
|
|
148
|
+
it("derives form-friendly initial values from the resource", () => {
|
|
149
|
+
expect(initialValuesFromResource(flight)).toEqual({
|
|
150
|
+
number: "",
|
|
151
|
+
status: "scheduled", // the machine's initial state, via the field default
|
|
152
|
+
active: false,
|
|
153
|
+
airport: "",
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
it("derives the same write schema the OpenAPI contract publishes", () => {
|
|
158
|
+
const schema = writeSchema(flight, false);
|
|
159
|
+
expect(schema.properties.status.enum).toEqual([
|
|
160
|
+
"scheduled",
|
|
161
|
+
"boarding",
|
|
162
|
+
"departed",
|
|
163
|
+
]);
|
|
164
|
+
expect(schema.properties.airport["x-rastack-relation"]).toEqual({
|
|
165
|
+
app: "airports",
|
|
166
|
+
model: "airport",
|
|
167
|
+
});
|
|
168
|
+
expect(schema["x-rastack-transitions"]).toBe(flight.transitions);
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it("renders the state field as a select and runs its member gate", () => {
|
|
172
|
+
const schema = writeSchema(flight, false);
|
|
173
|
+
|
|
174
|
+
const structure = getFieldStructure(schema, "status");
|
|
175
|
+
expect(structure.type).toBe("select");
|
|
176
|
+
expect(structure.options).toEqual([
|
|
177
|
+
{ label: "scheduled", value: "scheduled" },
|
|
178
|
+
{ label: "boarding", value: "boarding" },
|
|
179
|
+
{ label: "departed", value: "departed" },
|
|
180
|
+
]);
|
|
181
|
+
|
|
182
|
+
const machine = getFieldMachine(schema, "status")!;
|
|
183
|
+
expect(machine.states).toContain("member");
|
|
184
|
+
expect(runFieldMachine(machine, "boarding").state).toBe("valid");
|
|
185
|
+
expect(runFieldMachine(machine, "teleported").state).toBe("invalid");
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
it("humanises transition names into button labels", () => {
|
|
189
|
+
expect(humanizeName("board")).toBe("Board");
|
|
190
|
+
expect(humanizeName("close_out")).toBe("Close out");
|
|
191
|
+
expect(humanizeName("markShipped")).toBe("Mark shipped");
|
|
192
|
+
});
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
describe("TransitionNamesOf — transition names are literal types", () => {
|
|
196
|
+
it("reads names from a resource()'s options and a class's static block", () => {
|
|
197
|
+
const Flight = resource(
|
|
198
|
+
"airports",
|
|
199
|
+
"flight",
|
|
200
|
+
{ status: s.string({ maxLength: 20 }) },
|
|
201
|
+
{
|
|
202
|
+
transitions: {
|
|
203
|
+
field: "status",
|
|
204
|
+
states: ["scheduled", "boarding", "departed"],
|
|
205
|
+
initial: "scheduled",
|
|
206
|
+
on: {
|
|
207
|
+
board: { from: "scheduled", to: "boarding" },
|
|
208
|
+
depart: { from: "boarding", to: "departed" },
|
|
209
|
+
},
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
);
|
|
213
|
+
type FlightNames = TransitionNamesOf<typeof Flight>;
|
|
214
|
+
const boardName: FlightNames = "board";
|
|
215
|
+
const departName: FlightNames = "depart";
|
|
216
|
+
// @ts-expect-error — "explode" is not a declared transition
|
|
217
|
+
const bad: FlightNames = "explode";
|
|
218
|
+
expect([boardName, departName, bad]).toBeDefined();
|
|
219
|
+
|
|
220
|
+
class Order {
|
|
221
|
+
status = "draft";
|
|
222
|
+
static transitions = {
|
|
223
|
+
field: "status",
|
|
224
|
+
states: ["draft", "placed"],
|
|
225
|
+
initial: "draft",
|
|
226
|
+
on: { place: { from: "draft", to: "placed" } },
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
type OrderNames = TransitionNamesOf<typeof Order>;
|
|
230
|
+
const placeName: OrderNames = "place";
|
|
231
|
+
expect(placeName).toBe("place");
|
|
232
|
+
|
|
233
|
+
class Plain {
|
|
234
|
+
name!: string;
|
|
235
|
+
}
|
|
236
|
+
type None = TransitionNamesOf<typeof Plain>; // resolves to never
|
|
237
|
+
const nothing: None[] = [];
|
|
238
|
+
expect(nothing).toEqual([]);
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
// ---------------------------------------------------------------------------
|
|
243
|
+
// Row inference — no type argument needed
|
|
244
|
+
// ---------------------------------------------------------------------------
|
|
245
|
+
|
|
246
|
+
// What `rastack compile` emits as rastack-env.d.ts (declaration merging into
|
|
247
|
+
// the registry) — hand-rolled here so the inference is exercised in-test.
|
|
248
|
+
declare module "../hooks/registry" {
|
|
249
|
+
interface EntityTypes {
|
|
250
|
+
"airports.terminal": { id: number; label: string; airport: number };
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
describe("row inference — the type argument is not needed", () => {
|
|
255
|
+
it("a registered \"app.model\" string resolves its row type", () => {
|
|
256
|
+
type TerminalRow = RowForKey<"airports.terminal">;
|
|
257
|
+
const row: TerminalRow = { id: 1, label: "T1", airport: 2 };
|
|
258
|
+
// @ts-expect-error — `label` is required on the registered row type
|
|
259
|
+
const missing: TerminalRow = { id: 1, airport: 2 };
|
|
260
|
+
expect([row, missing]).toBeDefined();
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
it("a resource() value derives its row type from its fields", () => {
|
|
264
|
+
const Flight = resource("airports", "flight", {
|
|
265
|
+
number: s.string({ maxLength: 8 }),
|
|
266
|
+
seats: s.int(),
|
|
267
|
+
gate: s.string({ maxLength: 5, null: true }),
|
|
268
|
+
active: s.bool(),
|
|
269
|
+
});
|
|
270
|
+
type FlightRow = import("../src/define").RowOf<typeof Flight>;
|
|
271
|
+
const row: FlightRow = {
|
|
272
|
+
id: 1,
|
|
273
|
+
number: "BA1",
|
|
274
|
+
seats: 180,
|
|
275
|
+
gate: null, // `null: true` → `string | null`
|
|
276
|
+
active: true,
|
|
277
|
+
};
|
|
278
|
+
// @ts-expect-error — `seats` is a number
|
|
279
|
+
const wrong: FlightRow = { ...row, seats: "lots" };
|
|
280
|
+
// @ts-expect-error — `number` is not nullable
|
|
281
|
+
const wrongNull: FlightRow = { ...row, number: null };
|
|
282
|
+
expect([row, wrong, wrongNull]).toBeDefined();
|
|
283
|
+
});
|
|
284
|
+
|
|
285
|
+
// Type-level only — never executed (useData is a React hook).
|
|
286
|
+
function _typeOnly() {
|
|
287
|
+
const terminals = useData("airports.terminal");
|
|
288
|
+
const rows: Array<{ id: number; label: string; airport: number }> | undefined =
|
|
289
|
+
terminals.data;
|
|
290
|
+
// @ts-expect-error — rows are Terminal-shaped, not Airport-shaped
|
|
291
|
+
const wrong: Array<{ code: string }> | undefined = terminals.data;
|
|
292
|
+
return { rows, wrong };
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
it("keeps the explicit generic and unregistered strings working", () => {
|
|
296
|
+
expect(typeof _typeOnly).toBe("function");
|
|
297
|
+
function _fallbacks() {
|
|
298
|
+
interface IGate {
|
|
299
|
+
id: number;
|
|
300
|
+
number: string;
|
|
301
|
+
}
|
|
302
|
+
const explicit = useData<IGate>("airports.gate"); // unregistered → explicit
|
|
303
|
+
const gates: IGate[] | undefined = explicit.data;
|
|
304
|
+
const loose = useData("airports.gate"); // unregistered, no generic → any
|
|
305
|
+
const anything: undefined | Array<{ whatever: boolean }> = loose.data;
|
|
306
|
+
return { gates, anything };
|
|
307
|
+
}
|
|
308
|
+
expect(typeof _fallbacks).toBe("function");
|
|
309
|
+
});
|
|
310
|
+
});
|
|
311
|
+
|
|
312
|
+
describe("rastack compile — the emitted rastack-env.d.ts registry", () => {
|
|
313
|
+
const workRoot = join(__dirname, "registry-fixtures");
|
|
314
|
+
const resourcesDir = join(workRoot, "resources");
|
|
315
|
+
const outDir = join(workRoot, ".rastack");
|
|
316
|
+
|
|
317
|
+
beforeAll(() => {
|
|
318
|
+
mkdirSync(resourcesDir, { recursive: true });
|
|
319
|
+
writeFileSync(
|
|
320
|
+
join(resourcesDir, "entities.ts"),
|
|
321
|
+
`
|
|
322
|
+
export class Airport {
|
|
323
|
+
code!: string;
|
|
324
|
+
name!: string;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// Not exported — cannot be imported by the registry, so it is skipped.
|
|
328
|
+
class Secret {
|
|
329
|
+
token!: string;
|
|
330
|
+
}
|
|
331
|
+
export const _root = [Airport, Secret];
|
|
332
|
+
|
|
333
|
+
export interface Terminal {
|
|
334
|
+
id: number;
|
|
335
|
+
label: string;
|
|
336
|
+
}
|
|
337
|
+
`,
|
|
338
|
+
);
|
|
339
|
+
writeFileSync(
|
|
340
|
+
join(resourcesDir, "flights.ts"),
|
|
341
|
+
`
|
|
342
|
+
import { resource, s } from "rastack/define";
|
|
343
|
+
|
|
344
|
+
export const Flight = resource("airports", "flight", {
|
|
345
|
+
number: s.string({ maxLength: 8 }),
|
|
346
|
+
});
|
|
347
|
+
`,
|
|
348
|
+
);
|
|
349
|
+
// The dotted string argument roots the Terminal interface — no type
|
|
350
|
+
// argument, no JSDoc tag.
|
|
351
|
+
writeFileSync(
|
|
352
|
+
join(workRoot, "screen.tsx"),
|
|
353
|
+
`
|
|
354
|
+
export function Screen() {
|
|
355
|
+
const terminals = useData("entities.terminal");
|
|
356
|
+
return terminals;
|
|
357
|
+
}
|
|
358
|
+
declare function useData(key: string): unknown;
|
|
359
|
+
`,
|
|
360
|
+
);
|
|
361
|
+
});
|
|
362
|
+
|
|
363
|
+
afterAll(() => {
|
|
364
|
+
rmSync(workRoot, { recursive: true, force: true });
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
it("roots interfaces from dotted string hook arguments and registers every exported entity", () => {
|
|
368
|
+
const result = compile(workRoot, outDir);
|
|
369
|
+
|
|
370
|
+
// The string argument rooted the interface into the manifest…
|
|
371
|
+
expect(
|
|
372
|
+
result.manifest.resources.some(
|
|
373
|
+
(r) => r.app === "entities" && r.model === "terminal",
|
|
374
|
+
),
|
|
375
|
+
).toBe(true);
|
|
376
|
+
|
|
377
|
+
// …and the registry maps keys to the caller's own types.
|
|
378
|
+
const envPath = join(outDir, "rastack-env.d.ts");
|
|
379
|
+
expect(result.files).toContain(envPath);
|
|
380
|
+
const dts = readFileSync(envPath, "utf8");
|
|
381
|
+
expect(dts).toContain('declare module "rastack/hooks/registry"');
|
|
382
|
+
expect(dts).toContain(
|
|
383
|
+
'"entities.airport": import("../resources/entities").Airport;',
|
|
384
|
+
);
|
|
385
|
+
expect(dts).toContain(
|
|
386
|
+
'"entities.terminal": import("../resources/entities").Terminal;',
|
|
387
|
+
);
|
|
388
|
+
// DSL consts register through RowOf so string refs infer for them too.
|
|
389
|
+
expect(dts).toContain(
|
|
390
|
+
'"airports.flight": import("rastack/define").RowOf<typeof import("../resources/flights").Flight>;',
|
|
391
|
+
);
|
|
392
|
+
// Unexported declarations are skipped.
|
|
393
|
+
expect(dts).not.toContain("Secret");
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
it("emits no registry when nothing is exported", () => {
|
|
397
|
+
const emptyDir = join(workRoot, "empty");
|
|
398
|
+
mkdirSync(join(emptyDir, "src"), { recursive: true });
|
|
399
|
+
writeFileSync(
|
|
400
|
+
join(emptyDir, "src", "none.ts"),
|
|
401
|
+
`export const nothing = 1;\n`,
|
|
402
|
+
);
|
|
403
|
+
const out = join(emptyDir, "out");
|
|
404
|
+
compile(emptyDir, out);
|
|
405
|
+
expect(existsSync(join(out, "rastack-env.d.ts"))).toBe(false);
|
|
406
|
+
});
|
|
407
|
+
});
|
package/wasm/rastack_wasm.js
CHANGED
|
@@ -375,7 +375,7 @@ function __wbg_get_imports() {
|
|
|
375
375
|
return ret;
|
|
376
376
|
},
|
|
377
377
|
__wbindgen_cast_0000000000000001: function(arg0, arg1) {
|
|
378
|
-
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx:
|
|
378
|
+
// Cast intrinsic for `Closure(Closure { owned: true, function: Function { arguments: [Externref], shim_idx: 85, ret: Result(Unit), inner_ret: Some(Result(Unit)) }, mutable: true }) -> Externref`.
|
|
379
379
|
const ret = makeMutClosure(arg0, arg1, wasm_bindgen_1a7aa9db5392c486___convert__closures_____invoke___wasm_bindgen_1a7aa9db5392c486___JsValue__core_7d5f0a2ba6a62c33___result__Result_____wasm_bindgen_1a7aa9db5392c486___JsError___true_);
|
|
380
380
|
return ret;
|
|
381
381
|
},
|
|
Binary file
|