theokit 0.2.3 → 0.2.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.
- package/LICENSE +201 -0
- package/dist/{actions-virtual-module-E6PU47GV.js → actions-virtual-module-HWNTIEPI.js} +40 -6
- package/dist/actions-virtual-module-HWNTIEPI.js.map +1 -0
- package/dist/{actions-virtual-module-E7IELVHL.js → actions-virtual-module-SEIPACG5.js} +40 -6
- package/dist/actions-virtual-module-SEIPACG5.js.map +1 -0
- package/dist/add-2ZFFGGE4.js +0 -0
- package/dist/{app-typed-client-FOWJP534.js → app-typed-client-6GC6VWXS.js} +4 -4
- package/dist/{app-typed-client-IMILAGER.js → app-typed-client-US2ZXBEC.js} +3 -3
- package/dist/aws-lambda-XYCGZH3I.js +0 -0
- package/dist/broadcast-QOQGUNNK.js +0 -0
- package/dist/{build-KRSHWXMJ.js → build-MREW6MVS.js} +5 -5
- package/dist/build-request-body-preview-II2235E6.js +0 -0
- package/dist/bun-K73TQEWC.js +0 -0
- package/dist/check-PZR67OY5.js +0 -0
- package/dist/chunk-5ODOE6EF.js +0 -0
- package/dist/{chunk-MOT42NAH.js → chunk-5OFPQK6N.js} +18 -3
- package/dist/chunk-5OFPQK6N.js.map +1 -0
- package/dist/{chunk-RIBIAL7A.js → chunk-5OKZY2VL.js} +5 -5
- package/dist/{chunk-7DHGV77J.js → chunk-7TOMTMHT.js} +18 -3
- package/dist/chunk-7TOMTMHT.js.map +1 -0
- package/dist/{chunk-SEVYARIU.js → chunk-BE2LKDI7.js} +3 -3
- package/dist/chunk-F3TG5FJV.js +0 -0
- package/dist/chunk-KT3MWNZG.js +0 -0
- package/dist/chunk-O7335ZGH.js +0 -0
- package/dist/{chunk-QLGES2HC.js → chunk-SNDZQ64K.js} +2 -2
- package/dist/chunk-TPCT3MXV.js +0 -0
- package/dist/chunk-WZ7CPVQB.js +0 -0
- package/dist/{chunk-F7RLPDXW.js → chunk-X2OLD264.js} +6 -6
- package/dist/chunk-X4JAX2U3.js +0 -0
- package/dist/chunk-XMS5VRIK.js +0 -0
- package/dist/chunk-XP7YXRHO.js +0 -0
- package/dist/{chunk-ERAZNHHR.js → chunk-YWWHK7R6.js} +2 -2
- package/dist/chunk-ZJW5FFYJ.js +0 -0
- package/dist/chunk-ZOXNJV2O.js +0 -0
- package/dist/cli/index.js +5 -5
- package/dist/cloudflare-LCAOTRYZ.js +0 -0
- package/dist/configure-agent-registry-6YGTJYBC.js +0 -0
- package/dist/deno-deploy-ZN4RE5HF.js +0 -0
- package/dist/{dev-UZJVBUF3.js → dev-6P2DM33Q.js} +4 -4
- package/dist/{dev-emit-3CHM73TV.js → dev-emit-MLDFOLUU.js} +3 -3
- package/dist/{dev-emit-I3CKOHML.js → dev-emit-PRSRPDHA.js} +4 -4
- package/dist/dispatcher-E6QV32BO.js +0 -0
- package/dist/dist-E6BL4ZVY.js +0 -0
- package/dist/docker-EZDA5FT7.js +0 -0
- package/dist/generate-DT4IIAHF.js +0 -0
- package/dist/index.js +2 -2
- package/dist/info-FJ4NXKTB.js +0 -0
- package/dist/lib-NL5JXGEB.js +0 -0
- package/dist/netlify-5VQ22Z2P.js +0 -0
- package/dist/node-3APTLGWB.js +0 -0
- package/dist/{openapi-ILYEJ6OR.js → openapi-SOKZTFE3.js} +4 -4
- package/dist/proper-lockfile-4Y3DP3RP.js +0 -0
- package/dist/registry-5QFTLOL2.js +0 -0
- package/dist/{routes-IGT42JJO.js → routes-XVRAUH6H.js} +3 -3
- package/dist/scan-C2BOKLSY.js +0 -0
- package/dist/schema-VR6YNVLQ.js +0 -0
- package/dist/server/index.d.ts +10 -0
- package/dist/server/index.js +2 -2
- package/dist/services-typed-client-ZX5JUHH3.js +0 -0
- package/dist/sqlite-vec-ARPNUBWT.js +0 -0
- package/dist/{start-UX2IPPSH.js → start-R7XSQL5L.js} +4 -4
- package/dist/static-TZBVBDTB.js +0 -0
- package/dist/storage-manager-D5KBXXKB.js +0 -0
- package/dist/theo-cloud-3K4DGB3S.js +0 -0
- package/dist/upgrade-readiness-GUJBCJIS.js +0 -0
- package/dist/vercel-MWW24ABC.js +0 -0
- package/dist/vite-plugin/index.js +2 -2
- package/dist/{vite-plugin-FTYXDKKG.js → vite-plugin-6MPHTKIW.js} +4 -4
- package/package.json +7 -7
- package/dist/actions-virtual-module-E6PU47GV.js.map +0 -1
- package/dist/actions-virtual-module-E7IELVHL.js.map +0 -1
- package/dist/chunk-7DHGV77J.js.map +0 -1
- package/dist/chunk-MOT42NAH.js.map +0 -1
- /package/dist/{app-typed-client-FOWJP534.js.map → app-typed-client-6GC6VWXS.js.map} +0 -0
- /package/dist/{app-typed-client-IMILAGER.js.map → app-typed-client-US2ZXBEC.js.map} +0 -0
- /package/dist/{build-KRSHWXMJ.js.map → build-MREW6MVS.js.map} +0 -0
- /package/dist/{chunk-RIBIAL7A.js.map → chunk-5OKZY2VL.js.map} +0 -0
- /package/dist/{chunk-SEVYARIU.js.map → chunk-BE2LKDI7.js.map} +0 -0
- /package/dist/{chunk-QLGES2HC.js.map → chunk-SNDZQ64K.js.map} +0 -0
- /package/dist/{chunk-F7RLPDXW.js.map → chunk-X2OLD264.js.map} +0 -0
- /package/dist/{chunk-ERAZNHHR.js.map → chunk-YWWHK7R6.js.map} +0 -0
- /package/dist/{dev-UZJVBUF3.js.map → dev-6P2DM33Q.js.map} +0 -0
- /package/dist/{dev-emit-3CHM73TV.js.map → dev-emit-MLDFOLUU.js.map} +0 -0
- /package/dist/{dev-emit-I3CKOHML.js.map → dev-emit-PRSRPDHA.js.map} +0 -0
- /package/dist/{openapi-ILYEJ6OR.js.map → openapi-SOKZTFE3.js.map} +0 -0
- /package/dist/{routes-IGT42JJO.js.map → routes-XVRAUH6H.js.map} +0 -0
- /package/dist/{start-UX2IPPSH.js.map → start-R7XSQL5L.js.map} +0 -0
- /package/dist/{vite-plugin-FTYXDKKG.js.map → vite-plugin-6MPHTKIW.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/vite-plugin/actions-virtual-module.ts"],"sourcesContent":["/**\n * Vite plugin: resolves `@theo/actions` virtual module and emits a typed\n * Proxy facade that calls `theoFetch('/_actions/<name>', body)` against the\n * server-side action handlers.\n *\n * Per plan g3-server-actions-and-useaction v1.2 § Phase 3 / T3.1 + ADR D4.\n * Astro `vite-plugin-actions.ts` modular pattern. Single focused plugin\n * (not monolithic), virtual module + `configureServer` watcher.\n *\n * Module shape emitted on client environment: thin proxy that forwards\n * `actions.<name>(input)` to `POST /_actions/<name>` with JSON or\n * FormData body. On server environment: re-export of the manifest for\n * SSR / module-loader access (T1.3 sub-C consumer).\n *\n * EC-15 (DOCUMENT): HMR uses Vite default invalidation — coarse but\n * correct. Optimization (fine-grained invalidation of only consumers of\n * `@theo/actions`) deferred to G3.1 if dev-server p95 reload > 500ms.\n */\nimport { existsSync, mkdirSync, renameSync, watch as fsWatch, writeFileSync } from 'node:fs'\nimport { dirname, join, posix, resolve } from 'node:path'\n\nimport type { Plugin, ViteDevServer } from 'vite'\n\nimport { scanServerActionsEnriched, type ActionManifestEntry } from '../server/scan/action-scan.js'\n\nconst VIRTUAL_ID = '@theo/actions'\nconst RESOLVED_ID = `\\0${VIRTUAL_ID}`\n\nexport interface ActionsVirtualModuleOptions {\n /** Path to server directory (where `actions/` lives). */\n serverDir: string\n /**\n * Optional `.theo/` output dir for emitting `actions.d.ts`. When provided,\n * the plugin writes an ambient `declare module '@theo/actions'` so TS in\n * consumer apps can resolve the virtual module import. Mirrors the G1\n * `app-typed-client` emit pattern.\n */\n distDir?: string\n}\n\nexport function actionsVirtualModule(opts: ActionsVirtualModuleOptions): Plugin {\n const { serverDir, distDir } = opts\n\n function emitActionsDts(): void {\n if (distDir === undefined) return\n const entries = safeScan(serverDir)\n const dtsPath = posix.join(resolve(distDir).replace(/\\\\/g, '/'), 'actions.d.ts')\n const content = generateActionsDts(entries)\n try {\n // eslint-disable-next-line security/detect-non-literal-fs-filename -- build-time derived path\n mkdirSync(dirname(dtsPath), { recursive: true })\n const tmp = `${dtsPath}.${process.pid}.tmp`\n // eslint-disable-next-line security/detect-non-literal-fs-filename -- build-time derived path\n writeFileSync(tmp, content)\n // eslint-disable-next-line security/detect-non-literal-fs-filename -- build-time derived path\n renameSync(tmp, dtsPath)\n } catch (err) {\n console.error('[theokit:actions-virtual-module] dts emit error:', err)\n }\n }\n\n return {\n name: 'theo:actions-virtual-module',\n enforce: 'pre',\n configResolved() {\n emitActionsDts()\n },\n buildEnd() {\n emitActionsDts()\n },\n resolveId(id: string) {\n if (id === VIRTUAL_ID) return RESOLVED_ID\n return undefined\n },\n load(id: string) {\n if (id !== RESOLVED_ID) return undefined\n const entries = safeScan(serverDir)\n const ctx = this as unknown as { environment?: { name?: string } } | undefined\n const envName = ctx?.environment?.name\n const isClient = envName === 'client' || envName === undefined\n return isClient ? generateClientFacade(entries) : generateServerManifest(entries)\n },\n configureServer(server: ViteDevServer) {\n const actionsDir = join(serverDir, 'actions')\n // eslint-disable-next-line security/detect-non-literal-fs-filename -- build-time derived path\n if (!existsSync(actionsDir)) return\n // EC-15: coarse invalidation — invalidate ALL modules on actions file change.\n // Optimization deferred per plan ADR D4 note.\n // eslint-disable-next-line security/detect-non-literal-fs-filename -- build-time path\n const watcher = fsWatch(actionsDir, { recursive: true }, () => {\n emitActionsDts()\n const mod = server.moduleGraph.getModuleById(RESOLVED_ID)\n if (mod) {\n server.moduleGraph.invalidateModule(mod)\n }\n server.ws.send({ type: 'full-reload' })\n })\n server.httpServer?.once('close', () => {\n watcher.close()\n })\n },\n }\n}\n\n/**\n * Emit `.theo/actions.d.ts` — ambient declaration of `@theo/actions` so\n * consumer TS apps can `import { actions } from '@theo/actions'` and get\n * typed completions for each scanned action name. Each entry maps name to\n * a generic `(input: unknown) => Promise<{data, error}>` invoker — the full\n * input/output inference from defineAction would require either monomorphic\n * dts-bundle or virtual type emit (deferred to a future plan).\n */\nfunction generateActionsDts(entries: readonly ActionManifestEntry[]): string {\n const lines = entries\n .map(\n (entry) =>\n ` ${JSON.stringify(entry.name)}: (input: unknown) => Promise<{ data: unknown; error: undefined } | { data: undefined; error: { code: string; message: string; fields?: Record<string, string[]>; type?: string } }>`,\n )\n .join('\\n')\n return `// AUTO-GENERATED by @theo/actions virtual module. DO NOT EDIT MANUALLY.\ndeclare module '@theo/actions' {\n export const actions: {\n${lines}\n }\n}\n`\n}\n\nfunction safeScan(serverDir: string): ActionManifestEntry[] {\n try {\n return scanServerActionsEnriched(serverDir)\n } catch {\n // ActionScanError surfaces at build time; for HMR keep an empty manifest\n // so the dev server doesn't crash mid-edit.\n return []\n }\n}\n\n/**\n * Client-side module: emits a Proxy facade. For each action `name` in\n * manifest, `actions.<name>(input)` POSTs to `/_actions/<name>` with JSON\n * body (or FormData when input is a FormData instance) and parses the\n * `application/json+devalue` response via the runtime helper.\n */\nfunction generateClientFacade(entries: ActionManifestEntry[]): string {\n const entryLines = entries\n .map((entry) => ` ${JSON.stringify(entry.name)}: ${JSON.stringify(entry.urlPath)},`)\n .join('\\n')\n\n return `// AUTO-GENERATED by @theo/actions virtual module\n/* eslint-disable */\nconst ACTION_URL_MAP = {\n${entryLines}\n}\n\n// Devtools telemetry — fires in the SAME realm as the Overlay React tree\n// (browser), so the Actions tab updates immediately on each call.\n// The Overlay component installs \\`window.__theoDevtoolsDispatcher\\` on\n// mount (dev only; prod tree-shakes the Overlay entirely). Reading the\n// global avoids a cross-package dynamic import that Vite's virtual-module\n// resolver cannot trace. Same pattern as React DevTools'\n// \\`__REACT_DEVTOOLS_GLOBAL_HOOK__\\`.\nfunction emitTelemetry(name, startedAt, input, outcome) {\n if (typeof window === 'undefined') return\n const dispatcher = window.__theoDevtoolsDispatcher\n if (!dispatcher || typeof dispatcher.onActionCall !== 'function') return\n try {\n dispatcher.onActionCall({\n id: 'act-' + String(Date.now()) + '-' + Math.random().toString(36).slice(2, 8),\n timestamp: startedAt,\n name,\n input,\n output: outcome.status === 'success' ? outcome.data : undefined,\n error: outcome.status === 'error' ? outcome.error : undefined,\n durationMs: Date.now() - startedAt,\n status: outcome.status,\n })\n } catch (_) {\n // dispatcher threw — devtools UI bug; never bubble to consumer code\n }\n}\n\nasync function callAction(name, url, input) {\n const startedAt = Date.now()\n const isForm = typeof FormData !== 'undefined' && input instanceof FormData\n const headers = { 'x-theo-action': '1' }\n const body = isForm ? input : JSON.stringify(input ?? {})\n if (!isForm) headers['content-type'] = 'application/json'\n let response\n try {\n response = await fetch(url, { method: 'POST', headers, body, credentials: 'same-origin' })\n } catch (e) {\n const err = { code: 'NETWORK_ERROR', message: e && e.message ? e.message : 'fetch failed' }\n emitTelemetry(name, startedAt, input, { status: 'error', error: err })\n return { data: undefined, error: err }\n }\n const contentType = response.headers.get('content-type') ?? ''\n let result\n if (response.status === 204) {\n result = { data: undefined, error: undefined }\n } else if (contentType.startsWith('application/json+devalue')) {\n const text = await response.text()\n const { parse } = await import('devalue')\n result = { data: parse(text, { URL: (h) => new URL(h) }), error: undefined }\n } else if (contentType.startsWith('application/json')) {\n const json = await response.json()\n result = response.ok ? { data: json, error: undefined } : { data: undefined, error: json }\n } else {\n result = { data: undefined, error: { code: 'INTERNAL_SERVER_ERROR', message: await response.text() } }\n }\n emitTelemetry(name, startedAt, input, result.error\n ? { status: 'error', error: result.error }\n : { status: 'success', data: result.data })\n return result\n}\n\nexport const actions = new Proxy({}, {\n get(target, prop) {\n if (typeof prop !== 'string') return undefined\n const url = ACTION_URL_MAP[prop]\n if (!url) return undefined\n return (input) => callAction(prop, url, input)\n },\n})\n`\n}\n\n/**\n * Server-side module: re-exports the manifest entries for SSR / module-\n * loader consumption (T1.3 sub-C in action-execute.ts will route requests\n * via this manifest).\n */\nfunction generateServerManifest(entries: ActionManifestEntry[]): string {\n return `// AUTO-GENERATED by @theo/actions virtual module (server env)\n/* eslint-disable */\nexport const manifest = ${JSON.stringify(entries, null, 2)}\nexport const actions = manifest\n`\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/scan/action-scan.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * Build-time scanner: walks `serverDir/actions/` derived from cwd.\n * No HTTP input ever reaches these fs calls.\n */\nimport { existsSync, readFileSync, statSync } from 'node:fs'\nimport { extname, join, relative } from 'node:path'\n\nimport { walkSourceFiles } from '../_internal/scan-walker.js'\n\nexport interface ActionNode {\n filePath: string\n actionPath: string\n}\n\n/**\n * Enriched manifest entry per plan g3-server-actions-and-useaction v1.2\n * § Phase 1 / T1.4 + ADR D4. Consumed by virtual module `@theo/actions`\n * (T3.1) and G4 devtools \"Actions\" tab (T5.1).\n */\nexport interface ActionManifestEntry {\n name: string\n filePath: string\n urlPath: string\n accept: 'form' | 'json'\n hasInput: boolean\n}\n\n/**\n * EC-2: structured error for scan-time defects (name collision, reserved\n * identifier, etc.). Throw at scan time to fail loud — silent shadowing is\n * a security/correctness footgun.\n */\nexport class ActionScanError extends Error {\n readonly code: 'NAME_COLLISION' | 'RESERVED_NAME'\n readonly conflictingPaths: readonly string[]\n\n constructor(\n code: 'NAME_COLLISION' | 'RESERVED_NAME',\n message: string,\n conflictingPaths: readonly string[],\n ) {\n super(message)\n this.code = code\n this.conflictingPaths = conflictingPaths\n }\n}\n\nconst ACTION_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx'])\nconst TEST_FILE_RE = /\\.(test|spec)\\.(ts|tsx|js|jsx)$/\nconst RESERVED_NAMES = new Set(['index', 'constructor', '__proto__', 'prototype', 'hasOwnProperty'])\n\n/**\n * Backward-compatible: original simple-shape scanner used by existing\n * consumers. Preserved verbatim; new consumers should call\n * `scanServerActionsEnriched`.\n */\nexport function scanServerActions(serverDir: string): ActionNode[] {\n const actionsDir = join(serverDir, 'actions')\n if (!existsSync(actionsDir) || !statSync(actionsDir).isDirectory()) {\n return []\n }\n\n const results: ActionNode[] = []\n walkSourceFiles(actionsDir, { extensions: ACTION_EXTENSIONS }, (absPath) => {\n if (TEST_FILE_RE.test(absPath)) return\n let rel = relative(actionsDir, absPath)\n rel = rel.replace(/\\\\/g, '/')\n rel = rel.slice(0, -extname(rel).length)\n results.push({\n filePath: absPath,\n actionPath: rel,\n })\n })\n return results\n}\n\n/**\n * Enriched scan: light AST detection of `accept: 'form'|'json'` + `input:`\n * presence via regex-after-comment-stripping (EC-9). Throws ActionScanError\n * on file/dir name collision (EC-2) or reserved JS identifier names.\n *\n * Output `ActionManifestEntry[]` is sorted by `name` for deterministic\n * `.theo/actions-manifest.json` emission.\n */\nexport function scanServerActionsEnriched(serverDir: string): ActionManifestEntry[] {\n const actionsDir = join(serverDir, 'actions')\n if (!existsSync(actionsDir) || !statSync(actionsDir).isDirectory()) {\n return []\n }\n\n const seenNames = new Set<string>()\n const entries: ActionManifestEntry[] = []\n\n // Collect first; collision-check after the full walk.\n walkSourceFiles(actionsDir, { extensions: ACTION_EXTENSIONS }, (absPath) => {\n if (TEST_FILE_RE.test(absPath)) return\n const rel = relative(actionsDir, absPath).replace(/\\\\/g, '/')\n const name = rel.slice(0, -extname(rel).length)\n\n const basename = name.includes('/') ? (name.split('/').pop() ?? name) : name\n if (RESERVED_NAMES.has(basename)) {\n throw new ActionScanError(\n 'RESERVED_NAME',\n `Reserved JS identifier \"${basename}\" cannot be an action name (${absPath})`,\n [absPath],\n )\n }\n // File-level collision (one file appearing twice) is impossible via the\n // walker; per-export collision check happens inside the export loop below.\n const source = readFileSync(absPath, 'utf8')\n const stripped = stripComments(source)\n const accept = /\\baccept\\s*:\\s*['\"]form['\"]/.test(stripped) ? 'form' : 'json'\n const hasInput = /\\binput\\s*:\\s*z\\./.test(stripped) || /\\binput\\s*:\\s*\\w+\\(/.test(stripped)\n\n // T7.1 wire fix — extract exports so the urlPath includes the second\n // segment required by action-middleware (`/api/__actions/<file>/<export>`).\n // Each named action export becomes its own manifest entry.\n // Proxy key on the EXPORT name (so consumers write `actions.saveMemory(input)`).\n // URL keeps the runtime 2-segment shape `/api/__actions/<file>/<export>`\n // expected by action-middleware. Cross-file export collisions become a\n // scan error to surface the ambiguity early.\n const exportNames = extractActionExportNames(stripped)\n for (const exportName of exportNames) {\n const proxyKey = exportName === 'default' ? name : exportName\n if (seenNames.has(proxyKey)) {\n throw new ActionScanError(\n 'NAME_COLLISION',\n `Duplicate action proxy key \"${proxyKey}\" (two files export the same name)`,\n [absPath],\n )\n }\n seenNames.add(proxyKey)\n entries.push({\n name: proxyKey,\n filePath: absPath,\n urlPath: `/api/__actions/${name}/${exportName}`,\n accept,\n hasInput,\n })\n }\n })\n\n // EC-2: detect file vs dir collisions (e.g., foo.ts AND foo/bar.ts).\n // After walk completes, any name that has children prefixed `name/` triggers collision.\n for (const entry of entries) {\n const childPrefix = `${entry.name}/`\n const conflictingChild = entries.find((other) => other.name.startsWith(childPrefix))\n if (conflictingChild) {\n throw new ActionScanError(\n 'NAME_COLLISION',\n `Action \"${entry.name}\" conflicts with directory of same name containing \"${conflictingChild.name}\"`,\n [entry.filePath, conflictingChild.filePath],\n )\n }\n }\n\n entries.sort((a, b) => {\n if (a.name < b.name) return -1\n if (a.name > b.name) return 1\n return 0\n })\n return entries\n}\n\n/**\n * Strip JavaScript line + block comments from source. Simple state machine\n * (does not parse strings — false positives if a comment marker appears\n * inside a string literal, but that's an acceptable trade-off for v1 vs\n * full AST parse).\n */\n/**\n * Extract action export names via regex over comment-stripped source.\n * Matches `export const <name> = defineAction(...)`, `export default\n * defineAction(...)`, and `export function <name>(...)` forms. Returns\n * `['default']` when no named action exports are found (best-effort fallback\n * for default-export shapes the regex misses).\n */\nfunction extractActionExportNames(stripped: string): string[] {\n const names = new Set<string>()\n const namedRe = /\\bexport\\s+(?:const|let|var|function\\*?)\\s+([a-zA-Z_$][\\w$]*)\\s*[=(]/g\n let m: RegExpExecArray | null\n while ((m = namedRe.exec(stripped)) !== null) {\n const name = m[1]\n if (typeof name === 'string' && name.length > 0) names.add(name)\n }\n if (/\\bexport\\s+default\\s+defineAction\\b/.test(stripped)) {\n names.add('default')\n }\n if (names.size === 0) names.add('default')\n return [...names]\n}\n\nfunction stripComments(source: string): string {\n let out = ''\n let i = 0\n while (i < source.length) {\n const ch = source[i]\n const next = source[i + 1]\n if (ch === '/' && next === '/') {\n // Line comment: skip until newline\n while (i < source.length && source[i] !== '\\n') i++\n continue\n }\n if (ch === '/' && next === '*') {\n // Block comment: skip until */\n i += 2\n while (i < source.length - 1 && !(source[i] === '*' && source[i + 1] === '/')) i++\n i += 2\n continue\n }\n out += ch\n i++\n }\n return out\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/server/scan/action-scan.ts","../src/server/_internal/scan-walker.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * Build-time scanner: walks `serverDir/actions/` derived from cwd.\n * No HTTP input ever reaches these fs calls.\n */\nimport { existsSync, readFileSync, statSync } from 'node:fs'\nimport { extname, join, relative } from 'node:path'\n\nimport { walkSourceFiles } from '../_internal/scan-walker.js'\n\nexport interface ActionNode {\n filePath: string\n actionPath: string\n}\n\n/**\n * Enriched manifest entry per plan g3-server-actions-and-useaction v1.2\n * § Phase 1 / T1.4 + ADR D4. Consumed by virtual module `@theo/actions`\n * (T3.1) and G4 devtools \"Actions\" tab (T5.1).\n */\nexport interface ActionManifestEntry {\n name: string\n filePath: string\n urlPath: string\n accept: 'form' | 'json'\n hasInput: boolean\n}\n\n/**\n * EC-2: structured error for scan-time defects (name collision, reserved\n * identifier, etc.). Throw at scan time to fail loud — silent shadowing is\n * a security/correctness footgun.\n */\nexport class ActionScanError extends Error {\n readonly code: 'NAME_COLLISION' | 'RESERVED_NAME'\n readonly conflictingPaths: readonly string[]\n\n constructor(\n code: 'NAME_COLLISION' | 'RESERVED_NAME',\n message: string,\n conflictingPaths: readonly string[],\n ) {\n super(message)\n this.code = code\n this.conflictingPaths = conflictingPaths\n }\n}\n\nconst ACTION_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx'])\nconst TEST_FILE_RE = /\\.(test|spec)\\.(ts|tsx|js|jsx)$/\nconst RESERVED_NAMES = new Set(['index', 'constructor', '__proto__', 'prototype', 'hasOwnProperty'])\n\n/**\n * Backward-compatible: original simple-shape scanner used by existing\n * consumers. Preserved verbatim; new consumers should call\n * `scanServerActionsEnriched`.\n */\nexport function scanServerActions(serverDir: string): ActionNode[] {\n const actionsDir = join(serverDir, 'actions')\n if (!existsSync(actionsDir) || !statSync(actionsDir).isDirectory()) {\n return []\n }\n\n const results: ActionNode[] = []\n walkSourceFiles(actionsDir, { extensions: ACTION_EXTENSIONS }, (absPath) => {\n if (TEST_FILE_RE.test(absPath)) return\n let rel = relative(actionsDir, absPath)\n rel = rel.replace(/\\\\/g, '/')\n rel = rel.slice(0, -extname(rel).length)\n results.push({\n filePath: absPath,\n actionPath: rel,\n })\n })\n return results\n}\n\n/**\n * Enriched scan: light AST detection of `accept: 'form'|'json'` + `input:`\n * presence via regex-after-comment-stripping (EC-9). Throws ActionScanError\n * on file/dir name collision (EC-2) or reserved JS identifier names.\n *\n * Output `ActionManifestEntry[]` is sorted by `name` for deterministic\n * `.theo/actions-manifest.json` emission.\n */\nexport function scanServerActionsEnriched(serverDir: string): ActionManifestEntry[] {\n const actionsDir = join(serverDir, 'actions')\n if (!existsSync(actionsDir) || !statSync(actionsDir).isDirectory()) {\n return []\n }\n\n const seenNames = new Set<string>()\n const entries: ActionManifestEntry[] = []\n\n // Collect first; collision-check after the full walk.\n walkSourceFiles(actionsDir, { extensions: ACTION_EXTENSIONS }, (absPath) => {\n if (TEST_FILE_RE.test(absPath)) return\n const rel = relative(actionsDir, absPath).replace(/\\\\/g, '/')\n const name = rel.slice(0, -extname(rel).length)\n\n const basename = name.includes('/') ? (name.split('/').pop() ?? name) : name\n if (RESERVED_NAMES.has(basename)) {\n throw new ActionScanError(\n 'RESERVED_NAME',\n `Reserved JS identifier \"${basename}\" cannot be an action name (${absPath})`,\n [absPath],\n )\n }\n // File-level collision (one file appearing twice) is impossible via the\n // walker; per-export collision check happens inside the export loop below.\n const source = readFileSync(absPath, 'utf8')\n const stripped = stripComments(source)\n const accept = /\\baccept\\s*:\\s*['\"]form['\"]/.test(stripped) ? 'form' : 'json'\n const hasInput = /\\binput\\s*:\\s*z\\./.test(stripped) || /\\binput\\s*:\\s*\\w+\\(/.test(stripped)\n\n // T7.1 wire fix — extract exports so the urlPath includes the second\n // segment required by action-middleware (`/api/__actions/<file>/<export>`).\n // Each named action export becomes its own manifest entry.\n // Proxy key on the EXPORT name (so consumers write `actions.saveMemory(input)`).\n // URL keeps the runtime 2-segment shape `/api/__actions/<file>/<export>`\n // expected by action-middleware. Cross-file export collisions become a\n // scan error to surface the ambiguity early.\n const exportNames = extractActionExportNames(stripped)\n for (const exportName of exportNames) {\n const proxyKey = exportName === 'default' ? name : exportName\n if (seenNames.has(proxyKey)) {\n throw new ActionScanError(\n 'NAME_COLLISION',\n `Duplicate action proxy key \"${proxyKey}\" (two files export the same name)`,\n [absPath],\n )\n }\n seenNames.add(proxyKey)\n entries.push({\n name: proxyKey,\n filePath: absPath,\n urlPath: `/api/__actions/${name}/${exportName}`,\n accept,\n hasInput,\n })\n }\n })\n\n // EC-2: detect file vs dir collisions (e.g., foo.ts AND foo/bar.ts).\n // After walk completes, any name that has children prefixed `name/` triggers collision.\n for (const entry of entries) {\n const childPrefix = `${entry.name}/`\n const conflictingChild = entries.find((other) => other.name.startsWith(childPrefix))\n if (conflictingChild) {\n throw new ActionScanError(\n 'NAME_COLLISION',\n `Action \"${entry.name}\" conflicts with directory of same name containing \"${conflictingChild.name}\"`,\n [entry.filePath, conflictingChild.filePath],\n )\n }\n }\n\n entries.sort((a, b) => {\n if (a.name < b.name) return -1\n if (a.name > b.name) return 1\n return 0\n })\n return entries\n}\n\n/**\n * Strip JavaScript line + block comments from source. Simple state machine\n * (does not parse strings — false positives if a comment marker appears\n * inside a string literal, but that's an acceptable trade-off for v1 vs\n * full AST parse).\n */\n/**\n * Extract action export names via regex over comment-stripped source.\n * Matches `export const <name> = defineAction(...)`, `export default\n * defineAction(...)`, and `export function <name>(...)` forms. Returns\n * `['default']` when no named action exports are found (best-effort fallback\n * for default-export shapes the regex misses).\n */\nfunction extractActionExportNames(stripped: string): string[] {\n const names = new Set<string>()\n const namedRe = /\\bexport\\s+(?:const|let|var|function\\*?)\\s+([a-zA-Z_$][\\w$]*)\\s*[=(]/g\n let m: RegExpExecArray | null\n while ((m = namedRe.exec(stripped)) !== null) {\n const name = m[1]\n if (typeof name === 'string' && name.length > 0) names.add(name)\n }\n if (/\\bexport\\s+default\\s+defineAction\\b/.test(stripped)) {\n names.add('default')\n }\n if (names.size === 0) names.add('default')\n return [...names]\n}\n\nfunction stripComments(source: string): string {\n let out = ''\n let i = 0\n while (i < source.length) {\n const ch = source[i]\n const next = source[i + 1]\n if (ch === '/' && next === '/') {\n // Line comment: skip until newline\n while (i < source.length && source[i] !== '\\n') i++\n continue\n }\n if (ch === '/' && next === '*') {\n // Block comment: skip until */\n i += 2\n while (i < source.length - 1 && !(source[i] === '*' && source[i + 1] === '/')) i++\n i += 2\n continue\n }\n out += ch\n i++\n }\n return out\n}\n","/* eslint-disable security/detect-non-literal-fs-filename --\n * Build-time scanner: walks directories derived from cwd.\n * No HTTP input ever reaches these fs calls.\n */\nimport { readdirSync } from 'node:fs'\nimport { extname, join, resolve } from 'node:path'\n\n/**\n * Options for walkSourceFiles.\n *\n * Sequential by design — callers (route precedence) depend on insertion\n * order (EC-19 documented decision). Async-callback support is implicit\n * via JavaScript's serial await loop.\n *\n * Tested on macOS + Linux. Windows long-path support not validated (EC-20).\n */\nexport interface WalkOptions {\n /** File extensions to include (e.g., new Set(['.ts', '.tsx'])). */\n extensions: ReadonlySet<string>\n /** Skip directories whose name starts with any of these (default: ['_', '.']). */\n skipPrefixes?: readonly string[]\n}\n\n/**\n * Recursively walk `root`, invoking `onFile(absPath)` for every file matching\n * `opts.extensions`. Directories whose name starts with any `skipPrefixes`\n * char are skipped (defaults to `_` and `.`).\n *\n * Replaces 3 near-identical recursive walkers in scan.ts, action-scan.ts,\n * ws-scan.ts (PV-3 — DRY consolidation). Resolves T3.1 of\n * architecture-review-remediation-plan.\n *\n * Symlink loops are NOT tracked — callers must avoid them or pre-resolve\n * via `fs.realpath`. EC-11 documented but not implemented (rare in dev).\n */\nexport function walkSourceFiles(\n root: string,\n opts: WalkOptions,\n onFile: (absPath: string) => void,\n): void {\n const skipPrefixes = opts.skipPrefixes ?? ['_', '.']\n const visit = (dir: string): void => {\n let entries\n try {\n entries = readdirSync(dir, { withFileTypes: true })\n } catch {\n // Silently skip unreadable directories — caller controls discoverability\n return\n }\n for (const entry of entries) {\n const fullPath = join(dir, entry.name)\n if (entry.isDirectory() && !skipPrefixes.some((p) => entry.name.startsWith(p))) {\n visit(fullPath)\n } else if (entry.isFile() && opts.extensions.has(extname(entry.name))) {\n onFile(resolve(fullPath))\n }\n }\n }\n visit(root)\n}\n"],"mappings":";;;;AAIA,SAAS,YAAY,cAAc,gBAAgB;AACnD,SAAS,WAAAA,UAAS,QAAAC,OAAM,gBAAgB;;;ACDxC,SAAS,mBAAmB;AAC5B,SAAS,SAAS,MAAM,eAAe;AA8BhC,SAAS,gBACd,MACA,MACA,QACM;AACN,QAAM,eAAe,KAAK,gBAAgB,CAAC,KAAK,GAAG;AACnD,QAAM,QAAQ,CAAC,QAAsB;AACnC,QAAI;AACJ,QAAI;AACF,gBAAU,YAAY,KAAK,EAAE,eAAe,KAAK,CAAC;AAAA,IACpD,QAAQ;AAEN;AAAA,IACF;AACA,eAAW,SAAS,SAAS;AAC3B,YAAM,WAAW,KAAK,KAAK,MAAM,IAAI;AACrC,UAAI,MAAM,YAAY,KAAK,CAAC,aAAa,KAAK,CAAC,MAAM,MAAM,KAAK,WAAW,CAAC,CAAC,GAAG;AAC9E,cAAM,QAAQ;AAAA,MAChB,WAAW,MAAM,OAAO,KAAK,KAAK,WAAW,IAAI,QAAQ,MAAM,IAAI,CAAC,GAAG;AACrE,eAAO,QAAQ,QAAQ,CAAC;AAAA,MAC1B;AAAA,IACF;AAAA,EACF;AACA,QAAM,IAAI;AACZ;;;AD3BO,IAAM,kBAAN,cAA8B,MAAM;AAAA,EAChC;AAAA,EACA;AAAA,EAET,YACE,MACA,SACA,kBACA;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,mBAAmB;AAAA,EAC1B;AACF;AAEA,IAAM,oBAAoB,oBAAI,IAAI,CAAC,OAAO,QAAQ,OAAO,MAAM,CAAC;AAChE,IAAM,eAAe;AACrB,IAAM,iBAAiB,oBAAI,IAAI,CAAC,SAAS,eAAe,aAAa,aAAa,gBAAgB,CAAC;AAO5F,SAAS,kBAAkB,WAAiC;AACjE,QAAM,aAAaC,MAAK,WAAW,SAAS;AAC5C,MAAI,CAAC,WAAW,UAAU,KAAK,CAAC,SAAS,UAAU,EAAE,YAAY,GAAG;AAClE,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,UAAwB,CAAC;AAC/B,kBAAgB,YAAY,EAAE,YAAY,kBAAkB,GAAG,CAAC,YAAY;AAC1E,QAAI,aAAa,KAAK,OAAO,EAAG;AAChC,QAAI,MAAM,SAAS,YAAY,OAAO;AACtC,UAAM,IAAI,QAAQ,OAAO,GAAG;AAC5B,UAAM,IAAI,MAAM,GAAG,CAACC,SAAQ,GAAG,EAAE,MAAM;AACvC,YAAQ,KAAK;AAAA,MACX,UAAU;AAAA,MACV,YAAY;AAAA,IACd,CAAC;AAAA,EACH,CAAC;AACD,SAAO;AACT;AAUO,SAAS,0BAA0B,WAA0C;AAClF,QAAM,aAAaD,MAAK,WAAW,SAAS;AAC5C,MAAI,CAAC,WAAW,UAAU,KAAK,CAAC,SAAS,UAAU,EAAE,YAAY,GAAG;AAClE,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,YAAY,oBAAI,IAAY;AAClC,QAAM,UAAiC,CAAC;AAGxC,kBAAgB,YAAY,EAAE,YAAY,kBAAkB,GAAG,CAAC,YAAY;AAC1E,QAAI,aAAa,KAAK,OAAO,EAAG;AAChC,UAAM,MAAM,SAAS,YAAY,OAAO,EAAE,QAAQ,OAAO,GAAG;AAC5D,UAAM,OAAO,IAAI,MAAM,GAAG,CAACC,SAAQ,GAAG,EAAE,MAAM;AAE9C,UAAM,WAAW,KAAK,SAAS,GAAG,IAAK,KAAK,MAAM,GAAG,EAAE,IAAI,KAAK,OAAQ;AACxE,QAAI,eAAe,IAAI,QAAQ,GAAG;AAChC,YAAM,IAAI;AAAA,QACR;AAAA,QACA,2BAA2B,QAAQ,+BAA+B,OAAO;AAAA,QACzE,CAAC,OAAO;AAAA,MACV;AAAA,IACF;AAGA,UAAM,SAAS,aAAa,SAAS,MAAM;AAC3C,UAAM,WAAW,cAAc,MAAM;AACrC,UAAM,SAAS,8BAA8B,KAAK,QAAQ,IAAI,SAAS;AACvE,UAAM,WAAW,oBAAoB,KAAK,QAAQ,KAAK,sBAAsB,KAAK,QAAQ;AAS1F,UAAM,cAAc,yBAAyB,QAAQ;AACrD,eAAW,cAAc,aAAa;AACpC,YAAM,WAAW,eAAe,YAAY,OAAO;AACnD,UAAI,UAAU,IAAI,QAAQ,GAAG;AAC3B,cAAM,IAAI;AAAA,UACR;AAAA,UACA,+BAA+B,QAAQ;AAAA,UACvC,CAAC,OAAO;AAAA,QACV;AAAA,MACF;AACA,gBAAU,IAAI,QAAQ;AACtB,cAAQ,KAAK;AAAA,QACX,MAAM;AAAA,QACN,UAAU;AAAA,QACV,SAAS,kBAAkB,IAAI,IAAI,UAAU;AAAA,QAC7C;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF,CAAC;AAID,aAAW,SAAS,SAAS;AAC3B,UAAM,cAAc,GAAG,MAAM,IAAI;AACjC,UAAM,mBAAmB,QAAQ,KAAK,CAAC,UAAU,MAAM,KAAK,WAAW,WAAW,CAAC;AACnF,QAAI,kBAAkB;AACpB,YAAM,IAAI;AAAA,QACR;AAAA,QACA,WAAW,MAAM,IAAI,uDAAuD,iBAAiB,IAAI;AAAA,QACjG,CAAC,MAAM,UAAU,iBAAiB,QAAQ;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AAEA,UAAQ,KAAK,CAAC,GAAG,MAAM;AACrB,QAAI,EAAE,OAAO,EAAE,KAAM,QAAO;AAC5B,QAAI,EAAE,OAAO,EAAE,KAAM,QAAO;AAC5B,WAAO;AAAA,EACT,CAAC;AACD,SAAO;AACT;AAeA,SAAS,yBAAyB,UAA4B;AAC5D,QAAM,QAAQ,oBAAI,IAAY;AAC9B,QAAM,UAAU;AAChB,MAAI;AACJ,UAAQ,IAAI,QAAQ,KAAK,QAAQ,OAAO,MAAM;AAC5C,UAAM,OAAO,EAAE,CAAC;AAChB,QAAI,OAAO,SAAS,YAAY,KAAK,SAAS,EAAG,OAAM,IAAI,IAAI;AAAA,EACjE;AACA,MAAI,sCAAsC,KAAK,QAAQ,GAAG;AACxD,UAAM,IAAI,SAAS;AAAA,EACrB;AACA,MAAI,MAAM,SAAS,EAAG,OAAM,IAAI,SAAS;AACzC,SAAO,CAAC,GAAG,KAAK;AAClB;AAEA,SAAS,cAAc,QAAwB;AAC7C,MAAI,MAAM;AACV,MAAI,IAAI;AACR,SAAO,IAAI,OAAO,QAAQ;AACxB,UAAM,KAAK,OAAO,CAAC;AACnB,UAAM,OAAO,OAAO,IAAI,CAAC;AACzB,QAAI,OAAO,OAAO,SAAS,KAAK;AAE9B,aAAO,IAAI,OAAO,UAAU,OAAO,CAAC,MAAM,KAAM;AAChD;AAAA,IACF;AACA,QAAI,OAAO,OAAO,SAAS,KAAK;AAE9B,WAAK;AACL,aAAO,IAAI,OAAO,SAAS,KAAK,EAAE,OAAO,CAAC,MAAM,OAAO,OAAO,IAAI,CAAC,MAAM,KAAM;AAC/E,WAAK;AACL;AAAA,IACF;AACA,WAAO;AACP;AAAA,EACF;AACA,SAAO;AACT;","names":["extname","join","join","extname"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|