@meekojs/meeko 0.0.2 → 0.0.4

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.
Files changed (146) hide show
  1. package/README.md +40 -2
  2. package/dist/autoimports-ts.d.ts +26 -0
  3. package/dist/autoimports-ts.js +127 -0
  4. package/dist/autoimports-ts.js.map +1 -0
  5. package/dist/autoimports.d.ts +21 -0
  6. package/dist/autoimports.js +285 -0
  7. package/dist/autoimports.js.map +1 -0
  8. package/dist/check.js +35 -23
  9. package/dist/check.js.map +1 -0
  10. package/dist/cli.js +59 -19
  11. package/dist/cli.js.map +1 -0
  12. package/dist/compiler/import-graph.d.ts +8 -0
  13. package/dist/compiler/import-graph.js +33 -0
  14. package/dist/compiler/import-graph.js.map +1 -0
  15. package/dist/compiler/mapping.js +1 -0
  16. package/dist/compiler/mapping.js.map +1 -0
  17. package/dist/compiler/project-root.d.ts +2 -0
  18. package/dist/compiler/project-root.js +18 -0
  19. package/dist/compiler/project-root.js.map +1 -0
  20. package/dist/compiler/sfc.js +1 -0
  21. package/dist/compiler/sfc.js.map +1 -0
  22. package/dist/compiler/sourcemap.d.ts +3 -0
  23. package/dist/compiler/sourcemap.js +75 -0
  24. package/dist/compiler/sourcemap.js.map +1 -0
  25. package/dist/compiler/template.js +1 -0
  26. package/dist/compiler/template.js.map +1 -0
  27. package/dist/compiler.js +22 -11
  28. package/dist/compiler.js.map +1 -0
  29. package/dist/devtools-ui/index.js +56 -6
  30. package/dist/devtools-ui/index.js.map +1 -0
  31. package/dist/devtools.d.ts +9 -0
  32. package/dist/devtools.js +16 -6
  33. package/dist/devtools.js.map +1 -0
  34. package/dist/dom.d.ts +17 -6
  35. package/dist/dom.js +86 -19
  36. package/dist/dom.js.map +1 -0
  37. package/dist/framework/check-app.d.ts +5 -0
  38. package/dist/framework/check-app.js +59 -0
  39. package/dist/framework/check-app.js.map +1 -0
  40. package/dist/framework/client.d.ts +45 -0
  41. package/dist/framework/client.js +146 -0
  42. package/dist/framework/client.js.map +1 -0
  43. package/dist/framework/clients.d.ts +82 -0
  44. package/dist/framework/clients.js +182 -0
  45. package/dist/framework/clients.js.map +1 -0
  46. package/dist/framework/config-type.d.ts +10 -0
  47. package/dist/framework/config-type.js +4 -0
  48. package/dist/framework/config-type.js.map +1 -0
  49. package/dist/framework/config.d.ts +15 -0
  50. package/dist/framework/config.js +138 -0
  51. package/dist/framework/config.js.map +1 -0
  52. package/dist/framework/contracts-generate.d.ts +8 -0
  53. package/dist/framework/contracts-generate.js +227 -0
  54. package/dist/framework/contracts-generate.js.map +1 -0
  55. package/dist/framework/generate.d.ts +7 -0
  56. package/dist/framework/generate.js +67 -0
  57. package/dist/framework/generate.js.map +1 -0
  58. package/dist/framework/init.d.ts +2 -0
  59. package/dist/framework/init.js +362 -0
  60. package/dist/framework/init.js.map +1 -0
  61. package/dist/framework/modules.d.ts +22 -0
  62. package/dist/framework/modules.js +29 -0
  63. package/dist/framework/modules.js.map +1 -0
  64. package/dist/framework/page.d.ts +60 -0
  65. package/dist/framework/page.js +42 -0
  66. package/dist/framework/page.js.map +1 -0
  67. package/dist/framework/prerender.d.ts +14 -0
  68. package/dist/framework/prerender.js +104 -0
  69. package/dist/framework/prerender.js.map +1 -0
  70. package/dist/framework/router.d.ts +39 -0
  71. package/dist/framework/router.js +173 -0
  72. package/dist/framework/router.js.map +1 -0
  73. package/dist/framework/server.d.ts +51 -0
  74. package/dist/framework/server.js +192 -0
  75. package/dist/framework/server.js.map +1 -0
  76. package/dist/framework/socket-contracts-generate.d.ts +5 -0
  77. package/dist/framework/socket-contracts-generate.js +159 -0
  78. package/dist/framework/socket-contracts-generate.js.map +1 -0
  79. package/dist/framework/socket.d.ts +70 -0
  80. package/dist/framework/socket.js +150 -0
  81. package/dist/framework/socket.js.map +1 -0
  82. package/dist/framework/state.d.ts +15 -0
  83. package/dist/framework/state.js +72 -0
  84. package/dist/framework/state.js.map +1 -0
  85. package/dist/framework-server/auto-clients.d.ts +3 -0
  86. package/dist/framework-server/auto-clients.js +27 -0
  87. package/dist/framework-server/auto-clients.js.map +1 -0
  88. package/dist/framework-server/context.d.ts +21 -0
  89. package/dist/framework-server/context.js +22 -0
  90. package/dist/framework-server/context.js.map +1 -0
  91. package/dist/framework-server/contracts.d.ts +64 -0
  92. package/dist/framework-server/contracts.js +129 -0
  93. package/dist/framework-server/contracts.js.map +1 -0
  94. package/dist/framework-server/discovery.d.ts +40 -0
  95. package/dist/framework-server/discovery.js +252 -0
  96. package/dist/framework-server/discovery.js.map +1 -0
  97. package/dist/framework-server/local.d.ts +19 -0
  98. package/dist/framework-server/local.js +98 -0
  99. package/dist/framework-server/local.js.map +1 -0
  100. package/dist/framework-server/node-upgrade.d.ts +23 -0
  101. package/dist/framework-server/node-upgrade.js +78 -0
  102. package/dist/framework-server/node-upgrade.js.map +1 -0
  103. package/dist/framework-server/node-websocket.d.ts +16 -0
  104. package/dist/framework-server/node-websocket.js +125 -0
  105. package/dist/framework-server/node-websocket.js.map +1 -0
  106. package/dist/framework-server/openapi.d.ts +17 -0
  107. package/dist/framework-server/openapi.js +118 -0
  108. package/dist/framework-server/openapi.js.map +1 -0
  109. package/dist/framework-server/session-stores.d.ts +66 -0
  110. package/dist/framework-server/session-stores.js +96 -0
  111. package/dist/framework-server/session-stores.js.map +1 -0
  112. package/dist/framework-server/sessions.d.ts +64 -0
  113. package/dist/framework-server/sessions.js +136 -0
  114. package/dist/framework-server/sessions.js.map +1 -0
  115. package/dist/framework-server/socket.d.ts +83 -0
  116. package/dist/framework-server/socket.js +161 -0
  117. package/dist/framework-server/socket.js.map +1 -0
  118. package/dist/framework-server.d.ts +21 -0
  119. package/dist/framework-server.js +12 -0
  120. package/dist/framework-server.js.map +1 -0
  121. package/dist/framework.d.ts +29 -0
  122. package/dist/framework.js +13 -0
  123. package/dist/framework.js.map +1 -0
  124. package/dist/hmr.js +1 -0
  125. package/dist/hmr.js.map +1 -0
  126. package/dist/index.d.ts +3 -3
  127. package/dist/index.js +2 -1
  128. package/dist/index.js.map +1 -0
  129. package/dist/init.d.ts +2 -0
  130. package/dist/init.js +209 -0
  131. package/dist/init.js.map +1 -0
  132. package/dist/internal.js +1 -0
  133. package/dist/internal.js.map +1 -0
  134. package/dist/node.d.ts +12 -0
  135. package/dist/node.js +52 -0
  136. package/dist/node.js.map +1 -0
  137. package/dist/reactivity.d.ts +25 -1
  138. package/dist/reactivity.js +69 -10
  139. package/dist/reactivity.js.map +1 -0
  140. package/dist/server.js +1 -0
  141. package/dist/server.js.map +1 -0
  142. package/dist/types.js +23 -8
  143. package/dist/types.js.map +1 -0
  144. package/dist/vite.js +91 -6
  145. package/dist/vite.js.map +1 -0
  146. package/package.json +19 -3
