@meekojs/meeko 0.0.3 → 0.1.0
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 +35 -16
- package/dist/autoimports-ts.d.ts +26 -0
- package/dist/autoimports-ts.js +183 -0
- package/dist/autoimports-ts.js.map +1 -0
- package/dist/autoimports.d.ts +21 -0
- package/dist/autoimports.js +301 -0
- package/dist/autoimports.js.map +1 -0
- package/dist/check.js +74 -33
- package/dist/check.js.map +1 -0
- package/dist/cli.js +67 -5
- package/dist/cli.js.map +1 -0
- package/dist/compiler/events.d.ts +2 -0
- package/dist/compiler/events.js +6 -0
- package/dist/compiler/events.js.map +1 -0
- package/dist/compiler/import-graph.d.ts +8 -0
- package/dist/compiler/import-graph.js +33 -0
- package/dist/compiler/import-graph.js.map +1 -0
- package/dist/compiler/mapping.js +1 -0
- package/dist/compiler/mapping.js.map +1 -0
- package/dist/compiler/project-root.d.ts +2 -0
- package/dist/compiler/project-root.js +18 -0
- package/dist/compiler/project-root.js.map +1 -0
- package/dist/compiler/props.d.ts +12 -0
- package/dist/compiler/props.js +32 -0
- package/dist/compiler/props.js.map +1 -0
- package/dist/compiler/sfc.js +1 -0
- package/dist/compiler/sfc.js.map +1 -0
- package/dist/compiler/sourcemap.d.ts +3 -0
- package/dist/compiler/sourcemap.js +75 -0
- package/dist/compiler/sourcemap.js.map +1 -0
- package/dist/compiler/template.js +1 -0
- package/dist/compiler/template.js.map +1 -0
- package/dist/compiler.js +66 -17
- package/dist/compiler.js.map +1 -0
- package/dist/component-errors.d.ts +18 -0
- package/dist/component-errors.js +65 -0
- package/dist/component-errors.js.map +1 -0
- package/dist/devtools-ui/index.js +1 -0
- package/dist/devtools-ui/index.js.map +1 -0
- package/dist/devtools.js +3 -4
- package/dist/devtools.js.map +1 -0
- package/dist/dom.d.ts +18 -5
- package/dist/dom.js +295 -90
- package/dist/dom.js.map +1 -0
- package/dist/error-observer.d.ts +6 -0
- package/dist/error-observer.js +41 -0
- package/dist/error-observer.js.map +1 -0
- package/dist/framework/check-app.d.ts +5 -0
- package/dist/framework/check-app.js +214 -0
- package/dist/framework/check-app.js.map +1 -0
- package/dist/framework/check-project.d.ts +4 -0
- package/dist/framework/check-project.js +42 -0
- package/dist/framework/check-project.js.map +1 -0
- package/dist/framework/client.d.ts +48 -0
- package/dist/framework/client.js +249 -0
- package/dist/framework/client.js.map +1 -0
- package/dist/framework/clients.d.ts +82 -0
- package/dist/framework/clients.js +190 -0
- package/dist/framework/clients.js.map +1 -0
- package/dist/framework/config-type.d.ts +10 -0
- package/dist/framework/config-type.js +4 -0
- package/dist/framework/config-type.js.map +1 -0
- package/dist/framework/config.d.ts +15 -0
- package/dist/framework/config.js +138 -0
- package/dist/framework/config.js.map +1 -0
- package/dist/framework/contracts-generate.d.ts +8 -0
- package/dist/framework/contracts-generate.js +290 -0
- package/dist/framework/contracts-generate.js.map +1 -0
- package/dist/framework/generate.d.ts +7 -0
- package/dist/framework/generate.js +67 -0
- package/dist/framework/generate.js.map +1 -0
- package/dist/framework/init.d.ts +2 -0
- package/dist/framework/init.js +183 -0
- package/dist/framework/init.js.map +1 -0
- package/dist/framework/middleware.d.ts +14 -0
- package/dist/framework/middleware.js +16 -0
- package/dist/framework/middleware.js.map +1 -0
- package/dist/framework/modules.d.ts +22 -0
- package/dist/framework/modules.js +29 -0
- package/dist/framework/modules.js.map +1 -0
- package/dist/framework/page-contracts-check.d.ts +8 -0
- package/dist/framework/page-contracts-check.js +110 -0
- package/dist/framework/page-contracts-check.js.map +1 -0
- package/dist/framework/page-contracts-generate.d.ts +2 -0
- package/dist/framework/page-contracts-generate.js +94 -0
- package/dist/framework/page-contracts-generate.js.map +1 -0
- package/dist/framework/page.d.ts +64 -0
- package/dist/framework/page.js +44 -0
- package/dist/framework/page.js.map +1 -0
- package/dist/framework/prerender.d.ts +14 -0
- package/dist/framework/prerender.js +110 -0
- package/dist/framework/prerender.js.map +1 -0
- package/dist/framework/project-templates.d.ts +3 -0
- package/dist/framework/project-templates.js +119 -0
- package/dist/framework/project-templates.js.map +1 -0
- package/dist/framework/project.d.ts +9 -0
- package/dist/framework/project.js +272 -0
- package/dist/framework/project.js.map +1 -0
- package/dist/framework/router.d.ts +41 -0
- package/dist/framework/router.js +259 -0
- package/dist/framework/router.js.map +1 -0
- package/dist/framework/server.d.ts +65 -0
- package/dist/framework/server.js +239 -0
- package/dist/framework/server.js.map +1 -0
- package/dist/framework/socket-contracts-generate.d.ts +5 -0
- package/dist/framework/socket-contracts-generate.js +162 -0
- package/dist/framework/socket-contracts-generate.js.map +1 -0
- package/dist/framework/socket.d.ts +72 -0
- package/dist/framework/socket.js +252 -0
- package/dist/framework/socket.js.map +1 -0
- package/dist/framework/standard-schema-types.d.ts +7 -0
- package/dist/framework/standard-schema-types.js +69 -0
- package/dist/framework/standard-schema-types.js.map +1 -0
- package/dist/framework/state.d.ts +22 -0
- package/dist/framework/state.js +136 -0
- package/dist/framework/state.js.map +1 -0
- package/dist/framework/styles.d.ts +2 -0
- package/dist/framework/styles.js +6 -0
- package/dist/framework/styles.js.map +1 -0
- package/dist/framework/type-declarations.d.ts +5 -0
- package/dist/framework/type-declarations.js +84 -0
- package/dist/framework/type-declarations.js.map +1 -0
- package/dist/framework-server/auto-clients.d.ts +3 -0
- package/dist/framework-server/auto-clients.js +27 -0
- package/dist/framework-server/auto-clients.js.map +1 -0
- package/dist/framework-server/context.d.ts +21 -0
- package/dist/framework-server/context.js +22 -0
- package/dist/framework-server/context.js.map +1 -0
- package/dist/framework-server/contracts.d.ts +73 -0
- package/dist/framework-server/contracts.js +184 -0
- package/dist/framework-server/contracts.js.map +1 -0
- package/dist/framework-server/discovery.d.ts +43 -0
- package/dist/framework-server/discovery.js +257 -0
- package/dist/framework-server/discovery.js.map +1 -0
- package/dist/framework-server/local.d.ts +21 -0
- package/dist/framework-server/local.js +100 -0
- package/dist/framework-server/local.js.map +1 -0
- package/dist/framework-server/middleware.d.ts +4 -0
- package/dist/framework-server/middleware.js +56 -0
- package/dist/framework-server/middleware.js.map +1 -0
- package/dist/framework-server/node-upgrade.d.ts +23 -0
- package/dist/framework-server/node-upgrade.js +96 -0
- package/dist/framework-server/node-upgrade.js.map +1 -0
- package/dist/framework-server/node-websocket.d.ts +16 -0
- package/dist/framework-server/node-websocket.js +127 -0
- package/dist/framework-server/node-websocket.js.map +1 -0
- package/dist/framework-server/openapi.d.ts +17 -0
- package/dist/framework-server/openapi.js +118 -0
- package/dist/framework-server/openapi.js.map +1 -0
- package/dist/framework-server/session-stores.d.ts +73 -0
- package/dist/framework-server/session-stores.js +122 -0
- package/dist/framework-server/session-stores.js.map +1 -0
- package/dist/framework-server/sessions.d.ts +70 -0
- package/dist/framework-server/sessions.js +167 -0
- package/dist/framework-server/sessions.js.map +1 -0
- package/dist/framework-server/socket.d.ts +83 -0
- package/dist/framework-server/socket.js +196 -0
- package/dist/framework-server/socket.js.map +1 -0
- package/dist/framework-server.d.ts +23 -0
- package/dist/framework-server.js +13 -0
- package/dist/framework-server.js.map +1 -0
- package/dist/framework.d.ts +31 -0
- package/dist/framework.js +14 -0
- package/dist/framework.js.map +1 -0
- package/dist/hmr.js +75 -24
- package/dist/hmr.js.map +1 -0
- package/dist/index.d.ts +5 -3
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -0
- package/dist/init.js +31 -3
- package/dist/init.js.map +1 -0
- package/dist/internal.d.ts +2 -2
- package/dist/internal.js +3 -2
- package/dist/internal.js.map +1 -0
- package/dist/node.d.ts +16 -0
- package/dist/node.js +122 -0
- package/dist/node.js.map +1 -0
- package/dist/reactivity.d.ts +22 -1
- package/dist/reactivity.js +132 -18
- package/dist/reactivity.js.map +1 -0
- package/dist/server.js +1 -0
- package/dist/server.js.map +1 -0
- package/dist/types.d.ts +2 -0
- package/dist/types.js +26 -9
- package/dist/types.js.map +1 -0
- package/dist/vite.js +112 -7
- package/dist/vite.js.map +1 -0
- package/package.json +15 -4
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/** Attaches a rejection observer immediately, including to foreign thenables. */
|
|
2
|
+
export declare function observeReturnedPromise(result: unknown, report: (error: unknown) => void): boolean;
|
|
3
|
+
/** Observes synchronous callbacks and returned promises at browser event boundaries. */
|
|
4
|
+
export declare function observeCallback(call: () => unknown, report: (error: unknown) => void): void;
|
|
5
|
+
/** Last-resort client reporting when no application observer is available. */
|
|
6
|
+
export declare function logClientError(label: string, ...details: unknown[]): void;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** Attaches a rejection observer immediately, including to foreign thenables. */
|
|
2
|
+
export function observeReturnedPromise(result, report) {
|
|
3
|
+
const safeReport = (error) => {
|
|
4
|
+
try {
|
|
5
|
+
report(error);
|
|
6
|
+
}
|
|
7
|
+
catch { /* Reporting cannot escape an event callback or create another rejection. */ }
|
|
8
|
+
};
|
|
9
|
+
try {
|
|
10
|
+
if (result && (typeof result === "object" || typeof result === "function")
|
|
11
|
+
&& "then" in result && typeof result.then === "function") {
|
|
12
|
+
void Promise.resolve(result).catch(safeReport);
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
safeReport(error);
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
/** Observes synchronous callbacks and returned promises at browser event boundaries. */
|
|
23
|
+
export function observeCallback(call, report) {
|
|
24
|
+
try {
|
|
25
|
+
observeReturnedPromise(call(), report);
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
try {
|
|
29
|
+
report(error);
|
|
30
|
+
}
|
|
31
|
+
catch { /* Reporting cannot escape an event callback. */ }
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** Last-resort client reporting when no application observer is available. */
|
|
35
|
+
export function logClientError(label, ...details) {
|
|
36
|
+
try {
|
|
37
|
+
console.error(label, ...details);
|
|
38
|
+
}
|
|
39
|
+
catch { /* A broken console cannot escape an event callback. */ }
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=error-observer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-observer.js","sourceRoot":"","sources":["../src/error-observer.ts"],"names":[],"mappings":"AAAA,iFAAiF;AACjF,MAAM,UAAU,sBAAsB,CAAC,MAAe,EAAE,MAAgC;IACtF,MAAM,UAAU,GAAG,CAAC,KAAc,EAAE,EAAE;QACpC,IAAI,CAAC;YAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAAC,CAAC;QACtB,MAAM,CAAC,CAAC,4EAA4E,CAAC,CAAC;IACxF,CAAC,CAAC;IACF,IAAI,CAAC;QACH,IAAI,MAAM,IAAI,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,OAAO,MAAM,KAAK,UAAU,CAAC;eACrE,MAAM,IAAI,MAAM,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC3D,KAAK,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YAC/C,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAAC,OAAO,IAAI,CAAC;IAAC,CAAC;IACnD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,eAAe,CAAC,IAAmB,EAAE,MAAgC;IACnF,IAAI,CAAC;QAAC,sBAAsB,CAAC,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC;IAAC,CAAC;IAC/C,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,CAAC;YAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAAC,CAAC;QACtB,MAAM,CAAC,CAAC,gDAAgD,CAAC,CAAC;IAC5D,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,GAAG,OAAkB;IACjE,IAAI,CAAC;QAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,OAAO,CAAC,CAAC;IAAC,CAAC;IACzC,MAAM,CAAC,CAAC,uDAAuD,CAAC,CAAC;AACnE,CAAC","sourcesContent":["/** Attaches a rejection observer immediately, including to foreign thenables. */\nexport function observeReturnedPromise(result: unknown, report: (error: unknown) => void): boolean {\n const safeReport = (error: unknown) => {\n try { report(error); }\n catch { /* Reporting cannot escape an event callback or create another rejection. */ }\n };\n try {\n if (result && (typeof result === \"object\" || typeof result === \"function\")\n && \"then\" in result && typeof result.then === \"function\") {\n void Promise.resolve(result).catch(safeReport);\n return true;\n }\n } catch (error) { safeReport(error); return true; }\n return false;\n}\n\n/** Observes synchronous callbacks and returned promises at browser event boundaries. */\nexport function observeCallback(call: () => unknown, report: (error: unknown) => void): void {\n try { observeReturnedPromise(call(), report); }\n catch (error) {\n try { report(error); }\n catch { /* Reporting cannot escape an event callback. */ }\n }\n}\n\n/** Last-resort client reporting when no application observer is available. */\nexport function logClientError(label: string, ...details: unknown[]): void {\n try { console.error(label, ...details); }\n catch { /* A broken console cannot escape an event callback. */ }\n}\n"]}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { CompileDiagnostic } from "../compiler/sfc.js";
|
|
2
|
+
/** Checks every discovered application component, including new pages and layouts. */
|
|
3
|
+
export declare function checkApp(projectRoot: string): Promise<CompileDiagnostic[]>;
|
|
4
|
+
/** Mirrors app component declarations into the project's virtual type tree. */
|
|
5
|
+
export declare function generateAppTypes(projectRoot: string): Promise<string[]>;
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { access, mkdir, readFile, readdir, realpath, unlink, writeFile } from "node:fs/promises";
|
|
2
|
+
import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
3
|
+
import ts from "@typescript/typescript6";
|
|
4
|
+
import { checkSource } from "../check.js";
|
|
5
|
+
import { componentTypeDeclarationMarker, generateTypes } from "../types.js";
|
|
6
|
+
import { resolveConfigSources } from "./config.js";
|
|
7
|
+
const componentTypesManifest = "component-types.json";
|
|
8
|
+
const componentTypeSuffix = ".d.meeko.ts";
|
|
9
|
+
function inside(root, target) {
|
|
10
|
+
const path = relative(root, target);
|
|
11
|
+
return path === "" || (path !== ".." && !path.startsWith(`..${sep}`) && !isAbsolute(path));
|
|
12
|
+
}
|
|
13
|
+
function ownedTypePath(typesRoot, file) {
|
|
14
|
+
const path = relative(typesRoot, resolve(file));
|
|
15
|
+
if (!path || path === ".." || path.startsWith(`..${sep}`) || isAbsolute(path) || !path.endsWith(componentTypeSuffix))
|
|
16
|
+
return undefined;
|
|
17
|
+
return path.replaceAll("\\", "/");
|
|
18
|
+
}
|
|
19
|
+
async function readTypeOwnership(file) {
|
|
20
|
+
let source;
|
|
21
|
+
try {
|
|
22
|
+
source = await readFile(file, "utf8");
|
|
23
|
+
}
|
|
24
|
+
catch (error) {
|
|
25
|
+
if (error.code === "ENOENT")
|
|
26
|
+
return undefined;
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
let value;
|
|
30
|
+
try {
|
|
31
|
+
value = JSON.parse(source);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
throw new Error(`Invalid Meeko component type ownership manifest: ${file}`, { cause: error });
|
|
35
|
+
}
|
|
36
|
+
if (!value || typeof value !== "object" || value.version !== 1 ||
|
|
37
|
+
!Array.isArray(value.files) ||
|
|
38
|
+
value.files.some((entry) => typeof entry !== "string" || !entry)) {
|
|
39
|
+
throw new Error(`Invalid Meeko component type ownership manifest: ${file}`);
|
|
40
|
+
}
|
|
41
|
+
return value.files;
|
|
42
|
+
}
|
|
43
|
+
function generatedComponentDeclaration(source) {
|
|
44
|
+
if (source.startsWith(`${componentTypeDeclarationMarker}\n`) || source.startsWith(`${componentTypeDeclarationMarker}\r\n`))
|
|
45
|
+
return true;
|
|
46
|
+
// Releases before the ownership manifest did not preserve a comment marker.
|
|
47
|
+
// Parse their complete generated runtime surface so comments and strings cannot impersonate it.
|
|
48
|
+
const file = ts.createSourceFile("component.d.meeko.ts", source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);
|
|
49
|
+
const modifiers = (node) => node.modifiers ?? [];
|
|
50
|
+
const exportedDeclaration = (node) => modifiers(node).some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword) &&
|
|
51
|
+
modifiers(node).some((modifier) => modifier.kind === ts.SyntaxKind.DeclareKeyword);
|
|
52
|
+
const typeName = (node) => {
|
|
53
|
+
if (!node || !ts.isTypeReferenceNode(node))
|
|
54
|
+
return undefined;
|
|
55
|
+
if (ts.isIdentifier(node.typeName))
|
|
56
|
+
return node.typeName.text;
|
|
57
|
+
return ts.isIdentifier(node.typeName.left) && ts.isIdentifier(node.typeName.right)
|
|
58
|
+
? `${node.typeName.left.text}.${node.typeName.right.text}` : undefined;
|
|
59
|
+
};
|
|
60
|
+
const generatedFunction = (name, expected) => file.statements.some((statement) => ts.isFunctionDeclaration(statement) && statement.name?.text === name &&
|
|
61
|
+
exportedDeclaration(statement) && expected.every(([parameterName, parameterType], index) => {
|
|
62
|
+
const parameter = statement.parameters[index];
|
|
63
|
+
return parameter !== undefined && ts.isIdentifier(parameter.name) && parameter.name.text === parameterName && typeName(parameter.type) === parameterType;
|
|
64
|
+
}));
|
|
65
|
+
const internalImport = file.statements.some((statement) => {
|
|
66
|
+
if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier) ||
|
|
67
|
+
statement.moduleSpecifier.text !== "@meekojs/meeko/internal")
|
|
68
|
+
return false;
|
|
69
|
+
const bindings = statement.importClause?.namedBindings;
|
|
70
|
+
return bindings !== undefined && ts.isNamespaceImport(bindings) && bindings.name.text === "__meeko";
|
|
71
|
+
});
|
|
72
|
+
const componentProps = file.statements.some((statement) => ts.isTypeAliasDeclaration(statement) &&
|
|
73
|
+
statement.name.text === "ComponentProps" && modifiers(statement).some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword));
|
|
74
|
+
const css = file.statements.some((statement) => ts.isVariableStatement(statement) && exportedDeclaration(statement) &&
|
|
75
|
+
statement.declarationList.declarations.some((declaration) => ts.isIdentifier(declaration.name) && declaration.name.text === "css" &&
|
|
76
|
+
declaration.initializer !== undefined && ts.isStringLiteral(declaration.initializer)));
|
|
77
|
+
return internalImport && componentProps && css &&
|
|
78
|
+
generatedFunction("renderWithState", [["__inputProps", "ComponentProps"]]) &&
|
|
79
|
+
generatedFunction("renderToString", [["__inputProps", "ComponentProps"]]) &&
|
|
80
|
+
generatedFunction("hydrate", [["root", "Element"], ["__inputProps", "ComponentProps"]]) &&
|
|
81
|
+
generatedFunction("hydrateScope", [["__scope", "__meeko.DomScope"], ["__inputProps", "ComponentProps"]]);
|
|
82
|
+
}
|
|
83
|
+
/** Adopts only orphaned declarations with a current marker or the complete legacy generator fingerprint. */
|
|
84
|
+
async function adoptGeneratedTypes(projectRoot, typesRoot) {
|
|
85
|
+
const files = [];
|
|
86
|
+
async function walk(directory) {
|
|
87
|
+
for (const entry of await readdir(directory, { withFileTypes: true })) {
|
|
88
|
+
const file = join(directory, entry.name);
|
|
89
|
+
if (entry.isDirectory())
|
|
90
|
+
await walk(file);
|
|
91
|
+
else if (entry.isFile() && entry.name.endsWith(componentTypeSuffix) && generatedComponentDeclaration(await readFile(file, "utf8"))) {
|
|
92
|
+
const path = ownedTypePath(typesRoot, file);
|
|
93
|
+
if (!path)
|
|
94
|
+
continue;
|
|
95
|
+
const source = resolve(projectRoot, `${path.slice(0, -componentTypeSuffix.length)}.meeko`);
|
|
96
|
+
try {
|
|
97
|
+
await access(source);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
if (error.code === "ENOENT") {
|
|
101
|
+
files.push(path);
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
throw error;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
await walk(typesRoot);
|
|
110
|
+
return files;
|
|
111
|
+
}
|
|
112
|
+
/** Removes only declarations recorded by a previous successful generation. */
|
|
113
|
+
async function reconcileOwnedTypes(projectRoot, outputs) {
|
|
114
|
+
const root = resolve(projectRoot);
|
|
115
|
+
const typesRoot = resolve(root, ".meeko", "types");
|
|
116
|
+
const manifest = resolve(root, ".meeko", "manifests", componentTypesManifest);
|
|
117
|
+
const current = new Set(outputs.map((output) => ownedTypePath(typesRoot, output)).filter((path) => path !== undefined));
|
|
118
|
+
const recorded = await readTypeOwnership(manifest);
|
|
119
|
+
await mkdir(typesRoot, { recursive: true });
|
|
120
|
+
const actualRoot = await realpath(root);
|
|
121
|
+
const actualTypesRoot = await realpath(typesRoot);
|
|
122
|
+
if (!inside(actualRoot, actualTypesRoot))
|
|
123
|
+
throw new Error(`Meeko type directory escapes project root: ${typesRoot}`);
|
|
124
|
+
const previous = recorded ?? await adoptGeneratedTypes(root, typesRoot);
|
|
125
|
+
for (const path of previous) {
|
|
126
|
+
const target = resolve(typesRoot, path);
|
|
127
|
+
if (path.includes("\\") || ownedTypePath(typesRoot, target) !== path) {
|
|
128
|
+
throw new Error(`Invalid owned Meeko component type path: ${path}`);
|
|
129
|
+
}
|
|
130
|
+
if (current.has(path))
|
|
131
|
+
continue;
|
|
132
|
+
let actualTarget;
|
|
133
|
+
try {
|
|
134
|
+
actualTarget = await realpath(target);
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
if (error.code === "ENOENT")
|
|
138
|
+
continue;
|
|
139
|
+
throw error;
|
|
140
|
+
}
|
|
141
|
+
if (!inside(actualTypesRoot, actualTarget))
|
|
142
|
+
throw new Error(`Owned Meeko component type escapes generated directory: ${target}`);
|
|
143
|
+
await unlink(target);
|
|
144
|
+
}
|
|
145
|
+
const body = `${JSON.stringify({ version: 1, files: [...current].sort() }, null, 2)}\n`;
|
|
146
|
+
await mkdir(dirname(manifest), { recursive: true });
|
|
147
|
+
try {
|
|
148
|
+
if (await readFile(manifest, "utf8") === body)
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
if (error.code !== "ENOENT")
|
|
153
|
+
throw error;
|
|
154
|
+
}
|
|
155
|
+
await writeFile(manifest, body, "utf8");
|
|
156
|
+
}
|
|
157
|
+
async function appMeekoFiles(projectRoot) {
|
|
158
|
+
const root = resolve(projectRoot);
|
|
159
|
+
const files = [];
|
|
160
|
+
async function walk(directory) {
|
|
161
|
+
let entries;
|
|
162
|
+
try {
|
|
163
|
+
entries = await readdir(directory, { withFileTypes: true });
|
|
164
|
+
}
|
|
165
|
+
catch (error) {
|
|
166
|
+
if (error.code === "ENOENT")
|
|
167
|
+
return;
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
170
|
+
for (const entry of entries) {
|
|
171
|
+
const path = join(directory, entry.name);
|
|
172
|
+
if (entry.isDirectory())
|
|
173
|
+
await walk(path);
|
|
174
|
+
else if (entry.isFile() && entry.name.endsWith(".meeko"))
|
|
175
|
+
files.push(path);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
for (const source of await resolveConfigSources(root)) {
|
|
179
|
+
await walk(join(source.root, "app", "pages"));
|
|
180
|
+
await walk(join(source.root, "app", "layouts"));
|
|
181
|
+
await walk(join(source.root, "app", "components"));
|
|
182
|
+
for (const file of [join(source.root, "app", "app.meeko"), join(source.root, "app", "error.meeko")]) {
|
|
183
|
+
try {
|
|
184
|
+
await readFile(file);
|
|
185
|
+
files.push(file);
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
if (error.code !== "ENOENT")
|
|
189
|
+
throw error;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return files.sort();
|
|
194
|
+
}
|
|
195
|
+
/** Checks every discovered application component, including new pages and layouts. */
|
|
196
|
+
export async function checkApp(projectRoot) {
|
|
197
|
+
const diagnostics = [];
|
|
198
|
+
for (const file of await appMeekoFiles(projectRoot))
|
|
199
|
+
diagnostics.push(...await checkSource(await readFile(file, "utf8"), file));
|
|
200
|
+
return diagnostics;
|
|
201
|
+
}
|
|
202
|
+
/** Mirrors app component declarations into the project's virtual type tree. */
|
|
203
|
+
export async function generateAppTypes(projectRoot) {
|
|
204
|
+
const root = resolve(projectRoot);
|
|
205
|
+
const outputs = new Set();
|
|
206
|
+
for (const file of await appMeekoFiles(root)) {
|
|
207
|
+
for (const output of await generateTypes(await readFile(file, "utf8"), file))
|
|
208
|
+
outputs.add(output);
|
|
209
|
+
}
|
|
210
|
+
const generated = [...outputs].sort();
|
|
211
|
+
await reconcileOwnedTypes(root, generated);
|
|
212
|
+
return generated;
|
|
213
|
+
}
|
|
214
|
+
//# sourceMappingURL=check-app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-app.js","sourceRoot":"","sources":["../../src/framework/check-app.ts"],"names":[],"mappings":"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","sourcesContent":["import { access, mkdir, readFile, readdir, realpath, unlink, writeFile } from \"node:fs/promises\";\nimport { dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport ts from \"@typescript/typescript6\";\nimport { checkSource } from \"../check.js\";\nimport type { CompileDiagnostic } from \"../compiler/sfc.js\";\nimport { componentTypeDeclarationMarker, generateTypes } from \"../types.js\";\nimport { resolveConfigSources } from \"./config.js\";\n\nconst componentTypesManifest = \"component-types.json\";\nconst componentTypeSuffix = \".d.meeko.ts\";\n\ninterface ComponentTypesOwnership {\n readonly version: 1;\n readonly files: readonly string[];\n}\n\nfunction inside(root: string, target: string): boolean {\n const path = relative(root, target);\n return path === \"\" || (path !== \"..\" && !path.startsWith(`..${sep}`) && !isAbsolute(path));\n}\n\nfunction ownedTypePath(typesRoot: string, file: string): string | undefined {\n const path = relative(typesRoot, resolve(file));\n if (!path || path === \"..\" || path.startsWith(`..${sep}`) || isAbsolute(path) || !path.endsWith(componentTypeSuffix)) return undefined;\n return path.replaceAll(\"\\\\\", \"/\");\n}\n\nasync function readTypeOwnership(file: string): Promise<readonly string[] | undefined> {\n let source: string;\n try { source = await readFile(file, \"utf8\"); }\n catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return undefined;\n throw error;\n }\n let value: unknown;\n try { value = JSON.parse(source) as unknown; }\n catch (error) { throw new Error(`Invalid Meeko component type ownership manifest: ${file}`, { cause: error }); }\n if (!value || typeof value !== \"object\" || (value as Partial<ComponentTypesOwnership>).version !== 1 ||\n !Array.isArray((value as Partial<ComponentTypesOwnership>).files) ||\n (value as Partial<ComponentTypesOwnership>).files!.some((entry) => typeof entry !== \"string\" || !entry)) {\n throw new Error(`Invalid Meeko component type ownership manifest: ${file}`);\n }\n return (value as ComponentTypesOwnership).files;\n}\n\nfunction generatedComponentDeclaration(source: string): boolean {\n if (source.startsWith(`${componentTypeDeclarationMarker}\\n`) || source.startsWith(`${componentTypeDeclarationMarker}\\r\\n`)) return true;\n // Releases before the ownership manifest did not preserve a comment marker.\n // Parse their complete generated runtime surface so comments and strings cannot impersonate it.\n const file = ts.createSourceFile(\"component.d.meeko.ts\", source, ts.ScriptTarget.Latest, true, ts.ScriptKind.TS);\n const modifiers = (node: { readonly modifiers?: ts.NodeArray<ts.ModifierLike> }): readonly ts.ModifierLike[] => node.modifiers ?? [];\n const exportedDeclaration = (node: { readonly modifiers?: ts.NodeArray<ts.ModifierLike> }): boolean =>\n modifiers(node).some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword) &&\n modifiers(node).some((modifier) => modifier.kind === ts.SyntaxKind.DeclareKeyword);\n const typeName = (node: ts.TypeNode | undefined): string | undefined => {\n if (!node || !ts.isTypeReferenceNode(node)) return undefined;\n if (ts.isIdentifier(node.typeName)) return node.typeName.text;\n return ts.isIdentifier(node.typeName.left) && ts.isIdentifier(node.typeName.right)\n ? `${node.typeName.left.text}.${node.typeName.right.text}` : undefined;\n };\n const generatedFunction = (name: string, expected: readonly (readonly [string, string])[]): boolean =>\n file.statements.some((statement) => ts.isFunctionDeclaration(statement) && statement.name?.text === name &&\n exportedDeclaration(statement) && expected.every(([parameterName, parameterType], index) => {\n const parameter = statement.parameters[index];\n return parameter !== undefined && ts.isIdentifier(parameter.name) && parameter.name.text === parameterName && typeName(parameter.type) === parameterType;\n }));\n const internalImport = file.statements.some((statement) => {\n if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier) ||\n statement.moduleSpecifier.text !== \"@meekojs/meeko/internal\") return false;\n const bindings = statement.importClause?.namedBindings;\n return bindings !== undefined && ts.isNamespaceImport(bindings) && bindings.name.text === \"__meeko\";\n });\n const componentProps = file.statements.some((statement) => ts.isTypeAliasDeclaration(statement) &&\n statement.name.text === \"ComponentProps\" && modifiers(statement).some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword));\n const css = file.statements.some((statement) => ts.isVariableStatement(statement) && exportedDeclaration(statement) &&\n statement.declarationList.declarations.some((declaration) => ts.isIdentifier(declaration.name) && declaration.name.text === \"css\" &&\n declaration.initializer !== undefined && ts.isStringLiteral(declaration.initializer)));\n return internalImport && componentProps && css &&\n generatedFunction(\"renderWithState\", [[\"__inputProps\", \"ComponentProps\"]]) &&\n generatedFunction(\"renderToString\", [[\"__inputProps\", \"ComponentProps\"]]) &&\n generatedFunction(\"hydrate\", [[\"root\", \"Element\"], [\"__inputProps\", \"ComponentProps\"]]) &&\n generatedFunction(\"hydrateScope\", [[\"__scope\", \"__meeko.DomScope\"], [\"__inputProps\", \"ComponentProps\"]]);\n}\n\n/** Adopts only orphaned declarations with a current marker or the complete legacy generator fingerprint. */\nasync function adoptGeneratedTypes(projectRoot: string, typesRoot: string): Promise<readonly string[]> {\n const files: string[] = [];\n async function walk(directory: string): Promise<void> {\n for (const entry of await readdir(directory, { withFileTypes: true })) {\n const file = join(directory, entry.name);\n if (entry.isDirectory()) await walk(file);\n else if (entry.isFile() && entry.name.endsWith(componentTypeSuffix) && generatedComponentDeclaration(await readFile(file, \"utf8\"))) {\n const path = ownedTypePath(typesRoot, file);\n if (!path) continue;\n const source = resolve(projectRoot, `${path.slice(0, -componentTypeSuffix.length)}.meeko`);\n try { await access(source); }\n catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") { files.push(path); continue; }\n throw error;\n }\n }\n }\n }\n await walk(typesRoot);\n return files;\n}\n\n/** Removes only declarations recorded by a previous successful generation. */\nasync function reconcileOwnedTypes(projectRoot: string, outputs: readonly string[]): Promise<void> {\n const root = resolve(projectRoot);\n const typesRoot = resolve(root, \".meeko\", \"types\");\n const manifest = resolve(root, \".meeko\", \"manifests\", componentTypesManifest);\n const current = new Set(outputs.map((output) => ownedTypePath(typesRoot, output)).filter((path): path is string => path !== undefined));\n const recorded = await readTypeOwnership(manifest);\n await mkdir(typesRoot, { recursive: true });\n const actualRoot = await realpath(root);\n const actualTypesRoot = await realpath(typesRoot);\n if (!inside(actualRoot, actualTypesRoot)) throw new Error(`Meeko type directory escapes project root: ${typesRoot}`);\n const previous = recorded ?? await adoptGeneratedTypes(root, typesRoot);\n for (const path of previous) {\n const target = resolve(typesRoot, path);\n if (path.includes(\"\\\\\") || ownedTypePath(typesRoot, target) !== path) {\n throw new Error(`Invalid owned Meeko component type path: ${path}`);\n }\n if (current.has(path)) continue;\n let actualTarget: string;\n try { actualTarget = await realpath(target); }\n catch (error) { if ((error as NodeJS.ErrnoException).code === \"ENOENT\") continue; throw error; }\n if (!inside(actualTypesRoot, actualTarget)) throw new Error(`Owned Meeko component type escapes generated directory: ${target}`);\n await unlink(target);\n }\n const body = `${JSON.stringify({ version: 1, files: [...current].sort() } satisfies ComponentTypesOwnership, null, 2)}\\n`;\n await mkdir(dirname(manifest), { recursive: true });\n try { if (await readFile(manifest, \"utf8\") === body) return; }\n catch (error) { if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error; }\n await writeFile(manifest, body, \"utf8\");\n}\n\nasync function appMeekoFiles(projectRoot: string): Promise<string[]> {\n const root = resolve(projectRoot);\n const files: string[] = [];\n async function walk(directory: string): Promise<void> {\n let entries;\n try { entries = await readdir(directory, { withFileTypes: true }); }\n catch (error) { if ((error as NodeJS.ErrnoException).code === \"ENOENT\") return; throw error; }\n for (const entry of entries) {\n const path = join(directory, entry.name);\n if (entry.isDirectory()) await walk(path);\n else if (entry.isFile() && entry.name.endsWith(\".meeko\")) files.push(path);\n }\n }\n for (const source of await resolveConfigSources(root)) {\n await walk(join(source.root, \"app\", \"pages\"));\n await walk(join(source.root, \"app\", \"layouts\"));\n await walk(join(source.root, \"app\", \"components\"));\n for (const file of [join(source.root, \"app\", \"app.meeko\"), join(source.root, \"app\", \"error.meeko\")]) {\n try { await readFile(file); files.push(file); }\n catch (error) { if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error; }\n }\n }\n return files.sort();\n}\n\n/** Checks every discovered application component, including new pages and layouts. */\nexport async function checkApp(projectRoot: string): Promise<CompileDiagnostic[]> {\n const diagnostics: CompileDiagnostic[] = [];\n for (const file of await appMeekoFiles(projectRoot)) diagnostics.push(...await checkSource(await readFile(file, \"utf8\"), file));\n return diagnostics;\n}\n\n/** Mirrors app component declarations into the project's virtual type tree. */\nexport async function generateAppTypes(projectRoot: string): Promise<string[]> {\n const root = resolve(projectRoot);\n const outputs = new Set<string>();\n for (const file of await appMeekoFiles(root)) {\n for (const output of await generateTypes(await readFile(file, \"utf8\"), file)) outputs.add(output);\n }\n const generated = [...outputs].sort();\n await reconcileOwnedTypes(root, generated);\n return generated;\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
/** Prepares generated entries, declarations and editor projects without checking sources. */
|
|
2
|
+
export declare function prepareFrameworkTypes(projectRoot: string): Promise<void>;
|
|
3
|
+
/** Generates declarations, checks .meeko sources, then checks app/server/shared TS separately. */
|
|
4
|
+
export declare function checkFrameworkProject(projectRoot: string): Promise<void>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { dirname, join, resolve } from "node:path";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { execFile } from "node:child_process";
|
|
4
|
+
import { promisify } from "node:util";
|
|
5
|
+
import { checkApp } from "./check-app.js";
|
|
6
|
+
import { prepareProject } from "./project.js";
|
|
7
|
+
import { prepareFrameworkTypeDeclarations, projectNames } from "./type-declarations.js";
|
|
8
|
+
const execute = promisify(execFile);
|
|
9
|
+
const require = createRequire(import.meta.url);
|
|
10
|
+
async function checkTypeScript(configs) {
|
|
11
|
+
const compiler = join(dirname(require.resolve("typescript/package.json")), "bin", "tsc");
|
|
12
|
+
for (const config of configs) {
|
|
13
|
+
try {
|
|
14
|
+
await execute(process.execPath, [compiler, "-p", config, "--noEmit"]);
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
const failure = error;
|
|
18
|
+
throw new Error(`TypeScript check failed (${config}):\n${failure.stdout ?? ""}${failure.stderr ?? ""}`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** Prepares generated entries, declarations and editor projects without checking sources. */
|
|
23
|
+
export async function prepareFrameworkTypes(projectRoot) {
|
|
24
|
+
const root = resolve(projectRoot);
|
|
25
|
+
await prepareProject(root);
|
|
26
|
+
await prepareFrameworkTypeDeclarations(root);
|
|
27
|
+
}
|
|
28
|
+
/** Generates declarations, checks .meeko sources, then checks app/server/shared TS separately. */
|
|
29
|
+
export async function checkFrameworkProject(projectRoot) {
|
|
30
|
+
const root = resolve(projectRoot);
|
|
31
|
+
await prepareFrameworkTypes(root);
|
|
32
|
+
const sourceDiagnostics = await checkApp(root);
|
|
33
|
+
if (sourceDiagnostics.length > 0) {
|
|
34
|
+
throw new Error(sourceDiagnostics.map((diagnostic) => {
|
|
35
|
+
const { line, column } = diagnostic.location;
|
|
36
|
+
return `${diagnostic.filename}:${line}:${column} ${diagnostic.code}: ${diagnostic.message}`;
|
|
37
|
+
}).join("\n"));
|
|
38
|
+
}
|
|
39
|
+
const configs = projectNames.map((name) => join(root, ".meeko", `tsconfig.${name}.json`));
|
|
40
|
+
await checkTypeScript(configs);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=check-project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"check-project.js","sourceRoot":"","sources":["../../src/framework/check-project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,gCAAgC,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAExF,MAAM,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC,CAAC;AACpC,MAAM,OAAO,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAE/C,KAAK,UAAU,eAAe,CAAC,OAA0B;IACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IACzF,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,CAAC;YAAC,MAAM,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;QAAC,CAAC;QAC9E,OAAO,KAAK,EAAE,CAAC;YACb,MAAM,OAAO,GAAG,KAAqD,CAAC;YACtE,MAAM,IAAI,KAAK,CAAC,4BAA4B,MAAM,OAAO,OAAO,CAAC,MAAM,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC,CAAC;QAC1G,CAAC;IACH,CAAC;AACH,CAAC;AAED,6FAA6F;AAC7F,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,WAAmB;IAC7D,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAClC,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;IAC3B,MAAM,gCAAgC,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED,kGAAkG;AAClG,MAAM,CAAC,KAAK,UAAU,qBAAqB,CAAC,WAAmB;IAC7D,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAClC,MAAM,qBAAqB,CAAC,IAAI,CAAC,CAAC;IAClC,MAAM,iBAAiB,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,CAAC;IAC/C,IAAI,iBAAiB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,GAAG,CAAC,CAAC,UAAU,EAAE,EAAE;YACnD,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,QAAQ,CAAC;YAC7C,OAAO,GAAG,UAAU,CAAC,QAAQ,IAAI,IAAI,IAAI,MAAM,IAAI,UAAU,CAAC,IAAI,KAAK,UAAU,CAAC,OAAO,EAAE,CAAC;QAC9F,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACjB,CAAC;IACD,MAAM,OAAO,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,YAAY,IAAI,OAAO,CAAC,CAAC,CAAC;IAC1F,MAAM,eAAe,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC","sourcesContent":["import { dirname, join, resolve } from \"node:path\";\nimport { createRequire } from \"node:module\";\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { checkApp } from \"./check-app.js\";\nimport { prepareProject } from \"./project.js\";\nimport { prepareFrameworkTypeDeclarations, projectNames } from \"./type-declarations.js\";\n\nconst execute = promisify(execFile);\nconst require = createRequire(import.meta.url);\n\nasync function checkTypeScript(configs: readonly string[]): Promise<void> {\n const compiler = join(dirname(require.resolve(\"typescript/package.json\")), \"bin\", \"tsc\");\n for (const config of configs) {\n try { await execute(process.execPath, [compiler, \"-p\", config, \"--noEmit\"]); }\n catch (error) {\n const failure = error as Error & { stdout?: string; stderr?: string };\n throw new Error(`TypeScript check failed (${config}):\\n${failure.stdout ?? \"\"}${failure.stderr ?? \"\"}`);\n }\n }\n}\n\n/** Prepares generated entries, declarations and editor projects without checking sources. */\nexport async function prepareFrameworkTypes(projectRoot: string): Promise<void> {\n const root = resolve(projectRoot);\n await prepareProject(root);\n await prepareFrameworkTypeDeclarations(root);\n}\n\n/** Generates declarations, checks .meeko sources, then checks app/server/shared TS separately. */\nexport async function checkFrameworkProject(projectRoot: string): Promise<void> {\n const root = resolve(projectRoot);\n await prepareFrameworkTypes(root);\n const sourceDiagnostics = await checkApp(root);\n if (sourceDiagnostics.length > 0) {\n throw new Error(sourceDiagnostics.map((diagnostic) => {\n const { line, column } = diagnostic.location;\n return `${diagnostic.filename}:${line}:${column} ${diagnostic.code}: ${diagnostic.message}`;\n }).join(\"\\n\"));\n }\n const configs = projectNames.map((name) => join(root, \".meeko\", `tsconfig.${name}.json`));\n await checkTypeScript(configs);\n}\n"]}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { DomScope } from "../dom.js";
|
|
2
|
+
import type { PageSchema } from "./page.js";
|
|
3
|
+
import type { RouteMiddleware } from "./middleware.js";
|
|
4
|
+
import type { NavigationContext, Navigator, RouteRecord } from "./router.js";
|
|
5
|
+
import { StateStore } from "./state.js";
|
|
6
|
+
/** The public shape emitted by the .meeko compiler. */
|
|
7
|
+
export interface ClientComponent {
|
|
8
|
+
renderWithState(props: Record<string, unknown>): {
|
|
9
|
+
html: string;
|
|
10
|
+
state: Record<string, unknown>;
|
|
11
|
+
};
|
|
12
|
+
renderToString(props: Record<string, unknown>, state?: Record<string, unknown>): string;
|
|
13
|
+
hydrateScope(scope: DomScope, props: Record<string, unknown>, state?: Record<string, unknown>): () => void;
|
|
14
|
+
}
|
|
15
|
+
export interface ClientRoute {
|
|
16
|
+
/** Client-safe loader. Server-only sidecars must not be passed to loadRoute. */
|
|
17
|
+
params?: PageSchema;
|
|
18
|
+
search?: PageSchema;
|
|
19
|
+
load?: (context: NavigationContext & {
|
|
20
|
+
params: Readonly<Record<string, unknown>>;
|
|
21
|
+
search: Readonly<Record<string, unknown>>;
|
|
22
|
+
state: StateStore;
|
|
23
|
+
}) => Promise<unknown> | unknown;
|
|
24
|
+
}
|
|
25
|
+
export interface ClientAppOptions {
|
|
26
|
+
readonly routes: readonly RouteRecord[];
|
|
27
|
+
readonly root: Element;
|
|
28
|
+
readonly payload: string | unknown;
|
|
29
|
+
readonly loadPage: (file: string) => Promise<ClientComponent>;
|
|
30
|
+
readonly loadRoute?: (file: string) => Promise<ClientRoute>;
|
|
31
|
+
/** Runs the same route guards as SSR before a browser navigation fetch. */
|
|
32
|
+
readonly loadMiddleware?: () => Promise<readonly RouteMiddleware[]>;
|
|
33
|
+
/** Fetches public loader data from the SSR handler during browser navigation. */
|
|
34
|
+
readonly serverData?: boolean;
|
|
35
|
+
readonly fetch?: typeof fetch;
|
|
36
|
+
readonly onNavigationError?: (error: unknown) => void;
|
|
37
|
+
readonly browser?: Window;
|
|
38
|
+
}
|
|
39
|
+
export interface ClientApp {
|
|
40
|
+
navigate: Navigator["navigate"];
|
|
41
|
+
readonly state: StateStore;
|
|
42
|
+
dispose(): void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Hydrates the SSR tree and updates only the first changed outlet on navigation.
|
|
46
|
+
* Layout templates render their outlet with <component is="props.outlet"/>.
|
|
47
|
+
*/
|
|
48
|
+
export declare function mountClientApp(options: ClientAppOptions): Promise<ClientApp>;
|