@meekojs/meeko 0.0.4 → 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 +21 -19
- package/dist/autoimports-ts.d.ts +4 -4
- package/dist/autoimports-ts.js +86 -30
- package/dist/autoimports-ts.js.map +1 -1
- package/dist/autoimports.d.ts +2 -2
- package/dist/autoimports.js +23 -7
- package/dist/autoimports.js.map +1 -1
- package/dist/check.js +39 -10
- package/dist/check.js.map +1 -1
- package/dist/cli.js +37 -4
- package/dist/cli.js.map +1 -1
- 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/props.d.ts +12 -0
- package/dist/compiler/props.js +32 -0
- package/dist/compiler/props.js.map +1 -0
- package/dist/compiler.js +55 -12
- package/dist/compiler.js.map +1 -1
- 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.js +2 -4
- package/dist/devtools.js.map +1 -1
- package/dist/dom.d.ts +11 -5
- package/dist/dom.js +288 -88
- package/dist/dom.js.map +1 -1
- 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.js +160 -5
- package/dist/framework/check-app.js.map +1 -1
- 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 +3 -0
- package/dist/framework/client.js +136 -33
- package/dist/framework/client.js.map +1 -1
- package/dist/framework/clients.js +12 -4
- package/dist/framework/clients.js.map +1 -1
- package/dist/framework/contracts-generate.js +66 -3
- package/dist/framework/contracts-generate.js.map +1 -1
- package/dist/framework/init.js +21 -200
- package/dist/framework/init.js.map +1 -1
- 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/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 +7 -3
- package/dist/framework/page.js +3 -1
- package/dist/framework/page.js.map +1 -1
- package/dist/framework/prerender.js +11 -5
- package/dist/framework/prerender.js.map +1 -1
- 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 +3 -1
- package/dist/framework/router.js +94 -8
- package/dist/framework/router.js.map +1 -1
- package/dist/framework/server.d.ts +17 -3
- package/dist/framework/server.js +71 -24
- package/dist/framework/server.js.map +1 -1
- package/dist/framework/socket-contracts-generate.js +8 -5
- package/dist/framework/socket-contracts-generate.js.map +1 -1
- package/dist/framework/socket.d.ts +2 -0
- package/dist/framework/socket.js +119 -17
- package/dist/framework/socket.js.map +1 -1
- 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 +7 -0
- package/dist/framework/state.js +78 -14
- package/dist/framework/state.js.map +1 -1
- 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/contracts.d.ts +11 -2
- package/dist/framework-server/contracts.js +62 -7
- package/dist/framework-server/contracts.js.map +1 -1
- package/dist/framework-server/discovery.d.ts +4 -1
- package/dist/framework-server/discovery.js +21 -16
- package/dist/framework-server/discovery.js.map +1 -1
- package/dist/framework-server/local.d.ts +2 -0
- package/dist/framework-server/local.js +5 -3
- package/dist/framework-server/local.js.map +1 -1
- 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.js +27 -9
- package/dist/framework-server/node-upgrade.js.map +1 -1
- package/dist/framework-server/node-websocket.js +4 -2
- package/dist/framework-server/node-websocket.js.map +1 -1
- package/dist/framework-server/session-stores.d.ts +9 -2
- package/dist/framework-server/session-stores.js +37 -11
- package/dist/framework-server/session-stores.js.map +1 -1
- package/dist/framework-server/sessions.d.ts +6 -0
- package/dist/framework-server/sessions.js +41 -10
- package/dist/framework-server/sessions.js.map +1 -1
- package/dist/framework-server/socket.js +62 -27
- package/dist/framework-server/socket.js.map +1 -1
- package/dist/framework-server.d.ts +2 -0
- package/dist/framework-server.js +1 -0
- package/dist/framework-server.js.map +1 -1
- package/dist/framework.d.ts +3 -1
- package/dist/framework.js +1 -0
- package/dist/framework.js.map +1 -1
- package/dist/hmr.js +74 -24
- package/dist/hmr.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/init.js +27 -1
- package/dist/init.js.map +1 -1
- package/dist/internal.d.ts +2 -2
- package/dist/internal.js +2 -2
- package/dist/internal.js.map +1 -1
- package/dist/node.d.ts +5 -1
- package/dist/node.js +80 -10
- package/dist/node.js.map +1 -1
- package/dist/reactivity.d.ts +12 -3
- package/dist/reactivity.js +94 -17
- package/dist/reactivity.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/types.js +3 -1
- package/dist/types.js.map +1 -1
- package/dist/vite.js +29 -9
- package/dist/vite.js.map +1 -1
- package/package.json +2 -2
package/dist/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, readFile, readdir, stat, writeFile } from \"node:fs/promises\";\nimport { basename, dirname, join, resolve } from \"node:path\";\n\n/** Entradas que puede dejar un gestor de paquetes antes de generar el proyecto. */\nconst packageScaffoldEntries = new Set([\"package.json\", \"package-lock.json\", \"pnpm-lock.yaml\", \"pnpm-workspace.yaml\", \"yarn.lock\", \"bun.lock\", \"bun.lockb\", \"node_modules\", \".npmrc\", \".git\"]);\n\n/** Comprueba que un valor JSON sea un objeto de configuración. */\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** Archivos autocontenidos del proyecto inicial, incluidos en la CLI publicada. */\nconst starterFiles: Readonly<Record<string, string>> = {\n \".gitignore\": \"node_modules/\\ndist/\\n.meeko/\\n\",\n \"index.html\": `<!doctype html>\n<html lang=\"es\">\n <head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Meeko SSR</title></head>\n <body><div id=\"app\"></div><script type=\"module\" src=\"/src/entry-client.ts\"></script></body>\n</html>\n`,\n \"vite.config.ts\": `import { defineConfig } from \"vite\";\nimport { meeko } from \"@meekojs/meeko/vite\";\n\nexport default defineConfig({ plugins: [meeko()] });\n`,\n \"tsconfig.json\": `{\n \"compilerOptions\": {\n \"target\": \"ES2022\", \"module\": \"NodeNext\", \"moduleResolution\": \"NodeNext\",\n \"lib\": [\"ES2022\", \"DOM\"], \"types\": [\"node\", \"vite/client\"],\n \"strict\": true, \"noEmit\": true, \"allowArbitraryExtensions\": true,\n \"rootDirs\": [\"src\", \".meeko/types/src\"],\n \"skipLibCheck\": true\n },\n \"include\": [\"src/**/*.ts\", \"vite.config.ts\", \".meeko/types/routes.d.ts\"]\n}\n`,\n \"src/App.meeko\": `<script lang=\"ts\">\nimport { signal } from \"@meekojs/meeko\";\n\n/** Propiedades transferidas desde el servidor. */\nexport interface Props { initial: number }\n\nconst props = defineProps<Props>();\nconst count = signal(props.initial);\n</script>\n\n<template>\n <main>\n <h1>Meeko SSR</h1>\n <button type=\"button\" on:click=\"() => count.value++\">Contador: {count.value}</button>\n </main>\n</template>\n\n<style scoped>\nmain { max-width: 40rem; margin: 4rem auto; font: 1.2rem system-ui; }\nbutton { cursor: pointer; padding: .65rem 1rem; }\n</style>\n`,\n \"src/entry-server.ts\": `import { serializeJson } from \"@meekojs/meeko\";\nimport { css, renderWithState } from \"./App.meeko\";\n\n/** Genera HTML y estado inicial desde el mismo componente que hidrata el cliente. */\nexport function renderPage(clientSource: string, initial = 1): string {\n const props = { initial };\n const rendered = renderWithState(props);\n return '<!doctype html><html lang=\"es\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><title>Meeko SSR</title><style>'\n + css + '</style></head><body><div id=\"app\">' + rendered.html + '</div><script id=\"meeko-payload\" type=\"application/json\">'\n + serializeJson({ props, state: rendered.state }) + '</script><script type=\"module\" src=\"' + clientSource + '\"></script></body></html>';\n}\n`,\n \"src/entry-client.ts\": `import { hydrate } from \"./App.meeko\";\nimport type { HotState } from \"@meekojs/meeko\";\n\nconst root = document.getElementById(\"app\");\nconst payloadNode = document.getElementById(\"meeko-payload\");\nif (!root || !payloadNode?.textContent) throw new Error(\"Missing SSR root or payload\");\nconst payload: unknown = JSON.parse(payloadNode.textContent);\nif (typeof payload !== \"object\" || payload === null || !(\"props\" in payload) || !(\"state\" in payload)) throw new TypeError(\"Invalid SSR payload\");\nconst { props, state } = payload;\nif (typeof props !== \"object\" || props === null || !(\"initial\" in props) || typeof props.initial !== \"number\" || !Number.isFinite(props.initial)) throw new TypeError(\"Invalid SSR props\");\nif (typeof state !== \"object\" || state === null || !(\"count\" in state) || typeof state.count !== \"number\" || !Number.isFinite(state.count)) throw new TypeError(\"Invalid SSR state\");\nhydrate(root, { initial: props.initial }, { count: state.count } satisfies HotState);\n`,\n \"server.mjs\": `import { createServer } from \"node:http\";\nimport { readFile } from \"node:fs/promises\";\nimport { dirname, extname, resolve, sep } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { createServer as createViteServer } from \"vite\";\n\nconst root = dirname(fileURLToPath(import.meta.url));\nconst production = process.argv.includes(\"--production\");\nconst vite = production ? undefined : await createViteServer({ root, server: { middlewareMode: true }, appType: \"custom\" });\nconst clientRoot = resolve(root, \"dist/client\");\nlet clientSource = \"/src/entry-client.ts\";\nif (production) {\n const manifest = JSON.parse(await readFile(resolve(clientRoot, \".vite/manifest.json\"), \"utf8\"));\n const entry = manifest[\"index.html\"];\n if (!entry?.file) throw new Error(\"Missing Vite client entry\");\n clientSource = \"/\" + entry.file;\n}\n\nconst contentTypes = { \".js\": \"text/javascript\", \".css\": \"text/css\", \".png\": \"image/png\", \".svg\": \"image/svg+xml\", \".ico\": \"image/x-icon\" };\nconst server = createServer(async (request, response) => {\n try {\n const path = new URL(request.url ?? \"/\", \"http://localhost\").pathname;\n if (path === \"/\") {\n const module = vite ? await vite.ssrLoadModule(\"/src/entry-server.ts\") : await import(pathToFileURL(resolve(root, \"dist/server/entry-server.js\")).href);\n const html = module.renderPage(clientSource);\n response.writeHead(200, { \"content-type\": \"text/html; charset=utf-8\" });\n response.end(vite ? await vite.transformIndexHtml(path, html) : html);\n return;\n }\n if (vite) {\n vite.middlewares(request, response, () => { response.writeHead(404); response.end(); });\n return;\n }\n const file = resolve(clientRoot, \".\" + path);\n if (!file.startsWith(clientRoot + sep)) { response.writeHead(403); response.end(); return; }\n const body = await readFile(file);\n response.writeHead(200, { \"content-type\": contentTypes[extname(file)] ?? \"application/octet-stream\" });\n response.end(body);\n } catch (error) {\n console.error(error);\n response.writeHead(500);\n response.end(\"Internal server error\");\n }\n});\n\nconst port = Number(process.env.PORT ?? 4173);\nserver.listen(port, \"127.0.0.1\", () => console.log(\"http://127.0.0.1:\" + port));\nprocess.on(\"SIGINT\", () => { server.close(); void vite?.close(); });\n`,\n \"README.md\": `# Meeko SSR starter\n\nProyecto inicial con renderizado en servidor e hidratación del mismo componente \\`.meeko\\`.\n\n\\`\\`\\`sh\nnpm install\nnpm run dev\n\\`\\`\\`\n\nAbre http://127.0.0.1:4173. El servidor produce HTML y transfiere las props y señales al navegador.\n\n\\`npm run check\\` genera los tipos del componente y comprueba TypeScript. \\`npm run build\\` compila cliente y servidor; \\`npm start\\` sirve ambas compilaciones con SSR.\n`,\n};\n\n/** Crea un proyecto SSR independiente sin sobrescribir archivos del usuario. */\nexport async function initProject(directory: string): Promise<string> {\n const target = resolve(directory);\n const name = basename(target).toLowerCase().replace(/[^a-z0-9._-]+/g, \"-\").replace(/^[._-]+|[._-]+$/g, \"\") || \"meeko-app\";\n const packageMetadata: unknown = JSON.parse(await readFile(new URL(\"../package.json\", import.meta.url), \"utf8\"));\n if (typeof packageMetadata !== \"object\" || packageMetadata === null || !(\"version\" in packageMetadata) || typeof packageMetadata.version !== \"string\") {\n throw new Error(\"Meeko package version is unavailable\");\n }\n let existingEntries: string[] = [];\n try {\n if (!(await stat(target)).isDirectory()) throw new Error(`Destination is not a directory: ${target}`);\n existingEntries = await readdir(target);\n } catch (error) {\n if (!(error instanceof Error && \"code\" in error && error.code === \"ENOENT\")) throw error;\n }\n const unexpected = existingEntries.filter((entry) => !packageScaffoldEntries.has(entry));\n if (unexpected.length > 0 || (existingEntries.length > 0 && !existingEntries.includes(\"package.json\"))) {\n throw new Error(`Destination is not empty: ${target}${unexpected.length > 0 ? ` (${unexpected.join(\", \")})` : \"\"}`);\n }\n const existing: unknown = existingEntries.includes(\"package.json\") ? JSON.parse(await readFile(join(target, \"package.json\"), \"utf8\")) : {};\n if (!isRecord(existing)) throw new Error(`Invalid package.json in ${target}`);\n const existingScripts = existing.scripts ?? {};\n const existingDependencies = existing.dependencies ?? {};\n const existingDevDependencies = existing.devDependencies ?? {};\n const existingEngines = existing.engines ?? {};\n if (!isRecord(existingScripts) || !isRecord(existingDependencies) || !isRecord(existingDevDependencies) || !isRecord(existingEngines)) {\n throw new Error(`Invalid package.json in ${target}`);\n }\n const scripts = {\n dev: \"node server.mjs\",\n check: \"meeko types src/App.meeko && tsc --noEmit\",\n build: \"npm run check && vite build --outDir dist/client --manifest && vite build --ssr src/entry-server.ts --outDir dist/server\",\n start: \"node server.mjs --production\",\n };\n const devDependencies = { \"@types/node\": \"^24.0.0\", typescript: \"^7.0.2\", vite: \"^8.3.5\" };\n for (const command of Object.keys(scripts)) {\n if (command in existingScripts) throw new Error(`Destination already defines the ${command} script: ${target}`);\n }\n if (Object.keys(existingDependencies).some((dependency) => dependency !== \"@meekojs/meeko\") || Object.keys(existingDevDependencies).some((dependency) => !(dependency in devDependencies))) {\n throw new Error(`Destination contains other dependencies: ${target}`);\n }\n const packageFile = JSON.stringify({\n ...existing,\n name: typeof existing.name === \"string\" ? existing.name : name,\n private: true,\n type: \"module\",\n engines: { ...existingEngines, node: \">=24\" },\n scripts: { ...existingScripts, ...scripts },\n dependencies: { ...existingDependencies, \"@meekojs/meeko\": packageMetadata.version },\n devDependencies: { ...existingDevDependencies, ...devDependencies },\n }, null, 2) + \"\\n\";\n await mkdir(target, { recursive: true });\n for (const [filename, content] of Object.entries(starterFiles)) {\n const path = join(target, filename);\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, content, { encoding: \"utf8\", flag: \"wx\" });\n }\n await writeFile(join(target, \"package.json\"), packageFile, { encoding: \"utf8\", flag: existingEntries.includes(\"package.json\") ? \"w\" : \"wx\" });\n return target;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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","sourcesContent":["import { mkdir, readFile, readdir, stat, writeFile } from \"node:fs/promises\";\nimport { basename, dirname, join, resolve } from \"node:path\";\n\n/** Entradas que puede dejar un gestor de paquetes antes de generar el proyecto. */\nconst packageScaffoldEntries = new Set([\"package.json\", \"package-lock.json\", \"pnpm-lock.yaml\", \"pnpm-workspace.yaml\", \"yarn.lock\", \"bun.lock\", \"bun.lockb\", \"node_modules\", \".npmrc\", \".git\"]);\n\n/** Comprueba que un valor JSON sea un objeto de configuración. */\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\n/** Archivos autocontenidos del proyecto inicial, incluidos en la CLI publicada. */\nconst starterFiles: Readonly<Record<string, string>> = {\n \".gitignore\": \"node_modules/\\ndist/\\n.meeko/\\n\",\n \"index.html\": `<!doctype html>\n<html lang=\"es\">\n <head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>Meeko SSR</title></head>\n <body><div id=\"app\"></div><script type=\"module\" src=\"/src/entry-client.ts\"></script></body>\n</html>\n`,\n \"vite.config.ts\": `import { defineConfig } from \"vite\";\nimport { meeko } from \"@meekojs/meeko/vite\";\n\nexport default defineConfig({ plugins: [meeko()] });\n`,\n \"tsconfig.json\": `{\n \"compilerOptions\": {\n \"target\": \"ES2022\", \"module\": \"NodeNext\", \"moduleResolution\": \"NodeNext\",\n \"lib\": [\"ES2022\", \"DOM\"], \"types\": [\"node\", \"vite/client\"],\n \"strict\": true, \"noEmit\": true, \"allowArbitraryExtensions\": true,\n \"rootDirs\": [\"src\", \".meeko/types/src\"],\n \"skipLibCheck\": true\n },\n \"include\": [\"src/**/*.ts\", \"vite.config.ts\", \".meeko/types/routes.d.ts\"]\n}\n`,\n \"src/App.meeko\": `<script lang=\"ts\">\nimport { signal } from \"@meekojs/meeko\";\n\n/** Propiedades transferidas desde el servidor. */\nexport interface Props { initial: number }\n\nconst props = defineProps<Props>();\nconst count = signal(props.initial);\n</script>\n\n<template>\n <main>\n <h1>Meeko SSR</h1>\n <button type=\"button\" on:click=\"() => count.value++\">Contador: {count.value}</button>\n </main>\n</template>\n\n<style scoped>\nmain { max-width: 40rem; margin: 4rem auto; font: 1.2rem system-ui; }\nbutton { cursor: pointer; padding: .65rem 1rem; }\n</style>\n`,\n \"src/entry-server.ts\": `import { serializeJson } from \"@meekojs/meeko\";\nimport { css, renderWithState } from \"./App.meeko\";\n\n/** Genera HTML y estado inicial desde el mismo componente que hidrata el cliente. */\nexport function renderPage(clientSource: string, initial = 1): string {\n const props = { initial };\n const rendered = renderWithState(props);\n return '<!doctype html><html lang=\"es\"><head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><title>Meeko SSR</title><style>'\n + css + '</style></head><body><div id=\"app\">' + rendered.html + '</div><script id=\"meeko-payload\" type=\"application/json\">'\n + serializeJson({ props, state: rendered.state }) + '</script><script type=\"module\" src=\"' + clientSource + '\"></script></body></html>';\n}\n`,\n \"src/entry-client.ts\": `import { hydrate } from \"./App.meeko\";\nimport type { HotState } from \"@meekojs/meeko\";\n\nconst root = document.getElementById(\"app\");\nconst payloadNode = document.getElementById(\"meeko-payload\");\nif (!root || !payloadNode?.textContent) throw new Error(\"Missing SSR root or payload\");\nconst payload: unknown = JSON.parse(payloadNode.textContent);\nif (typeof payload !== \"object\" || payload === null || !(\"props\" in payload) || !(\"state\" in payload)) throw new TypeError(\"Invalid SSR payload\");\nconst { props, state } = payload;\nif (typeof props !== \"object\" || props === null || !(\"initial\" in props) || typeof props.initial !== \"number\" || !Number.isFinite(props.initial)) throw new TypeError(\"Invalid SSR props\");\nif (typeof state !== \"object\" || state === null || !(\"count\" in state) || typeof state.count !== \"number\" || !Number.isFinite(state.count)) throw new TypeError(\"Invalid SSR state\");\nhydrate(root, { initial: props.initial }, { count: state.count } satisfies HotState);\n`,\n \"server.mjs\": `import { createServer } from \"node:http\";\nimport { readFile } from \"node:fs/promises\";\nimport { dirname, extname, resolve, sep } from \"node:path\";\nimport { fileURLToPath, pathToFileURL } from \"node:url\";\nimport { createServer as createViteServer } from \"vite\";\n\nconst root = dirname(fileURLToPath(import.meta.url));\nconst production = process.argv.includes(\"--production\");\nconst vite = production ? undefined : await createViteServer({ root, server: { middlewareMode: true }, appType: \"custom\" });\nconst clientRoot = resolve(root, \"dist/client\");\nlet clientSource = \"/src/entry-client.ts\";\nif (production) {\n const manifest = JSON.parse(await readFile(resolve(clientRoot, \".vite/manifest.json\"), \"utf8\"));\n const entry = manifest[\"index.html\"];\n if (!entry?.file) throw new Error(\"Missing Vite client entry\");\n clientSource = \"/\" + entry.file;\n}\n\nconst contentTypes = { \".js\": \"text/javascript\", \".css\": \"text/css\", \".png\": \"image/png\", \".svg\": \"image/svg+xml\", \".ico\": \"image/x-icon\" };\nconst server = createServer(async (request, response) => {\n try {\n const path = new URL(request.url ?? \"/\", \"http://localhost\").pathname;\n if (path === \"/\") {\n const module = vite ? await vite.ssrLoadModule(\"/src/entry-server.ts\") : await import(pathToFileURL(resolve(root, \"dist/server/entry-server.js\")).href);\n const html = module.renderPage(clientSource);\n response.writeHead(200, { \"content-type\": \"text/html; charset=utf-8\" });\n response.end(vite ? await vite.transformIndexHtml(path, html) : html);\n return;\n }\n if (vite) {\n vite.middlewares(request, response, () => { response.writeHead(404); response.end(); });\n return;\n }\n const file = resolve(clientRoot, \".\" + path);\n if (!file.startsWith(clientRoot + sep)) { response.writeHead(403); response.end(); return; }\n const body = await readFile(file);\n response.writeHead(200, { \"content-type\": contentTypes[extname(file)] ?? \"application/octet-stream\" });\n response.end(body);\n } catch (error) {\n console.error(error);\n response.writeHead(500);\n response.end(\"Internal server error\");\n }\n});\n\nconst port = Number(process.env.PORT ?? 4173);\nserver.listen(port, \"127.0.0.1\", () => console.log(\"http://127.0.0.1:\" + port));\nlet shutdownPromise;\nconst closeServer = () => new Promise((resolveClose, rejectClose) => {\n server.close((error) => error ? rejectClose(error) : resolveClose());\n});\nasync function shutdown() {\n if (shutdownPromise) return shutdownPromise;\n shutdownPromise = (async () => {\n const results = await Promise.allSettled([\n closeServer(),\n vite?.close() ?? Promise.resolve(),\n ]);\n const failures = results.flatMap((result) => result.status === \"rejected\" ? [result.reason] : []);\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1) throw new AggregateError(failures, \"Meeko server shutdown failed\");\n })();\n return shutdownPromise;\n}\nconst onSignal = () => {\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n void shutdown().catch((error) => {\n try { console.error(\"Meeko server shutdown failed\", error); }\n finally { process.exitCode = 1; }\n });\n};\nprocess.once(\"SIGINT\", onSignal);\nprocess.once(\"SIGTERM\", onSignal);\n`,\n \"README.md\": `# Meeko SSR starter\n\nProyecto inicial con renderizado en servidor e hidratación del mismo componente \\`.meeko\\`.\n\n\\`\\`\\`sh\nnpm install\nnpm run dev\n\\`\\`\\`\n\nAbre http://127.0.0.1:4173. El servidor produce HTML y transfiere las props y señales al navegador.\n\n\\`npm run check\\` genera los tipos del componente y comprueba TypeScript. \\`npm run build\\` compila cliente y servidor; \\`npm start\\` sirve ambas compilaciones con SSR.\n`,\n};\n\n/** Crea un proyecto SSR independiente sin sobrescribir archivos del usuario. */\nexport async function initProject(directory: string): Promise<string> {\n const target = resolve(directory);\n const name = basename(target).toLowerCase().replace(/[^a-z0-9._-]+/g, \"-\").replace(/^[._-]+|[._-]+$/g, \"\") || \"meeko-app\";\n const packageMetadata: unknown = JSON.parse(await readFile(new URL(\"../package.json\", import.meta.url), \"utf8\"));\n if (typeof packageMetadata !== \"object\" || packageMetadata === null || !(\"version\" in packageMetadata) || typeof packageMetadata.version !== \"string\") {\n throw new Error(\"Meeko package version is unavailable\");\n }\n let existingEntries: string[] = [];\n try {\n if (!(await stat(target)).isDirectory()) throw new Error(`Destination is not a directory: ${target}`);\n existingEntries = await readdir(target);\n } catch (error) {\n if (!(error instanceof Error && \"code\" in error && error.code === \"ENOENT\")) throw error;\n }\n const unexpected = existingEntries.filter((entry) => !packageScaffoldEntries.has(entry));\n if (unexpected.length > 0 || (existingEntries.length > 0 && !existingEntries.includes(\"package.json\"))) {\n throw new Error(`Destination is not empty: ${target}${unexpected.length > 0 ? ` (${unexpected.join(\", \")})` : \"\"}`);\n }\n const existing: unknown = existingEntries.includes(\"package.json\") ? JSON.parse(await readFile(join(target, \"package.json\"), \"utf8\")) : {};\n if (!isRecord(existing)) throw new Error(`Invalid package.json in ${target}`);\n const existingScripts = existing.scripts ?? {};\n const existingDependencies = existing.dependencies ?? {};\n const existingDevDependencies = existing.devDependencies ?? {};\n const existingEngines = existing.engines ?? {};\n if (!isRecord(existingScripts) || !isRecord(existingDependencies) || !isRecord(existingDevDependencies) || !isRecord(existingEngines)) {\n throw new Error(`Invalid package.json in ${target}`);\n }\n const scripts = {\n dev: \"node server.mjs\",\n check: \"meeko types src/App.meeko && tsc --noEmit\",\n build: \"npm run check && vite build --outDir dist/client --manifest && vite build --ssr src/entry-server.ts --outDir dist/server\",\n start: \"node server.mjs --production\",\n };\n const devDependencies = { \"@types/node\": \"^24.0.0\", typescript: \"^7.0.2\", vite: \"^8.3.5\" };\n for (const command of Object.keys(scripts)) {\n if (command in existingScripts) throw new Error(`Destination already defines the ${command} script: ${target}`);\n }\n if (Object.keys(existingDependencies).some((dependency) => dependency !== \"@meekojs/meeko\") || Object.keys(existingDevDependencies).some((dependency) => !(dependency in devDependencies))) {\n throw new Error(`Destination contains other dependencies: ${target}`);\n }\n const packageFile = JSON.stringify({\n ...existing,\n name: typeof existing.name === \"string\" ? existing.name : name,\n private: true,\n type: \"module\",\n engines: { ...existingEngines, node: \">=24\" },\n scripts: { ...existingScripts, ...scripts },\n dependencies: { ...existingDependencies, \"@meekojs/meeko\": packageMetadata.version },\n devDependencies: { ...existingDevDependencies, ...devDependencies },\n }, null, 2) + \"\\n\";\n await mkdir(target, { recursive: true });\n for (const [filename, content] of Object.entries(starterFiles)) {\n const path = join(target, filename);\n await mkdir(dirname(path), { recursive: true });\n await writeFile(path, content, { encoding: \"utf8\", flag: \"wx\" });\n }\n await writeFile(join(target, \"package.json\"), packageFile, { encoding: \"utf8\", flag: existingEntries.includes(\"package.json\") ? \"w\" : \"wx\" });\n return target;\n}\n"]}
|
package/dist/internal.d.ts
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* Esta ruta es interna y puede cambiar junto con el compilador. Las aplicaciones
|
|
5
5
|
* deben importar las API documentadas desde la raíz del paquete.
|
|
6
6
|
*/
|
|
7
|
-
export { createRoot } from "./reactivity.js";
|
|
7
|
+
export { createRoot, finishWithCleanup } from "./reactivity.js";
|
|
8
8
|
export { attributeValue, escapeHtml, renderAttribute, serializeJson } from "./server.js";
|
|
9
|
-
export { bindAttribute, bindComponent, bindEvent, bindFor, bindIf, bindText, keyToken, renderComponent, renderFor, renderIf, withStateSnapshot } from "./dom.js";
|
|
9
|
+
export { bindAttribute, bindComponent, bindEvent, bindFor, bindIf, bindText, keyToken, releaseAll, renderComponent, renderFor, renderIf, withStateSnapshot } from "./dom.js";
|
|
10
10
|
export type { ComponentModule, ComponentRelease, DomScope } from "./dom.js";
|
|
11
11
|
export { enableHotModule, registerHotInstance, registerHotScope, replaceHotModule, replaceHotStyle, restoreSignals, snapshotSignals } from "./hmr.js";
|
|
12
12
|
export type { HotComponent, HotState } from "./hmr.js";
|
package/dist/internal.js
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* Esta ruta es interna y puede cambiar junto con el compilador. Las aplicaciones
|
|
5
5
|
* deben importar las API documentadas desde la raíz del paquete.
|
|
6
6
|
*/
|
|
7
|
-
export { createRoot } from "./reactivity.js";
|
|
7
|
+
export { createRoot, finishWithCleanup } from "./reactivity.js";
|
|
8
8
|
export { attributeValue, escapeHtml, renderAttribute, serializeJson } from "./server.js";
|
|
9
|
-
export { bindAttribute, bindComponent, bindEvent, bindFor, bindIf, bindText, keyToken, renderComponent, renderFor, renderIf, withStateSnapshot } from "./dom.js";
|
|
9
|
+
export { bindAttribute, bindComponent, bindEvent, bindFor, bindIf, bindText, keyToken, releaseAll, renderComponent, renderFor, renderIf, withStateSnapshot } from "./dom.js";
|
|
10
10
|
export { enableHotModule, registerHotInstance, registerHotScope, replaceHotModule, replaceHotStyle, restoreSignals, snapshotSignals } from "./hmr.js";
|
|
11
11
|
export { registerDevtoolsInstance } from "./devtools.js";
|
|
12
12
|
//# sourceMappingURL=internal.js.map
|
package/dist/internal.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"internal.js","sourceRoot":"","sources":["../src/internal.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACzF,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,eAAe,EAAE,SAAS,EAAE,QAAQ,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE7K,OAAO,EAAE,eAAe,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAEtJ,OAAO,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC","sourcesContent":["/**\n * Contrato del runtime generado por el compilador Meeko.\n *\n * Esta ruta es interna y puede cambiar junto con el compilador. Las aplicaciones\n * deben importar las API documentadas desde la raíz del paquete.\n */\nexport { createRoot, finishWithCleanup } from \"./reactivity.js\";\nexport { attributeValue, escapeHtml, renderAttribute, serializeJson } from \"./server.js\";\nexport { bindAttribute, bindComponent, bindEvent, bindFor, bindIf, bindText, keyToken, releaseAll, renderComponent, renderFor, renderIf, withStateSnapshot } from \"./dom.js\";\nexport type { ComponentModule, ComponentRelease, DomScope } from \"./dom.js\";\nexport { enableHotModule, registerHotInstance, registerHotScope, replaceHotModule, replaceHotStyle, restoreSignals, snapshotSignals } from \"./hmr.js\";\nexport type { HotComponent, HotState } from \"./hmr.js\";\nexport { registerDevtoolsInstance } from \"./devtools.js\";\n"]}
|
package/dist/node.d.ts
CHANGED
|
@@ -8,5 +8,9 @@ export type { RouteLayer, RouteModule, ComposeRoutesOptions } from "./framework/
|
|
|
8
8
|
export { prerenderRoutes, prerenderProject } from "./framework/prerender.js";
|
|
9
9
|
export type { PrerenderOptions } from "./framework/prerender.js";
|
|
10
10
|
export * from "./framework-server.js";
|
|
11
|
+
export interface NodeListenerOptions {
|
|
12
|
+
/** Receives uncaught handler or response-stream failures with a correlation ID. */
|
|
13
|
+
onError?: (error: unknown, requestId: string) => void;
|
|
14
|
+
}
|
|
11
15
|
/** Adapts a portable Fetch handler to Node 24's HTTP server callback. */
|
|
12
|
-
export declare function toNodeListener(handler: (request: Request) => Promise<Response> | Response): (request: IncomingMessage, response: ServerResponse) => void;
|
|
16
|
+
export declare function toNodeListener(handler: (request: Request) => Promise<Response> | Response, options?: NodeListenerOptions): (request: IncomingMessage, response: ServerResponse) => void;
|
package/dist/node.js
CHANGED
|
@@ -1,13 +1,24 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
1
2
|
import { Readable } from "node:stream";
|
|
2
3
|
import { TLSSocket } from "node:tls";
|
|
4
|
+
import { ApiError, errorResponse, observeServerError } from "./framework-server/contracts.js";
|
|
3
5
|
export { discoverRoutes, createFrameworkHandler } from "./framework/server.js";
|
|
4
6
|
export { composeFrameworkRoutes } from "./framework/modules.js";
|
|
5
7
|
export { discoverConfiguredRoutes, loadMeekoConfig, resolveConfigSources, readMeekoConfigSync } from "./framework/config.js";
|
|
6
8
|
export { prerenderRoutes, prerenderProject } from "./framework/prerender.js";
|
|
7
9
|
export * from "./framework-server.js";
|
|
10
|
+
function nodeResponseHeaders(headers) {
|
|
11
|
+
const result = {};
|
|
12
|
+
headers.forEach((value, name) => { result[name] = value; });
|
|
13
|
+
const cookies = headers.getSetCookie();
|
|
14
|
+
if (cookies.length)
|
|
15
|
+
result["set-cookie"] = cookies;
|
|
16
|
+
return result;
|
|
17
|
+
}
|
|
8
18
|
/** Adapts a portable Fetch handler to Node 24's HTTP server callback. */
|
|
9
|
-
export function toNodeListener(handler) {
|
|
19
|
+
export function toNodeListener(handler, options = {}) {
|
|
10
20
|
return (incoming, outgoing) => {
|
|
21
|
+
let responseRequestId;
|
|
11
22
|
void (async () => {
|
|
12
23
|
const controller = new AbortController();
|
|
13
24
|
const abort = () => controller.abort();
|
|
@@ -16,7 +27,13 @@ export function toNodeListener(handler) {
|
|
|
16
27
|
try {
|
|
17
28
|
const authority = incoming.headers.host ?? "localhost";
|
|
18
29
|
const protocol = incoming.socket instanceof TLSSocket ? "https" : "http";
|
|
19
|
-
|
|
30
|
+
let url;
|
|
31
|
+
try {
|
|
32
|
+
url = new URL(incoming.url ?? "/", `${protocol}://${authority}`);
|
|
33
|
+
}
|
|
34
|
+
catch {
|
|
35
|
+
throw new ApiError("INVALID_URL", 400);
|
|
36
|
+
}
|
|
20
37
|
const method = incoming.method ?? "GET";
|
|
21
38
|
const headers = new Headers();
|
|
22
39
|
for (const [name, value] of Object.entries(incoming.headers)) {
|
|
@@ -29,23 +46,76 @@ export function toNodeListener(handler) {
|
|
|
29
46
|
...(hasBody ? { body: Readable.toWeb(incoming), duplex: "half" } : {}),
|
|
30
47
|
});
|
|
31
48
|
const result = await handler(request);
|
|
32
|
-
|
|
49
|
+
const candidateRequestId = result.headers.get("x-request-id");
|
|
50
|
+
if (candidateRequestId && /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(candidateRequestId)) {
|
|
51
|
+
responseRequestId = candidateRequestId;
|
|
52
|
+
}
|
|
53
|
+
if (controller.signal.aborted || outgoing.destroyed)
|
|
54
|
+
return;
|
|
55
|
+
outgoing.writeHead(result.status, nodeResponseHeaders(result.headers));
|
|
33
56
|
if (method === "HEAD" || !result.body) {
|
|
34
57
|
outgoing.end();
|
|
35
58
|
return;
|
|
36
59
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
60
|
+
const reader = result.body.getReader();
|
|
61
|
+
try {
|
|
62
|
+
while (true) {
|
|
63
|
+
if (controller.signal.aborted || outgoing.destroyed) {
|
|
64
|
+
await reader.cancel();
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const chunk = await reader.read();
|
|
68
|
+
if (chunk.done)
|
|
69
|
+
break;
|
|
70
|
+
if (controller.signal.aborted || outgoing.destroyed) {
|
|
71
|
+
await reader.cancel();
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
outgoing.write(chunk.value);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
finally {
|
|
78
|
+
reader.releaseLock();
|
|
79
|
+
}
|
|
80
|
+
if (!controller.signal.aborted && !outgoing.destroyed)
|
|
81
|
+
outgoing.end();
|
|
40
82
|
}
|
|
41
83
|
finally {
|
|
42
84
|
incoming.off("aborted", abort);
|
|
43
85
|
outgoing.off("close", abort);
|
|
44
86
|
}
|
|
45
|
-
})().catch(() => {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
outgoing.
|
|
87
|
+
})().catch(async (error) => {
|
|
88
|
+
const requestId = responseRequestId ?? randomUUID();
|
|
89
|
+
observeServerError(error, requestId, options.onError);
|
|
90
|
+
if (outgoing.destroyed)
|
|
91
|
+
return;
|
|
92
|
+
const reportSecondary = (failure) => {
|
|
93
|
+
if (!Object.is(failure, error))
|
|
94
|
+
observeServerError(failure, requestId, options.onError);
|
|
95
|
+
};
|
|
96
|
+
const destroySafely = (cause) => {
|
|
97
|
+
try {
|
|
98
|
+
outgoing.destroy(cause instanceof Error ? cause : undefined);
|
|
99
|
+
}
|
|
100
|
+
catch (destroyError) {
|
|
101
|
+
if (!Object.is(destroyError, error) && !Object.is(destroyError, cause)) {
|
|
102
|
+
observeServerError(destroyError, requestId, options.onError);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
if (outgoing.headersSent) {
|
|
107
|
+
destroySafely(error);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
const failure = errorResponse(error, requestId);
|
|
112
|
+
outgoing.writeHead(failure.status, nodeResponseHeaders(failure.headers));
|
|
113
|
+
outgoing.end(incoming.method === "HEAD" ? undefined : await failure.text());
|
|
114
|
+
}
|
|
115
|
+
catch (failure) {
|
|
116
|
+
reportSecondary(failure);
|
|
117
|
+
destroySafely(failure);
|
|
118
|
+
}
|
|
49
119
|
});
|
|
50
120
|
};
|
|
51
121
|
}
|
package/dist/node.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"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","sourcesContent":["import { Readable } from \"node:stream\";\nimport { TLSSocket } from \"node:tls\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\nexport { discoverRoutes, createFrameworkHandler } from \"./framework/server.js\";\nexport type { FrameworkHandlerOptions, PageModule, PageRoute, PageRequestContext } from \"./framework/server.js\";\nexport { composeFrameworkRoutes } from \"./framework/modules.js\";\nexport { discoverConfiguredRoutes, loadMeekoConfig, resolveConfigSources, readMeekoConfigSync } from \"./framework/config.js\";\nexport type { MeekoConfig, ConfigSource } from \"./framework/config.js\";\nexport type { RouteLayer, RouteModule, ComposeRoutesOptions } from \"./framework/modules.js\";\nexport { prerenderRoutes, prerenderProject } from \"./framework/prerender.js\";\nexport type { PrerenderOptions } from \"./framework/prerender.js\";\nexport * from \"./framework-server.js\";\n\n/** Adapts a portable Fetch handler to Node 24's HTTP server callback. */\nexport function toNodeListener(handler: (request: Request) => Promise<Response> | Response): (request: IncomingMessage, response: ServerResponse) => void {\n return (incoming, outgoing) => {\n void (async () => {\n const controller = new AbortController();\n const abort = () => controller.abort();\n incoming.once(\"aborted\", abort);\n outgoing.once(\"close\", abort);\n try {\n const authority = incoming.headers.host ?? \"localhost\";\n const protocol = incoming.socket instanceof TLSSocket ? \"https\" : \"http\";\n const url = new URL(incoming.url ?? \"/\", `${protocol}://${authority}`);\n const method = incoming.method ?? \"GET\";\n const headers = new Headers();\n for (const [name, value] of Object.entries(incoming.headers)) {\n if (value !== undefined) headers.set(name, Array.isArray(value) ? value.join(\", \") : value);\n }\n const hasBody = method !== \"GET\" && method !== \"HEAD\";\n const request = new Request(url, {\n method, headers, signal: controller.signal,\n ...(hasBody ? { body: Readable.toWeb(incoming) as ReadableStream<Uint8Array>, duplex: \"half\" as const } : {}),\n });\n const result = await handler(request);\n outgoing.writeHead(result.status, Object.fromEntries(result.headers));\n if (method === \"HEAD\" || !result.body) { outgoing.end(); return; }\n for await (const chunk of result.body) outgoing.write(chunk);\n outgoing.end();\n } finally {\n incoming.off(\"aborted\", abort);\n outgoing.off(\"close\", abort);\n }\n })().catch(() => {\n if (!outgoing.headersSent) outgoing.writeHead(500, { \"content-type\": \"text/plain; charset=utf-8\" });\n outgoing.end(\"Internal server error\");\n });\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../src/node.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { Readable } from \"node:stream\";\nimport { TLSSocket } from \"node:tls\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { ApiError, errorResponse, observeServerError } from \"./framework-server/contracts.js\";\n\nexport { discoverRoutes, createFrameworkHandler } from \"./framework/server.js\";\nexport type { FrameworkHandlerOptions, PageModule, PageRoute, PageRequestContext } from \"./framework/server.js\";\nexport { composeFrameworkRoutes } from \"./framework/modules.js\";\nexport { discoverConfiguredRoutes, loadMeekoConfig, resolveConfigSources, readMeekoConfigSync } from \"./framework/config.js\";\nexport type { MeekoConfig, ConfigSource } from \"./framework/config.js\";\nexport type { RouteLayer, RouteModule, ComposeRoutesOptions } from \"./framework/modules.js\";\nexport { prerenderRoutes, prerenderProject } from \"./framework/prerender.js\";\nexport type { PrerenderOptions } from \"./framework/prerender.js\";\nexport * from \"./framework-server.js\";\n\nexport interface NodeListenerOptions {\n /** Receives uncaught handler or response-stream failures with a correlation ID. */\n onError?: (error: unknown, requestId: string) => void;\n}\n\nfunction nodeResponseHeaders(headers: Headers): Record<string, string | string[]> {\n const result: Record<string, string | string[]> = {};\n headers.forEach((value, name) => { result[name] = value; });\n const cookies = headers.getSetCookie();\n if (cookies.length) result[\"set-cookie\"] = cookies;\n return result;\n}\n\n/** Adapts a portable Fetch handler to Node 24's HTTP server callback. */\nexport function toNodeListener(handler: (request: Request) => Promise<Response> | Response, options: NodeListenerOptions = {}): (request: IncomingMessage, response: ServerResponse) => void {\n return (incoming, outgoing) => {\n let responseRequestId: string | undefined;\n void (async () => {\n const controller = new AbortController();\n const abort = () => controller.abort();\n incoming.once(\"aborted\", abort);\n outgoing.once(\"close\", abort);\n try {\n const authority = incoming.headers.host ?? \"localhost\";\n const protocol = incoming.socket instanceof TLSSocket ? \"https\" : \"http\";\n let url: URL;\n try { url = new URL(incoming.url ?? \"/\", `${protocol}://${authority}`); }\n catch { throw new ApiError(\"INVALID_URL\", 400); }\n const method = incoming.method ?? \"GET\";\n const headers = new Headers();\n for (const [name, value] of Object.entries(incoming.headers)) {\n if (value !== undefined) headers.set(name, Array.isArray(value) ? value.join(\", \") : value);\n }\n const hasBody = method !== \"GET\" && method !== \"HEAD\";\n const request = new Request(url, {\n method, headers, signal: controller.signal,\n ...(hasBody ? { body: Readable.toWeb(incoming) as ReadableStream<Uint8Array>, duplex: \"half\" as const } : {}),\n });\n const result = await handler(request);\n const candidateRequestId = result.headers.get(\"x-request-id\");\n if (candidateRequestId && /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(candidateRequestId)) {\n responseRequestId = candidateRequestId;\n }\n if (controller.signal.aborted || outgoing.destroyed) return;\n outgoing.writeHead(result.status, nodeResponseHeaders(result.headers));\n if (method === \"HEAD\" || !result.body) { outgoing.end(); return; }\n const reader = result.body.getReader();\n try {\n while (true) {\n if (controller.signal.aborted || outgoing.destroyed) { await reader.cancel(); return; }\n const chunk = await reader.read();\n if (chunk.done) break;\n if (controller.signal.aborted || outgoing.destroyed) { await reader.cancel(); return; }\n outgoing.write(chunk.value);\n }\n } finally { reader.releaseLock(); }\n if (!controller.signal.aborted && !outgoing.destroyed) outgoing.end();\n } finally {\n incoming.off(\"aborted\", abort);\n outgoing.off(\"close\", abort);\n }\n })().catch(async (error: unknown) => {\n const requestId = responseRequestId ?? randomUUID();\n observeServerError(error, requestId, options.onError);\n if (outgoing.destroyed) return;\n const reportSecondary = (failure: unknown): void => {\n if (!Object.is(failure, error)) observeServerError(failure, requestId, options.onError);\n };\n const destroySafely = (cause: unknown): void => {\n try { outgoing.destroy(cause instanceof Error ? cause : undefined); }\n catch (destroyError) {\n if (!Object.is(destroyError, error) && !Object.is(destroyError, cause)) {\n observeServerError(destroyError, requestId, options.onError);\n }\n }\n };\n if (outgoing.headersSent) { destroySafely(error); return; }\n try {\n const failure = errorResponse(error, requestId);\n outgoing.writeHead(failure.status, nodeResponseHeaders(failure.headers));\n outgoing.end(incoming.method === \"HEAD\" ? undefined : await failure.text());\n } catch (failure) {\n reportSecondary(failure);\n destroySafely(failure);\n }\n });\n };\n}\n"]}
|
package/dist/reactivity.d.ts
CHANGED
|
@@ -26,14 +26,20 @@ export declare function isWritableSignal(value: unknown): value is Signal<unknow
|
|
|
26
26
|
export declare function provide<T>(key: ContextKey<T>, value: T): void;
|
|
27
27
|
/** Lee el proveedor más cercano; falla si falta para evitar un valor implícito. */
|
|
28
28
|
export declare function inject<T>(key: ContextKey<T>): T;
|
|
29
|
-
/**
|
|
30
|
-
export declare function
|
|
29
|
+
/** Looks up optional context without creating a process-wide fallback. */
|
|
30
|
+
export declare function findContext<T>(key: ContextKey<T>): T | undefined;
|
|
31
|
+
type SyncCleanupCallback<F extends () => unknown> = [Extract<ReturnType<F>, PromiseLike<unknown>>] extends [never] ? F : never;
|
|
32
|
+
/** Registers a synchronous external-resource release with the current component root. */
|
|
33
|
+
export declare function onCleanup<const F extends () => unknown>(release: SyncCleanupCallback<F>): void;
|
|
31
34
|
/** Crea un valor observable. Las escrituras iguales no notifican cambios. */
|
|
32
35
|
export declare function signal<T>(initial: T): Signal<T>;
|
|
33
36
|
/** Ejecuta una función cuando cambian las señales leídas por ella. */
|
|
34
|
-
|
|
37
|
+
type SyncEffectCallback<F extends () => unknown> = [Extract<ReturnType<F>, PromiseLike<unknown>>] extends [never] ? F : never;
|
|
38
|
+
export declare function effect<const F extends () => unknown>(fn: SyncEffectCallback<F>, source?: EffectSource): () => void;
|
|
35
39
|
/** Identidad opaca de la raíz reactiva activa; permite aislar instancias anidadas. */
|
|
36
40
|
export declare function currentEffectOwner(): object | undefined;
|
|
41
|
+
/** Captures the parent of a component root for a later HMR replacement. */
|
|
42
|
+
export declare function captureParentOwner(): <T>(work: () => T) => T;
|
|
37
43
|
/** Devuelve expresiones de plantilla actualmente dependientes de una señal en una raíz. */
|
|
38
44
|
export declare function signalReadSites(value: Signal<unknown>, owner: object | undefined): EffectSource[];
|
|
39
45
|
/** Deriva un valor de otras señales y lo actualiza cuando cambian. */
|
|
@@ -44,3 +50,6 @@ export declare function batch<T>(fn: () => T): T;
|
|
|
44
50
|
export declare function untrack<T>(fn: () => T): T;
|
|
45
51
|
/** Asocia efectos a una instancia y entrega una función para liberarlos. */
|
|
46
52
|
export declare function createRoot<T>(fn: (dispose: () => void) => T): T;
|
|
53
|
+
/** Runs cleanup on either outcome without losing an earlier failure. */
|
|
54
|
+
export declare function finishWithCleanup<T>(work: () => T, cleanup: () => void): T;
|
|
55
|
+
export {};
|
package/dist/reactivity.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { logClientError, observeReturnedPromise } from "./error-observer.js";
|
|
1
2
|
/** Crea una clave única; el tipo no se infiere de un valor global compartido. */
|
|
2
3
|
export function createContext(description) {
|
|
3
4
|
return Symbol(description);
|
|
@@ -28,7 +29,15 @@ export function inject(key) {
|
|
|
28
29
|
}
|
|
29
30
|
throw new Error(`Missing Meeko context${key.description ? `: ${key.description}` : ""}`);
|
|
30
31
|
}
|
|
31
|
-
/**
|
|
32
|
+
/** Looks up optional context without creating a process-wide fallback. */
|
|
33
|
+
export function findContext(key) {
|
|
34
|
+
for (let owner = activeOwner; owner; owner = owner.parent) {
|
|
35
|
+
if (owner.context.has(key))
|
|
36
|
+
return owner.context.get(key);
|
|
37
|
+
}
|
|
38
|
+
return undefined;
|
|
39
|
+
}
|
|
40
|
+
/** Registers a synchronous external-resource release with the current component root. */
|
|
32
41
|
export function onCleanup(release) {
|
|
33
42
|
if (!activeOwner)
|
|
34
43
|
throw new Error("onCleanup() requires an active component root");
|
|
@@ -43,21 +52,36 @@ function flush() {
|
|
|
43
52
|
if (flushing || batchDepth > 0)
|
|
44
53
|
return;
|
|
45
54
|
flushing = true;
|
|
55
|
+
const failures = [];
|
|
46
56
|
try {
|
|
47
57
|
let iterations = 0;
|
|
48
58
|
while (pending.size > 0) {
|
|
49
|
-
if (++iterations > 1000)
|
|
50
|
-
|
|
59
|
+
if (++iterations > 1000) {
|
|
60
|
+
pending.clear();
|
|
61
|
+
failures.push(new Error("Reactive update cycle exceeded 1000 iterations"));
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
51
64
|
const observers = [...pending];
|
|
52
65
|
pending.clear();
|
|
53
|
-
for (const observer of observers)
|
|
54
|
-
if (
|
|
66
|
+
for (const observer of observers) {
|
|
67
|
+
if (observer.disposed)
|
|
68
|
+
continue;
|
|
69
|
+
try {
|
|
55
70
|
observer.run();
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
failures.push(error);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
56
76
|
}
|
|
57
77
|
}
|
|
58
78
|
finally {
|
|
59
79
|
flushing = false;
|
|
60
80
|
}
|
|
81
|
+
if (failures.length === 1)
|
|
82
|
+
throw failures[0];
|
|
83
|
+
if (failures.length > 1)
|
|
84
|
+
throw new AggregateError(failures, "Meeko reactive observers failed");
|
|
61
85
|
}
|
|
62
86
|
/** Crea un valor observable. Las escrituras iguales no notifican cambios. */
|
|
63
87
|
export function signal(initial) {
|
|
@@ -84,7 +108,6 @@ export function signal(initial) {
|
|
|
84
108
|
writableSignals.add(result);
|
|
85
109
|
return result;
|
|
86
110
|
}
|
|
87
|
-
/** Ejecuta una función cuando cambian las señales leídas por ella. */
|
|
88
111
|
export function effect(fn, source) {
|
|
89
112
|
const owner = activeOwner;
|
|
90
113
|
const observer = {
|
|
@@ -97,7 +120,11 @@ export function effect(fn, source) {
|
|
|
97
120
|
activeObserver = observer;
|
|
98
121
|
activeOwner = owner;
|
|
99
122
|
try {
|
|
100
|
-
fn();
|
|
123
|
+
const result = fn();
|
|
124
|
+
if (observeReturnedPromise(result, (error) => logClientError("Meeko asynchronous effect rejected", error))) {
|
|
125
|
+
stop();
|
|
126
|
+
throw new TypeError("Meeko effect callbacks must be synchronous");
|
|
127
|
+
}
|
|
101
128
|
}
|
|
102
129
|
finally {
|
|
103
130
|
activeObserver = previous;
|
|
@@ -108,18 +135,39 @@ export function effect(fn, source) {
|
|
|
108
135
|
if (source)
|
|
109
136
|
effectSources.set(observer, { owner, source });
|
|
110
137
|
owner?.observers.add(observer);
|
|
111
|
-
|
|
112
|
-
return () => {
|
|
138
|
+
function stop() {
|
|
113
139
|
observer.disposed = true;
|
|
114
140
|
pending.delete(observer);
|
|
115
141
|
detach(observer);
|
|
116
142
|
owner?.observers.delete(observer);
|
|
117
|
-
}
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
observer.run();
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
stop();
|
|
149
|
+
throw error;
|
|
150
|
+
}
|
|
151
|
+
return stop;
|
|
118
152
|
}
|
|
119
153
|
/** Identidad opaca de la raíz reactiva activa; permite aislar instancias anidadas. */
|
|
120
154
|
export function currentEffectOwner() {
|
|
121
155
|
return activeOwner;
|
|
122
156
|
}
|
|
157
|
+
/** Captures the parent of a component root for a later HMR replacement. */
|
|
158
|
+
export function captureParentOwner() {
|
|
159
|
+
const parent = activeOwner?.parent;
|
|
160
|
+
return (work) => {
|
|
161
|
+
const previous = activeOwner;
|
|
162
|
+
activeOwner = parent;
|
|
163
|
+
try {
|
|
164
|
+
return work();
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
activeOwner = previous;
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
}
|
|
123
171
|
/** Devuelve expresiones de plantilla actualmente dependientes de una señal en una raíz. */
|
|
124
172
|
export function signalReadSites(value, owner) {
|
|
125
173
|
if (!owner || !isWritableSignal(value))
|
|
@@ -147,13 +195,10 @@ export function computed(fn) {
|
|
|
147
195
|
/** Agrupa varias escrituras en una sola ronda de notificaciones. */
|
|
148
196
|
export function batch(fn) {
|
|
149
197
|
batchDepth++;
|
|
150
|
-
|
|
151
|
-
return fn();
|
|
152
|
-
}
|
|
153
|
-
finally {
|
|
198
|
+
return finishWithCleanup(fn, () => {
|
|
154
199
|
batchDepth--;
|
|
155
200
|
flush();
|
|
156
|
-
}
|
|
201
|
+
});
|
|
157
202
|
}
|
|
158
203
|
/** Lee señales sin registrar dependencias en el observador activo. */
|
|
159
204
|
export function untrack(fn) {
|
|
@@ -175,7 +220,10 @@ export function createRoot(fn) {
|
|
|
175
220
|
const failures = [];
|
|
176
221
|
for (const child of [...owner.children]) {
|
|
177
222
|
try {
|
|
178
|
-
child();
|
|
223
|
+
const result = child();
|
|
224
|
+
if (observeReturnedPromise(result, (error) => logClientError("Meeko asynchronous cleanup rejected", error))) {
|
|
225
|
+
failures.push(new TypeError("Meeko cleanup callbacks must be synchronous"));
|
|
226
|
+
}
|
|
179
227
|
}
|
|
180
228
|
catch (error) {
|
|
181
229
|
failures.push(error);
|
|
@@ -200,11 +248,40 @@ export function createRoot(fn) {
|
|
|
200
248
|
return fn(dispose);
|
|
201
249
|
}
|
|
202
250
|
catch (error) {
|
|
203
|
-
|
|
251
|
+
try {
|
|
252
|
+
dispose();
|
|
253
|
+
}
|
|
254
|
+
catch (cleanupError) {
|
|
255
|
+
throw new AggregateError([error, cleanupError], "Meeko root setup and cleanup failed");
|
|
256
|
+
}
|
|
204
257
|
throw error;
|
|
205
258
|
}
|
|
206
259
|
finally {
|
|
207
260
|
activeOwner = previous;
|
|
208
261
|
}
|
|
209
262
|
}
|
|
263
|
+
/** Runs cleanup on either outcome without losing an earlier failure. */
|
|
264
|
+
export function finishWithCleanup(work, cleanup) {
|
|
265
|
+
let failed = false;
|
|
266
|
+
let failure;
|
|
267
|
+
let value;
|
|
268
|
+
try {
|
|
269
|
+
value = work();
|
|
270
|
+
}
|
|
271
|
+
catch (error) {
|
|
272
|
+
failed = true;
|
|
273
|
+
failure = error;
|
|
274
|
+
}
|
|
275
|
+
try {
|
|
276
|
+
cleanup();
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
if (failed)
|
|
280
|
+
throw new AggregateError([failure, error], "Meeko work and cleanup failed");
|
|
281
|
+
throw error;
|
|
282
|
+
}
|
|
283
|
+
if (failed)
|
|
284
|
+
throw failure;
|
|
285
|
+
return value;
|
|
286
|
+
}
|
|
210
287
|
//# sourceMappingURL=reactivity.js.map
|
package/dist/reactivity.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"reactivity.js","sourceRoot":"","sources":["../src/reactivity.ts"],"names":[],"mappings":"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","sourcesContent":["/** Señal de solo lectura que registra dependencias al consultar su valor. */\nexport interface ReadonlySignal<T> {\n readonly value: T;\n}\n\n/** Señal cuyo valor puede actualizarse de forma reactiva. */\nexport interface Signal<T> extends ReadonlySignal<T> {\n value: T;\n}\n\n/** Clave nominal para compartir un valor tipado entre instancias anidadas. */\nexport type ContextKey<T> = symbol & { readonly __meekoValue?: (value: T) => T };\n\n/** Crea una clave única; el tipo no se infiere de un valor global compartido. */\nexport function createContext<T>(description?: string): ContextKey<T> {\n return Symbol(description) as ContextKey<T>;\n}\n\n/** Ubicación de una expresión de plantilla que lee una señal durante desarrollo. */\nexport interface EffectSource {\n file: string;\n line: number;\n column: number;\n expression: string;\n kind: \"text\" | \"attribute\";\n}\n\ninterface Observer {\n run: () => void;\n dependencies: Set<InternalSignal<unknown>>;\n disposed: boolean;\n}\n\ninterface Owner {\n observers: Set<Observer>;\n children: Set<() => void>;\n parent: Owner | undefined;\n context: Map<symbol, unknown>;\n}\n\ninterface InternalSignal<T> extends Signal<T> {\n subscribers: Set<Observer> | undefined;\n}\n\nconst writableSignals = new WeakSet<object>();\nconst derivedSignals = new WeakSet<object>();\nconst effectSources = new WeakMap<Observer, { owner: Owner | undefined; source: EffectSource }>();\n\n/** Identifica señales editables creadas por Meeko para conservarlas durante HMR. */\nexport function isWritableSignal(value: unknown): value is Signal<unknown> {\n return typeof value === \"object\" && value !== null && writableSignals.has(value) && !derivedSignals.has(value);\n}\n\nlet activeObserver: Observer | undefined;\nlet activeOwner: Owner | undefined;\nlet batchDepth = 0;\nlet flushing = false;\nconst pending = new Set<Observer>();\n\n/** Publica un valor en la instancia activa y sus descendientes. */\nexport function provide<T>(key: ContextKey<T>, value: T): void {\n if (!activeOwner) throw new Error(\"provide() requires an active component root\");\n activeOwner.context.set(key, value);\n}\n\n/** Lee el proveedor más cercano; falla si falta para evitar un valor implícito. */\nexport function inject<T>(key: ContextKey<T>): T {\n for (let owner = activeOwner; owner; owner = owner.parent) {\n if (owner.context.has(key)) return owner.context.get(key) as T;\n }\n throw new Error(`Missing Meeko context${key.description ? `: ${key.description}` : \"\"}`);\n}\n\n/** Registers an external resource to be released with the current component root. */\nexport function onCleanup(release: () => void): void {\n if (!activeOwner) throw new Error(\"onCleanup() requires an active component root\");\n activeOwner.children.add(release);\n}\n\nfunction detach(observer: Observer): void {\n for (const dependency of observer.dependencies) dependency.subscribers?.delete(observer);\n observer.dependencies.clear();\n}\n\nfunction flush(): void {\n if (flushing || batchDepth > 0) return;\n flushing = true;\n try {\n let iterations = 0;\n while (pending.size > 0) {\n if (++iterations > 1000) throw new Error(\"Reactive update cycle exceeded 1000 iterations\");\n const observers = [...pending];\n pending.clear();\n for (const observer of observers) if (!observer.disposed) observer.run();\n }\n } finally {\n flushing = false;\n }\n}\n\n/** Crea un valor observable. Las escrituras iguales no notifican cambios. */\nexport function signal<T>(initial: T): Signal<T> {\n let current = initial;\n const result: InternalSignal<T> = {\n subscribers: undefined,\n get value() {\n if (activeObserver) {\n (result.subscribers ??= new Set()).add(activeObserver);\n activeObserver.dependencies.add(result as InternalSignal<unknown>);\n }\n return current;\n },\n set value(next: T) {\n if (Object.is(current, next)) return;\n current = next;\n if (result.subscribers) for (const observer of result.subscribers) pending.add(observer);\n flush();\n },\n };\n writableSignals.add(result);\n return result;\n}\n\n/** Ejecuta una función cuando cambian las señales leídas por ella. */\nexport function effect(fn: () => void, source?: EffectSource): () => void {\n const owner = activeOwner;\n const observer: Observer = {\n dependencies: new Set(),\n disposed: false,\n run() {\n detach(observer);\n const previous = activeObserver;\n const previousOwner = activeOwner;\n activeObserver = observer;\n activeOwner = owner;\n try {\n fn();\n } finally {\n activeObserver = previous;\n activeOwner = previousOwner;\n }\n },\n };\n if (source) effectSources.set(observer, { owner, source });\n owner?.observers.add(observer);\n observer.run();\n return () => {\n observer.disposed = true;\n pending.delete(observer);\n detach(observer);\n owner?.observers.delete(observer);\n };\n}\n\n/** Identidad opaca de la raíz reactiva activa; permite aislar instancias anidadas. */\nexport function currentEffectOwner(): object | undefined {\n return activeOwner;\n}\n\n/** Devuelve expresiones de plantilla actualmente dependientes de una señal en una raíz. */\nexport function signalReadSites(value: Signal<unknown>, owner: object | undefined): EffectSource[] {\n if (!owner || !isWritableSignal(value)) return [];\n const sites = new Map<string, EffectSource>();\n for (const observer of (value as InternalSignal<unknown>).subscribers ?? []) {\n const metadata = effectSources.get(observer);\n if (observer.disposed || metadata?.owner !== owner || !metadata) continue;\n const source = metadata.source;\n const key = `${source.file}\\u0000${source.line}\\u0000${source.column}\\u0000${source.kind}\\u0000${source.expression}`;\n sites.set(key, source);\n }\n return [...sites.values()];\n}\n\n/** Deriva un valor de otras señales y lo actualiza cuando cambian. */\nexport function computed<T>(fn: () => T): ReadonlySignal<T> {\n const result = signal<T>(undefined as T);\n derivedSignals.add(result);\n effect(() => {\n result.value = fn();\n });\n return result;\n}\n\n/** Agrupa varias escrituras en una sola ronda de notificaciones. */\nexport function batch<T>(fn: () => T): T {\n batchDepth++;\n try {\n return fn();\n } finally {\n batchDepth--;\n flush();\n }\n}\n\n/** Lee señales sin registrar dependencias en el observador activo. */\nexport function untrack<T>(fn: () => T): T {\n const previous = activeObserver;\n activeObserver = undefined;\n try {\n return fn();\n } finally {\n activeObserver = previous;\n }\n}\n\n/** Asocia efectos a una instancia y entrega una función para liberarlos. */\nexport function createRoot<T>(fn: (dispose: () => void) => T): T {\n const owner: Owner = { observers: new Set(), children: new Set(), parent: activeOwner, context: new Map() };\n const previous = activeOwner;\n activeOwner = owner;\n const dispose = () => {\n const failures: unknown[] = [];\n for (const child of [...owner.children]) {\n try { child(); } catch (error) { failures.push(error); }\n }\n owner.children.clear();\n for (const observer of owner.observers) {\n observer.disposed = true;\n pending.delete(observer);\n detach(observer);\n }\n owner.observers.clear();\n owner.context.clear();\n owner.parent?.children.delete(dispose);\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1) throw new AggregateError(failures, \"Meeko root cleanup failed\");\n };\n owner.parent?.children.add(dispose);\n try {\n return fn(dispose);\n } catch (error) {\n dispose();\n throw error;\n } finally {\n activeOwner = previous;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"reactivity.js","sourceRoot":"","sources":["../src/reactivity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAe7E,iFAAiF;AACjF,MAAM,UAAU,aAAa,CAAI,WAAoB;IACnD,OAAO,MAAM,CAAC,WAAW,CAAkB,CAAC;AAC9C,CAAC;AA4BD,MAAM,eAAe,GAAG,IAAI,OAAO,EAAU,CAAC;AAC9C,MAAM,cAAc,GAAG,IAAI,OAAO,EAAU,CAAC;AAC7C,MAAM,aAAa,GAAG,IAAI,OAAO,EAAgE,CAAC;AAElG,oFAAoF;AACpF,MAAM,UAAU,gBAAgB,CAAC,KAAc;IAC7C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AACjH,CAAC;AAED,IAAI,cAAoC,CAAC;AACzC,IAAI,WAA8B,CAAC;AACnC,IAAI,UAAU,GAAG,CAAC,CAAC;AACnB,IAAI,QAAQ,GAAG,KAAK,CAAC;AACrB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAY,CAAC;AAEpC,mEAAmE;AACnE,MAAM,UAAU,OAAO,CAAI,GAAkB,EAAE,KAAQ;IACrD,IAAI,CAAC,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IACjF,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;AACtC,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,MAAM,CAAI,GAAkB;IAC1C,KAAK,IAAI,KAAK,GAAG,WAAW,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAC1D,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAM,CAAC;IACjE,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,wBAAwB,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC3F,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,WAAW,CAAI,GAAkB;IAC/C,KAAK,IAAI,KAAK,GAAG,WAAW,EAAE,KAAK,EAAE,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC;QAC1D,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAM,CAAC;IACjE,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAID,yFAAyF;AACzF,MAAM,UAAU,SAAS,CAAgC,OAA+B;IACtF,IAAI,CAAC,WAAW;QAAE,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;IACnF,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;AACpC,CAAC;AAED,SAAS,MAAM,CAAC,QAAkB;IAChC,KAAK,MAAM,UAAU,IAAI,QAAQ,CAAC,YAAY;QAAE,UAAU,CAAC,WAAW,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IACzF,QAAQ,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;AAChC,CAAC;AAED,SAAS,KAAK;IACZ,IAAI,QAAQ,IAAI,UAAU,GAAG,CAAC;QAAE,OAAO;IACvC,QAAQ,GAAG,IAAI,CAAC;IAChB,MAAM,QAAQ,GAAc,EAAE,CAAC;IAC/B,IAAI,CAAC;QACH,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,OAAO,OAAO,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YACxB,IAAI,EAAE,UAAU,GAAG,IAAI,EAAE,CAAC;gBACxB,OAAO,CAAC,KAAK,EAAE,CAAC;gBAChB,QAAQ,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,gDAAgD,CAAC,CAAC,CAAC;gBAC3E,MAAM;YACR,CAAC;YACD,MAAM,SAAS,GAAG,CAAC,GAAG,OAAO,CAAC,CAAC;YAC/B,OAAO,CAAC,KAAK,EAAE,CAAC;YAChB,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,IAAI,QAAQ,CAAC,QAAQ;oBAAE,SAAS;gBAChC,IAAI,CAAC;oBAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;gBAAC,CAAC;gBACvB,OAAO,KAAK,EAAE,CAAC;oBAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;gBAAC,CAAC;YACzC,CAAC;QACH,CAAC;IACH,CAAC;YAAS,CAAC;QACT,QAAQ,GAAG,KAAK,CAAC;IACnB,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,QAAQ,CAAC,CAAC,CAAC,CAAC;IAC7C,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,MAAM,IAAI,cAAc,CAAC,QAAQ,EAAE,iCAAiC,CAAC,CAAC;AACjG,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,MAAM,CAAI,OAAU;IAClC,IAAI,OAAO,GAAG,OAAO,CAAC;IACtB,MAAM,MAAM,GAAsB;QAChC,WAAW,EAAE,SAAS;QACtB,IAAI,KAAK;YACP,IAAI,cAAc,EAAE,CAAC;gBACnB,CAAC,MAAM,CAAC,WAAW,KAAK,IAAI,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBACvD,cAAc,CAAC,YAAY,CAAC,GAAG,CAAC,MAAiC,CAAC,CAAC;YACrE,CAAC;YACD,OAAO,OAAO,CAAC;QACjB,CAAC;QACD,IAAI,KAAK,CAAC,IAAO;YACf,IAAI,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,IAAI,CAAC;gBAAE,OAAO;YACrC,OAAO,GAAG,IAAI,CAAC;YACf,IAAI,MAAM,CAAC,WAAW;gBAAE,KAAK,MAAM,QAAQ,IAAI,MAAM,CAAC,WAAW;oBAAE,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACzF,KAAK,EAAE,CAAC;QACV,CAAC;KACF,CAAC;IACF,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5B,OAAO,MAAM,CAAC;AAChB,CAAC;AAKD,MAAM,UAAU,MAAM,CAAgC,EAAyB,EAAE,MAAqB;IACpG,MAAM,KAAK,GAAG,WAAW,CAAC;IAC1B,MAAM,QAAQ,GAAa;QACzB,YAAY,EAAE,IAAI,GAAG,EAAE;QACvB,QAAQ,EAAE,KAAK;QACf,GAAG;YACD,MAAM,CAAC,QAAQ,CAAC,CAAC;YACjB,MAAM,QAAQ,GAAG,cAAc,CAAC;YAChC,MAAM,aAAa,GAAG,WAAW,CAAC;YAClC,cAAc,GAAG,QAAQ,CAAC;YAC1B,WAAW,GAAG,KAAK,CAAC;YACpB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAY,EAAE,EAAE,CAAC;gBAC7B,IAAI,sBAAsB,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,oCAAoC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;oBAC3G,IAAI,EAAE,CAAC;oBACP,MAAM,IAAI,SAAS,CAAC,4CAA4C,CAAC,CAAC;gBACpE,CAAC;YACH,CAAC;oBAAS,CAAC;gBACT,cAAc,GAAG,QAAQ,CAAC;gBAC1B,WAAW,GAAG,aAAa,CAAC;YAC9B,CAAC;QACH,CAAC;KACF,CAAC;IACF,IAAI,MAAM;QAAE,aAAa,CAAC,GAAG,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IAC3D,KAAK,EAAE,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC/B,SAAS,IAAI;QACX,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAAC;QACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzB,MAAM,CAAC,QAAQ,CAAC,CAAC;QACjB,KAAK,EAAE,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACpC,CAAC;IACD,IAAI,CAAC;QAAC,QAAQ,CAAC,GAAG,EAAE,CAAC;IAAC,CAAC;IACvB,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,EAAE,CAAC;QACP,MAAM,KAAK,CAAC;IACd,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,kBAAkB;IAChC,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,2EAA2E;AAC3E,MAAM,UAAU,kBAAkB;IAChC,MAAM,MAAM,GAAG,WAAW,EAAE,MAAM,CAAC;IACnC,OAAO,CAAI,IAAa,EAAK,EAAE;QAC7B,MAAM,QAAQ,GAAG,WAAW,CAAC;QAC7B,WAAW,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC;YAAC,OAAO,IAAI,EAAE,CAAC;QAAC,CAAC;gBACd,CAAC;YAAC,WAAW,GAAG,QAAQ,CAAC;QAAC,CAAC;IACrC,CAAC,CAAC;AACJ,CAAC;AAED,2FAA2F;AAC3F,MAAM,UAAU,eAAe,CAAC,KAAsB,EAAE,KAAyB;IAC/E,IAAI,CAAC,KAAK,IAAI,CAAC,gBAAgB,CAAC,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAClD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC9C,KAAK,MAAM,QAAQ,IAAK,KAAiC,CAAC,WAAW,IAAI,EAAE,EAAE,CAAC;QAC5E,MAAM,QAAQ,GAAG,aAAa,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7C,IAAI,QAAQ,CAAC,QAAQ,IAAI,QAAQ,EAAE,KAAK,KAAK,KAAK,IAAI,CAAC,QAAQ;YAAE,SAAS;QAC1E,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;QAC/B,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,IAAI,SAAS,MAAM,CAAC,IAAI,SAAS,MAAM,CAAC,MAAM,SAAS,MAAM,CAAC,IAAI,SAAS,MAAM,CAAC,UAAU,EAAE,CAAC;QACrH,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACzB,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC;AAC7B,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,QAAQ,CAAI,EAAW;IACrC,MAAM,MAAM,GAAG,MAAM,CAAI,SAAc,CAAC,CAAC;IACzC,cAAc,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B,MAAM,CAAC,GAAG,EAAE;QACV,MAAM,CAAC,KAAK,GAAG,EAAE,EAAE,CAAC;IACtB,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,KAAK,CAAI,EAAW;IAClC,UAAU,EAAE,CAAC;IACb,OAAO,iBAAiB,CAAC,EAAE,EAAE,GAAG,EAAE;QAChC,UAAU,EAAE,CAAC;QACb,KAAK,EAAE,CAAC;IACV,CAAC,CAAC,CAAC;AACL,CAAC;AAED,sEAAsE;AACtE,MAAM,UAAU,OAAO,CAAI,EAAW;IACpC,MAAM,QAAQ,GAAG,cAAc,CAAC;IAChC,cAAc,GAAG,SAAS,CAAC;IAC3B,IAAI,CAAC;QACH,OAAO,EAAE,EAAE,CAAC;IACd,CAAC;YAAS,CAAC;QACT,cAAc,GAAG,QAAQ,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,UAAU,CAAI,EAA8B;IAC1D,MAAM,KAAK,GAAU,EAAE,SAAS,EAAE,IAAI,GAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;IAC5G,MAAM,QAAQ,GAAG,WAAW,CAAC;IAC7B,WAAW,GAAG,KAAK,CAAC;IACpB,MAAM,OAAO,GAAG,GAAG,EAAE;QACnB,MAAM,QAAQ,GAAc,EAAE,CAAC;QAC/B,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC;YACxC,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,KAAK,EAAE,CAAC;gBACvB,IAAI,sBAAsB,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,qCAAqC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC;oBAC5G,QAAQ,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,6CAA6C,CAAC,CAAC,CAAC;gBAC9E,CAAC;YACH,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAAC,CAAC;QAC3C,CAAC;QACD,KAAK,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC;QACvB,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;YACvC,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAAC;YACzB,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YACzB,MAAM,CAAC,QAAQ,CAAC,CAAC;QACnB,CAAC;QACD,KAAK,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACxB,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACtB,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QACvC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;YAAE,MAAM,QAAQ,CAAC,CAAC,CAAC,CAAC;QAC7C,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;YAAE,MAAM,IAAI,cAAc,CAAC,QAAQ,EAAE,2BAA2B,CAAC,CAAC;IAC3F,CAAC,CAAC;IACF,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACpC,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC;IACrB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CAAC;YAAC,OAAO,EAAE,CAAC;QAAC,CAAC;QAClB,OAAO,YAAY,EAAE,CAAC;YACpB,MAAM,IAAI,cAAc,CAAC,CAAC,KAAK,EAAE,YAAY,CAAC,EAAE,qCAAqC,CAAC,CAAC;QACzF,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;YAAS,CAAC;QACT,WAAW,GAAG,QAAQ,CAAC;IACzB,CAAC;AACH,CAAC;AAED,wEAAwE;AACxE,MAAM,UAAU,iBAAiB,CAAI,IAAa,EAAE,OAAmB;IACrE,IAAI,MAAM,GAAG,KAAK,CAAC;IACnB,IAAI,OAAgB,CAAC;IACrB,IAAI,KAAS,CAAC;IACd,IAAI,CAAC;QAAC,KAAK,GAAG,IAAI,EAAE,CAAC;IAAC,CAAC;IACvB,OAAO,KAAK,EAAE,CAAC;QAAC,MAAM,GAAG,IAAI,CAAC;QAAC,OAAO,GAAG,KAAK,CAAC;IAAC,CAAC;IACjD,IAAI,CAAC;QAAC,OAAO,EAAE,CAAC;IAAC,CAAC;IAClB,OAAO,KAAK,EAAE,CAAC;QACb,IAAI,MAAM;YAAE,MAAM,IAAI,cAAc,CAAC,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,+BAA+B,CAAC,CAAC;QACxF,MAAM,KAAK,CAAC;IACd,CAAC;IACD,IAAI,MAAM;QAAE,MAAM,OAAO,CAAC;IAC1B,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["import { logClientError, observeReturnedPromise } from \"./error-observer.js\";\n\n/** Señal de solo lectura que registra dependencias al consultar su valor. */\nexport interface ReadonlySignal<T> {\n readonly value: T;\n}\n\n/** Señal cuyo valor puede actualizarse de forma reactiva. */\nexport interface Signal<T> extends ReadonlySignal<T> {\n value: T;\n}\n\n/** Clave nominal para compartir un valor tipado entre instancias anidadas. */\nexport type ContextKey<T> = symbol & { readonly __meekoValue?: (value: T) => T };\n\n/** Crea una clave única; el tipo no se infiere de un valor global compartido. */\nexport function createContext<T>(description?: string): ContextKey<T> {\n return Symbol(description) as ContextKey<T>;\n}\n\n/** Ubicación de una expresión de plantilla que lee una señal durante desarrollo. */\nexport interface EffectSource {\n file: string;\n line: number;\n column: number;\n expression: string;\n kind: \"text\" | \"attribute\";\n}\n\ninterface Observer {\n run: () => void;\n dependencies: Set<InternalSignal<unknown>>;\n disposed: boolean;\n}\n\ninterface Owner {\n observers: Set<Observer>;\n children: Set<() => unknown>;\n parent: Owner | undefined;\n context: Map<symbol, unknown>;\n}\n\ninterface InternalSignal<T> extends Signal<T> {\n subscribers: Set<Observer> | undefined;\n}\n\nconst writableSignals = new WeakSet<object>();\nconst derivedSignals = new WeakSet<object>();\nconst effectSources = new WeakMap<Observer, { owner: Owner | undefined; source: EffectSource }>();\n\n/** Identifica señales editables creadas por Meeko para conservarlas durante HMR. */\nexport function isWritableSignal(value: unknown): value is Signal<unknown> {\n return typeof value === \"object\" && value !== null && writableSignals.has(value) && !derivedSignals.has(value);\n}\n\nlet activeObserver: Observer | undefined;\nlet activeOwner: Owner | undefined;\nlet batchDepth = 0;\nlet flushing = false;\nconst pending = new Set<Observer>();\n\n/** Publica un valor en la instancia activa y sus descendientes. */\nexport function provide<T>(key: ContextKey<T>, value: T): void {\n if (!activeOwner) throw new Error(\"provide() requires an active component root\");\n activeOwner.context.set(key, value);\n}\n\n/** Lee el proveedor más cercano; falla si falta para evitar un valor implícito. */\nexport function inject<T>(key: ContextKey<T>): T {\n for (let owner = activeOwner; owner; owner = owner.parent) {\n if (owner.context.has(key)) return owner.context.get(key) as T;\n }\n throw new Error(`Missing Meeko context${key.description ? `: ${key.description}` : \"\"}`);\n}\n\n/** Looks up optional context without creating a process-wide fallback. */\nexport function findContext<T>(key: ContextKey<T>): T | undefined {\n for (let owner = activeOwner; owner; owner = owner.parent) {\n if (owner.context.has(key)) return owner.context.get(key) as T;\n }\n return undefined;\n}\n\ntype SyncCleanupCallback<F extends () => unknown> = [Extract<ReturnType<F>, PromiseLike<unknown>>] extends [never] ? F : never;\n\n/** Registers a synchronous external-resource release with the current component root. */\nexport function onCleanup<const F extends () => unknown>(release: SyncCleanupCallback<F>): void {\n if (!activeOwner) throw new Error(\"onCleanup() requires an active component root\");\n activeOwner.children.add(release);\n}\n\nfunction detach(observer: Observer): void {\n for (const dependency of observer.dependencies) dependency.subscribers?.delete(observer);\n observer.dependencies.clear();\n}\n\nfunction flush(): void {\n if (flushing || batchDepth > 0) return;\n flushing = true;\n const failures: unknown[] = [];\n try {\n let iterations = 0;\n while (pending.size > 0) {\n if (++iterations > 1000) {\n pending.clear();\n failures.push(new Error(\"Reactive update cycle exceeded 1000 iterations\"));\n break;\n }\n const observers = [...pending];\n pending.clear();\n for (const observer of observers) {\n if (observer.disposed) continue;\n try { observer.run(); }\n catch (error) { failures.push(error); }\n }\n }\n } finally {\n flushing = false;\n }\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1) throw new AggregateError(failures, \"Meeko reactive observers failed\");\n}\n\n/** Crea un valor observable. Las escrituras iguales no notifican cambios. */\nexport function signal<T>(initial: T): Signal<T> {\n let current = initial;\n const result: InternalSignal<T> = {\n subscribers: undefined,\n get value() {\n if (activeObserver) {\n (result.subscribers ??= new Set()).add(activeObserver);\n activeObserver.dependencies.add(result as InternalSignal<unknown>);\n }\n return current;\n },\n set value(next: T) {\n if (Object.is(current, next)) return;\n current = next;\n if (result.subscribers) for (const observer of result.subscribers) pending.add(observer);\n flush();\n },\n };\n writableSignals.add(result);\n return result;\n}\n\n/** Ejecuta una función cuando cambian las señales leídas por ella. */\ntype SyncEffectCallback<F extends () => unknown> = [Extract<ReturnType<F>, PromiseLike<unknown>>] extends [never] ? F : never;\n\nexport function effect<const F extends () => unknown>(fn: SyncEffectCallback<F>, source?: EffectSource): () => void {\n const owner = activeOwner;\n const observer: Observer = {\n dependencies: new Set(),\n disposed: false,\n run() {\n detach(observer);\n const previous = activeObserver;\n const previousOwner = activeOwner;\n activeObserver = observer;\n activeOwner = owner;\n try {\n const result: unknown = fn();\n if (observeReturnedPromise(result, (error) => logClientError(\"Meeko asynchronous effect rejected\", error))) {\n stop();\n throw new TypeError(\"Meeko effect callbacks must be synchronous\");\n }\n } finally {\n activeObserver = previous;\n activeOwner = previousOwner;\n }\n },\n };\n if (source) effectSources.set(observer, { owner, source });\n owner?.observers.add(observer);\n function stop(): void {\n observer.disposed = true;\n pending.delete(observer);\n detach(observer);\n owner?.observers.delete(observer);\n }\n try { observer.run(); }\n catch (error) {\n stop();\n throw error;\n }\n return stop;\n}\n\n/** Identidad opaca de la raíz reactiva activa; permite aislar instancias anidadas. */\nexport function currentEffectOwner(): object | undefined {\n return activeOwner;\n}\n\n/** Captures the parent of a component root for a later HMR replacement. */\nexport function captureParentOwner(): <T>(work: () => T) => T {\n const parent = activeOwner?.parent;\n return <T>(work: () => T): T => {\n const previous = activeOwner;\n activeOwner = parent;\n try { return work(); }\n finally { activeOwner = previous; }\n };\n}\n\n/** Devuelve expresiones de plantilla actualmente dependientes de una señal en una raíz. */\nexport function signalReadSites(value: Signal<unknown>, owner: object | undefined): EffectSource[] {\n if (!owner || !isWritableSignal(value)) return [];\n const sites = new Map<string, EffectSource>();\n for (const observer of (value as InternalSignal<unknown>).subscribers ?? []) {\n const metadata = effectSources.get(observer);\n if (observer.disposed || metadata?.owner !== owner || !metadata) continue;\n const source = metadata.source;\n const key = `${source.file}\\u0000${source.line}\\u0000${source.column}\\u0000${source.kind}\\u0000${source.expression}`;\n sites.set(key, source);\n }\n return [...sites.values()];\n}\n\n/** Deriva un valor de otras señales y lo actualiza cuando cambian. */\nexport function computed<T>(fn: () => T): ReadonlySignal<T> {\n const result = signal<T>(undefined as T);\n derivedSignals.add(result);\n effect(() => {\n result.value = fn();\n });\n return result;\n}\n\n/** Agrupa varias escrituras en una sola ronda de notificaciones. */\nexport function batch<T>(fn: () => T): T {\n batchDepth++;\n return finishWithCleanup(fn, () => {\n batchDepth--;\n flush();\n });\n}\n\n/** Lee señales sin registrar dependencias en el observador activo. */\nexport function untrack<T>(fn: () => T): T {\n const previous = activeObserver;\n activeObserver = undefined;\n try {\n return fn();\n } finally {\n activeObserver = previous;\n }\n}\n\n/** Asocia efectos a una instancia y entrega una función para liberarlos. */\nexport function createRoot<T>(fn: (dispose: () => void) => T): T {\n const owner: Owner = { observers: new Set(), children: new Set(), parent: activeOwner, context: new Map() };\n const previous = activeOwner;\n activeOwner = owner;\n const dispose = () => {\n const failures: unknown[] = [];\n for (const child of [...owner.children]) {\n try {\n const result = child();\n if (observeReturnedPromise(result, (error) => logClientError(\"Meeko asynchronous cleanup rejected\", error))) {\n failures.push(new TypeError(\"Meeko cleanup callbacks must be synchronous\"));\n }\n } catch (error) { failures.push(error); }\n }\n owner.children.clear();\n for (const observer of owner.observers) {\n observer.disposed = true;\n pending.delete(observer);\n detach(observer);\n }\n owner.observers.clear();\n owner.context.clear();\n owner.parent?.children.delete(dispose);\n if (failures.length === 1) throw failures[0];\n if (failures.length > 1) throw new AggregateError(failures, \"Meeko root cleanup failed\");\n };\n owner.parent?.children.add(dispose);\n try {\n return fn(dispose);\n } catch (error) {\n try { dispose(); }\n catch (cleanupError) {\n throw new AggregateError([error, cleanupError], \"Meeko root setup and cleanup failed\");\n }\n throw error;\n } finally {\n activeOwner = previous;\n }\n}\n\n/** Runs cleanup on either outcome without losing an earlier failure. */\nexport function finishWithCleanup<T>(work: () => T, cleanup: () => void): T {\n let failed = false;\n let failure: unknown;\n let value!: T;\n try { value = work(); }\n catch (error) { failed = true; failure = error; }\n try { cleanup(); }\n catch (error) {\n if (failed) throw new AggregateError([failure, error], \"Meeko work and cleanup failed\");\n throw error;\n }\n if (failed) throw failure;\n return value;\n}\n"]}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,2 +1,4 @@
|
|
|
1
|
+
/** Stable ownership marker for generated component declarations. */
|
|
2
|
+
export declare const componentTypeDeclarationMarker = "// @meeko-generated component-declaration v1";
|
|
1
3
|
/** Genera declaraciones TypeScript para un componente y sus imports .meeko relativos. */
|
|
2
4
|
export declare function generateTypes(source: string, filename: string): Promise<string[]>;
|