@tailorkit/app 0.1.0-beta.23 → 0.1.0-beta.24
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 +111 -0
- package/dist/builder/database-paths.d.ts +4 -0
- package/dist/builder/define-view.d.ts +3 -0
- package/dist/builder/file-routes.d.ts +34 -0
- package/dist/builder/index.d.ts +1 -0
- package/dist/builder.js +521 -90
- package/dist/{chunk-7NOEYJOB.js → chunk-ANTVMHDZ.js} +28 -4
- package/dist/{chunk-GVB2PAK7.js → chunk-DA2TE2FW.js} +0 -1
- package/dist/{chunk-DEU6RITM.js → chunk-L5ECQGR7.js} +1 -6
- package/dist/chunk-LIPODQ7B.js +307 -0
- package/dist/chunk-Z3TAZHOT.js +437 -0
- package/dist/client-connection.js +14 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.js +13 -7
- package/dist/config/config.d.ts +2 -16
- package/dist/config-loader.js +2 -2
- package/dist/config.js +1 -1
- package/dist/database/definition.d.ts +8 -0
- package/dist/database/types.d.ts +5 -4
- package/dist/index.js +16 -8
- package/dist/routing.d.ts +34 -0
- package/dist/server/builder.d.ts +18 -13
- package/dist/server/bundle.d.ts +1 -1
- package/dist/server/functions.d.ts +15 -8
- package/dist/server.d.ts +2 -0
- package/dist/server.js +3 -1
- package/dist/views.d.ts +10 -24
- package/package.json +5 -1
- package/dist/chunk-LQJEPSUZ.js +0 -647
package/dist/builder.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
loadTailorKitConfig
|
|
3
|
-
} from "./chunk-
|
|
4
|
-
import "./chunk-
|
|
3
|
+
} from "./chunk-L5ECQGR7.js";
|
|
4
|
+
import "./chunk-DA2TE2FW.js";
|
|
5
5
|
|
|
6
6
|
// src/builder/index.ts
|
|
7
|
-
import
|
|
7
|
+
import path9 from "path";
|
|
8
8
|
import { createRequire as createRequire2 } from "module";
|
|
9
|
-
import { readFile as readFile4, realpath, writeFile as
|
|
9
|
+
import { readFile as readFile4, realpath, writeFile as writeFile3 } from "fs/promises";
|
|
10
10
|
|
|
11
11
|
// ../asset-delivery/dist/logo-validation.mjs
|
|
12
12
|
var maxLogoBytes = 262144;
|
|
@@ -136,7 +136,7 @@ var inspectClient = `
|
|
|
136
136
|
import { readFile } from "node:fs/promises";
|
|
137
137
|
const source = await readFile(process.argv[1], "utf8");
|
|
138
138
|
const { default: client } = await import("data:text/javascript;base64," + Buffer.from(source).toString("base64"));
|
|
139
|
-
if (!client?.slots || typeof client.slots !== "object") throw new Error("
|
|
139
|
+
if (!client?.slots || typeof client.slots !== "object") throw new Error("Invalid generated app client: missing slots");
|
|
140
140
|
const instanceResolvers = [];
|
|
141
141
|
const views = Object.entries(client.slots).flatMap(([slot, definitions]) =>
|
|
142
142
|
Object.entries(definitions).flatMap(([path, view]) => {
|
|
@@ -169,15 +169,15 @@ async function readClientManifest(filename) {
|
|
|
169
169
|
return { views, instanceResolvers: manifest.instanceResolvers };
|
|
170
170
|
} catch (error) {
|
|
171
171
|
throw new Error(
|
|
172
|
-
"Unable to read app views during the build. Keep browser-only side effects inside components or effects, and
|
|
172
|
+
"Unable to read app views during the build. Keep browser-only side effects inside components or effects. Check the default exports of your roots, layouts and .view.tsx files.",
|
|
173
173
|
{ cause: error }
|
|
174
174
|
);
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
// src/builder/server.ts
|
|
179
|
-
import { mkdir, mkdtemp as
|
|
180
|
-
import
|
|
179
|
+
import { mkdir as mkdir2, mkdtemp as mkdtemp3, writeFile as writeFile2, cp, rm as rm3 } from "fs/promises";
|
|
180
|
+
import path7 from "path";
|
|
181
181
|
import { build } from "vite";
|
|
182
182
|
|
|
183
183
|
// src/builder/migrations.ts
|
|
@@ -219,24 +219,35 @@ async function readAppMigrations(directory, optional = false) {
|
|
|
219
219
|
// src/server/bundle.ts
|
|
220
220
|
var runtimeManifest = {
|
|
221
221
|
apiVersion: 1,
|
|
222
|
-
requires: ["database", "actions"]
|
|
222
|
+
requires: ["database", "actions", "database-relations"]
|
|
223
223
|
};
|
|
224
224
|
|
|
225
225
|
// src/builder/schema-check.ts
|
|
226
226
|
import { execFile as execFile2 } from "child_process";
|
|
227
227
|
import { access as access2, mkdtemp, readFile as readFile2, readdir as readdir2, rm } from "fs/promises";
|
|
228
228
|
import { tmpdir } from "os";
|
|
229
|
-
import
|
|
229
|
+
import path4 from "path";
|
|
230
230
|
import { promisify as promisify2 } from "util";
|
|
231
231
|
|
|
232
232
|
// src/builder/drizzle.ts
|
|
233
233
|
import { access } from "fs/promises";
|
|
234
234
|
import { createRequire } from "module";
|
|
235
|
+
import path3 from "path";
|
|
236
|
+
|
|
237
|
+
// src/builder/database-paths.ts
|
|
235
238
|
import path2 from "path";
|
|
239
|
+
function appDatabasePaths(root, migrations) {
|
|
240
|
+
return {
|
|
241
|
+
schema: path2.join(root, "src/db/schema.ts"),
|
|
242
|
+
migrations: path2.resolve(root, migrations ?? "./src/db/migrations")
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// src/builder/drizzle.ts
|
|
236
247
|
async function drizzleGenerateArguments(root, output, name) {
|
|
237
|
-
const require2 = createRequire(
|
|
248
|
+
const require2 = createRequire(path3.join(root, "package.json"));
|
|
238
249
|
for (const directory of require2.resolve.paths("drizzle-kit") ?? []) {
|
|
239
|
-
const cli =
|
|
250
|
+
const cli = path3.join(directory, "drizzle-kit/bin.cjs");
|
|
240
251
|
if (await access(cli).then(() => true).catch(() => false)) {
|
|
241
252
|
return [
|
|
242
253
|
"--preserve-symlinks-main",
|
|
@@ -245,7 +256,7 @@ async function drizzleGenerateArguments(root, output, name) {
|
|
|
245
256
|
"--dialect",
|
|
246
257
|
"sqlite",
|
|
247
258
|
"--schema",
|
|
248
|
-
|
|
259
|
+
appDatabasePaths(root).schema,
|
|
249
260
|
"--out",
|
|
250
261
|
output,
|
|
251
262
|
...name === void 0 ? [] : ["--name", name]
|
|
@@ -266,7 +277,7 @@ async function snapshot(directory) {
|
|
|
266
277
|
});
|
|
267
278
|
const latest = entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort().at(-1);
|
|
268
279
|
if (!latest) return;
|
|
269
|
-
const filename =
|
|
280
|
+
const filename = path4.join(directory, latest, "snapshot.json");
|
|
270
281
|
const value = JSON.parse(await readFile2(filename, "utf8"));
|
|
271
282
|
if (value.version !== "7" || value.dialect !== "sqlite" || !Array.isArray(value.ddl)) {
|
|
272
283
|
throw new Error(
|
|
@@ -283,14 +294,14 @@ function canonical(value) {
|
|
|
283
294
|
return JSON.stringify(value);
|
|
284
295
|
}
|
|
285
296
|
async function checkAppSchema(root, migrationsDirectory) {
|
|
286
|
-
const schema =
|
|
297
|
+
const schema = appDatabasePaths(root).schema;
|
|
287
298
|
try {
|
|
288
299
|
await access2(schema);
|
|
289
300
|
} catch (error) {
|
|
290
301
|
if (error.code === "ENOENT") return;
|
|
291
302
|
throw error;
|
|
292
303
|
}
|
|
293
|
-
const temporary = await mkdtemp(
|
|
304
|
+
const temporary = await mkdtemp(path4.join(tmpdir(), "tailorkit-schema-check-"));
|
|
294
305
|
try {
|
|
295
306
|
const { stdout } = await run(
|
|
296
307
|
process.execPath,
|
|
@@ -303,14 +314,14 @@ async function checkAppSchema(root, migrationsDirectory) {
|
|
|
303
314
|
}
|
|
304
315
|
).catch((error) => {
|
|
305
316
|
throw new Error(
|
|
306
|
-
|
|
317
|
+
`Could not check the app database schema with Drizzle Kit. Check ${path4.relative(root, schema)} and your drizzle-kit/drizzle-orm dependencies.`,
|
|
307
318
|
{ cause: error }
|
|
308
319
|
);
|
|
309
320
|
});
|
|
310
321
|
const current = await snapshot(temporary);
|
|
311
322
|
if (!current && !stdout.includes("No schema changes")) {
|
|
312
323
|
throw new Error(
|
|
313
|
-
|
|
324
|
+
`Drizzle Kit did not produce a schema snapshot. Check ${path4.relative(root, schema)} and run tailorkit db generate.`
|
|
314
325
|
);
|
|
315
326
|
}
|
|
316
327
|
const saved = await snapshot(migrationsDirectory);
|
|
@@ -318,7 +329,7 @@ async function checkAppSchema(root, migrationsDirectory) {
|
|
|
318
329
|
const actual = (saved?.ddl ?? []).map(canonical).sort();
|
|
319
330
|
if (canonical(expected) !== canonical(actual)) {
|
|
320
331
|
throw new Error(
|
|
321
|
-
`App database migrations are missing or out of sync with
|
|
332
|
+
`App database migrations are missing or out of sync with ${path4.relative(root, schema)}. Run tailorkit db generate, commit the generated files in ${path4.relative(root, migrationsDirectory)}, then build again.`
|
|
322
333
|
);
|
|
323
334
|
}
|
|
324
335
|
} finally {
|
|
@@ -329,14 +340,432 @@ async function checkAppSchema(root, migrationsDirectory) {
|
|
|
329
340
|
// src/builder/instances.ts
|
|
330
341
|
import { createHash as createHash2 } from "crypto";
|
|
331
342
|
import { readFile as readFile3 } from "fs/promises";
|
|
332
|
-
import
|
|
333
|
-
import { parseSync, transformWithOxc } from "vite";
|
|
334
|
-
|
|
343
|
+
import path6 from "path";
|
|
344
|
+
import { parseSync as parseSync2, transformWithOxc } from "vite";
|
|
345
|
+
|
|
346
|
+
// src/builder/file-routes.ts
|
|
347
|
+
import { readdir as readdir3, mkdir, mkdtemp as mkdtemp2, writeFile, rm as rm2 } from "fs/promises";
|
|
348
|
+
import { existsSync, watch } from "fs";
|
|
349
|
+
import path5 from "path";
|
|
350
|
+
import { parseSync } from "vite";
|
|
351
|
+
|
|
352
|
+
// src/builder/define-view.ts
|
|
335
353
|
var clientImports = /* @__PURE__ */ new Set([
|
|
336
354
|
"tailorkit/client",
|
|
355
|
+
"tailorkit/app",
|
|
337
356
|
"tailorkit/app/client",
|
|
338
|
-
"@tailorkit/app/client"
|
|
357
|
+
"@tailorkit/app/client",
|
|
358
|
+
"@tailorkit/app"
|
|
339
359
|
]);
|
|
360
|
+
function createScope(parent, functionScope = false) {
|
|
361
|
+
return { parent, functionScope, bindings: /* @__PURE__ */ new Map() };
|
|
362
|
+
}
|
|
363
|
+
function bindingNames(node) {
|
|
364
|
+
if (!node) {
|
|
365
|
+
return [];
|
|
366
|
+
}
|
|
367
|
+
switch (node.type) {
|
|
368
|
+
case "Identifier": {
|
|
369
|
+
return [node.name];
|
|
370
|
+
}
|
|
371
|
+
case "RestElement": {
|
|
372
|
+
return bindingNames(node.argument);
|
|
373
|
+
}
|
|
374
|
+
case "AssignmentPattern": {
|
|
375
|
+
return bindingNames(node.left);
|
|
376
|
+
}
|
|
377
|
+
case "ArrayPattern": {
|
|
378
|
+
return node.elements.flatMap(bindingNames);
|
|
379
|
+
}
|
|
380
|
+
case "ObjectPattern": {
|
|
381
|
+
return node.properties.flatMap(
|
|
382
|
+
(property2) => bindingNames(property2.type === "Property" ? property2.value : property2.argument)
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
case "TSParameterProperty": {
|
|
386
|
+
return bindingNames(node.parameter);
|
|
387
|
+
}
|
|
388
|
+
default: {
|
|
389
|
+
return [];
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
function bind(node, scope) {
|
|
394
|
+
for (const name of bindingNames(node)) {
|
|
395
|
+
scope.bindings.set(name, "local");
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
function classScope(node, parent) {
|
|
399
|
+
if (node.type === "ClassDeclaration") {
|
|
400
|
+
bind(node.id, parent);
|
|
401
|
+
}
|
|
402
|
+
const scope = createScope(parent);
|
|
403
|
+
bind(node.id, scope);
|
|
404
|
+
return scope;
|
|
405
|
+
}
|
|
406
|
+
function resolve(scope, name) {
|
|
407
|
+
for (let current = scope; current; current = current.parent) {
|
|
408
|
+
if (current.bindings.has(name)) {
|
|
409
|
+
return current.bindings.get(name);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
function childNodes(node) {
|
|
414
|
+
return Object.values(node).flatMap((value) => {
|
|
415
|
+
const children2 = Array.isArray(value) ? value : [value];
|
|
416
|
+
return children2.filter(
|
|
417
|
+
(child) => !!child && typeof child === "object" && "type" in child
|
|
418
|
+
);
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
function bindImports(node, scope) {
|
|
422
|
+
const sdk = node.importKind !== "type" && clientImports.has(String(node.source.value));
|
|
423
|
+
for (const specifier of node.specifiers) {
|
|
424
|
+
let binding = "local";
|
|
425
|
+
if (sdk && specifier.type === "ImportNamespaceSpecifier") {
|
|
426
|
+
binding = "namespace";
|
|
427
|
+
} else if (sdk && specifier.type === "ImportSpecifier" && specifier.importKind !== "type" && specifier.imported.type === "Identifier" && specifier.imported.name === "defineView") {
|
|
428
|
+
binding = "view";
|
|
429
|
+
}
|
|
430
|
+
scope.bindings.set(specifier.local.name, binding);
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
function callScopes(program) {
|
|
434
|
+
const scopes = /* @__PURE__ */ new WeakMap();
|
|
435
|
+
function visitFunction(node, scope) {
|
|
436
|
+
if (node.type === "FunctionDeclaration") {
|
|
437
|
+
bind(node.id, scope);
|
|
438
|
+
}
|
|
439
|
+
const parameters = createScope(scope, true);
|
|
440
|
+
if (node.type !== "ArrowFunctionExpression") {
|
|
441
|
+
bind(node.id, parameters);
|
|
442
|
+
}
|
|
443
|
+
for (const parameter of node.params) {
|
|
444
|
+
bind(parameter, parameters);
|
|
445
|
+
}
|
|
446
|
+
for (const parameter of node.params) {
|
|
447
|
+
visit(parameter, parameters);
|
|
448
|
+
}
|
|
449
|
+
if (node.body) {
|
|
450
|
+
visit(node.body, createScope(parameters, true));
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
function bindVariables(node, scope) {
|
|
454
|
+
let target = scope;
|
|
455
|
+
if (node.kind === "var") {
|
|
456
|
+
while (!target.functionScope && target.parent) {
|
|
457
|
+
target = target.parent;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
for (const declaration of node.declarations) {
|
|
461
|
+
bind(declaration.id, target);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
function visit(node, scope) {
|
|
465
|
+
scopes.set(node, scope);
|
|
466
|
+
switch (node.type) {
|
|
467
|
+
case "ImportDeclaration": {
|
|
468
|
+
bindImports(node, scope);
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
case "VariableDeclaration": {
|
|
472
|
+
bindVariables(node, scope);
|
|
473
|
+
break;
|
|
474
|
+
}
|
|
475
|
+
case "FunctionDeclaration":
|
|
476
|
+
case "FunctionExpression":
|
|
477
|
+
case "ArrowFunctionExpression": {
|
|
478
|
+
visitFunction(node, scope);
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
case "ClassDeclaration":
|
|
482
|
+
case "ClassExpression": {
|
|
483
|
+
scope = classScope(node, scope);
|
|
484
|
+
break;
|
|
485
|
+
}
|
|
486
|
+
case "CatchClause": {
|
|
487
|
+
scope = createScope(scope);
|
|
488
|
+
bind(node.param, scope);
|
|
489
|
+
break;
|
|
490
|
+
}
|
|
491
|
+
case "SwitchStatement": {
|
|
492
|
+
visit(node.discriminant, scope);
|
|
493
|
+
scope = createScope(scope);
|
|
494
|
+
for (const branch of node.cases) {
|
|
495
|
+
visit(branch, scope);
|
|
496
|
+
}
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
case "BlockStatement":
|
|
500
|
+
case "ForStatement":
|
|
501
|
+
case "ForInStatement":
|
|
502
|
+
case "ForOfStatement": {
|
|
503
|
+
scope = createScope(scope);
|
|
504
|
+
break;
|
|
505
|
+
}
|
|
506
|
+
case "StaticBlock":
|
|
507
|
+
case "TSModuleBlock": {
|
|
508
|
+
scope = createScope(scope, true);
|
|
509
|
+
break;
|
|
510
|
+
}
|
|
511
|
+
case "TSEnumDeclaration":
|
|
512
|
+
case "TSModuleDeclaration": {
|
|
513
|
+
bind(node.id, scope);
|
|
514
|
+
break;
|
|
515
|
+
}
|
|
516
|
+
default: {
|
|
517
|
+
break;
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
for (const child of childNodes(node)) {
|
|
521
|
+
visit(child, scope);
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
visit(program, createScope(void 0, true));
|
|
525
|
+
return scopes;
|
|
526
|
+
}
|
|
527
|
+
function createDefineViewMatcher(program) {
|
|
528
|
+
const scopes = callScopes(program);
|
|
529
|
+
return (node) => {
|
|
530
|
+
if (node.type !== "CallExpression") {
|
|
531
|
+
return false;
|
|
532
|
+
}
|
|
533
|
+
const { callee } = node;
|
|
534
|
+
const scope = scopes.get(node);
|
|
535
|
+
if (callee.type === "Identifier") {
|
|
536
|
+
return resolve(scope, callee.name) === "view";
|
|
537
|
+
}
|
|
538
|
+
if (callee.type !== "MemberExpression" || callee.object.type !== "Identifier" || resolve(scope, callee.object.name) !== "namespace") {
|
|
539
|
+
return false;
|
|
540
|
+
}
|
|
541
|
+
return callee.computed ? callee.property.type === "Literal" && callee.property.value === "defineView" : callee.property.type === "Identifier" && callee.property.name === "defineView";
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
// src/builder/file-routes.ts
|
|
546
|
+
var clientRuntimeImport = "tailorkit:file-client-runtime";
|
|
547
|
+
function fileViewLocation(filename, root) {
|
|
548
|
+
const relative = path5.relative(path5.join(root, "src/slots"), filename).split(path5.sep);
|
|
549
|
+
if (relative.length < 2 || relative[0] === ".." || !filename.endsWith(".view.tsx")) {
|
|
550
|
+
return;
|
|
551
|
+
}
|
|
552
|
+
const [slot, ...routeSegments] = relative;
|
|
553
|
+
if (!slot) {
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
556
|
+
const basename = routeSegments.join("/").slice(0, -".view.tsx".length);
|
|
557
|
+
return { slot, path: routePath(basename, filename) };
|
|
558
|
+
}
|
|
559
|
+
function routePath(name, filename) {
|
|
560
|
+
const segments = name.split(/[./]/u);
|
|
561
|
+
if (segments.some((segment) => !segment || segment === "..")) {
|
|
562
|
+
throw new Error(`${filename} has an empty route segment. Use route.nested-route.view.tsx.`);
|
|
563
|
+
}
|
|
564
|
+
return `/${segments.join("/")}`;
|
|
565
|
+
}
|
|
566
|
+
function inferFileView(source, filename, root) {
|
|
567
|
+
const location = fileViewLocation(filename, root);
|
|
568
|
+
if (!location) {
|
|
569
|
+
return source;
|
|
570
|
+
}
|
|
571
|
+
const { slot, path: viewPath } = location;
|
|
572
|
+
const parsed = parseSync(filename, source);
|
|
573
|
+
if (parsed.errors.length) {
|
|
574
|
+
throw new Error(`${filename}: ${parsed.errors[0]?.message}`);
|
|
575
|
+
}
|
|
576
|
+
const isDefineViewCall = createDefineViewMatcher(parsed.program);
|
|
577
|
+
const edits = [];
|
|
578
|
+
function visit(node) {
|
|
579
|
+
if (isDefineViewCall(node)) {
|
|
580
|
+
const options = node.arguments[0];
|
|
581
|
+
if (options?.type !== "ObjectExpression") {
|
|
582
|
+
throw new Error(
|
|
583
|
+
`${filename}: file views require defineView with an inline options object.`
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
const properties = new Set(
|
|
587
|
+
options.properties.flatMap((property2) => {
|
|
588
|
+
if (property2.type !== "Property" || property2.computed) {
|
|
589
|
+
return [];
|
|
590
|
+
}
|
|
591
|
+
if (property2.key.type === "Identifier") {
|
|
592
|
+
return [property2.key.name];
|
|
593
|
+
}
|
|
594
|
+
if (property2.key.type === "Literal") {
|
|
595
|
+
return [String(property2.key.value)];
|
|
596
|
+
}
|
|
597
|
+
return [];
|
|
598
|
+
})
|
|
599
|
+
);
|
|
600
|
+
const defaults = [
|
|
601
|
+
!properties.has("slot") ? `slot: ${JSON.stringify(slot)},` : "",
|
|
602
|
+
!properties.has("view") ? `view: ${JSON.stringify(viewPath)},` : ""
|
|
603
|
+
].join("");
|
|
604
|
+
if (defaults) {
|
|
605
|
+
edits.push({ position: options.start + 1, text: defaults });
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
for (const value of Object.values(node)) {
|
|
609
|
+
const children2 = Array.isArray(value) ? value : [value];
|
|
610
|
+
for (const child of children2) {
|
|
611
|
+
if (child && typeof child === "object" && "type" in child) {
|
|
612
|
+
visit(child);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
visit(parsed.program);
|
|
618
|
+
for (const edit of edits.toSorted((a, b) => b.position - a.position)) {
|
|
619
|
+
source = source.slice(0, edit.position) + edit.text + source.slice(edit.position);
|
|
620
|
+
}
|
|
621
|
+
return source;
|
|
622
|
+
}
|
|
623
|
+
async function discoverFileRoutes(root) {
|
|
624
|
+
const views = [];
|
|
625
|
+
const roots = [];
|
|
626
|
+
const layouts = [];
|
|
627
|
+
const slotsDir = path5.join(root, "src/slots");
|
|
628
|
+
async function scan(directory, slot, prefix = "") {
|
|
629
|
+
const entries = await readdir3(directory, { withFileTypes: true }).catch(
|
|
630
|
+
(error) => {
|
|
631
|
+
if (error.code === "ENOENT") {
|
|
632
|
+
return [];
|
|
633
|
+
}
|
|
634
|
+
throw error;
|
|
635
|
+
}
|
|
636
|
+
);
|
|
637
|
+
for (const entry of entries.toSorted((a, b) => a.name.localeCompare(b.name))) {
|
|
638
|
+
const filename = path5.join(directory, entry.name);
|
|
639
|
+
if (entry.isDirectory()) {
|
|
640
|
+
await scan(filename, slot ?? entry.name, slot ? `${prefix}${entry.name}/` : "");
|
|
641
|
+
} else if (entry.isFile() && slot) {
|
|
642
|
+
if (entry.name.endsWith(".view.tsx")) {
|
|
643
|
+
fileViewLocation(filename, root);
|
|
644
|
+
views.push({ filename, slot });
|
|
645
|
+
} else if (entry.name === "root.tsx" && !prefix) {
|
|
646
|
+
roots.push({ filename, slot });
|
|
647
|
+
} else if (entry.name === "layout.tsx" || entry.name.endsWith(".layout.tsx")) {
|
|
648
|
+
const name = entry.name === "layout.tsx" ? prefix.replace(/\/$/u, "") : prefix + entry.name.slice(0, -".layout.tsx".length);
|
|
649
|
+
layouts.push({ filename, slot, path: name ? routePath(name, filename) : "/" });
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
await scan(slotsDir);
|
|
655
|
+
const rootFile = path5.join(root, "src/root.tsx");
|
|
656
|
+
return {
|
|
657
|
+
root: existsSync(rootFile) ? { filename: rootFile } : void 0,
|
|
658
|
+
roots,
|
|
659
|
+
layouts,
|
|
660
|
+
views
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
async function getClientSourceFiles(root) {
|
|
664
|
+
const discovered = await discoverFileRoutes(root);
|
|
665
|
+
const bindings = path5.join(root, "src/tailorkit.gen.ts");
|
|
666
|
+
return [
|
|
667
|
+
...discovered.root ? [discovered.root.filename] : [],
|
|
668
|
+
...discovered.roots.map((module) => module.filename),
|
|
669
|
+
...discovered.layouts.map((module) => module.filename),
|
|
670
|
+
...discovered.views.map((module) => module.filename),
|
|
671
|
+
...existsSync(bindings) ? [bindings] : []
|
|
672
|
+
];
|
|
673
|
+
}
|
|
674
|
+
async function fileClientSource(root) {
|
|
675
|
+
const discovered = await discoverFileRoutes(root);
|
|
676
|
+
const imports = [`import { createFileClient } from ${JSON.stringify(clientRuntimeImport)};`];
|
|
677
|
+
let index = 0;
|
|
678
|
+
function module(entry) {
|
|
679
|
+
const binding = `module${index++}`;
|
|
680
|
+
imports.push(`import ${binding} from ${JSON.stringify(entry.filename)};`);
|
|
681
|
+
return `{ filename: ${JSON.stringify(path5.relative(root, entry.filename))}, definition: ${binding}`;
|
|
682
|
+
}
|
|
683
|
+
const rootModule = discovered.root ? `${module(discovered.root)} }` : "undefined";
|
|
684
|
+
const roots = discovered.roots.map(
|
|
685
|
+
(entry) => `${module(entry)}, slot: ${JSON.stringify(entry.slot)} }`
|
|
686
|
+
);
|
|
687
|
+
const layouts = discovered.layouts.map(
|
|
688
|
+
(entry) => `${module(entry)}, slot: ${JSON.stringify(entry.slot)}, path: ${JSON.stringify(entry.path)} }`
|
|
689
|
+
);
|
|
690
|
+
const views = discovered.views.map(
|
|
691
|
+
(entry) => `${module(entry)}, slot: ${JSON.stringify(entry.slot)} }`
|
|
692
|
+
);
|
|
693
|
+
return `${imports.join("\n")}
|
|
694
|
+
export default createFileClient({ root: ${rootModule}, roots: [${roots.join(",")}], layouts: [${layouts.join(",")}], views: [${views.join(",")}] });`;
|
|
695
|
+
}
|
|
696
|
+
async function createFileRouteEntry(root, output, watching) {
|
|
697
|
+
let source = await fileClientSource(root);
|
|
698
|
+
const temporaryRoot = path5.join(output, "tmp");
|
|
699
|
+
await mkdir(temporaryRoot, { recursive: true });
|
|
700
|
+
const directory = await mkdtemp2(path5.join(temporaryRoot, "client-"));
|
|
701
|
+
const entry = path5.join(directory, "entry.ts");
|
|
702
|
+
await writeFile(entry, source);
|
|
703
|
+
let pending = Promise.resolve();
|
|
704
|
+
let closed = false;
|
|
705
|
+
let timer;
|
|
706
|
+
async function refresh() {
|
|
707
|
+
if (closed) {
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
710
|
+
let next;
|
|
711
|
+
try {
|
|
712
|
+
next = await fileClientSource(root);
|
|
713
|
+
} catch (error) {
|
|
714
|
+
next = `throw new Error(${JSON.stringify(error instanceof Error ? error.message : String(error))});`;
|
|
715
|
+
}
|
|
716
|
+
if (next === source) {
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
source = next;
|
|
720
|
+
await writeFile(entry, next);
|
|
721
|
+
}
|
|
722
|
+
const watcher = watching ? watch(path5.join(root, "src"), { recursive: true }, () => {
|
|
723
|
+
if (timer) {
|
|
724
|
+
clearTimeout(timer);
|
|
725
|
+
}
|
|
726
|
+
timer = setTimeout(() => {
|
|
727
|
+
pending = pending.then(refresh);
|
|
728
|
+
}, 25);
|
|
729
|
+
}) : void 0;
|
|
730
|
+
return {
|
|
731
|
+
entry,
|
|
732
|
+
async close() {
|
|
733
|
+
closed = true;
|
|
734
|
+
if (timer) {
|
|
735
|
+
clearTimeout(timer);
|
|
736
|
+
}
|
|
737
|
+
watcher?.close();
|
|
738
|
+
try {
|
|
739
|
+
await pending;
|
|
740
|
+
} finally {
|
|
741
|
+
await rm2(directory, { recursive: true, force: true });
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
};
|
|
745
|
+
}
|
|
746
|
+
function fileRoutesPlugin(root) {
|
|
747
|
+
return {
|
|
748
|
+
name: "tailorkit-file-routes",
|
|
749
|
+
enforce: "pre",
|
|
750
|
+
async resolveId(id) {
|
|
751
|
+
if (id !== clientRuntimeImport) {
|
|
752
|
+
return;
|
|
753
|
+
}
|
|
754
|
+
const importer = path5.join(root, "src/root.tsx");
|
|
755
|
+
return await this.resolve("tailorkit/client", importer, { skipSelf: true }) ?? this.resolve("@tailorkit/app/client", importer, { skipSelf: true });
|
|
756
|
+
},
|
|
757
|
+
transform(source, filename) {
|
|
758
|
+
if (!filename.endsWith(".view.tsx")) {
|
|
759
|
+
return;
|
|
760
|
+
}
|
|
761
|
+
const code = inferFileView(source, filename, root);
|
|
762
|
+
return code === source ? void 0 : { code, map: null };
|
|
763
|
+
}
|
|
764
|
+
};
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
// src/builder/instances.ts
|
|
768
|
+
var suffix = "?tailorkit-instances";
|
|
340
769
|
var browserGlobals = /* @__PURE__ */ new Set([
|
|
341
770
|
"window",
|
|
342
771
|
"document",
|
|
@@ -487,7 +916,7 @@ function property(node, name) {
|
|
|
487
916
|
);
|
|
488
917
|
}
|
|
489
918
|
function parse(filename, source) {
|
|
490
|
-
const result =
|
|
919
|
+
const result = parseSync2(filename, source);
|
|
491
920
|
if (result.errors.length)
|
|
492
921
|
throw new Error(`Unable to parse ${filename}: ${result.errors[0]?.message}`);
|
|
493
922
|
return result.program;
|
|
@@ -552,25 +981,19 @@ function renderImports(imports, needed, source, sideEffects) {
|
|
|
552
981
|
}).join("\n");
|
|
553
982
|
}
|
|
554
983
|
async function extractInstances(filename, source, root, includedNames) {
|
|
984
|
+
source = inferFileView(source, filename, root);
|
|
555
985
|
const transformed = await transformWithOxc(source, filename, {
|
|
556
986
|
jsx: { importSource: "preact" },
|
|
557
987
|
sourcemap: false
|
|
558
988
|
});
|
|
559
989
|
source = transformed.code;
|
|
560
990
|
const program = parse(filename.replace(/\.[^.]+$/u, ".js"), source);
|
|
561
|
-
const
|
|
562
|
-
for (const statement of program.body) {
|
|
563
|
-
if (statement.type !== "ImportDeclaration" || !clientImports.has(String(statement.source.value)))
|
|
564
|
-
continue;
|
|
565
|
-
for (const s of statement.specifiers) {
|
|
566
|
-
if (s.type === "ImportSpecifier" && s.imported.type === "Identifier" && s.imported.name === "defineView")
|
|
567
|
-
aliases.add(s.local.name);
|
|
568
|
-
}
|
|
569
|
-
}
|
|
991
|
+
const isDefineViewCall = createDefineViewMatcher(program);
|
|
570
992
|
let resolvers = [];
|
|
571
993
|
walk(program, (node, ancestors) => {
|
|
572
|
-
if (
|
|
994
|
+
if (!isDefineViewCall(node)) {
|
|
573
995
|
return;
|
|
996
|
+
}
|
|
574
997
|
const options = node.arguments[0];
|
|
575
998
|
if (options?.type !== "ObjectExpression") return;
|
|
576
999
|
const instances = property(options, "instances");
|
|
@@ -590,12 +1013,12 @@ async function extractInstances(filename, source, root, includedNames) {
|
|
|
590
1013
|
const config = instances.value;
|
|
591
1014
|
if (config.properties.some((p) => p.type !== "Property" || p.computed || p.kind !== "init"))
|
|
592
1015
|
fail("Instance options cannot contain spreads, getters or computed properties.");
|
|
593
|
-
const
|
|
1016
|
+
const resolve2 = property(config, "resolve");
|
|
594
1017
|
const schema = property(config, "dataSchema");
|
|
595
|
-
if (!
|
|
1018
|
+
if (!resolve2 || !schema || resolve2.method || !["ArrowFunctionExpression", "FunctionExpression"].includes(resolve2.value.type))
|
|
596
1019
|
fail("instances requires dataSchema and an inline resolve function.");
|
|
597
1020
|
const name = `i${createHash2("sha256").update(
|
|
598
|
-
`${
|
|
1021
|
+
`${path6.relative(root, filename).split(path6.sep).join("/")}\0${viewName}\0${view.value}`
|
|
599
1022
|
).digest("hex").slice(0, 24)}`;
|
|
600
1023
|
if (resolvers.some((r) => r.name === name))
|
|
601
1024
|
fail("Instance resolvers must have distinct module-level variable names.");
|
|
@@ -604,7 +1027,7 @@ async function extractInstances(filename, source, root, includedNames) {
|
|
|
604
1027
|
view: view.value,
|
|
605
1028
|
call: node,
|
|
606
1029
|
instances,
|
|
607
|
-
resolve,
|
|
1030
|
+
resolve: resolve2,
|
|
608
1031
|
schema
|
|
609
1032
|
});
|
|
610
1033
|
});
|
|
@@ -720,34 +1143,34 @@ function instanceServerBindings(modules, registrations) {
|
|
|
720
1143
|
}
|
|
721
1144
|
|
|
722
1145
|
// src/builder/server.ts
|
|
723
|
-
async function buildServer(loaded,
|
|
1146
|
+
async function buildServer(loaded, watch2 = false, buildOutDir, instances = [], registrations = []) {
|
|
724
1147
|
const config = loaded.config.server;
|
|
725
1148
|
if (!config) {
|
|
726
1149
|
return;
|
|
727
1150
|
}
|
|
728
|
-
const output = buildOutDir ??
|
|
729
|
-
const directory =
|
|
730
|
-
const migrationsDirectory =
|
|
731
|
-
const migrationsOutput =
|
|
732
|
-
const temporaryRoot =
|
|
1151
|
+
const output = buildOutDir ?? path7.resolve(loaded.root, loaded.config.build?.outDir ?? ".tailorkit");
|
|
1152
|
+
const directory = path7.join(output, "server");
|
|
1153
|
+
const migrationsDirectory = appDatabasePaths(loaded.root, config.migrations).migrations;
|
|
1154
|
+
const migrationsOutput = path7.join(output, "migrations");
|
|
1155
|
+
const temporaryRoot = path7.join(output, "tmp");
|
|
733
1156
|
validateServerBuildOutput(loaded, output);
|
|
734
|
-
await
|
|
735
|
-
await
|
|
736
|
-
await
|
|
737
|
-
const temporary = await
|
|
738
|
-
const entry =
|
|
1157
|
+
await rm3(directory, { recursive: true, force: true });
|
|
1158
|
+
await mkdir2(directory, { recursive: true });
|
|
1159
|
+
await mkdir2(temporaryRoot, { recursive: true });
|
|
1160
|
+
const temporary = await mkdtemp3(path7.join(temporaryRoot, "server-"));
|
|
1161
|
+
const entry = path7.join(temporary, "entry.mjs");
|
|
739
1162
|
let watching = false;
|
|
740
1163
|
let ready;
|
|
741
|
-
const initialBuild =
|
|
742
|
-
ready =
|
|
1164
|
+
const initialBuild = watch2 ? new Promise((resolve2) => {
|
|
1165
|
+
ready = resolve2;
|
|
743
1166
|
}) : void 0;
|
|
744
1167
|
try {
|
|
745
|
-
await
|
|
1168
|
+
await writeFile2(
|
|
746
1169
|
entry,
|
|
747
|
-
`${instances.length ? `import app from ${JSON.stringify(
|
|
1170
|
+
`${instances.length ? `import app from ${JSON.stringify(path7.resolve(loaded.root, config.entry ?? "src/server.ts"))};
|
|
748
1171
|
import { withInstanceResolvers } from "tailorkit/server";
|
|
749
1172
|
${instanceServerImports(instances)}
|
|
750
|
-
export default withInstanceResolvers(app, ${instanceServerBindings(instances, registrations)});` : `export { default } from ${JSON.stringify(
|
|
1173
|
+
export default withInstanceResolvers(app, ${instanceServerBindings(instances, registrations)});` : `export { default } from ${JSON.stringify(path7.resolve(loaded.root, config.entry ?? "src/server.ts"))};`}
|
|
751
1174
|
export { default as migrations } from "tailorkit:migrations";
|
|
752
1175
|
export const runtimeManifest = ${JSON.stringify(runtimeManifest)};
|
|
753
1176
|
`
|
|
@@ -759,7 +1182,7 @@ export const runtimeManifest = ${JSON.stringify(runtimeManifest)};
|
|
|
759
1182
|
instanceServerPlugin(loaded.root, instances),
|
|
760
1183
|
{
|
|
761
1184
|
name: "tailorkit-app-migrations",
|
|
762
|
-
closeWatcher: () =>
|
|
1185
|
+
closeWatcher: () => rm3(temporary, { recursive: true, force: true }),
|
|
763
1186
|
resolveId(id) {
|
|
764
1187
|
if (id === "tailorkit:migrations") {
|
|
765
1188
|
return "\0tailorkit:migrations";
|
|
@@ -774,12 +1197,12 @@ export const runtimeManifest = ${JSON.stringify(runtimeManifest)};
|
|
|
774
1197
|
config.migrations === void 0
|
|
775
1198
|
);
|
|
776
1199
|
await checkAppSchema(loaded.root, migrationsDirectory);
|
|
777
|
-
this.addWatchFile(
|
|
1200
|
+
this.addWatchFile(appDatabasePaths(loaded.root).schema);
|
|
778
1201
|
for (const file of files) {
|
|
779
1202
|
this.addWatchFile(file);
|
|
780
1203
|
}
|
|
781
|
-
await
|
|
782
|
-
await
|
|
1204
|
+
await rm3(migrationsOutput, { recursive: true, force: true });
|
|
1205
|
+
await mkdir2(migrationsOutput, { recursive: true });
|
|
783
1206
|
await cp(migrationsDirectory, migrationsOutput, { recursive: true }).catch(
|
|
784
1207
|
(error) => {
|
|
785
1208
|
if (config.migrations === void 0 && error.code === "ENOENT") {
|
|
@@ -797,7 +1220,7 @@ export const runtimeManifest = ${JSON.stringify(runtimeManifest)};
|
|
|
797
1220
|
outDir: directory,
|
|
798
1221
|
emptyOutDir: false,
|
|
799
1222
|
target: "es2022",
|
|
800
|
-
watch:
|
|
1223
|
+
watch: watch2 ? {} : null,
|
|
801
1224
|
minify: "oxc",
|
|
802
1225
|
rollupOptions: {
|
|
803
1226
|
external: [],
|
|
@@ -811,8 +1234,8 @@ export const runtimeManifest = ${JSON.stringify(runtimeManifest)};
|
|
|
811
1234
|
},
|
|
812
1235
|
ssr: { noExternal: true }
|
|
813
1236
|
});
|
|
814
|
-
watching =
|
|
815
|
-
if (
|
|
1237
|
+
watching = watch2;
|
|
1238
|
+
if (watch2 && "on" in result && initialBuild) {
|
|
816
1239
|
try {
|
|
817
1240
|
await Promise.race([
|
|
818
1241
|
initialBuild,
|
|
@@ -830,25 +1253,25 @@ export const runtimeManifest = ${JSON.stringify(runtimeManifest)};
|
|
|
830
1253
|
}
|
|
831
1254
|
return result;
|
|
832
1255
|
} finally {
|
|
833
|
-
if (!watching) await
|
|
1256
|
+
if (!watching) await rm3(temporary, { recursive: true, force: true });
|
|
834
1257
|
}
|
|
835
1258
|
}
|
|
836
1259
|
function validateServerBuildOutput(loaded, output) {
|
|
837
1260
|
if (!loaded.config.server) return;
|
|
838
|
-
const migrationsDirectory =
|
|
1261
|
+
const migrationsDirectory = appDatabasePaths(
|
|
839
1262
|
loaded.root,
|
|
840
|
-
loaded.config.server.migrations
|
|
841
|
-
);
|
|
1263
|
+
loaded.config.server.migrations
|
|
1264
|
+
).migrations;
|
|
842
1265
|
for (const name of ["server", "client", "migrations", "tmp"]) {
|
|
843
|
-
if (overlaps(migrationsDirectory,
|
|
1266
|
+
if (overlaps(migrationsDirectory, path7.join(output, name))) {
|
|
844
1267
|
throw new Error("App build output must not overlap migration source");
|
|
845
1268
|
}
|
|
846
1269
|
}
|
|
847
1270
|
}
|
|
848
1271
|
function overlaps(source, destination) {
|
|
849
1272
|
const contains = (parent, child) => {
|
|
850
|
-
const relative =
|
|
851
|
-
return relative === "" || !
|
|
1273
|
+
const relative = path7.relative(parent, child);
|
|
1274
|
+
return relative === "" || !path7.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path7.sep}`);
|
|
852
1275
|
};
|
|
853
1276
|
return contains(source, destination) || contains(destination, source);
|
|
854
1277
|
}
|
|
@@ -856,7 +1279,7 @@ function overlaps(source, destination) {
|
|
|
856
1279
|
// src/builder/generate-migrations.ts
|
|
857
1280
|
import { spawn } from "child_process";
|
|
858
1281
|
import { access as access3 } from "fs/promises";
|
|
859
|
-
import
|
|
1282
|
+
import path8 from "path";
|
|
860
1283
|
async function generateAppMigrations(options = {}) {
|
|
861
1284
|
const loaded = await loadTailorKitConfig(options.configPath, options.cwd);
|
|
862
1285
|
if (!loaded.config.server) {
|
|
@@ -864,19 +1287,20 @@ async function generateAppMigrations(options = {}) {
|
|
|
864
1287
|
"Enable server: {} in tailorkit.config.ts before generating database migrations."
|
|
865
1288
|
);
|
|
866
1289
|
}
|
|
867
|
-
|
|
1290
|
+
const paths = appDatabasePaths(loaded.root, loaded.config.server.migrations);
|
|
1291
|
+
await access3(paths.schema).catch((error) => {
|
|
868
1292
|
throw new Error(
|
|
869
|
-
|
|
1293
|
+
`Define the app database schema in ${path8.relative(loaded.root, paths.schema)} before generating migrations.`,
|
|
870
1294
|
{ cause: error }
|
|
871
1295
|
);
|
|
872
1296
|
});
|
|
873
|
-
const directory =
|
|
1297
|
+
const directory = paths.migrations;
|
|
874
1298
|
const args = await drizzleGenerateArguments(loaded.root, directory, options.name);
|
|
875
|
-
await new Promise((
|
|
1299
|
+
await new Promise((resolve2, reject) => {
|
|
876
1300
|
const child = spawn(process.execPath, args, { cwd: loaded.root, stdio: "inherit" });
|
|
877
1301
|
child.once("error", reject);
|
|
878
1302
|
child.once("close", (code, signal) => {
|
|
879
|
-
if (code === 0)
|
|
1303
|
+
if (code === 0) resolve2();
|
|
880
1304
|
else reject(new Error(`Drizzle migration generation failed (${signal ?? code}).`));
|
|
881
1305
|
});
|
|
882
1306
|
});
|
|
@@ -890,19 +1314,20 @@ var preactPackageJsonModuleId = "\0tailorkit-preact-package-json";
|
|
|
890
1314
|
var buildApp = async (options = {}) => {
|
|
891
1315
|
const loaded = await loadTailorKitConfig(options.configPath, options.cwd);
|
|
892
1316
|
loaded.root = await realpath(loaded.root);
|
|
893
|
-
const
|
|
894
|
-
const serverEntry = path7.resolve(loaded.root, loaded.config.server?.entry ?? "src/server.ts");
|
|
1317
|
+
const serverEntry = path9.resolve(loaded.root, loaded.config.server?.entry ?? "src/server.ts");
|
|
895
1318
|
const outDir = options.outDir ?? loaded.config.build?.outDir ?? ".tailorkit";
|
|
896
1319
|
const preactVersion = getInstalledPreactVersion(loaded.root);
|
|
897
1320
|
assertSupportedPreactVersion(preactVersion);
|
|
898
|
-
const resolvedOutDir =
|
|
1321
|
+
const resolvedOutDir = path9.resolve(loaded.root, outDir);
|
|
899
1322
|
validateServerBuildOutput(loaded, resolvedOutDir);
|
|
900
|
-
const clientOutDir =
|
|
1323
|
+
const clientOutDir = path9.join(resolvedOutDir, "client");
|
|
1324
|
+
const fileEntry = await createFileRouteEntry(loaded.root, resolvedOutDir, Boolean(options.watch));
|
|
1325
|
+
const entry = fileEntry.entry;
|
|
901
1326
|
const instanceModules = /* @__PURE__ */ new Map();
|
|
902
1327
|
let serverWatcher;
|
|
903
1328
|
const writeBuildExtras = async () => {
|
|
904
1329
|
const { views, instanceResolvers } = await readClientManifest(
|
|
905
|
-
|
|
1330
|
+
path9.join(clientOutDir, "client.js")
|
|
906
1331
|
);
|
|
907
1332
|
const resolverNames = new Set(instanceResolvers.map((registration) => registration.resolver));
|
|
908
1333
|
const activeModules = [...instanceModules.values()].map((module) => ({
|
|
@@ -928,21 +1353,21 @@ var buildApp = async (options = {}) => {
|
|
|
928
1353
|
if (!configuredPath) {
|
|
929
1354
|
continue;
|
|
930
1355
|
}
|
|
931
|
-
const extension =
|
|
1356
|
+
const extension = path9.extname(configuredPath).toLowerCase().slice(1);
|
|
932
1357
|
const contentType = { png: "image/png", svg: "image/svg+xml", webp: "image/webp" }[extension];
|
|
933
1358
|
if (!contentType) {
|
|
934
1359
|
throw new Error(`The ${variant} logo must be an SVG, PNG, or WebP file.`);
|
|
935
1360
|
}
|
|
936
|
-
const content = await readFile4(
|
|
1361
|
+
const content = await readFile4(path9.resolve(loaded.root, configuredPath));
|
|
937
1362
|
validateLogoAsset(content, contentType);
|
|
938
1363
|
const filename = `logo-${variant}.${extension}`;
|
|
939
|
-
await
|
|
1364
|
+
await writeFile3(path9.join(clientOutDir, filename), content);
|
|
940
1365
|
logoManifest[variant] = `client/${filename}`;
|
|
941
1366
|
}
|
|
942
|
-
await
|
|
1367
|
+
await writeFile3(path9.join(clientOutDir, "views.json"), `${JSON.stringify(views)}
|
|
943
1368
|
`);
|
|
944
|
-
await
|
|
945
|
-
|
|
1369
|
+
await writeFile3(
|
|
1370
|
+
path9.join(resolvedOutDir, "tailorkit-upload.json"),
|
|
946
1371
|
`${JSON.stringify(createTailorKitUploadManifest(logoManifest, Boolean(loaded.config.server), views), null, 2)}
|
|
947
1372
|
`,
|
|
948
1373
|
"utf-8"
|
|
@@ -950,8 +1375,8 @@ var buildApp = async (options = {}) => {
|
|
|
950
1375
|
};
|
|
951
1376
|
let firstBuildDone;
|
|
952
1377
|
let firstBuildFailed;
|
|
953
|
-
const firstBuild = new Promise((
|
|
954
|
-
firstBuildDone =
|
|
1378
|
+
const firstBuild = new Promise((resolve2, reject) => {
|
|
1379
|
+
firstBuildDone = resolve2;
|
|
955
1380
|
firstBuildFailed = reject;
|
|
956
1381
|
});
|
|
957
1382
|
if (!options.watch) {
|
|
@@ -994,6 +1419,7 @@ var buildApp = async (options = {}) => {
|
|
|
994
1419
|
mode: options.mode,
|
|
995
1420
|
oxc: { jsx: { importSource: "preact" } },
|
|
996
1421
|
plugins: [
|
|
1422
|
+
fileRoutesPlugin(loaded.root),
|
|
997
1423
|
instanceExtractionPlugin(loaded.root, Boolean(loaded.config.server), instanceModules),
|
|
998
1424
|
{
|
|
999
1425
|
name: "tailorkit-browser-server-boundary",
|
|
@@ -1001,7 +1427,7 @@ var buildApp = async (options = {}) => {
|
|
|
1001
1427
|
async resolveId(id, importer) {
|
|
1002
1428
|
if (/^(?:@tailorkit\/app\/server$|tailorkit\/(?:server|app\/server)$|effect(?:\/|$))/u.test(
|
|
1003
1429
|
id
|
|
1004
|
-
) || importer &&
|
|
1430
|
+
) || importer && path9.resolve(path9.dirname(importer), id) === serverEntry) {
|
|
1005
1431
|
throw new Error(
|
|
1006
1432
|
"App server implementations cannot be imported into a browser bundle. Import api from #tailorkit and server types with import type."
|
|
1007
1433
|
);
|
|
@@ -1043,6 +1469,7 @@ var buildApp = async (options = {}) => {
|
|
|
1043
1469
|
],
|
|
1044
1470
|
root: loaded.root
|
|
1045
1471
|
}).catch(async (error) => {
|
|
1472
|
+
await fileEntry.close();
|
|
1046
1473
|
if (serverWatcher && "close" in serverWatcher) await serverWatcher.close();
|
|
1047
1474
|
throw error;
|
|
1048
1475
|
});
|
|
@@ -1061,23 +1488,26 @@ var buildApp = async (options = {}) => {
|
|
|
1061
1488
|
await result.close();
|
|
1062
1489
|
}
|
|
1063
1490
|
if (serverWatcher && "close" in serverWatcher) await serverWatcher.close();
|
|
1491
|
+
await fileEntry.close();
|
|
1064
1492
|
throw error;
|
|
1065
1493
|
}
|
|
1066
|
-
if (result && "close" in result
|
|
1494
|
+
if (result && "close" in result) {
|
|
1067
1495
|
const clientWatcher = result;
|
|
1068
1496
|
return {
|
|
1069
1497
|
on: clientWatcher.on.bind(clientWatcher),
|
|
1070
1498
|
async close() {
|
|
1071
1499
|
await clientWatcher.close();
|
|
1072
1500
|
if (serverWatcher && "close" in serverWatcher) await serverWatcher.close();
|
|
1501
|
+
await fileEntry.close();
|
|
1073
1502
|
}
|
|
1074
1503
|
};
|
|
1075
1504
|
}
|
|
1076
1505
|
}
|
|
1506
|
+
await fileEntry.close();
|
|
1077
1507
|
return result;
|
|
1078
1508
|
};
|
|
1079
1509
|
function getInstalledPreactVersion(root) {
|
|
1080
|
-
const require2 = createRequire2(
|
|
1510
|
+
const require2 = createRequire2(path9.join(root, "package.json"));
|
|
1081
1511
|
try {
|
|
1082
1512
|
const packageJsonPath = require2.resolve("preact/package.json");
|
|
1083
1513
|
const packageJson = require2(packageJsonPath);
|
|
@@ -1096,5 +1526,6 @@ export {
|
|
|
1096
1526
|
buildApp,
|
|
1097
1527
|
createTailorKitUploadManifest,
|
|
1098
1528
|
generateAppMigrations,
|
|
1529
|
+
getClientSourceFiles,
|
|
1099
1530
|
tailorkitUploadManifestSchema
|
|
1100
1531
|
};
|