@@ -0,0 +1,227 @@
1
+ import { mkdir, readFile, writeFile } from "node:fs/promises";
2
+ import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
3
+ import ts from "@typescript/typescript6";
4
+ import { discoverServerManifest } from "../framework-server/discovery.js";
5
+ import { generateSocketContracts } from "./socket-contracts-generate.js";
6
+ async function writeIfChanged(file, source) {
7
+ try {
8
+ if (await readFile(file, "utf8") === source)
9
+ return;
10
+ }
11
+ catch (error) {
12
+ if (error.code !== "ENOENT")
13
+ throw error;
14
+ }
15
+ await writeFile(file, source, "utf8");
16
+ }
17
+ function inside(parent, child) {
18
+ const path = relative(parent, child);
19
+ return path === "" || (path !== ".." && !path.startsWith(`..${sep}`) && !isAbsolute(path));
20
+ }
21
+ function optionsFor(root) {
22
+ const config = ts.findConfigFile(root, ts.sys.fileExists, "tsconfig.json");
23
+ if (!config)
24
+ return { module: ts.ModuleKind.NodeNext, moduleResolution: ts.ModuleResolutionKind.NodeNext, target: ts.ScriptTarget.ES2022, skipLibCheck: true };
25
+ const loaded = ts.readConfigFile(config, ts.sys.readFile);
26
+ if (loaded.error)
27
+ throw new Error(ts.flattenDiagnosticMessageText(loaded.error.messageText, "\n"));
28
+ return ts.parseJsonConfigFileContent(loaded.config, ts.sys, dirname(config)).options;
29
+ }
30
+ function resolvedImport(specifier, importer, options) {
31
+ return ts.resolveModuleName(specifier, importer, options, ts.sys).resolvedModule?.resolvedFileName;
32
+ }
33
+ function importMap(file, sharedRoot, options) {
34
+ const imports = new Map();
35
+ for (const statement of file.statements) {
36
+ if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier))
37
+ continue;
38
+ const specifier = statement.moduleSpecifier.text;
39
+ const target = resolvedImport(specifier, file.fileName, options);
40
+ if (!target || !inside(sharedRoot, target))
41
+ continue;
42
+ const clause = statement.importClause;
43
+ if (!clause)
44
+ continue;
45
+ if (clause.name)
46
+ imports.set(clause.name.text, { file: target, exported: "default" });
47
+ if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {
48
+ for (const element of clause.namedBindings.elements)
49
+ imports.set(element.name.text, { file: target, exported: element.propertyName?.text ?? element.name.text });
50
+ }
51
+ if (clause.namedBindings && ts.isNamespaceImport(clause.namedBindings))
52
+ imports.set(clause.namedBindings.name.text, { file: target, exported: "*" });
53
+ }
54
+ return imports;
55
+ }
56
+ function objectProperty(object, name) {
57
+ const property = object.properties.find((candidate) => {
58
+ if (!ts.isPropertyAssignment(candidate) && !ts.isShorthandPropertyAssignment(candidate))
59
+ return false;
60
+ return candidate.name.getText(object.getSourceFile()).replace(/^['"]|['"]$/g, "") === name;
61
+ });
62
+ if (!property)
63
+ return undefined;
64
+ if (ts.isPropertyAssignment(property))
65
+ return property.initializer;
66
+ return ts.isShorthandPropertyAssignment(property) ? property.name : undefined;
67
+ }
68
+ function definition(file, kind) {
69
+ const assignment = file.statements.find((statement) => ts.isExportAssignment(statement) && !statement.isExportEquals);
70
+ const expression = assignment?.expression;
71
+ const name = kind === "api" ? "defineApiRoute" : "defineRpc";
72
+ if (!expression || !ts.isCallExpression(expression) || !ts.isIdentifier(expression.expression) || expression.expression.text !== name || !expression.arguments[0] || !ts.isObjectLiteralExpression(expression.arguments[0])) {
73
+ throw new Error(`${file.fileName}: public ${kind.toUpperCase()} contract requires export default ${name}({...})`);
74
+ }
75
+ return expression.arguments[0];
76
+ }
77
+ function publicSchema(expression, label, file, imports, checker, root, sharedRoot, options, outputDir) {
78
+ if (!expression)
79
+ return undefined;
80
+ let local;
81
+ let member;
82
+ if (ts.isIdentifier(expression))
83
+ local = expression.text;
84
+ else if (ts.isPropertyAccessExpression(expression) && ts.isIdentifier(expression.expression)) {
85
+ local = expression.expression.text;
86
+ member = expression.name.text;
87
+ }
88
+ else
89
+ throw new Error(`${file.fileName}: ${label} must reference an imported shared schema`);
90
+ const imported = imports.get(local);
91
+ if (!imported)
92
+ throw new Error(`${file.fileName}: ${label} must come from shared/`);
93
+ const exported = imported.exported === "*" ? member : imported.exported;
94
+ if (!exported || (imported.exported !== "*" && member))
95
+ throw new Error(`${file.fileName}: ${label} must reference one shared export`);
96
+ const type = checker.getTypeAtLocation(expression);
97
+ if (type.flags & ts.TypeFlags.Any)
98
+ throw new Error(`${file.fileName}: ${label} has type any; public schema cannot be inferred`);
99
+ validateSharedGraph(imported.file, root, sharedRoot, options, new Set());
100
+ const target = relative(outputDir, imported.file).replaceAll("\\", "/").replace(/\.(?:ts|mts|cts)$/, (suffix) => suffix === ".mts" ? ".mjs" : suffix === ".cts" ? ".cjs" : ".js");
101
+ const specifier = target.startsWith(".") ? target : `./${target}`;
102
+ return `typeof import(${JSON.stringify(specifier)})[${JSON.stringify(exported)}]`;
103
+ }
104
+ function validateSharedGraph(file, root, sharedRoot, options, seen) {
105
+ if (seen.has(file))
106
+ return;
107
+ seen.add(file);
108
+ if (!inside(sharedRoot, file))
109
+ throw new Error(`${file}: public schema dependency escapes shared/`);
110
+ const source = ts.sys.readFile(file);
111
+ if (source === undefined)
112
+ throw new Error(`${file}: public schema dependency not found`);
113
+ const ast = ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true);
114
+ const checkDependency = (specifier) => {
115
+ const target = resolvedImport(specifier, file, options);
116
+ if (!target)
117
+ throw new Error(`${file}: unresolved public schema dependency ${specifier}`);
118
+ if (inside(root, target) && !relative(root, target).split(sep).includes("node_modules"))
119
+ validateSharedGraph(target, root, sharedRoot, options, seen);
120
+ };
121
+ for (const statement of ast.statements) {
122
+ if (!ts.isImportDeclaration(statement) && !ts.isExportDeclaration(statement))
123
+ continue;
124
+ const literal = statement.moduleSpecifier;
125
+ if (!literal || !ts.isStringLiteral(literal))
126
+ continue;
127
+ checkDependency(literal.text);
128
+ }
129
+ const visit = (node) => {
130
+ if (ts.isImportTypeNode(node) && ts.isLiteralTypeNode(node.argument) && ts.isStringLiteral(node.argument.literal))
131
+ checkDependency(node.argument.literal.text);
132
+ ts.forEachChild(node, visit);
133
+ };
134
+ visit(ast);
135
+ }
136
+ function shapeFor(endpoint, checker, program, root, options, outputDir) {
137
+ const file = program.getSourceFile(endpoint.file);
138
+ if (!file)
139
+ throw new Error(`Handler not found: ${endpoint.file}`);
140
+ const sharedRoot = join(root, "shared");
141
+ const imports = importMap(file, sharedRoot, options);
142
+ const kind = endpoint.kind;
143
+ const contract = definition(file, kind);
144
+ const schema = (name) => publicSchema(objectProperty(contract, name), name, file, imports, checker, root, sharedRoot, options, outputDir);
145
+ if (kind === "rpc") {
146
+ const input = schema("input");
147
+ const output = schema("output");
148
+ if (!input || !output)
149
+ throw new Error(`${file.fileName}: RPC requires public input and output schemas`);
150
+ return { type: `import("@meekojs/meeko/framework").RpcOperation<__Input<${input}>, __Output<${output}>>` };
151
+ }
152
+ const params = schema("params");
153
+ const query = schema("query");
154
+ const body = schema("body");
155
+ const response = schema("response");
156
+ const content = objectProperty(contract, "contentType");
157
+ if (content && (!ts.isStringLiteral(content) || (content.text !== "json" && content.text !== "response")))
158
+ throw new Error(`${file.fileName}: contentType must be a static json or response literal`);
159
+ const responseType = content && ts.isStringLiteral(content) && content.text === "response";
160
+ if (!responseType && !response)
161
+ throw new Error(`${file.fileName}: API requires a public response schema`);
162
+ if (endpoint.pathname.includes("[") && !params)
163
+ throw new Error(`${file.fileName}: dynamic API path requires a public params schema`);
164
+ return {
165
+ type: `import("@meekojs/meeko/framework").ApiOperation<${params ? `__Input<${params}>` : "undefined"}, ${query ? `__Input<${query}>` : "undefined"}, ${body ? `__Input<${body}>` : "undefined"}, ${responseType ? "Response" : `__Output<${response}>`}>`,
166
+ ...(responseType ? { contentType: "response" } : {}),
167
+ };
168
+ }
169
+ /** Generate public API/RPC declarations without importing handler modules. */
170
+ export async function generateServerContracts(projectRoot) {
171
+ const root = resolve(projectRoot);
172
+ await generateSocketContracts(root);
173
+ const discovered = await discoverServerManifest(root);
174
+ const outputDir = join(root, ".meeko", "types");
175
+ const types = join(outputDir, "server-contracts.d.ts");
176
+ const manifest = join(root, ".meeko", "manifests", "server.json");
177
+ const generatedDir = join(root, ".meeko", "generated");
178
+ const options = optionsFor(root);
179
+ const files = [...discovered.api, ...discovered.rpc].map((entry) => entry.file);
180
+ const program = ts.createProgram(files, { ...options, noEmit: true });
181
+ const checker = program.getTypeChecker();
182
+ const api = discovered.api.map((endpoint) => ({ endpoint, shape: shapeFor(endpoint, checker, program, root, options, outputDir) }));
183
+ const rpc = discovered.rpc.map((endpoint) => ({ endpoint, shape: shapeFor(endpoint, checker, program, root, options, outputDir) }));
184
+ const apiMethods = new Map();
185
+ for (const { endpoint, shape } of api) {
186
+ const methods = apiMethods.get(endpoint.clientKey) ?? [];
187
+ methods.push(`${endpoint.method.toLowerCase()}: ${shape.type}`);
188
+ apiMethods.set(endpoint.clientKey, methods);
189
+ }
190
+ const lines = [
191
+ "// Generated by Meeko. Public schemas must live in shared/.",
192
+ 'type __Input<S> = S extends { readonly "~standard": { readonly types?: infer T } } ? NonNullable<T> extends { readonly input: infer I } ? I : never : never;',
193
+ 'type __Output<S> = S extends { readonly "~standard": { readonly types?: infer T } } ? NonNullable<T> extends { readonly output: infer O } ? O : never : never;',
194
+ "export type ApiContract = {",
195
+ ...[...apiMethods].map(([key, methods]) => ` ${JSON.stringify(key)}: { ${methods.join("; ")} };`),
196
+ "};",
197
+ "export type RpcContract = {",
198
+ ...rpc.map(({ endpoint, shape }) => ` ${JSON.stringify(endpoint.id)}: ${shape.type};`),
199
+ "};",
200
+ "",
201
+ ];
202
+ await mkdir(outputDir, { recursive: true });
203
+ await mkdir(dirname(manifest), { recursive: true });
204
+ await writeIfChanged(types, lines.join("\n"));
205
+ const publicManifest = { version: 1, api: api.map(({ endpoint, shape }) => ({ clientKey: endpoint.clientKey, pathname: endpoint.pathname, method: endpoint.method, ...(shape.contentType ? { contentType: shape.contentType } : {}) })), rpc: rpc.map(({ endpoint }) => ({ id: endpoint.id, pathname: endpoint.pathname })) };
206
+ await writeIfChanged(manifest, `${JSON.stringify(publicManifest, null, 2)}\n`);
207
+ await mkdir(generatedDir, { recursive: true });
208
+ const clientSource = (server) => [
209
+ "// Generated by Meeko. Contains only public route descriptors and shared contract types.",
210
+ `import { createApiClient, createRpcClient${server ? "" : ", createBrowserClientOptions"} } from "@meekojs/meeko/framework";`,
211
+ 'import { createSocketRegistry, useSocketChannel, type SocketRegistryOptions } from "@meekojs/meeko/framework";',
212
+ ...(server ? ['import { createServerClientOptions } from "@meekojs/meeko/server";'] : []),
213
+ 'import type { ApiContract, RpcContract } from "../types/server-contracts.js";',
214
+ 'import { socketContracts } from "./socket-contracts.js";',
215
+ `const manifest = ${JSON.stringify(publicManifest, null, 2)} as const;`,
216
+ `const options = ${server ? "createServerClientOptions()" : "createBrowserClientOptions()"};`,
217
+ "export const api = createApiClient<ApiContract>(manifest, options);",
218
+ "export const rpc = createRpcClient<RpcContract>(manifest, options);",
219
+ "export const socket = createSocketRegistry(socketContracts);",
220
+ "export const useSocket = <K extends keyof typeof socketContracts & string>(name: K, options?: SocketRegistryOptions) => useSocketChannel(socketContracts, name, options);",
221
+ "",
222
+ ].join("\n");
223
+ await writeIfChanged(join(generatedDir, "clients.client.ts"), clientSource(false));
224
+ await writeIfChanged(join(generatedDir, "clients.server.ts"), clientSource(true));
225
+ return { types, manifest, apiCount: api.length, rpcCount: rpc.length };
226
+ }
227
+ //# sourceMappingURL=contracts-generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contracts-generate.js","sourceRoot":"","sources":["../../src/framework/contracts-generate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAC9E,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAE1E,OAAO,EAAE,uBAAuB,EAAE,MAAM,gCAAgC,CAAC;AASzE,KAAK,UAAU,cAAc,CAAC,IAAY,EAAE,MAAc;IACxD,IAAI,CAAC;QAAC,IAAI,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,KAAK,MAAM;YAAE,OAAO;IAAC,CAAC;IAC5D,OAAO,KAAK,EAAE,CAAC;QAAC,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,KAAK,CAAC;IAAC,CAAC;IACtF,MAAM,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;AACxC,CAAC;AAKD,SAAS,MAAM,CAAC,MAAc,EAAE,KAAa;IAC3C,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACrC,OAAO,IAAI,KAAK,EAAE,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7F,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,MAAM,MAAM,GAAG,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,EAAE,CAAC,GAAG,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC;IAC3E,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,gBAAgB,EAAE,EAAE,CAAC,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,CAAC;IAC/J,MAAM,MAAM,GAAG,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC1D,IAAI,MAAM,CAAC,KAAK;QAAE,MAAM,IAAI,KAAK,CAAC,EAAE,CAAC,4BAA4B,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC,CAAC;IACnG,OAAO,EAAE,CAAC,0BAA0B,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;AACvF,CAAC;AAED,SAAS,cAAc,CAAC,SAAiB,EAAE,QAAgB,EAAE,OAA2B;IACtF,OAAO,EAAE,CAAC,iBAAiB,CAAC,SAAS,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,cAAc,EAAE,gBAAgB,CAAC;AACrG,CAAC;AAED,SAAS,SAAS,CAAC,IAAmB,EAAE,UAAkB,EAAE,OAA2B;IACrF,MAAM,OAAO,GAAY,IAAI,GAAG,EAAE,CAAC;IACnC,KAAK,MAAM,SAAS,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QACxC,IAAI,CAAC,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,SAAS,CAAC,eAAe,CAAC;YAAE,SAAS;QACnG,MAAM,SAAS,GAAG,SAAS,CAAC,eAAe,CAAC,IAAI,CAAC;QACjD,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACjE,IAAI,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC;YAAE,SAAS;QACrD,MAAM,MAAM,GAAG,SAAS,CAAC,YAAY,CAAC;QACtC,IAAI,CAAC,MAAM;YAAE,SAAS;QACtB,IAAI,MAAM,CAAC,IAAI;YAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC;QACtF,IAAI,MAAM,CAAC,aAAa,IAAI,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;YACpE,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,aAAa,CAAC,QAAQ;gBAAE,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,CAAC,YAAY,EAAE,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QACnK,CAAC;QACD,IAAI,MAAM,CAAC,aAAa,IAAI,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,aAAa,CAAC;YAAE,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;IACvJ,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,cAAc,CAAC,MAAkC,EAAE,IAAY;IACtE,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE;QACpD,IAAI,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,6BAA6B,CAAC,SAAS,CAAC;YAAE,OAAO,KAAK,CAAC;QACtG,OAAO,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC;IAC7F,CAAC,CAAC,CAAC;IACH,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IAChC,IAAI,EAAE,CAAC,oBAAoB,CAAC,QAAQ,CAAC;QAAE,OAAO,QAAQ,CAAC,WAAW,CAAC;IACnE,OAAO,EAAE,CAAC,6BAA6B,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;AAChF,CAAC;AAED,SAAS,UAAU,CAAC,IAAmB,EAAE,IAAU;IACjD,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,SAAS,EAAoC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC;IACxJ,MAAM,UAAU,GAAG,UAAU,EAAE,UAAU,CAAC;IAC1C,MAAM,IAAI,GAAG,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,WAAW,CAAC;IAC7D,IAAI,CAAC,UAAU,IAAI,CAAC,EAAE,CAAC,gBAAgB,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,UAAU,CAAC,IAAI,KAAK,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,yBAAyB,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAC5N,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,YAAY,IAAI,CAAC,WAAW,EAAE,qCAAqC,IAAI,SAAS,CAAC,CAAC;IACpH,CAAC;IACD,OAAO,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,YAAY,CAAC,UAAqC,EAAE,KAAa,EAAE,IAAmB,EAAE,OAAgB,EAAE,OAAuB,EAAE,IAAY,EAAE,UAAkB,EAAE,OAA2B,EAAE,SAAiB;IAC1N,IAAI,CAAC,UAAU;QAAE,OAAO,SAAS,CAAC;IAClC,IAAI,KAAa,CAAC;IAClB,IAAI,MAA0B,CAAC;IAC/B,IAAI,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC;QAAE,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC;SACpD,IAAI,EAAE,CAAC,0BAA0B,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAAC,KAAK,GAAG,UAAU,CAAC,UAAU,CAAC,IAAI,CAAC;QAAC,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;IAAC,CAAC;;QAC/J,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,KAAK,KAAK,2CAA2C,CAAC,CAAC;IAC5F,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;IACpC,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,KAAK,KAAK,yBAAyB,CAAC,CAAC;IACpF,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,KAAK,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;IACxE,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,QAAQ,KAAK,GAAG,IAAI,MAAM,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,KAAK,KAAK,mCAAmC,CAAC,CAAC;IACvI,MAAM,IAAI,GAAG,OAAO,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;IACnD,IAAI,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,KAAK,KAAK,iDAAiD,CAAC,CAAC;IAChI,mBAAmB,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,CAAC,CAAC;IACzE,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,mBAAmB,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAClL,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;IAClE,OAAO,iBAAiB,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC;AACpF,CAAC;AAED,SAAS,mBAAmB,CAAC,IAAY,EAAE,IAAY,EAAE,UAAkB,EAAE,OAA2B,EAAE,IAAiB;IACzH,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;QAAE,OAAO;IAC3B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACf,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,4CAA4C,CAAC,CAAC;IACpG,MAAM,MAAM,GAAG,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,MAAM,KAAK,SAAS;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,sCAAsC,CAAC,CAAC;IACzF,MAAM,GAAG,GAAG,EAAE,CAAC,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC5E,MAAM,eAAe,GAAG,CAAC,SAAiB,EAAQ,EAAE;QAClD,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,EAAE,IAAI,EAAE,OAAO,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,yCAAyC,SAAS,EAAE,CAAC,CAAC;QAC1F,IAAI,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC;YAAE,mBAAmB,CAAC,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,CAAC;IACxJ,CAAC,CAAC;IACF,KAAK,MAAM,SAAS,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QACvC,IAAI,CAAC,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC;YAAE,SAAS;QACvF,MAAM,OAAO,GAAG,SAAS,CAAC,eAAe,CAAC;QAC1C,IAAI,CAAC,OAAO,IAAI,CAAC,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC;YAAE,SAAS;QACvD,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IACD,MAAM,KAAK,GAAG,CAAC,IAAa,EAAQ,EAAE;QACpC,IAAI,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;YAAE,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC/J,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAC/B,CAAC,CAAC;IACF,KAAK,CAAC,GAAG,CAAC,CAAC;AACb,CAAC;AAED,SAAS,QAAQ,CAAC,QAAmC,EAAE,OAAuB,EAAE,OAAmB,EAAE,IAAY,EAAE,OAA2B,EAAE,SAAiB;IAC/J,MAAM,IAAI,GAAG,OAAO,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAClD,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,sBAAsB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IAClE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IACxC,MAAM,OAAO,GAAG,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,CAAC,CAAC;IACrD,MAAM,IAAI,GAAS,QAAQ,CAAC,IAAI,CAAC;IACjC,MAAM,QAAQ,GAAG,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACxC,MAAM,MAAM,GAAG,CAAC,IAAY,EAAsB,EAAE,CAAC,YAAY,CAAC,cAAc,CAAC,QAAQ,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IACtK,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACnB,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;QAChC,IAAI,CAAC,KAAK,IAAI,CAAC,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,gDAAgD,CAAC,CAAC;QACzG,OAAO,EAAE,IAAI,EAAE,2DAA2D,KAAK,eAAe,MAAM,IAAI,EAAE,CAAC;IAC7G,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;IAChC,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC9B,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IAC5B,MAAM,QAAQ,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;IACpC,MAAM,OAAO,GAAG,cAAc,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC;IACxD,IAAI,OAAO,IAAI,CAAC,CAAC,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,KAAK,MAAM,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,yDAAyD,CAAC,CAAC;IACtM,MAAM,YAAY,GAAG,OAAO,IAAI,EAAE,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,KAAK,UAAU,CAAC;IAC3F,IAAI,CAAC,YAAY,IAAI,CAAC,QAAQ;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,yCAAyC,CAAC,CAAC;IAC3G,IAAI,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,QAAQ,oDAAoD,CAAC,CAAC;IACtI,OAAO;QACL,IAAI,EAAE,mDAAmD,MAAM,CAAC,CAAC,CAAC,WAAW,MAAM,GAAG,CAAC,CAAC,CAAC,WAAW,KAAK,KAAK,CAAC,CAAC,CAAC,WAAW,KAAK,GAAG,CAAC,CAAC,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,WAAW,IAAI,GAAG,CAAC,CAAC,CAAC,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,QAAQ,GAAG,GAAG;QACzP,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,UAAmB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC9D,CAAC;AACJ,CAAC;AAED,8EAA8E;AAC9E,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,WAAmB;IAC/D,MAAM,IAAI,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IAClC,MAAM,uBAAuB,CAAC,IAAI,CAAC,CAAC;IACpC,MAAM,UAAU,GAAG,MAAM,sBAAsB,CAAC,IAAI,CAAC,CAAC;IACtD,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,EAAE,uBAAuB,CAAC,CAAC;IACvD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,CAAC,CAAC;IAClE,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;IACvD,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;IACjC,MAAM,KAAK,GAAG,CAAC,GAAG,UAAU,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChF,MAAM,OAAO,GAAG,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,EAAE,GAAG,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACtE,MAAM,OAAO,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IACzC,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IACpI,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;IACpI,MAAM,UAAU,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC/C,KAAK,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,GAAG,EAAE,CAAC;QACtC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QACzD,OAAO,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAChE,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC9C,CAAC;IACD,MAAM,KAAK,GAAG;QACZ,6DAA6D;QAC7D,8JAA8J;QAC9J,gKAAgK;QAChK,6BAA6B;QAC7B,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;QAClG,IAAI;QACJ,6BAA6B;QAC7B,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,KAAK,CAAC,IAAI,GAAG,CAAC;QACvF,IAAI;QACJ,EAAE;KACH,CAAC;IACF,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACpD,MAAM,cAAc,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,MAAM,cAAc,GAAG,EAAE,OAAO,EAAE,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,QAAQ,CAAC,SAAS,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,EAAE,EAAE,QAAQ,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,CAAC;IAC9T,MAAM,cAAc,CAAC,QAAQ,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAC/E,MAAM,KAAK,CAAC,YAAY,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/C,MAAM,YAAY,GAAG,CAAC,MAAe,EAAU,EAAE,CAAC;QAChD,0FAA0F;QAC1F,4CAA4C,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,8BAA8B,qCAAqC;QAC7H,gHAAgH;QAChH,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,oEAAoE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACzF,+EAA+E;QAC/E,0DAA0D;QAC1D,oBAAoB,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,YAAY;QACvE,mBAAmB,MAAM,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,8BAA8B,GAAG;QAC7F,qEAAqE;QACrE,qEAAqE;QACrE,8DAA8D;QAC9D,2KAA2K;QAC3K,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,MAAM,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,mBAAmB,CAAC,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;IACnF,MAAM,cAAc,CAAC,IAAI,CAAC,YAAY,EAAE,mBAAmB,CAAC,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;IAClF,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC;AACzE,CAAC","sourcesContent":["import { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { dirname, isAbsolute, join, relative, resolve, sep } from \"node:path\";\nimport ts from \"@typescript/typescript6\";\nimport { discoverServerManifest } from \"../framework-server/discovery.js\";\nimport type { ApiEndpoint, RpcEndpoint } from \"../framework-server/discovery.js\";\nimport { generateSocketContracts } from \"./socket-contracts-generate.js\";\n\nexport interface GeneratedServerContracts {\n readonly types: string;\n readonly manifest: string;\n readonly apiCount: number;\n readonly rpcCount: number;\n}\n\nasync function writeIfChanged(file: string, source: string): Promise<void> {\n try { if (await readFile(file, \"utf8\") === source) return; }\n catch (error) { if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") throw error; }\n await writeFile(file, source, \"utf8\");\n}\n\ntype Kind = \"api\" | \"rpc\";\ntype Imports = Map<string, { file: string; exported: string }>;\n\nfunction inside(parent: string, child: string): boolean {\n const path = relative(parent, child);\n return path === \"\" || (path !== \"..\" && !path.startsWith(`..${sep}`) && !isAbsolute(path));\n}\n\nfunction optionsFor(root: string): ts.CompilerOptions {\n const config = ts.findConfigFile(root, ts.sys.fileExists, \"tsconfig.json\");\n if (!config) return { module: ts.ModuleKind.NodeNext, moduleResolution: ts.ModuleResolutionKind.NodeNext, target: ts.ScriptTarget.ES2022, skipLibCheck: true };\n const loaded = ts.readConfigFile(config, ts.sys.readFile);\n if (loaded.error) throw new Error(ts.flattenDiagnosticMessageText(loaded.error.messageText, \"\\n\"));\n return ts.parseJsonConfigFileContent(loaded.config, ts.sys, dirname(config)).options;\n}\n\nfunction resolvedImport(specifier: string, importer: string, options: ts.CompilerOptions): string | undefined {\n return ts.resolveModuleName(specifier, importer, options, ts.sys).resolvedModule?.resolvedFileName;\n}\n\nfunction importMap(file: ts.SourceFile, sharedRoot: string, options: ts.CompilerOptions): Imports {\n const imports: Imports = new Map();\n for (const statement of file.statements) {\n if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier)) continue;\n const specifier = statement.moduleSpecifier.text;\n const target = resolvedImport(specifier, file.fileName, options);\n if (!target || !inside(sharedRoot, target)) continue;\n const clause = statement.importClause;\n if (!clause) continue;\n if (clause.name) imports.set(clause.name.text, { file: target, exported: \"default\" });\n if (clause.namedBindings && ts.isNamedImports(clause.namedBindings)) {\n for (const element of clause.namedBindings.elements) imports.set(element.name.text, { file: target, exported: element.propertyName?.text ?? element.name.text });\n }\n if (clause.namedBindings && ts.isNamespaceImport(clause.namedBindings)) imports.set(clause.namedBindings.name.text, { file: target, exported: \"*\" });\n }\n return imports;\n}\n\nfunction objectProperty(object: ts.ObjectLiteralExpression, name: string): ts.Expression | undefined {\n const property = object.properties.find((candidate) => {\n if (!ts.isPropertyAssignment(candidate) && !ts.isShorthandPropertyAssignment(candidate)) return false;\n return candidate.name.getText(object.getSourceFile()).replace(/^['\"]|['\"]$/g, \"\") === name;\n });\n if (!property) return undefined;\n if (ts.isPropertyAssignment(property)) return property.initializer;\n return ts.isShorthandPropertyAssignment(property) ? property.name : undefined;\n}\n\nfunction definition(file: ts.SourceFile, kind: Kind): ts.ObjectLiteralExpression {\n const assignment = file.statements.find((statement): statement is ts.ExportAssignment => ts.isExportAssignment(statement) && !statement.isExportEquals);\n const expression = assignment?.expression;\n const name = kind === \"api\" ? \"defineApiRoute\" : \"defineRpc\";\n if (!expression || !ts.isCallExpression(expression) || !ts.isIdentifier(expression.expression) || expression.expression.text !== name || !expression.arguments[0] || !ts.isObjectLiteralExpression(expression.arguments[0])) {\n throw new Error(`${file.fileName}: public ${kind.toUpperCase()} contract requires export default ${name}({...})`);\n }\n return expression.arguments[0];\n}\n\nfunction publicSchema(expression: ts.Expression | undefined, label: string, file: ts.SourceFile, imports: Imports, checker: ts.TypeChecker, root: string, sharedRoot: string, options: ts.CompilerOptions, outputDir: string): string | undefined {\n if (!expression) return undefined;\n let local: string;\n let member: string | undefined;\n if (ts.isIdentifier(expression)) local = expression.text;\n else if (ts.isPropertyAccessExpression(expression) && ts.isIdentifier(expression.expression)) { local = expression.expression.text; member = expression.name.text; }\n else throw new Error(`${file.fileName}: ${label} must reference an imported shared schema`);\n const imported = imports.get(local);\n if (!imported) throw new Error(`${file.fileName}: ${label} must come from shared/`);\n const exported = imported.exported === \"*\" ? member : imported.exported;\n if (!exported || (imported.exported !== \"*\" && member)) throw new Error(`${file.fileName}: ${label} must reference one shared export`);\n const type = checker.getTypeAtLocation(expression);\n if (type.flags & ts.TypeFlags.Any) throw new Error(`${file.fileName}: ${label} has type any; public schema cannot be inferred`);\n validateSharedGraph(imported.file, root, sharedRoot, options, new Set());\n const target = relative(outputDir, imported.file).replaceAll(\"\\\\\", \"/\").replace(/\\.(?:ts|mts|cts)$/, (suffix) => suffix === \".mts\" ? \".mjs\" : suffix === \".cts\" ? \".cjs\" : \".js\");\n const specifier = target.startsWith(\".\") ? target : `./${target}`;\n return `typeof import(${JSON.stringify(specifier)})[${JSON.stringify(exported)}]`;\n}\n\nfunction validateSharedGraph(file: string, root: string, sharedRoot: string, options: ts.CompilerOptions, seen: Set<string>): void {\n if (seen.has(file)) return;\n seen.add(file);\n if (!inside(sharedRoot, file)) throw new Error(`${file}: public schema dependency escapes shared/`);\n const source = ts.sys.readFile(file);\n if (source === undefined) throw new Error(`${file}: public schema dependency not found`);\n const ast = ts.createSourceFile(file, source, ts.ScriptTarget.Latest, true);\n const checkDependency = (specifier: string): void => {\n const target = resolvedImport(specifier, file, options);\n if (!target) throw new Error(`${file}: unresolved public schema dependency ${specifier}`);\n if (inside(root, target) && !relative(root, target).split(sep).includes(\"node_modules\")) validateSharedGraph(target, root, sharedRoot, options, seen);\n };\n for (const statement of ast.statements) {\n if (!ts.isImportDeclaration(statement) && !ts.isExportDeclaration(statement)) continue;\n const literal = statement.moduleSpecifier;\n if (!literal || !ts.isStringLiteral(literal)) continue;\n checkDependency(literal.text);\n }\n const visit = (node: ts.Node): void => {\n if (ts.isImportTypeNode(node) && ts.isLiteralTypeNode(node.argument) && ts.isStringLiteral(node.argument.literal)) checkDependency(node.argument.literal.text);\n ts.forEachChild(node, visit);\n };\n visit(ast);\n}\n\nfunction shapeFor(endpoint: ApiEndpoint | RpcEndpoint, checker: ts.TypeChecker, program: ts.Program, root: string, options: ts.CompilerOptions, outputDir: string): { type: string; contentType?: \"response\" } {\n const file = program.getSourceFile(endpoint.file);\n if (!file) throw new Error(`Handler not found: ${endpoint.file}`);\n const sharedRoot = join(root, \"shared\");\n const imports = importMap(file, sharedRoot, options);\n const kind: Kind = endpoint.kind;\n const contract = definition(file, kind);\n const schema = (name: string): string | undefined => publicSchema(objectProperty(contract, name), name, file, imports, checker, root, sharedRoot, options, outputDir);\n if (kind === \"rpc\") {\n const input = schema(\"input\");\n const output = schema(\"output\");\n if (!input || !output) throw new Error(`${file.fileName}: RPC requires public input and output schemas`);\n return { type: `import(\"@meekojs/meeko/framework\").RpcOperation<__Input<${input}>, __Output<${output}>>` };\n }\n const params = schema(\"params\");\n const query = schema(\"query\");\n const body = schema(\"body\");\n const response = schema(\"response\");\n const content = objectProperty(contract, \"contentType\");\n if (content && (!ts.isStringLiteral(content) || (content.text !== \"json\" && content.text !== \"response\"))) throw new Error(`${file.fileName}: contentType must be a static json or response literal`);\n const responseType = content && ts.isStringLiteral(content) && content.text === \"response\";\n if (!responseType && !response) throw new Error(`${file.fileName}: API requires a public response schema`);\n if (endpoint.pathname.includes(\"[\") && !params) throw new Error(`${file.fileName}: dynamic API path requires a public params schema`);\n return {\n type: `import(\"@meekojs/meeko/framework\").ApiOperation<${params ? `__Input<${params}>` : \"undefined\"}, ${query ? `__Input<${query}>` : \"undefined\"}, ${body ? `__Input<${body}>` : \"undefined\"}, ${responseType ? \"Response\" : `__Output<${response}>`}>`,\n ...(responseType ? { contentType: \"response\" as const } : {}),\n };\n}\n\n/** Generate public API/RPC declarations without importing handler modules. */\nexport async function generateServerContracts(projectRoot: string): Promise<GeneratedServerContracts> {\n const root = resolve(projectRoot);\n await generateSocketContracts(root);\n const discovered = await discoverServerManifest(root);\n const outputDir = join(root, \".meeko\", \"types\");\n const types = join(outputDir, \"server-contracts.d.ts\");\n const manifest = join(root, \".meeko\", \"manifests\", \"server.json\");\n const generatedDir = join(root, \".meeko\", \"generated\");\n const options = optionsFor(root);\n const files = [...discovered.api, ...discovered.rpc].map((entry) => entry.file);\n const program = ts.createProgram(files, { ...options, noEmit: true });\n const checker = program.getTypeChecker();\n const api = discovered.api.map((endpoint) => ({ endpoint, shape: shapeFor(endpoint, checker, program, root, options, outputDir) }));\n const rpc = discovered.rpc.map((endpoint) => ({ endpoint, shape: shapeFor(endpoint, checker, program, root, options, outputDir) }));\n const apiMethods = new Map<string, string[]>();\n for (const { endpoint, shape } of api) {\n const methods = apiMethods.get(endpoint.clientKey) ?? [];\n methods.push(`${endpoint.method.toLowerCase()}: ${shape.type}`);\n apiMethods.set(endpoint.clientKey, methods);\n }\n const lines = [\n \"// Generated by Meeko. Public schemas must live in shared/.\",\n 'type __Input<S> = S extends { readonly \"~standard\": { readonly types?: infer T } } ? NonNullable<T> extends { readonly input: infer I } ? I : never : never;',\n 'type __Output<S> = S extends { readonly \"~standard\": { readonly types?: infer T } } ? NonNullable<T> extends { readonly output: infer O } ? O : never : never;',\n \"export type ApiContract = {\",\n ...[...apiMethods].map(([key, methods]) => ` ${JSON.stringify(key)}: { ${methods.join(\"; \")} };`),\n \"};\",\n \"export type RpcContract = {\",\n ...rpc.map(({ endpoint, shape }) => ` ${JSON.stringify(endpoint.id)}: ${shape.type};`),\n \"};\",\n \"\",\n ];\n await mkdir(outputDir, { recursive: true });\n await mkdir(dirname(manifest), { recursive: true });\n await writeIfChanged(types, lines.join(\"\\n\"));\n const publicManifest = { version: 1, api: api.map(({ endpoint, shape }) => ({ clientKey: endpoint.clientKey, pathname: endpoint.pathname, method: endpoint.method, ...(shape.contentType ? { contentType: shape.contentType } : {}) })), rpc: rpc.map(({ endpoint }) => ({ id: endpoint.id, pathname: endpoint.pathname })) };\n await writeIfChanged(manifest, `${JSON.stringify(publicManifest, null, 2)}\\n`);\n await mkdir(generatedDir, { recursive: true });\n const clientSource = (server: boolean): string => [\n \"// Generated by Meeko. Contains only public route descriptors and shared contract types.\",\n `import { createApiClient, createRpcClient${server ? \"\" : \", createBrowserClientOptions\"} } from \"@meekojs/meeko/framework\";`,\n 'import { createSocketRegistry, useSocketChannel, type SocketRegistryOptions } from \"@meekojs/meeko/framework\";',\n ...(server ? ['import { createServerClientOptions } from \"@meekojs/meeko/server\";'] : []),\n 'import type { ApiContract, RpcContract } from \"../types/server-contracts.js\";',\n 'import { socketContracts } from \"./socket-contracts.js\";',\n `const manifest = ${JSON.stringify(publicManifest, null, 2)} as const;`,\n `const options = ${server ? \"createServerClientOptions()\" : \"createBrowserClientOptions()\"};`,\n \"export const api = createApiClient<ApiContract>(manifest, options);\",\n \"export const rpc = createRpcClient<RpcContract>(manifest, options);\",\n \"export const socket = createSocketRegistry(socketContracts);\",\n \"export const useSocket = <K extends keyof typeof socketContracts & string>(name: K, options?: SocketRegistryOptions) => useSocketChannel(socketContracts, name, options);\",\n \"\",\n ].join(\"\\n\");\n await writeIfChanged(join(generatedDir, \"clients.client.ts\"), clientSource(false));\n await writeIfChanged(join(generatedDir, \"clients.server.ts\"), clientSource(true));\n return { types, manifest, apiCount: api.length, rpcCount: rpc.length };\n}\n"]}
@@ -0,0 +1,7 @@
1
+ export interface GeneratedRouteFiles {
2
+ readonly types: string;
3
+ readonly manifest: string;
4
+ readonly count: number;
5
+ }
6
+ /** Generates public route types and a portable manifest from one route discovery pass. */
7
+ export declare function generateRoutes(projectRoot: string): Promise<GeneratedRouteFiles>;
@@ -0,0 +1,67 @@
1
+ import { mkdir, writeFile } from "node:fs/promises";
2
+ import { join, relative, resolve } from "node:path";
3
+ import { discoverConfiguredRoutes } from "./config.js";
4
+ function paramsFor(id) {
5
+ const params = [];
6
+ for (const part of id.split("/").filter(Boolean)) {
7
+ const match = /^\[(?:\.\.\.)?([A-Za-z_$][\w$]*)\]$/.exec(part);
8
+ if (!match)
9
+ continue;
10
+ const name = match[1];
11
+ if (params.includes(name))
12
+ throw new Error(`Duplicate route parameter ${name} in ${id}`);
13
+ params.push(name);
14
+ }
15
+ return params;
16
+ }
17
+ function portable(root, file) {
18
+ const path = relative(root, file).replaceAll("\\", "/");
19
+ if (path.startsWith("../") || path === "..")
20
+ throw new Error(`Route file escapes project root: ${file}`);
21
+ return path;
22
+ }
23
+ /** Generates public route types and a portable manifest from one route discovery pass. */
24
+ export async function generateRoutes(projectRoot) {
25
+ const root = resolve(projectRoot);
26
+ const routes = await discoverConfiguredRoutes(root);
27
+ const types = join(root, ".meeko", "types", "routes.d.ts");
28
+ const manifest = join(root, ".meeko", "manifests", "routes.json");
29
+ const virtualTypes = join(root, ".meeko", "types", "virtual-pages.d.ts");
30
+ const lines = routes.map((route) => {
31
+ const params = paramsFor(route.id);
32
+ const shape = params.length ? `{ ${params.map((param) => `${JSON.stringify(param)}: string`).join("; ")} }` : "Record<never, never>";
33
+ return ` ${JSON.stringify(route.id)}: ${shape};`;
34
+ });
35
+ const declarations = [
36
+ "// Generated by Meeko. Edit app/pages instead.",
37
+ 'import "@meekojs/meeko/framework";',
38
+ 'declare module "@meekojs/meeko/framework" {',
39
+ " interface GeneratedRoutes {",
40
+ ...lines,
41
+ " }",
42
+ "}",
43
+ `export type RouteId = ${routes.length ? routes.map((route) => JSON.stringify(route.id)).join(" | ") : "never"};`,
44
+ 'export type RouteParams<Id extends RouteId> = import("@meekojs/meeko/framework").GeneratedRoutes[Id];',
45
+ "export {};",
46
+ "",
47
+ ].join("\n");
48
+ const portableRoutes = routes.map((route) => ({
49
+ id: route.id,
50
+ file: portable(root, route.file),
51
+ layouts: route.layouts.map((layout) => portable(root, layout)),
52
+ ...(route.error ? { error: portable(root, route.error) } : {}),
53
+ ...(route.sidecar ? { sidecar: portable(root, route.sidecar) } : {}),
54
+ }));
55
+ await mkdir(join(root, ".meeko", "types"), { recursive: true });
56
+ await mkdir(join(root, ".meeko", "manifests"), { recursive: true });
57
+ await writeFile(types, declarations, "utf8");
58
+ await writeFile(virtualTypes, [
59
+ 'declare module "virtual:meeko-client-pages" { export const modules: Record<string, () => Promise<unknown>>; }',
60
+ 'declare module "virtual:meeko-server-pages" { export const modules: Record<string, unknown>; }',
61
+ 'declare module "virtual:meeko-server-routes" { export const modules: Record<string, unknown>; }',
62
+ "",
63
+ ].join("\n"), "utf8");
64
+ await writeFile(manifest, `${JSON.stringify({ version: 1, routes: portableRoutes }, null, 2)}\n`, "utf8");
65
+ return { types, manifest, count: routes.length };
66
+ }
67
+ //# sourceMappingURL=generate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.js","sourceRoot":"","sources":["../../src/framework/generate.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, writeFile } from \"node:fs/promises\";\nimport { join, relative, resolve } from \"node:path\";\nimport { discoverConfiguredRoutes } from \"./config.js\";\n\nexport interface GeneratedRouteFiles {\n readonly types: string;\n readonly manifest: string;\n readonly count: number;\n}\n\nfunction paramsFor(id: string): readonly string[] {\n const params: string[] = [];\n for (const part of id.split(\"/\").filter(Boolean)) {\n const match = /^\\[(?:\\.\\.\\.)?([A-Za-z_$][\\w$]*)\\]$/.exec(part);\n if (!match) continue;\n const name = match[1]!;\n if (params.includes(name)) throw new Error(`Duplicate route parameter ${name} in ${id}`);\n params.push(name);\n }\n return params;\n}\n\nfunction portable(root: string, file: string): string {\n const path = relative(root, file).replaceAll(\"\\\\\", \"/\");\n if (path.startsWith(\"../\") || path === \"..\") throw new Error(`Route file escapes project root: ${file}`);\n return path;\n}\n\n/** Generates public route types and a portable manifest from one route discovery pass. */\nexport async function generateRoutes(projectRoot: string): Promise<GeneratedRouteFiles> {\n const root = resolve(projectRoot);\n const routes = await discoverConfiguredRoutes(root);\n const types = join(root, \".meeko\", \"types\", \"routes.d.ts\");\n const manifest = join(root, \".meeko\", \"manifests\", \"routes.json\");\n const virtualTypes = join(root, \".meeko\", \"types\", \"virtual-pages.d.ts\");\n const lines = routes.map((route) => {\n const params = paramsFor(route.id);\n const shape = params.length ? `{ ${params.map((param) => `${JSON.stringify(param)}: string`).join(\"; \")} }` : \"Record<never, never>\";\n return ` ${JSON.stringify(route.id)}: ${shape};`;\n });\n const declarations = [\n \"// Generated by Meeko. Edit app/pages instead.\",\n 'import \"@meekojs/meeko/framework\";',\n 'declare module \"@meekojs/meeko/framework\" {',\n \" interface GeneratedRoutes {\",\n ...lines,\n \" }\",\n \"}\",\n `export type RouteId = ${routes.length ? routes.map((route) => JSON.stringify(route.id)).join(\" | \") : \"never\"};`,\n 'export type RouteParams<Id extends RouteId> = import(\"@meekojs/meeko/framework\").GeneratedRoutes[Id];',\n \"export {};\",\n \"\",\n ].join(\"\\n\");\n const portableRoutes = routes.map((route) => ({\n id: route.id,\n file: portable(root, route.file),\n layouts: route.layouts.map((layout) => portable(root, layout)),\n ...(route.error ? { error: portable(root, route.error) } : {}),\n ...(route.sidecar ? { sidecar: portable(root, route.sidecar) } : {}),\n }));\n await mkdir(join(root, \".meeko\", \"types\"), { recursive: true });\n await mkdir(join(root, \".meeko\", \"manifests\"), { recursive: true });\n await writeFile(types, declarations, \"utf8\");\n await writeFile(virtualTypes, [\n 'declare module \"virtual:meeko-client-pages\" { export const modules: Record<string, () => Promise<unknown>>; }',\n 'declare module \"virtual:meeko-server-pages\" { export const modules: Record<string, unknown>; }',\n 'declare module \"virtual:meeko-server-routes\" { export const modules: Record<string, unknown>; }',\n \"\",\n ].join(\"\\n\"), \"utf8\");\n await writeFile(manifest, `${JSON.stringify({ version: 1, routes: portableRoutes }, null, 2)}\\n`, \"utf8\");\n return { types, manifest, count: routes.length };\n}\n"]}
@@ -0,0 +1,2 @@
1
+ /** Creates a framework project without overwriting unrelated user files. */
2
+ export declare function initFrameworkProject(directory: string): Promise<string>;