@kuratchi/js 0.0.14 → 0.0.16
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 +135 -68
- package/dist/cli.js +80 -47
- package/dist/compiler/api-route-pipeline.d.ts +8 -0
- package/dist/compiler/api-route-pipeline.js +23 -0
- package/dist/compiler/asset-pipeline.d.ts +7 -0
- package/dist/compiler/asset-pipeline.js +33 -0
- package/dist/compiler/client-module-pipeline.d.ts +25 -0
- package/dist/compiler/client-module-pipeline.js +257 -0
- package/dist/compiler/compiler-shared.d.ts +55 -0
- package/dist/compiler/compiler-shared.js +4 -0
- package/dist/compiler/component-pipeline.d.ts +15 -0
- package/dist/compiler/component-pipeline.js +163 -0
- package/dist/compiler/config-reading.d.ts +11 -0
- package/dist/compiler/config-reading.js +323 -0
- package/dist/compiler/convention-discovery.d.ts +9 -0
- package/dist/compiler/convention-discovery.js +83 -0
- package/dist/compiler/durable-object-pipeline.d.ts +9 -0
- package/dist/compiler/durable-object-pipeline.js +255 -0
- package/dist/compiler/error-page-pipeline.d.ts +1 -0
- package/dist/compiler/error-page-pipeline.js +16 -0
- package/dist/compiler/import-linking.d.ts +36 -0
- package/dist/compiler/import-linking.js +139 -0
- package/dist/compiler/index.d.ts +3 -3
- package/dist/compiler/index.js +137 -3265
- package/dist/compiler/layout-pipeline.d.ts +31 -0
- package/dist/compiler/layout-pipeline.js +155 -0
- package/dist/compiler/page-route-pipeline.d.ts +16 -0
- package/dist/compiler/page-route-pipeline.js +62 -0
- package/dist/compiler/parser.d.ts +4 -0
- package/dist/compiler/parser.js +433 -51
- package/dist/compiler/root-layout-pipeline.d.ts +10 -0
- package/dist/compiler/root-layout-pipeline.js +517 -0
- package/dist/compiler/route-discovery.d.ts +7 -0
- package/dist/compiler/route-discovery.js +87 -0
- package/dist/compiler/route-pipeline.d.ts +57 -0
- package/dist/compiler/route-pipeline.js +296 -0
- package/dist/compiler/route-state-pipeline.d.ts +25 -0
- package/dist/compiler/route-state-pipeline.js +139 -0
- package/dist/compiler/routes-module-feature-blocks.d.ts +2 -0
- package/dist/compiler/routes-module-feature-blocks.js +330 -0
- package/dist/compiler/routes-module-pipeline.d.ts +2 -0
- package/dist/compiler/routes-module-pipeline.js +6 -0
- package/dist/compiler/routes-module-runtime-shell.d.ts +2 -0
- package/dist/compiler/routes-module-runtime-shell.js +81 -0
- package/dist/compiler/routes-module-types.d.ts +44 -0
- package/dist/compiler/routes-module-types.js +1 -0
- package/dist/compiler/script-transform.d.ts +16 -0
- package/dist/compiler/script-transform.js +218 -0
- package/dist/compiler/server-module-pipeline.d.ts +13 -0
- package/dist/compiler/server-module-pipeline.js +124 -0
- package/dist/compiler/template.d.ts +13 -1
- package/dist/compiler/template.js +323 -60
- package/dist/compiler/worker-output-pipeline.d.ts +13 -0
- package/dist/compiler/worker-output-pipeline.js +37 -0
- package/dist/compiler/wrangler-sync.d.ts +14 -0
- package/dist/compiler/wrangler-sync.js +185 -0
- package/dist/runtime/app.js +15 -3
- package/dist/runtime/generated-worker.d.ts +33 -0
- package/dist/runtime/generated-worker.js +412 -0
- package/dist/runtime/index.d.ts +2 -1
- package/dist/runtime/index.js +1 -0
- package/dist/runtime/router.d.ts +2 -1
- package/dist/runtime/router.js +12 -3
- package/dist/runtime/types.d.ts +8 -2
- package/package.json +5 -1
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { compileTemplate } from './template.js';
|
|
4
|
+
export function compileErrorPages(routesDir) {
|
|
5
|
+
const compiledErrorPages = new Map();
|
|
6
|
+
for (const file of fs.readdirSync(routesDir)) {
|
|
7
|
+
const match = file.match(/^(\d{3})\.html$/);
|
|
8
|
+
if (!match)
|
|
9
|
+
continue;
|
|
10
|
+
const status = parseInt(match[1], 10);
|
|
11
|
+
const source = fs.readFileSync(path.join(routesDir, file), 'utf-8');
|
|
12
|
+
const body = compileTemplate(source);
|
|
13
|
+
compiledErrorPages.set(status, `function __error_${status}(error) {\n ${body}\n return __html;\n}`);
|
|
14
|
+
}
|
|
15
|
+
return compiledErrorPages;
|
|
16
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export interface ImportBinding {
|
|
2
|
+
imported: string;
|
|
3
|
+
local: string;
|
|
4
|
+
}
|
|
5
|
+
export interface ParsedImportStatement {
|
|
6
|
+
bindings: ImportBinding[];
|
|
7
|
+
moduleSpecifier: string | null;
|
|
8
|
+
namespaceImport: string | null;
|
|
9
|
+
}
|
|
10
|
+
export interface RouteImportEntry {
|
|
11
|
+
line: string;
|
|
12
|
+
importerDir: string;
|
|
13
|
+
}
|
|
14
|
+
interface RouteQueryReference {
|
|
15
|
+
fnName: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function parseImportStatement(source: string): ParsedImportStatement;
|
|
18
|
+
export declare function collectReferencedIdentifiers(source: string): Set<string>;
|
|
19
|
+
export declare function parseNamedImportBindings(line: string): ImportBinding[];
|
|
20
|
+
export declare function filterImportsByNeededBindings(imports: string[], neededBindings: Set<string>): string[];
|
|
21
|
+
export declare function linkRouteServerImports(opts: {
|
|
22
|
+
routeServerImportEntries: RouteImportEntry[];
|
|
23
|
+
routeClientImportEntries: RouteImportEntry[];
|
|
24
|
+
actionFunctions: string[];
|
|
25
|
+
pollFunctions: string[];
|
|
26
|
+
dataGetQueries: RouteQueryReference[];
|
|
27
|
+
routeScriptReferenceSource: string;
|
|
28
|
+
resolveCompiledImportPath: (origPath: string, importerDir: string, outFileDir: string) => string;
|
|
29
|
+
outFileDir: string;
|
|
30
|
+
allocateModuleId: () => string;
|
|
31
|
+
}): {
|
|
32
|
+
fnToModule: Record<string, string>;
|
|
33
|
+
routeImportDecls: string[];
|
|
34
|
+
importStatements: string[];
|
|
35
|
+
};
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
export function parseImportStatement(source) {
|
|
3
|
+
const sourceFile = ts.createSourceFile('kuratchi-import.ts', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
4
|
+
const statement = sourceFile.statements.find(ts.isImportDeclaration);
|
|
5
|
+
if (!statement || !ts.isStringLiteral(statement.moduleSpecifier)) {
|
|
6
|
+
return { bindings: [], moduleSpecifier: null, namespaceImport: null };
|
|
7
|
+
}
|
|
8
|
+
const bindings = [];
|
|
9
|
+
let namespaceImport = null;
|
|
10
|
+
const clause = statement.importClause;
|
|
11
|
+
if (clause) {
|
|
12
|
+
if (clause.name) {
|
|
13
|
+
bindings.push({ imported: 'default', local: clause.name.text });
|
|
14
|
+
}
|
|
15
|
+
if (clause.namedBindings) {
|
|
16
|
+
if (ts.isNamedImports(clause.namedBindings)) {
|
|
17
|
+
for (const element of clause.namedBindings.elements) {
|
|
18
|
+
bindings.push({
|
|
19
|
+
imported: element.propertyName?.text || element.name.text,
|
|
20
|
+
local: element.name.text,
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
else if (ts.isNamespaceImport(clause.namedBindings)) {
|
|
25
|
+
namespaceImport = clause.namedBindings.name.text;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return {
|
|
30
|
+
bindings,
|
|
31
|
+
moduleSpecifier: statement.moduleSpecifier.text,
|
|
32
|
+
namespaceImport,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function isTypePosition(node) {
|
|
36
|
+
for (let current = node; current; current = current.parent) {
|
|
37
|
+
if (ts.isTypeNode(current))
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
function isReferenceIdentifier(node) {
|
|
43
|
+
const parent = node.parent;
|
|
44
|
+
if (!parent)
|
|
45
|
+
return false;
|
|
46
|
+
if (isTypePosition(node))
|
|
47
|
+
return false;
|
|
48
|
+
if (ts.isImportClause(parent) || ts.isImportSpecifier(parent) || ts.isNamespaceImport(parent) || ts.isNamedImports(parent))
|
|
49
|
+
return false;
|
|
50
|
+
if (ts.isExportSpecifier(parent))
|
|
51
|
+
return false;
|
|
52
|
+
if (ts.isBindingElement(parent) || ts.isParameter(parent) || ts.isVariableDeclaration(parent) || ts.isFunctionDeclaration(parent) || ts.isClassDeclaration(parent)) {
|
|
53
|
+
return parent.name !== node;
|
|
54
|
+
}
|
|
55
|
+
if (ts.isPropertyAssignment(parent) && parent.name === node)
|
|
56
|
+
return false;
|
|
57
|
+
if (ts.isShorthandPropertyAssignment(parent) && parent.name === node)
|
|
58
|
+
return true;
|
|
59
|
+
if (ts.isPropertyAccessExpression(parent) && parent.name === node)
|
|
60
|
+
return false;
|
|
61
|
+
if (ts.isQualifiedName(parent) && parent.right === node)
|
|
62
|
+
return false;
|
|
63
|
+
if (ts.isPropertyDeclaration(parent) || ts.isMethodDeclaration(parent) || ts.isGetAccessorDeclaration(parent) || ts.isSetAccessorDeclaration(parent)) {
|
|
64
|
+
return parent.name !== node;
|
|
65
|
+
}
|
|
66
|
+
if (ts.isLabeledStatement(parent) || ts.isBreakStatement(parent) || ts.isContinueStatement(parent))
|
|
67
|
+
return false;
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
export function collectReferencedIdentifiers(source) {
|
|
71
|
+
const refs = new Set();
|
|
72
|
+
const sourceFile = ts.createSourceFile('kuratchi-ref.ts', source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
73
|
+
const visit = (node) => {
|
|
74
|
+
if (ts.isIdentifier(node) && isReferenceIdentifier(node)) {
|
|
75
|
+
refs.add(node.text);
|
|
76
|
+
}
|
|
77
|
+
ts.forEachChild(node, visit);
|
|
78
|
+
};
|
|
79
|
+
visit(sourceFile);
|
|
80
|
+
return refs;
|
|
81
|
+
}
|
|
82
|
+
export function parseNamedImportBindings(line) {
|
|
83
|
+
return parseImportStatement(line).bindings.filter((binding) => binding.imported !== 'default');
|
|
84
|
+
}
|
|
85
|
+
export function filterImportsByNeededBindings(imports, neededBindings) {
|
|
86
|
+
const selected = [];
|
|
87
|
+
for (const line of imports) {
|
|
88
|
+
const parsed = parseImportStatement(line);
|
|
89
|
+
const hasNeededBinding = parsed.bindings.some((binding) => neededBindings.has(binding.local))
|
|
90
|
+
|| (parsed.namespaceImport ? neededBindings.has(parsed.namespaceImport) : false);
|
|
91
|
+
if (hasNeededBinding)
|
|
92
|
+
selected.push(line);
|
|
93
|
+
}
|
|
94
|
+
return selected;
|
|
95
|
+
}
|
|
96
|
+
export function linkRouteServerImports(opts) {
|
|
97
|
+
const fnToModule = {};
|
|
98
|
+
const routeImportDeclMap = new Map();
|
|
99
|
+
const importStatements = [];
|
|
100
|
+
const neededServerFns = new Set([
|
|
101
|
+
...opts.actionFunctions,
|
|
102
|
+
...opts.pollFunctions,
|
|
103
|
+
...opts.dataGetQueries.map((query) => query.fnName),
|
|
104
|
+
]);
|
|
105
|
+
const routeServerImports = opts.routeServerImportEntries.length > 0
|
|
106
|
+
? opts.routeServerImportEntries
|
|
107
|
+
: opts.routeClientImportEntries.filter((entry) => (filterImportsByNeededBindings([entry.line], neededServerFns).length > 0));
|
|
108
|
+
for (const entry of routeServerImports) {
|
|
109
|
+
const parsed = parseImportStatement(entry.line);
|
|
110
|
+
if (!parsed.moduleSpecifier)
|
|
111
|
+
continue;
|
|
112
|
+
const isWorkerEnvModule = parsed.moduleSpecifier === 'cloudflare:workers';
|
|
113
|
+
const isKuratchiEnvModule = parsed.moduleSpecifier === '@kuratchi/js/environment';
|
|
114
|
+
const importPath = opts.resolveCompiledImportPath(parsed.moduleSpecifier, entry.importerDir, opts.outFileDir);
|
|
115
|
+
const moduleId = opts.allocateModuleId();
|
|
116
|
+
importStatements.push(`import * as ${moduleId} from '${importPath}';`);
|
|
117
|
+
for (const binding of parsed.bindings) {
|
|
118
|
+
if ((isWorkerEnvModule && binding.imported === 'env') || (isKuratchiEnvModule && binding.imported === 'dev')) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
fnToModule[binding.local] = moduleId;
|
|
122
|
+
if (!routeImportDeclMap.has(binding.local)) {
|
|
123
|
+
const accessExpr = binding.imported === 'default' ? `${moduleId}.default` : `${moduleId}.${binding.imported}`;
|
|
124
|
+
routeImportDeclMap.set(binding.local, `const ${binding.local} = ${accessExpr};`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (parsed.namespaceImport) {
|
|
128
|
+
fnToModule[parsed.namespaceImport] = moduleId;
|
|
129
|
+
if (!routeImportDeclMap.has(parsed.namespaceImport)) {
|
|
130
|
+
routeImportDeclMap.set(parsed.namespaceImport, `const ${parsed.namespaceImport} = ${moduleId};`);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
fnToModule,
|
|
136
|
+
routeImportDecls: Array.from(routeImportDeclMap.values()),
|
|
137
|
+
importStatements,
|
|
138
|
+
};
|
|
139
|
+
}
|
package/dist/compiler/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Compiler
|
|
2
|
+
* Compiler ?" scans a project's routes/ directory, parses .html files,
|
|
3
3
|
* and generates a single Worker entry point.
|
|
4
4
|
*/
|
|
5
5
|
export { parseFile } from './parser.js';
|
|
@@ -27,9 +27,9 @@ export interface CompiledRoute {
|
|
|
27
27
|
/**
|
|
28
28
|
* Compile a project's src/routes/ into .kuratchi/routes.js
|
|
29
29
|
*
|
|
30
|
-
* The generated module exports { app }
|
|
30
|
+
* The generated module exports { app } ?" an object with a fetch() method
|
|
31
31
|
* that handles routing, load functions, form actions, and rendering.
|
|
32
|
-
* Returns the path to .kuratchi/worker.js
|
|
32
|
+
* Returns the path to .kuratchi/worker.js ? the stable wrangler entry point that
|
|
33
33
|
* re-exports everything from routes.js (default fetch handler + named DO class exports).
|
|
34
34
|
* No src/index.ts is needed in user projects.
|
|
35
35
|
*/
|