@kosmojs/lib 0.0.26 → 0.0.28
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/package.json +11 -11
- package/pkg/ast.d.ts +3 -3
- package/pkg/generators.d.ts +2 -56
- package/pkg/index.d.ts +1 -2
- package/pkg/index.js +353 -246
- package/pkg/index.js.map +4 -4
- package/pkg/paths.d.ts +8 -6
- package/pkg/render.d.ts +6 -11
- package/pkg/routes/base.d.ts +12 -44
- package/pkg/routes/index.d.ts +2 -1
- package/pkg/routes/nesting.d.ts +1 -1
- package/pkg/routes/paths.d.ts +25 -0
- package/pkg/routes/resolve.d.ts +1 -1
- package/pkg/routes/templates.d.ts +2 -0
- package/pkg/typebox.d.ts +1 -1
- package/pkg/vite.d.ts +4 -0
- package/pkg/defaults.d.ts +0 -14
- package/pkg/types.d.ts +0 -314
package/pkg/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/ast.ts
|
|
2
|
-
import { resolve } from "node:path";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
3
|
import { styleText } from "node:util";
|
|
4
4
|
import crc from "crc/crc32";
|
|
5
5
|
import { flattener } from "tfusion";
|
|
@@ -8,9 +8,10 @@ import {
|
|
|
8
8
|
SyntaxKind
|
|
9
9
|
} from "ts-morph";
|
|
10
10
|
import {
|
|
11
|
-
|
|
11
|
+
defaults,
|
|
12
12
|
RequestValidationTargets
|
|
13
|
-
} from "@kosmojs/
|
|
13
|
+
} from "@kosmojs/core";
|
|
14
|
+
import { HTTPMethods } from "@kosmojs/core/api";
|
|
14
15
|
var astFactory = () => {
|
|
15
16
|
const createProject = (opts) => new Project(opts);
|
|
16
17
|
const resolveRouteSignature = async (route, opts) => {
|
|
@@ -272,6 +273,21 @@ var astFactory = () => {
|
|
|
272
273
|
referencedFiles.push(...getReferencedFiles(defaultImport));
|
|
273
274
|
}
|
|
274
275
|
}
|
|
276
|
+
const namespaceImport = typeOnlyDeclaration ? declaration.getNamespaceImport() : void 0;
|
|
277
|
+
if (namespaceImport) {
|
|
278
|
+
const name = namespaceImport.getText();
|
|
279
|
+
const text = `import type * as ${name} from "${path}";`;
|
|
280
|
+
declarations.push({
|
|
281
|
+
importDeclaration: {
|
|
282
|
+
name,
|
|
283
|
+
path
|
|
284
|
+
},
|
|
285
|
+
text
|
|
286
|
+
});
|
|
287
|
+
if (referencedFiles) {
|
|
288
|
+
referencedFiles.push(...getReferencedFiles(namespaceImport));
|
|
289
|
+
}
|
|
290
|
+
}
|
|
275
291
|
for (const namedImport of declaration.getNamedImports()) {
|
|
276
292
|
if (namedImport.isTypeOnly() || typeOnlyDeclaration) {
|
|
277
293
|
const nameNode = namedImport.getNameNode();
|
|
@@ -356,9 +372,12 @@ var astFactory = () => {
|
|
|
356
372
|
const extractGenerics = (callExpression) => {
|
|
357
373
|
return callExpression.getTypeArguments();
|
|
358
374
|
};
|
|
359
|
-
const typeResolverFactory = ({ root }) => {
|
|
375
|
+
const typeResolverFactory = ({ root, name }) => {
|
|
360
376
|
const project = createProject({
|
|
361
|
-
tsConfigFilePath: resolve(
|
|
377
|
+
tsConfigFilePath: resolve(
|
|
378
|
+
root,
|
|
379
|
+
join(defaults.srcDir, name, "tsconfig.json")
|
|
380
|
+
),
|
|
362
381
|
skipAddingFilesFromTsConfig: true
|
|
363
382
|
});
|
|
364
383
|
const literalTypesResolver = (literalTypes, options) => {
|
|
@@ -398,136 +417,105 @@ var astFactory = () => {
|
|
|
398
417
|
};
|
|
399
418
|
};
|
|
400
419
|
|
|
401
|
-
// src/defaults.ts
|
|
402
|
-
var defaults = {
|
|
403
|
-
appPrefix: "~",
|
|
404
|
-
srcPrefix: "@",
|
|
405
|
-
libPrefix: "_",
|
|
406
|
-
coreDir: "core",
|
|
407
|
-
srcDir: "src",
|
|
408
|
-
libDir: "lib",
|
|
409
|
-
configDir: "config",
|
|
410
|
-
apiDir: "api",
|
|
411
|
-
pagesDir: "pages",
|
|
412
|
-
entryDir: "entry",
|
|
413
|
-
fetchDir: "fetch",
|
|
414
|
-
refineTypeName: "VRefine"
|
|
415
|
-
};
|
|
416
|
-
|
|
417
420
|
// src/generators.ts
|
|
418
|
-
|
|
419
|
-
var defineGenerator = (
|
|
420
|
-
const value = meta ? deepFreeze(structuredClone(meta)) : void 0;
|
|
421
|
-
const defineProperty = (fn) => {
|
|
422
|
-
Object.defineProperty(fn, GENERATOR_META, {
|
|
423
|
-
value,
|
|
424
|
-
enumerable: false,
|
|
425
|
-
writable: false,
|
|
426
|
-
configurable: false
|
|
427
|
-
});
|
|
428
|
-
return fn;
|
|
429
|
-
};
|
|
430
|
-
return defineProperty((...args) => {
|
|
431
|
-
return defineProperty(factory(...args));
|
|
432
|
-
});
|
|
433
|
-
};
|
|
434
|
-
var isGenerator = (fn) => {
|
|
435
|
-
return GENERATOR_META in fn;
|
|
436
|
-
};
|
|
437
|
-
var getGeneratorMeta = (fn) => {
|
|
438
|
-
return fn[GENERATOR_META];
|
|
439
|
-
};
|
|
421
|
+
import picomatch from "picomatch";
|
|
422
|
+
var defineGenerator = (f) => f;
|
|
440
423
|
var defineGeneratorFactory = (f) => f;
|
|
441
|
-
var
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
424
|
+
var createTemplateResolver = (customTemplates, defaultTemplate) => {
|
|
425
|
+
const templates = Object.entries({
|
|
426
|
+
...customTemplates
|
|
427
|
+
}).map(([pattern, template]) => [picomatch(pattern), template]);
|
|
428
|
+
return (pattern, entry) => {
|
|
429
|
+
const match = templates.find(([isMatch]) => isMatch(pattern));
|
|
430
|
+
if (!match) {
|
|
431
|
+
return defaultTemplate;
|
|
446
432
|
}
|
|
447
|
-
|
|
448
|
-
|
|
433
|
+
return typeof match[1] === "function" ? match[1](entry) : match[1];
|
|
434
|
+
};
|
|
449
435
|
};
|
|
450
436
|
|
|
451
437
|
// src/paths.ts
|
|
452
438
|
import { access, constants } from "node:fs/promises";
|
|
453
|
-
import { join, resolve as resolve2 } from "node:path";
|
|
454
|
-
|
|
455
|
-
return {
|
|
456
|
-
[`${defaults.appPrefix}/*`]: [`${prefix}/*`],
|
|
457
|
-
[`${defaults.srcPrefix}/*`]: [`${prefix}/${defaults.srcDir}/*`],
|
|
458
|
-
[`${defaults.libPrefix}/*`]: [
|
|
459
|
-
`${prefix}/${defaults.libDir}/${defaults.srcDir}/*`
|
|
460
|
-
]
|
|
461
|
-
};
|
|
462
|
-
};
|
|
439
|
+
import { join as join2, resolve as resolve2 } from "node:path";
|
|
440
|
+
import { defaults as defaults2 } from "@kosmojs/core";
|
|
463
441
|
var pathResolver = (sourceFolder) => {
|
|
464
442
|
const createPath = (...a) => {
|
|
465
|
-
return sourceFolder.root ? resolve2(sourceFolder.root,
|
|
443
|
+
return sourceFolder.root ? resolve2(sourceFolder.root, join2(...a)) : join2(...a);
|
|
466
444
|
};
|
|
467
445
|
const createImport = {
|
|
468
|
-
src(
|
|
469
|
-
return
|
|
446
|
+
src(a, { origin }) {
|
|
447
|
+
return origin === "src" ? join2(defaults2.srcPrefix, ...a) : join2(defaults2.appPrefix, defaults2.srcDir, sourceFolder.name, ...a);
|
|
448
|
+
},
|
|
449
|
+
config(a, o) {
|
|
450
|
+
return this.src([defaults2.configDir, ...a], o);
|
|
470
451
|
},
|
|
471
|
-
|
|
472
|
-
return this.src(
|
|
452
|
+
api(a, o) {
|
|
453
|
+
return this.src([defaults2.apiDir, ...a], o);
|
|
473
454
|
},
|
|
474
|
-
|
|
475
|
-
return this.src(
|
|
455
|
+
pages(a, o) {
|
|
456
|
+
return this.src([defaults2.pagesDir, ...a], o);
|
|
476
457
|
},
|
|
477
|
-
|
|
478
|
-
return
|
|
458
|
+
lib(a, { origin }) {
|
|
459
|
+
return origin === "src" ? join2(defaults2.libPrefix, ...a) : join2(defaults2.appPrefix, defaults2.libDir, sourceFolder.name, ...a);
|
|
479
460
|
},
|
|
480
|
-
|
|
481
|
-
return
|
|
461
|
+
libCore(a, o) {
|
|
462
|
+
return this.lib(["core", ...a], o);
|
|
482
463
|
},
|
|
483
|
-
libApi(
|
|
484
|
-
return this.lib(
|
|
464
|
+
libApi(a, o) {
|
|
465
|
+
return this.lib([defaults2.apiDir, ...a], o);
|
|
485
466
|
},
|
|
486
|
-
libEntry(
|
|
487
|
-
return this.lib(
|
|
467
|
+
libEntry(a, o) {
|
|
468
|
+
return this.lib([defaults2.entryDir, ...a], o);
|
|
488
469
|
}
|
|
489
470
|
};
|
|
490
471
|
return {
|
|
491
472
|
createPath: {
|
|
492
473
|
src(...a) {
|
|
493
|
-
return createPath(
|
|
474
|
+
return createPath(defaults2.srcDir, sourceFolder.name, ...a);
|
|
494
475
|
},
|
|
495
476
|
api(...a) {
|
|
496
|
-
return this.src(
|
|
477
|
+
return this.src(defaults2.apiDir, ...a);
|
|
497
478
|
},
|
|
498
479
|
pages(...a) {
|
|
499
|
-
return this.src(
|
|
480
|
+
return this.src(defaults2.pagesDir, ...a);
|
|
500
481
|
},
|
|
501
482
|
config(...a) {
|
|
502
|
-
return this.src(
|
|
483
|
+
return this.src(defaults2.configDir, ...a);
|
|
503
484
|
},
|
|
504
485
|
entry(...a) {
|
|
505
|
-
return this.src(
|
|
486
|
+
return this.src(defaults2.entryDir, ...a);
|
|
506
487
|
},
|
|
507
488
|
lib(...a) {
|
|
508
|
-
return createPath(
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
...a
|
|
513
|
-
);
|
|
489
|
+
return createPath(defaults2.libDir, sourceFolder.name, ...a);
|
|
490
|
+
},
|
|
491
|
+
libCore(...a) {
|
|
492
|
+
return this.lib("core", ...a);
|
|
514
493
|
},
|
|
515
494
|
libApi(...a) {
|
|
516
|
-
return this.lib(
|
|
495
|
+
return this.lib(defaults2.apiDir, ...a);
|
|
517
496
|
},
|
|
518
497
|
libEntry(...a) {
|
|
519
|
-
return this.lib(
|
|
498
|
+
return this.lib(defaults2.entryDir, ...a);
|
|
520
499
|
},
|
|
521
500
|
libPages(...a) {
|
|
522
|
-
return this.lib(
|
|
501
|
+
return this.lib(defaults2.pagesDir, ...a);
|
|
523
502
|
},
|
|
524
503
|
distDir(...a) {
|
|
525
504
|
return createPath(sourceFolder.distDir, sourceFolder.name, ...a);
|
|
526
505
|
}
|
|
527
506
|
},
|
|
528
507
|
createImport,
|
|
529
|
-
|
|
530
|
-
|
|
508
|
+
createImportHelpers(o) {
|
|
509
|
+
if (!["src", "lib"].includes(o?.origin)) {
|
|
510
|
+
throw new Error(
|
|
511
|
+
`createImportHelpers: required exactly one argument of shape { origin: "src|lib" }`
|
|
512
|
+
);
|
|
513
|
+
}
|
|
514
|
+
return {
|
|
515
|
+
createImport(key, ...a) {
|
|
516
|
+
return createImport[key](a.slice(0, -1), o);
|
|
517
|
+
}
|
|
518
|
+
};
|
|
531
519
|
}
|
|
532
520
|
};
|
|
533
521
|
};
|
|
@@ -542,7 +530,7 @@ var pathExists = async (path) => {
|
|
|
542
530
|
|
|
543
531
|
// src/render.ts
|
|
544
532
|
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
545
|
-
import { dirname, join as
|
|
533
|
+
import { dirname, join as join3 } from "node:path";
|
|
546
534
|
import crc2 from "crc/crc32";
|
|
547
535
|
import handlebars from "handlebars";
|
|
548
536
|
var render = (template, context, options) => {
|
|
@@ -568,114 +556,59 @@ var renderToFile = async (file, template, context, options) => {
|
|
|
568
556
|
await writeFile(file, content, "utf8");
|
|
569
557
|
};
|
|
570
558
|
var renderFactory = (options) => {
|
|
571
|
-
const
|
|
572
|
-
|
|
573
|
-
|
|
559
|
+
const createRenderer = (selfOoptions) => {
|
|
560
|
+
const renderer = handlebars.create();
|
|
561
|
+
renderer.registerPartial({
|
|
562
|
+
...options?.partials,
|
|
563
|
+
...selfOoptions?.partials
|
|
564
|
+
});
|
|
565
|
+
renderer.registerHelper({
|
|
566
|
+
...options?.helpers,
|
|
567
|
+
...selfOoptions?.helpers
|
|
568
|
+
});
|
|
569
|
+
return renderer;
|
|
570
|
+
};
|
|
574
571
|
return {
|
|
575
572
|
render(template, context, selfOoptions) {
|
|
576
573
|
return render(template, context, {
|
|
577
|
-
renderer,
|
|
578
574
|
...options,
|
|
579
|
-
...selfOoptions
|
|
575
|
+
...selfOoptions,
|
|
576
|
+
renderer: createRenderer(selfOoptions)
|
|
580
577
|
});
|
|
581
578
|
},
|
|
582
579
|
async renderToFile(file, template, context, selfOoptions) {
|
|
583
580
|
return renderToFile(
|
|
584
|
-
options?.outdir ?
|
|
581
|
+
options?.outdir ? join3(options.outdir, file) : file,
|
|
585
582
|
template,
|
|
586
583
|
context,
|
|
587
|
-
{
|
|
584
|
+
{
|
|
585
|
+
...options,
|
|
586
|
+
...selfOoptions,
|
|
587
|
+
renderer: createRenderer(selfOoptions)
|
|
588
|
+
}
|
|
588
589
|
);
|
|
589
590
|
}
|
|
590
591
|
};
|
|
591
592
|
};
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
}
|
|
598
|
-
};
|
|
593
|
+
|
|
594
|
+
// src/routes/index.ts
|
|
595
|
+
import {
|
|
596
|
+
defaults as defaults5
|
|
597
|
+
} from "@kosmojs/core";
|
|
599
598
|
|
|
600
599
|
// src/routes/base.ts
|
|
601
|
-
import { dirname as dirname2, join as
|
|
600
|
+
import { dirname as dirname2, join as join4, resolve as resolve3 } from "node:path";
|
|
602
601
|
import { styleText as styleText2 } from "node:util";
|
|
602
|
+
import crc4 from "crc/crc32";
|
|
603
|
+
import picomatch2 from "picomatch";
|
|
604
|
+
import { glob } from "tinyglobby";
|
|
605
|
+
import {
|
|
606
|
+
defaults as defaults3
|
|
607
|
+
} from "@kosmojs/core";
|
|
608
|
+
|
|
609
|
+
// src/routes/paths.ts
|
|
603
610
|
import crc3 from "crc/crc32";
|
|
604
611
|
import { parse } from "path-to-regexp";
|
|
605
|
-
import picomatch from "picomatch";
|
|
606
|
-
import { glob } from "tinyglobby";
|
|
607
|
-
var API_INDEX_BASENAME = "index";
|
|
608
|
-
var API_INDEX_PATTERN = `${API_INDEX_BASENAME}.ts`;
|
|
609
|
-
var API_USE_BASENAME = "use";
|
|
610
|
-
var API_USE_PATTERN = `${API_USE_BASENAME}.ts`;
|
|
611
|
-
var PAGE_INDEX_BASENAME = "index";
|
|
612
|
-
var PAGE_INDEX_PATTERN = `${PAGE_INDEX_BASENAME}.{tsx,vue}`;
|
|
613
|
-
var PAGE_LAYOUT_BASENAME = "layout";
|
|
614
|
-
var PAGE_LAYOUT_PATTERN = `${PAGE_LAYOUT_BASENAME}.{tsx,vue}`;
|
|
615
|
-
var ROUTE_FILE_PATTERNS = [
|
|
616
|
-
// match index files in api dir
|
|
617
|
-
`${defaults.apiDir}/**/${API_INDEX_PATTERN}`,
|
|
618
|
-
// match use files in api dir
|
|
619
|
-
`${defaults.apiDir}/**/${API_USE_PATTERN}`,
|
|
620
|
-
// match index files in pages dir
|
|
621
|
-
`${defaults.pagesDir}/**/${PAGE_INDEX_PATTERN}`,
|
|
622
|
-
// match layout files in pages dir
|
|
623
|
-
`${defaults.pagesDir}/**/${PAGE_LAYOUT_PATTERN}`
|
|
624
|
-
];
|
|
625
|
-
var scanRoutes = async (sourceFolder) => {
|
|
626
|
-
const { createPath } = pathResolver(sourceFolder);
|
|
627
|
-
return glob(ROUTE_FILE_PATTERNS, {
|
|
628
|
-
cwd: createPath.src(),
|
|
629
|
-
absolute: true,
|
|
630
|
-
onlyFiles: true,
|
|
631
|
-
followSymbolicLinks: false,
|
|
632
|
-
ignore: [
|
|
633
|
-
// ignore top-level matches, routes resides in folders, even index route
|
|
634
|
-
`${defaults.apiDir}/${API_INDEX_PATTERN}`,
|
|
635
|
-
`${defaults.apiDir}/${API_USE_PATTERN}`,
|
|
636
|
-
`${defaults.pagesDir}/${PAGE_INDEX_PATTERN}`,
|
|
637
|
-
`${defaults.pagesDir}/${PAGE_LAYOUT_PATTERN}`
|
|
638
|
-
]
|
|
639
|
-
});
|
|
640
|
-
};
|
|
641
|
-
var isRouteFile = (file, sourceFolder) => {
|
|
642
|
-
const [_sourceFolder, _folder, ...rest] = resolve3(sourceFolder.root, file).replace(`${sourceFolder.root}/${defaults.srcDir}/`, "").split("/");
|
|
643
|
-
if (!_folder || _sourceFolder !== sourceFolder.name || rest.length < 2) {
|
|
644
|
-
return false;
|
|
645
|
-
}
|
|
646
|
-
return picomatch.isMatch(join3(_folder, ...rest), ROUTE_FILE_PATTERNS) ? [_folder, rest.join("/")] : false;
|
|
647
|
-
};
|
|
648
|
-
var isApiRoute = (file) => {
|
|
649
|
-
return picomatch.matchBase(file, `**/${API_INDEX_PATTERN}`);
|
|
650
|
-
};
|
|
651
|
-
var isApiUse = (file) => {
|
|
652
|
-
return picomatch.matchBase(file, `**/${API_USE_PATTERN}`);
|
|
653
|
-
};
|
|
654
|
-
var isPageRoute = (file) => {
|
|
655
|
-
return picomatch.matchBase(file, `**/${PAGE_INDEX_PATTERN}`);
|
|
656
|
-
};
|
|
657
|
-
var isPageLayout = (file) => {
|
|
658
|
-
return picomatch.matchBase(file, `**/${PAGE_LAYOUT_PATTERN}`);
|
|
659
|
-
};
|
|
660
|
-
var createRouteEntry = (fileFullpath, sourceFolder) => {
|
|
661
|
-
const resolvedPaths = isRouteFile(fileFullpath, sourceFolder);
|
|
662
|
-
if (!resolvedPaths) {
|
|
663
|
-
return;
|
|
664
|
-
}
|
|
665
|
-
const [folder, file] = resolvedPaths;
|
|
666
|
-
const id = `${file.replace(/\W+/g, "_")}_${crc3(file)}`;
|
|
667
|
-
const name = dirname2(file);
|
|
668
|
-
try {
|
|
669
|
-
const [pathTokens, pathPattern] = pathTokensFactory(dirname2(file));
|
|
670
|
-
return { id, name, folder, file, fileFullpath, pathTokens, pathPattern };
|
|
671
|
-
} catch (error) {
|
|
672
|
-
console.error(
|
|
673
|
-
`\u2757${styleText2("red", "ERROR")}: Failed parsing path for "${styleText2("cyan", file)}"`
|
|
674
|
-
);
|
|
675
|
-
console.error(error);
|
|
676
|
-
return;
|
|
677
|
-
}
|
|
678
|
-
};
|
|
679
612
|
var pathTokensFactory = (path, {
|
|
680
613
|
transformStaticValue = normalizeStaticValue
|
|
681
614
|
} = {}) => {
|
|
@@ -765,7 +698,9 @@ var pathTokensFactory = (path, {
|
|
|
765
698
|
);
|
|
766
699
|
}
|
|
767
700
|
const pattern = patternTransforms.reduce((src, fn) => fn(src), orig);
|
|
768
|
-
const { tokens: tokens2 } = parse(
|
|
701
|
+
const { tokens: tokens2 } = parse(
|
|
702
|
+
pattern.replace(/\{[^}]*\}|(\+)/g, (m, p1) => p1 ? "\\+" : m)
|
|
703
|
+
);
|
|
769
704
|
const parts = extractParts(tokens2, (val) => {
|
|
770
705
|
return /\W/.test(val) || /^\d/.test(val) ? [val.replace(/^\d+|\W/g, "_"), crc3(orig)].join("_") : val;
|
|
771
706
|
});
|
|
@@ -781,70 +716,219 @@ var pathTokensFactory = (path, {
|
|
|
781
716
|
}
|
|
782
717
|
];
|
|
783
718
|
});
|
|
784
|
-
return
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
719
|
+
return tokens;
|
|
720
|
+
};
|
|
721
|
+
var createPathPattern = (tokens) => {
|
|
722
|
+
return tokens.map(({ pattern }, i) => {
|
|
723
|
+
const next = tokens[i + 1];
|
|
724
|
+
if (!next || next.pattern.includes("/")) {
|
|
725
|
+
return pattern;
|
|
726
|
+
}
|
|
727
|
+
const slashRequired = tokens.slice(i + 1).some((e) => {
|
|
728
|
+
return e.parts.some((e2) => {
|
|
729
|
+
return e2.type === "static" || e2.kind === "required";
|
|
795
730
|
});
|
|
796
|
-
|
|
797
|
-
}
|
|
798
|
-
|
|
731
|
+
});
|
|
732
|
+
return slashRequired ? `${pattern}/` : pattern;
|
|
733
|
+
}).join("");
|
|
734
|
+
};
|
|
735
|
+
var createHonoPattern = (tokens) => {
|
|
736
|
+
const staticValue = ({ value }) => {
|
|
737
|
+
return normalizeStaticValue(value);
|
|
738
|
+
};
|
|
739
|
+
const paramValue = (p) => {
|
|
740
|
+
if (p.kind === "splat") {
|
|
741
|
+
return `*`;
|
|
742
|
+
}
|
|
743
|
+
if (p.kind === "optional") {
|
|
744
|
+
return `:${p.name}?`;
|
|
745
|
+
}
|
|
746
|
+
return `:${p.name}`;
|
|
747
|
+
};
|
|
748
|
+
const escapeRegex = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
749
|
+
const tokensToRegex = (tokens2) => {
|
|
750
|
+
return tokens2.flatMap((t) => {
|
|
751
|
+
if (t.type === "text") {
|
|
752
|
+
return t.value === "/" ? [] : [escapeRegex(t.value)];
|
|
753
|
+
}
|
|
754
|
+
if (t.type === "wildcard") {
|
|
755
|
+
return [".+"];
|
|
756
|
+
}
|
|
757
|
+
if (t.type === "param") {
|
|
758
|
+
return ["[^/]+"];
|
|
759
|
+
}
|
|
760
|
+
if (t.type === "group") {
|
|
761
|
+
return [`(?:${tokensToRegex(t.tokens)})?`];
|
|
762
|
+
}
|
|
763
|
+
return [];
|
|
764
|
+
}).join("");
|
|
765
|
+
};
|
|
766
|
+
return tokens.flatMap((token, i) => {
|
|
767
|
+
if (token.kind === "static") {
|
|
768
|
+
return [staticValue(token.parts[0])];
|
|
769
|
+
}
|
|
770
|
+
if (token.kind === "param") {
|
|
771
|
+
return [paramValue(token.parts[0])];
|
|
772
|
+
}
|
|
773
|
+
const { tokens: tokens2 } = parse(token.pattern.replace(/\//g, ""));
|
|
774
|
+
const regex = tokensToRegex(tokens2);
|
|
775
|
+
return [`:_${i}{${regex}}`];
|
|
776
|
+
}).join("/");
|
|
799
777
|
};
|
|
800
778
|
var normalizeStaticValue = (value) => {
|
|
801
779
|
return value.replace(/\+/g, "\\\\+");
|
|
802
780
|
};
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
781
|
+
|
|
782
|
+
// src/routes/base.ts
|
|
783
|
+
var API_INDEX_BASENAME = "index";
|
|
784
|
+
var API_INDEX_PATTERN = `${API_INDEX_BASENAME}.ts`;
|
|
785
|
+
var API_USE_BASENAME = "use";
|
|
786
|
+
var API_USE_PATTERN = `${API_USE_BASENAME}.ts`;
|
|
787
|
+
var PAGE_INDEX_BASENAME = "index";
|
|
788
|
+
var PAGE_INDEX_PATTERN = `${PAGE_INDEX_BASENAME}.{tsx,vue,mdx,md}`;
|
|
789
|
+
var PAGE_LAYOUT_BASENAME = "layout";
|
|
790
|
+
var PAGE_LAYOUT_PATTERN = `${PAGE_LAYOUT_BASENAME}.{tsx,vue,mdx}`;
|
|
791
|
+
var ROUTE_FILE_PATTERNS = [
|
|
792
|
+
// match index files in api dir
|
|
793
|
+
`${defaults3.apiDir}/**/${API_INDEX_PATTERN}`,
|
|
794
|
+
// match use files in api dir
|
|
795
|
+
`${defaults3.apiDir}/**/${API_USE_PATTERN}`,
|
|
796
|
+
// match index files in pages dir
|
|
797
|
+
`${defaults3.pagesDir}/**/${PAGE_INDEX_PATTERN}`,
|
|
798
|
+
// match layout files in pages dir
|
|
799
|
+
`${defaults3.pagesDir}/**/${PAGE_LAYOUT_PATTERN}`
|
|
800
|
+
];
|
|
801
|
+
var scanRoutes = async (sourceFolder) => {
|
|
802
|
+
const { createPath } = pathResolver(sourceFolder);
|
|
803
|
+
return glob(ROUTE_FILE_PATTERNS, {
|
|
804
|
+
cwd: createPath.src(),
|
|
805
|
+
absolute: true,
|
|
806
|
+
onlyFiles: true,
|
|
807
|
+
followSymbolicLinks: false,
|
|
808
|
+
ignore: [
|
|
809
|
+
// ignore top-level matches, routes resides in folders, even index route
|
|
810
|
+
`${defaults3.apiDir}/${API_INDEX_PATTERN}`,
|
|
811
|
+
`${defaults3.apiDir}/${API_USE_PATTERN}`,
|
|
812
|
+
`${defaults3.pagesDir}/${PAGE_INDEX_PATTERN}`,
|
|
813
|
+
`${defaults3.pagesDir}/${PAGE_LAYOUT_PATTERN}`
|
|
814
|
+
]
|
|
815
|
+
});
|
|
816
|
+
};
|
|
817
|
+
var isRouteFile = (file, sourceFolder) => {
|
|
818
|
+
const [
|
|
819
|
+
// source folder name
|
|
820
|
+
_sourceFolder,
|
|
821
|
+
// route folder, api or pages
|
|
822
|
+
_folder,
|
|
823
|
+
...rest
|
|
824
|
+
] = resolve3(sourceFolder.root, file).replace(`${sourceFolder.root}/${defaults3.srcDir}/`, "").split("/");
|
|
825
|
+
if (!_folder || _sourceFolder !== sourceFolder.name || rest.length < 2) {
|
|
826
|
+
return false;
|
|
811
827
|
}
|
|
812
|
-
return
|
|
828
|
+
return picomatch2.isMatch(join4(_folder, ...rest), ROUTE_FILE_PATTERNS) ? [_folder, rest.join("/")] : false;
|
|
813
829
|
};
|
|
814
|
-
var
|
|
815
|
-
return {
|
|
816
|
-
required: 2,
|
|
817
|
-
optional: 1,
|
|
818
|
-
splat: 0
|
|
819
|
-
}[part.kind];
|
|
830
|
+
var isApiRoute = (file) => {
|
|
831
|
+
return picomatch2.matchBase(file, `**/${API_INDEX_PATTERN}`);
|
|
820
832
|
};
|
|
821
|
-
var
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
return
|
|
833
|
+
var isApiUse = (file) => {
|
|
834
|
+
return picomatch2.matchBase(file, `**/${API_USE_PATTERN}`);
|
|
835
|
+
};
|
|
836
|
+
var isPageRoute = (file) => {
|
|
837
|
+
return picomatch2.matchBase(file, `**/${PAGE_INDEX_PATTERN}`);
|
|
838
|
+
};
|
|
839
|
+
var isPageLayout = (file) => {
|
|
840
|
+
return picomatch2.matchBase(file, `**/${PAGE_LAYOUT_PATTERN}`);
|
|
841
|
+
};
|
|
842
|
+
var createRouteEntry = (fileFullpath, sourceFolder) => {
|
|
843
|
+
const resolvedPaths = isRouteFile(fileFullpath, sourceFolder);
|
|
844
|
+
if (!resolvedPaths) {
|
|
845
|
+
return;
|
|
846
|
+
}
|
|
847
|
+
const [folder, file] = resolvedPaths;
|
|
848
|
+
const id = `${file.replace(/\W+/g, "_")}_${crc4(file)}`;
|
|
849
|
+
const name = dirname2(file);
|
|
850
|
+
try {
|
|
851
|
+
const pathTokens = pathTokensFactory(dirname2(file));
|
|
852
|
+
return {
|
|
853
|
+
id,
|
|
854
|
+
name,
|
|
855
|
+
folder,
|
|
856
|
+
file,
|
|
857
|
+
fileFullpath,
|
|
858
|
+
pathTokens,
|
|
859
|
+
pathPattern: createPathPattern(pathTokens),
|
|
860
|
+
honoPattern: createHonoPattern(pathTokens)
|
|
861
|
+
};
|
|
862
|
+
} catch (error) {
|
|
863
|
+
console.error(
|
|
864
|
+
`\u2757${styleText2("red", "ERROR")}: Failed parsing path for "${styleText2("cyan", file)}"`
|
|
865
|
+
);
|
|
866
|
+
console.error(error);
|
|
867
|
+
return;
|
|
868
|
+
}
|
|
826
869
|
};
|
|
827
870
|
var segmentWeight = (token) => {
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
871
|
+
if (token.kind === "static") {
|
|
872
|
+
return 4;
|
|
873
|
+
}
|
|
874
|
+
if (token.kind === "mixed") {
|
|
875
|
+
let statics = 0;
|
|
876
|
+
let optionals = 0;
|
|
877
|
+
for (const part2 of token.parts) {
|
|
878
|
+
if (part2.type === "static") {
|
|
879
|
+
statics += 1;
|
|
880
|
+
} else if (part2.kind === "optional" || part2.kind === "splat") {
|
|
881
|
+
optionals += 1;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
return 3 + statics * 0.01 - optionals * 5e-3;
|
|
885
|
+
}
|
|
886
|
+
const part = token.parts[0];
|
|
887
|
+
switch (part.kind) {
|
|
888
|
+
case "required":
|
|
889
|
+
return 2;
|
|
890
|
+
case "optional":
|
|
891
|
+
return 1;
|
|
892
|
+
case "splat":
|
|
893
|
+
return 0;
|
|
894
|
+
}
|
|
833
895
|
};
|
|
834
|
-
var
|
|
835
|
-
|
|
896
|
+
var sortRoutes = (a, b) => {
|
|
897
|
+
const pairs = Array.from(
|
|
898
|
+
{ length: Math.max(a.pathTokens.length, b.pathTokens.length) },
|
|
899
|
+
(_, i) => [a.pathTokens[i], b.pathTokens[i]]
|
|
900
|
+
);
|
|
901
|
+
for (const [at, bt] of pairs) {
|
|
902
|
+
if (!at || !bt) {
|
|
903
|
+
const extra = at ?? bt;
|
|
904
|
+
const isSplat = extra?.kind === "param" ? extra.parts[0].kind === "splat" : false;
|
|
905
|
+
if (isSplat) {
|
|
906
|
+
return at ? 1 : -1;
|
|
907
|
+
}
|
|
908
|
+
return at ? -1 : 1;
|
|
909
|
+
}
|
|
910
|
+
const aw = segmentWeight(at);
|
|
911
|
+
const bw = segmentWeight(bt);
|
|
912
|
+
if (aw !== bw) {
|
|
913
|
+
return bw - aw;
|
|
914
|
+
}
|
|
915
|
+
}
|
|
916
|
+
return a.pathPattern.localeCompare(b.pathPattern);
|
|
836
917
|
};
|
|
837
918
|
|
|
838
919
|
// src/routes/resolve.ts
|
|
839
|
-
import { dirname as dirname3, join as
|
|
920
|
+
import { dirname as dirname3, join as join5, resolve as resolve4 } from "node:path";
|
|
840
921
|
import { styleText as styleText3 } from "node:util";
|
|
841
|
-
import
|
|
922
|
+
import crc5 from "crc/crc32";
|
|
842
923
|
import mimeTypes from "mime-types";
|
|
924
|
+
import {
|
|
925
|
+
defaults as defaults4
|
|
926
|
+
} from "@kosmojs/core";
|
|
843
927
|
|
|
844
|
-
// src/
|
|
928
|
+
// src/templates/resolved-types.hbs
|
|
845
929
|
var resolved_types_default = "{{#each resolvedTypes}}\nexport type {{name}} = {{text}};\n{{/each}}\n";
|
|
846
930
|
|
|
847
|
-
// src/
|
|
931
|
+
// src/templates/types.hbs
|
|
848
932
|
var types_default = '{{#each typeDeclarations}}{{text}}\n{{/each}}\n\nexport type {{params.id}} = {\n {{#each paramsSchema}}\n "{{name}}"{{#unless isRequired}}?{{/unless}}: {{#if refinement}}\n {{refinement.text}},\n {{else}}\n {{#if isSplat}}Array<string>{{else}}string{{/if}},\n {{/if}}\n {{/each}}\n};\n\n{{#each validationTypes}}export type {{id}} = {{text}};\n{{/each}}\n';
|
|
849
933
|
|
|
850
934
|
// src/routes/resolve.ts
|
|
@@ -852,12 +936,10 @@ var resolverFactory = (sourceFolder, cacheFactory) => {
|
|
|
852
936
|
const {
|
|
853
937
|
//
|
|
854
938
|
generators = [],
|
|
855
|
-
refineTypeName =
|
|
939
|
+
refineTypeName = defaults4.refineTypeName
|
|
856
940
|
} = sourceFolder.config;
|
|
857
941
|
const { typeResolverFactory, resolveRouteSignature } = astFactory();
|
|
858
|
-
const resolveTypes = generators.some(
|
|
859
|
-
(e) => getGeneratorMeta(e)?.resolveTypes
|
|
860
|
-
);
|
|
942
|
+
const resolveTypes = generators.some(({ meta }) => meta.resolveTypes);
|
|
861
943
|
const {
|
|
862
944
|
//
|
|
863
945
|
literalTypesResolver,
|
|
@@ -876,13 +958,23 @@ var resolverFactory = (sourceFolder, cacheFactory) => {
|
|
|
876
958
|
return { name, handler };
|
|
877
959
|
},
|
|
878
960
|
pageRouteResolver(entry) {
|
|
879
|
-
const {
|
|
961
|
+
const {
|
|
962
|
+
id,
|
|
963
|
+
name,
|
|
964
|
+
folder,
|
|
965
|
+
file,
|
|
966
|
+
fileFullpath,
|
|
967
|
+
pathTokens,
|
|
968
|
+
pathPattern,
|
|
969
|
+
honoPattern
|
|
970
|
+
} = entry;
|
|
880
971
|
const handler = async () => {
|
|
881
972
|
const entry2 = {
|
|
882
973
|
id,
|
|
883
974
|
name,
|
|
884
975
|
pathTokens,
|
|
885
976
|
pathPattern,
|
|
977
|
+
honoPattern,
|
|
886
978
|
params: {
|
|
887
979
|
schema: pathTokens.flatMap((e) => {
|
|
888
980
|
return e.parts.filter((p) => p.type === "param");
|
|
@@ -911,14 +1003,14 @@ var resolverFactory = (sourceFolder, cacheFactory) => {
|
|
|
911
1003
|
},
|
|
912
1004
|
apiRouteResolver(entry) {
|
|
913
1005
|
const {
|
|
914
|
-
//
|
|
915
1006
|
id,
|
|
916
1007
|
name,
|
|
917
1008
|
file,
|
|
918
1009
|
folder,
|
|
919
1010
|
fileFullpath,
|
|
920
1011
|
pathTokens,
|
|
921
|
-
pathPattern
|
|
1012
|
+
pathPattern,
|
|
1013
|
+
honoPattern
|
|
922
1014
|
} = entry;
|
|
923
1015
|
const handler = async (updatedFile) => {
|
|
924
1016
|
const paramsSchema = pathTokens.flatMap(
|
|
@@ -949,9 +1041,9 @@ var resolverFactory = (sourceFolder, cacheFactory) => {
|
|
|
949
1041
|
withReferencedFiles: true,
|
|
950
1042
|
sourceFile: getSourceFile(fileFullpath),
|
|
951
1043
|
relpathResolver(path) {
|
|
952
|
-
return
|
|
1044
|
+
return join5(
|
|
953
1045
|
sourceFolder.name,
|
|
954
|
-
|
|
1046
|
+
defaults4.apiDir,
|
|
955
1047
|
dirname3(file),
|
|
956
1048
|
path
|
|
957
1049
|
);
|
|
@@ -975,7 +1067,7 @@ var resolverFactory = (sourceFolder, cacheFactory) => {
|
|
|
975
1067
|
"types.ts"
|
|
976
1068
|
);
|
|
977
1069
|
const params = {
|
|
978
|
-
id: ["ParamsT",
|
|
1070
|
+
id: ["ParamsT", crc5(name)].join(""),
|
|
979
1071
|
schema: paramsSchema,
|
|
980
1072
|
resolvedType: void 0
|
|
981
1073
|
};
|
|
@@ -1109,6 +1201,7 @@ var resolverFactory = (sourceFolder, cacheFactory) => {
|
|
|
1109
1201
|
name,
|
|
1110
1202
|
pathTokens,
|
|
1111
1203
|
pathPattern,
|
|
1204
|
+
honoPattern,
|
|
1112
1205
|
params: cache.params,
|
|
1113
1206
|
numericParams: cache.numericParams,
|
|
1114
1207
|
optionalParams,
|
|
@@ -1234,13 +1327,13 @@ var routesFactory = async (sourceFolder, cacheFactory) => {
|
|
|
1234
1327
|
return entry ? [entry] : [];
|
|
1235
1328
|
});
|
|
1236
1329
|
for (const entry of entries) {
|
|
1237
|
-
if (entry.folder ===
|
|
1330
|
+
if (entry.folder === defaults5.apiDir) {
|
|
1238
1331
|
if (isApiRoute(entry.file)) {
|
|
1239
1332
|
resolvers.set(entry.fileFullpath, apiRouteResolver(entry));
|
|
1240
1333
|
} else if (isApiUse(entry.file)) {
|
|
1241
1334
|
resolvers.set(entry.fileFullpath, apiUseResolver(entry));
|
|
1242
1335
|
}
|
|
1243
|
-
} else if (entry.folder ===
|
|
1336
|
+
} else if (entry.folder === defaults5.pagesDir) {
|
|
1244
1337
|
if (isPageRoute(entry.file)) {
|
|
1245
1338
|
resolvers.set(entry.fileFullpath, pageRouteResolver(entry));
|
|
1246
1339
|
} else if (isPageLayout(entry.file)) {
|
|
@@ -1289,8 +1382,9 @@ var spinnerFactory = (startText) => {
|
|
|
1289
1382
|
var withSpinner = (text, pipe, spinner) => pipe(spinner || spinnerFactory(text));
|
|
1290
1383
|
|
|
1291
1384
|
// src/typebox.ts
|
|
1385
|
+
import { defaults as defaults6 } from "@kosmojs/core";
|
|
1292
1386
|
var typeboxLiteralText = (text, sourceFolder) => {
|
|
1293
|
-
const { refineTypeName =
|
|
1387
|
+
const { refineTypeName = defaults6.refineTypeName } = sourceFolder.config;
|
|
1294
1388
|
return [
|
|
1295
1389
|
// Escape backticks for safe use in template literals
|
|
1296
1390
|
[/(?<!\\)`/g, "\\`"],
|
|
@@ -1304,26 +1398,39 @@ var typeboxLiteralText = (text, sourceFolder) => {
|
|
|
1304
1398
|
[new RegExp(`\\b${refineTypeName}\\s*<`, "g"), "Options<"]
|
|
1305
1399
|
].reduce((text2, [a, b]) => text2.replace(a, b), text);
|
|
1306
1400
|
};
|
|
1401
|
+
|
|
1402
|
+
// src/vite.ts
|
|
1403
|
+
import { builtinModules } from "node:module";
|
|
1404
|
+
var nodePrefix = () => {
|
|
1405
|
+
return {
|
|
1406
|
+
name: "kosmojs:node-prefix",
|
|
1407
|
+
enforce: "pre",
|
|
1408
|
+
resolveId(source) {
|
|
1409
|
+
return builtinModules.includes(source) ? { id: `node:${source}`, external: true } : void 0;
|
|
1410
|
+
}
|
|
1411
|
+
};
|
|
1412
|
+
};
|
|
1413
|
+
var vitePlugins = {
|
|
1414
|
+
nodePrefix
|
|
1415
|
+
};
|
|
1307
1416
|
export {
|
|
1308
1417
|
API_INDEX_BASENAME,
|
|
1309
1418
|
API_INDEX_PATTERN,
|
|
1310
1419
|
API_USE_BASENAME,
|
|
1311
1420
|
API_USE_PATTERN,
|
|
1312
|
-
GENERATOR_META,
|
|
1313
1421
|
PAGE_INDEX_BASENAME,
|
|
1314
1422
|
PAGE_INDEX_PATTERN,
|
|
1315
1423
|
PAGE_LAYOUT_BASENAME,
|
|
1316
1424
|
PAGE_LAYOUT_PATTERN,
|
|
1317
1425
|
astFactory,
|
|
1426
|
+
createHonoPattern,
|
|
1427
|
+
createPathPattern,
|
|
1318
1428
|
createRouteEntry,
|
|
1319
|
-
|
|
1320
|
-
defaults,
|
|
1429
|
+
createTemplateResolver,
|
|
1321
1430
|
defineGenerator,
|
|
1322
1431
|
defineGeneratorFactory,
|
|
1323
|
-
getGeneratorMeta,
|
|
1324
1432
|
isApiRoute,
|
|
1325
1433
|
isApiUse,
|
|
1326
|
-
isGenerator,
|
|
1327
1434
|
isPageLayout,
|
|
1328
1435
|
isPageRoute,
|
|
1329
1436
|
isRouteFile,
|
|
@@ -1334,13 +1441,13 @@ export {
|
|
|
1334
1441
|
pathTokensFactory,
|
|
1335
1442
|
render,
|
|
1336
1443
|
renderFactory,
|
|
1337
|
-
renderHelpers,
|
|
1338
1444
|
renderToFile,
|
|
1339
1445
|
routesFactory,
|
|
1340
1446
|
scanRoutes,
|
|
1341
1447
|
sortRoutes,
|
|
1342
1448
|
spinnerFactory,
|
|
1343
1449
|
typeboxLiteralText,
|
|
1450
|
+
vitePlugins,
|
|
1344
1451
|
withSpinner
|
|
1345
1452
|
};
|
|
1346
1453
|
//# sourceMappingURL=index.js.map
|