@mionjs/devtools 0.8.0-alpha.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/LICENSE +21 -0
- package/build/eslint/cjs/index.cjs +41 -0
- package/build/eslint/cjs/index.cjs.map +1 -0
- package/build/eslint/cjs/package.json +1 -0
- package/build/eslint/cjs/src/eslint/index.cjs +13 -0
- package/build/eslint/cjs/src/eslint/index.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/index.d.ts +3 -0
- package/build/eslint/cjs/src/eslint/rules/enforce-type-imports.cjs +121 -0
- package/build/eslint/cjs/src/eslint/rules/enforce-type-imports.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/enforce-type-imports.d.ts +7 -0
- package/build/eslint/cjs/src/eslint/rules/formatTypeNames.cjs +71 -0
- package/build/eslint/cjs/src/eslint/rules/formatTypeNames.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/formatTypeNames.d.ts +3 -0
- package/build/eslint/cjs/src/eslint/rules/no-mixed-union-properties.cjs +220 -0
- package/build/eslint/cjs/src/eslint/rules/no-mixed-union-properties.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/no-mixed-union-properties.d.ts +3 -0
- package/build/eslint/cjs/src/eslint/rules/no-type-imports.cjs +251 -0
- package/build/eslint/cjs/src/eslint/rules/no-type-imports.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/no-type-imports.d.ts +3 -0
- package/build/eslint/cjs/src/eslint/rules/no-typeof-runtype.cjs +72 -0
- package/build/eslint/cjs/src/eslint/rules/no-typeof-runtype.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/no-typeof-runtype.d.ts +3 -0
- package/build/eslint/cjs/src/eslint/rules/no-unreachable-union-types.cjs +220 -0
- package/build/eslint/cjs/src/eslint/rules/no-unreachable-union-types.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/no-unreachable-union-types.d.ts +3 -0
- package/build/eslint/cjs/src/eslint/rules/no-vite-client.cjs +71 -0
- package/build/eslint/cjs/src/eslint/rules/no-vite-client.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/no-vite-client.d.ts +4 -0
- package/build/eslint/cjs/src/eslint/rules/pure-functions.cjs +346 -0
- package/build/eslint/cjs/src/eslint/rules/pure-functions.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/pure-functions.d.ts +4 -0
- package/build/eslint/cjs/src/eslint/rules/strong-typed-routes.cjs +328 -0
- package/build/eslint/cjs/src/eslint/rules/strong-typed-routes.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/strong-typed-routes.d.ts +4 -0
- package/build/eslint/cjs/src/eslint/rules/type-formats-imports.cjs +52 -0
- package/build/eslint/cjs/src/eslint/rules/type-formats-imports.cjs.map +1 -0
- package/build/eslint/cjs/src/eslint/rules/type-formats-imports.d.ts +3 -0
- package/build/eslint/cjs/src/pureFns/purityRules.cjs +67 -0
- package/build/eslint/cjs/src/pureFns/purityRules.cjs.map +1 -0
- package/build/eslint/cjs/src/pureFns/purityRules.d.ts +4 -0
- package/build/eslint/esm/index.js +42 -0
- package/build/eslint/esm/index.js.map +1 -0
- package/build/eslint/esm/src/eslint/index.d.ts +3 -0
- package/build/eslint/esm/src/eslint/index.js +14 -0
- package/build/eslint/esm/src/eslint/index.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/enforce-type-imports.d.ts +7 -0
- package/build/eslint/esm/src/eslint/rules/enforce-type-imports.js +122 -0
- package/build/eslint/esm/src/eslint/rules/enforce-type-imports.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/formatTypeNames.d.ts +3 -0
- package/build/eslint/esm/src/eslint/rules/formatTypeNames.js +71 -0
- package/build/eslint/esm/src/eslint/rules/formatTypeNames.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/no-mixed-union-properties.d.ts +3 -0
- package/build/eslint/esm/src/eslint/rules/no-mixed-union-properties.js +221 -0
- package/build/eslint/esm/src/eslint/rules/no-mixed-union-properties.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/no-type-imports.d.ts +3 -0
- package/build/eslint/esm/src/eslint/rules/no-type-imports.js +252 -0
- package/build/eslint/esm/src/eslint/rules/no-type-imports.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/no-typeof-runtype.d.ts +3 -0
- package/build/eslint/esm/src/eslint/rules/no-typeof-runtype.js +73 -0
- package/build/eslint/esm/src/eslint/rules/no-typeof-runtype.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/no-unreachable-union-types.d.ts +3 -0
- package/build/eslint/esm/src/eslint/rules/no-unreachable-union-types.js +221 -0
- package/build/eslint/esm/src/eslint/rules/no-unreachable-union-types.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/no-vite-client.d.ts +4 -0
- package/build/eslint/esm/src/eslint/rules/no-vite-client.js +72 -0
- package/build/eslint/esm/src/eslint/rules/no-vite-client.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/pure-functions.d.ts +4 -0
- package/build/eslint/esm/src/eslint/rules/pure-functions.js +347 -0
- package/build/eslint/esm/src/eslint/rules/pure-functions.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/strong-typed-routes.d.ts +4 -0
- package/build/eslint/esm/src/eslint/rules/strong-typed-routes.js +329 -0
- package/build/eslint/esm/src/eslint/rules/strong-typed-routes.js.map +1 -0
- package/build/eslint/esm/src/eslint/rules/type-formats-imports.d.ts +3 -0
- package/build/eslint/esm/src/eslint/rules/type-formats-imports.js +53 -0
- package/build/eslint/esm/src/eslint/rules/type-formats-imports.js.map +1 -0
- package/build/eslint/esm/src/pureFns/purityRules.d.ts +4 -0
- package/build/eslint/esm/src/pureFns/purityRules.js +67 -0
- package/build/eslint/esm/src/pureFns/purityRules.js.map +1 -0
- package/build/vite-plugin/cjs/index.cjs +14 -0
- package/build/vite-plugin/cjs/index.cjs.map +1 -0
- package/build/vite-plugin/cjs/package.json +1 -0
- package/build/vite-plugin/cjs/src/pureFns/purityRules.cjs +65 -0
- package/build/vite-plugin/cjs/src/pureFns/purityRules.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/pureFns/purityRules.d.ts +4 -0
- package/build/vite-plugin/cjs/src/vite-plugin/aotCacheGenerator.cjs +235 -0
- package/build/vite-plugin/cjs/src/vite-plugin/aotCacheGenerator.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/aotCacheGenerator.d.ts +23 -0
- package/build/vite-plugin/cjs/src/vite-plugin/aotDiskCache.cjs +134 -0
- package/build/vite-plugin/cjs/src/vite-plugin/aotDiskCache.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/aotDiskCache.d.ts +6 -0
- package/build/vite-plugin/cjs/src/vite-plugin/cjsPackageJsonPlugin.cjs +15 -0
- package/build/vite-plugin/cjs/src/vite-plugin/cjsPackageJsonPlugin.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/cjsPackageJsonPlugin.d.ts +2 -0
- package/build/vite-plugin/cjs/src/vite-plugin/constants.cjs +25 -0
- package/build/vite-plugin/cjs/src/vite-plugin/constants.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/constants.d.ts +10 -0
- package/build/vite-plugin/cjs/src/vite-plugin/extractPureFn.cjs +628 -0
- package/build/vite-plugin/cjs/src/vite-plugin/extractPureFn.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/extractPureFn.d.ts +13 -0
- package/build/vite-plugin/cjs/src/vite-plugin/index.cjs +14 -0
- package/build/vite-plugin/cjs/src/vite-plugin/index.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/index.d.ts +5 -0
- package/build/vite-plugin/cjs/src/vite-plugin/mionVitePlugin.cjs +404 -0
- package/build/vite-plugin/cjs/src/vite-plugin/mionVitePlugin.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/mionVitePlugin.d.ts +36 -0
- package/build/vite-plugin/cjs/src/vite-plugin/resolveModule.cjs +55 -0
- package/build/vite-plugin/cjs/src/vite-plugin/resolveModule.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/resolveModule.d.ts +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/transformers.cjs +165 -0
- package/build/vite-plugin/cjs/src/vite-plugin/transformers.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/transformers.d.ts +10 -0
- package/build/vite-plugin/cjs/src/vite-plugin/types.cjs +2 -0
- package/build/vite-plugin/cjs/src/vite-plugin/types.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/types.d.ts +57 -0
- package/build/vite-plugin/cjs/src/vite-plugin/virtual-modules.d.cjs +2 -0
- package/build/vite-plugin/cjs/src/vite-plugin/virtual-modules.d.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/virtualModule.cjs +68 -0
- package/build/vite-plugin/cjs/src/vite-plugin/virtualModule.cjs.map +1 -0
- package/build/vite-plugin/cjs/src/vite-plugin/virtualModule.d.ts +2 -0
- package/build/vite-plugin/esm/index.js +14 -0
- package/build/vite-plugin/esm/index.js.map +1 -0
- package/build/vite-plugin/esm/src/pureFns/purityRules.d.ts +4 -0
- package/build/vite-plugin/esm/src/pureFns/purityRules.js +65 -0
- package/build/vite-plugin/esm/src/pureFns/purityRules.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/aotCacheGenerator.d.ts +23 -0
- package/build/vite-plugin/esm/src/vite-plugin/aotCacheGenerator.js +235 -0
- package/build/vite-plugin/esm/src/vite-plugin/aotCacheGenerator.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/aotDiskCache.d.ts +6 -0
- package/build/vite-plugin/esm/src/vite-plugin/aotDiskCache.js +133 -0
- package/build/vite-plugin/esm/src/vite-plugin/aotDiskCache.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/cjsPackageJsonPlugin.d.ts +2 -0
- package/build/vite-plugin/esm/src/vite-plugin/cjsPackageJsonPlugin.js +15 -0
- package/build/vite-plugin/esm/src/vite-plugin/cjsPackageJsonPlugin.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/constants.d.ts +10 -0
- package/build/vite-plugin/esm/src/vite-plugin/constants.js +25 -0
- package/build/vite-plugin/esm/src/vite-plugin/constants.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/extractPureFn.d.ts +13 -0
- package/build/vite-plugin/esm/src/vite-plugin/extractPureFn.js +611 -0
- package/build/vite-plugin/esm/src/vite-plugin/extractPureFn.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/index.d.ts +5 -0
- package/build/vite-plugin/esm/src/vite-plugin/index.js +14 -0
- package/build/vite-plugin/esm/src/vite-plugin/index.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/mionVitePlugin.d.ts +36 -0
- package/build/vite-plugin/esm/src/vite-plugin/mionVitePlugin.js +387 -0
- package/build/vite-plugin/esm/src/vite-plugin/mionVitePlugin.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/resolveModule.d.ts +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/resolveModule.js +33 -0
- package/build/vite-plugin/esm/src/vite-plugin/resolveModule.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/transformers.d.ts +10 -0
- package/build/vite-plugin/esm/src/vite-plugin/transformers.js +148 -0
- package/build/vite-plugin/esm/src/vite-plugin/transformers.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/types.d.ts +57 -0
- package/build/vite-plugin/esm/src/vite-plugin/types.js +2 -0
- package/build/vite-plugin/esm/src/vite-plugin/types.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/virtual-modules.d.js +2 -0
- package/build/vite-plugin/esm/src/vite-plugin/virtual-modules.d.js.map +1 -0
- package/build/vite-plugin/esm/src/vite-plugin/virtualModule.d.ts +2 -0
- package/build/vite-plugin/esm/src/vite-plugin/virtualModule.js +68 -0
- package/build/vite-plugin/esm/src/vite-plugin/virtualModule.js.map +1 -0
- package/package.json +94 -0
- package/src/vite-plugin/virtual-modules.d.ts +48 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extractPureFn.js","sources":["../../../../../src/vite-plugin/extractPureFn.ts"],"sourcesContent":["/* ########\n * 2026 mion\n * Author: Ma-jerez\n * License: MIT\n * The software is provided \"as is\", without warranty of any kind.\n * ######## */\n\nimport * as ts from 'typescript';\nimport {createHash} from 'crypto';\nimport {transformSync} from 'esbuild';\nimport {ExtractedPureFn, ServerPureFunctionsOptions} from './types.ts';\nimport {BODY_HASH_LENGTH, PURE_SERVER_FN_NAMESPACE} from './constants.ts';\nimport {ALLOWED_GLOBALS, FORBIDDEN_IDENTIFIERS} from '../pureFns/purityRules.ts';\nimport {readdirSync, statSync, readFileSync} from 'fs';\nimport {resolve, join} from 'path/posix';\nimport {isIncluded} from './mionVitePlugin.ts';\n\n/**\n * Extracts all <script> block contents and lang attributes from a Vue SFC source.\n * Uses a regex + state machine approach instead of a full XML/HTML AST parser. Vue SFCs have\n * a simple, well-defined structure (top-level <script> blocks only) so this is sufficient.\n * This avoids adding @vue/compiler-sfc as a dependency just for keyword detection in the\n * scan pipeline. The Vite transform pipeline relies on @vitejs/plugin-vue for proper parsing.\n * A small string-literal tracker skips </script> inside quotes so embedded script tags\n * in string literals (e.g. injecting a header script as pure text) don't break extraction.\n */\nexport function extractVueScriptContent(source: string): {content: string; lang: string} | null {\n // Matches <script ...> allowing > inside quoted attribute values (e.g. generic=\"T extends Foo<Bar>\")\n const openRegex = /<script\\b((?:[^>\"']|\"[^\"]*\"|'[^']*')*)>/gi;\n const closeTag = '</script>';\n let combined = '';\n let lang = 'js';\n let found = false;\n\n let openMatch: RegExpExecArray | null;\n while ((openMatch = openRegex.exec(source)) !== null) {\n const attrs = openMatch[1];\n const contentStart = openMatch.index + openMatch[0].length;\n const closeIdx = findClosingScriptTag(source, contentStart, closeTag);\n if (closeIdx === -1) break;\n\n found = true;\n combined += source.slice(contentStart, closeIdx) + '\\n';\n // Advance the regex past the closing tag so the next iteration finds the next block\n openRegex.lastIndex = closeIdx + closeTag.length;\n\n const langMatch = attrs.match(/lang=[\"'](\\w+)[\"']/);\n if (langMatch) lang = langMatch[1];\n }\n\n return found ? {content: combined.trim(), lang} : null;\n}\n\n/** Finds the position of </script> while skipping occurrences inside string literals */\nfunction findClosingScriptTag(source: string, start: number, closeTag: string): number {\n let i = start;\n while (i < source.length) {\n const ch = source[i];\n\n // Skip string literals (single, double, template)\n if (ch === \"'\" || ch === '\"' || ch === '`') {\n i = skipStringLiteral(source, i, ch);\n continue;\n }\n\n // Check for closing tag (case-insensitive)\n if (ch === '<' && source.slice(i, i + closeTag.length).toLowerCase() === closeTag) {\n return i;\n }\n\n i++;\n }\n return -1;\n}\n\n/** Advances past a string literal, handling escape sequences and template literal nesting */\nfunction skipStringLiteral(source: string, start: number, quote: string): number {\n let i = start + 1;\n while (i < source.length) {\n const ch = source[i];\n if (ch === '\\\\') {\n i += 2; // skip escaped character\n continue;\n }\n if (ch === quote) return i + 1;\n i++;\n }\n return i;\n}\n\n/** Scans the client source directory and extracts all pure functions */\nexport function scanClientSource(options: ServerPureFunctionsOptions): ExtractedPureFn[] {\n const include = options.include || ['**/*.ts', '**/*.tsx', '**/*.vue'];\n const exclude = options.exclude || ['../node_modules/**', '**/.dist/**', '**/dist/**'];\n const clientSrcPath = resolve(options.clientSrcPath);\n const fns: ExtractedPureFn[] = [];\n\n function scanDir(dir: string) {\n const entries = readdirSync(dir);\n for (const entry of entries) {\n const fullPath = join(dir, entry);\n const stat = statSync(fullPath);\n\n if (stat.isDirectory()) {\n // Skip excluded directories\n if (!isIncluded(fullPath + '/', include, exclude)) continue;\n scanDir(fullPath);\n } else if (stat.isFile()) {\n // Only process included files\n if (!isIncluded(fullPath, include, exclude)) continue;\n\n try {\n let code = readFileSync(fullPath, 'utf-8');\n let effectivePath = fullPath;\n\n // For .vue files, extract script content\n if (fullPath.endsWith('.vue')) {\n const scriptBlock = extractVueScriptContent(code);\n if (!scriptBlock) continue;\n code = scriptBlock.content;\n effectivePath = `${fullPath}.${scriptBlock.lang}`;\n }\n\n // Quick check: does this file contain pureServerFn or mapFrom?\n const hasPureFn = code.includes('pureServerFn');\n const hasMapFrom = code.includes('mapFrom');\n if (!hasPureFn && !hasMapFrom) continue;\n\n if (hasPureFn) {\n const extracted = extractPureFnsFromSource(code, effectivePath, 'pureServerFn', options.noViteClient);\n fns.push(...extracted);\n }\n if (hasMapFrom) {\n const extracted = extractPureFnsFromSource(code, effectivePath, 'mapFrom', options.noViteClient);\n fns.push(...extracted);\n }\n } catch (err: any) {\n // Log but don't fail - some files might not be parseable\n console.warn(`[mion-pure-functions] Warning: Could not parse ${fullPath}: ${err.message}`);\n }\n }\n }\n }\n\n scanDir(clientSrcPath);\n return fns;\n}\n\n/** Extracts all calls to the given function name from a source file using AST */\nexport function extractPureFnsFromSource(\n source: string,\n filePath: string,\n fnName = 'pureServerFn',\n noViteClient = false\n): ExtractedPureFn[] {\n const results: ExtractedPureFn[] = [];\n\n // Quick check: does this file even contain the target function?\n if (!source.includes(fnName)) return results;\n\n // First, strip TypeScript types to get clean JavaScript\n const jsSource = stripTypes(source, filePath);\n\n // Parse the JavaScript into an AST\n const sourceFile = ts.createSourceFile(filePath, jsSource, ts.ScriptTarget.Latest, true, ts.ScriptKind.JS);\n\n // Visit all nodes and extract pure functions\n function visit(node: ts.Node): void {\n if (ts.isCallExpression(node)) {\n const callee = node.expression;\n if (ts.isIdentifier(callee) && callee.text === fnName) {\n if (fnName === 'registerPureFnFactory') {\n const extracted = extractDataFromRegisterPureFnFactoryAST(node, sourceFile, filePath);\n results.push(extracted);\n } else if (fnName === 'mapFrom') {\n const extracted = extractDataFromMapFromCallAST(node, sourceFile, filePath, noViteClient);\n results.push(extracted);\n } else {\n const extracted = extractDataFromPureFnDefAST(node, sourceFile, filePath, noViteClient);\n results.push(extracted);\n }\n }\n }\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n\n return results;\n}\n\n/**\n * Strips TypeScript type annotations from code, returning pure JavaScript.\n * Uses esbuild instead of ts.transpileModule to avoid deepkit type compiler patches\n * that would inject __assignType artifacts into the output.\n */\nexport function stripTypes(code: string, filePath?: string): string {\n try {\n let loader: 'ts' | 'tsx' | 'js' | 'jsx' = 'ts';\n if (filePath) {\n if (filePath.endsWith('.tsx')) loader = 'tsx';\n else if (filePath.endsWith('.jsx')) loader = 'jsx';\n else if (filePath.endsWith('.js')) loader = 'js';\n }\n const result = transformSync(code, {\n loader,\n target: 'esnext',\n minify: false,\n });\n return result.code.trim();\n } catch (err: any) {\n // esbuild errors (e.g. await in non-async) are transformed to PurityError\n // so the extraction pipeline has a consistent error type\n throw new PurityError(err.message || String(err), '<esbuild>', 0);\n }\n}\n\n/** Extracts a single PureFnDef from a pureServerFn() call expression */\nfunction extractDataFromPureFnDefAST(\n call: ts.CallExpression,\n sourceFile: ts.SourceFile,\n filePath: string,\n noViteClient = false\n): ExtractedPureFn {\n // Accept 1 or 2 arguments: pureServerFn(fnOrDef) or pureServerFn(fnOrDef, 'name') (user-provided name or already transformed)\n if (call.arguments.length < 1 || call.arguments.length > 2) {\n throw new PurityError(\n 'pureServerFn() requires 1 or 2 arguments: a function/PureFnDef and an optional name/bodyHash string',\n filePath,\n call.getStart(sourceFile)\n );\n }\n\n // Extract user-provided name from 2nd argument if present\n let userProvidedName: string | undefined;\n if (call.arguments.length === 2) {\n const nameArg = call.arguments[1];\n if (!ts.isStringLiteral(nameArg)) {\n throw new PurityError(\n 'pureServerFn() second argument (name/bodyHash) must be a string literal',\n filePath,\n nameArg.getStart(sourceFile)\n );\n }\n if (nameArg.text.length === 0) {\n throw new PurityError(\n 'pureServerFn() second argument (name/bodyHash) must not be an empty string',\n filePath,\n nameArg.getStart(sourceFile)\n );\n }\n userProvidedName = nameArg.text;\n } else if (noViteClient) {\n throw new PurityError(\n 'pureServerFn() requires a name as the second argument (string literal) when noViteClient is enabled',\n filePath,\n call.getStart(sourceFile)\n );\n }\n\n let arg = call.arguments[0];\n\n // If the argument is a variable reference, resolve it to its initializer\n if (ts.isIdentifier(arg)) {\n const resolved = resolveVariableInitializer(arg.text, sourceFile);\n if (!resolved) {\n if (isImportedIdentifier(arg.text, sourceFile)) {\n throw new PurityError(\n `pureServerFn() argument \"${arg.text}\" is imported from another module. Pure functions must be defined inline or as a variable in the same file`,\n filePath,\n arg.getStart(sourceFile)\n );\n }\n throw new PurityError(\n `pureServerFn() argument \"${arg.text}\" could not be resolved to a variable declaration in this file. Pure functions must be defined inline or as a variable in the same file`,\n filePath,\n arg.getStart(sourceFile)\n );\n }\n arg = resolved;\n }\n\n // Plain function shorthand: pureServerFn((x) => x + 1) or pureServerFn(function myFn(x) { ... })\n if (ts.isFunctionExpression(arg) || ts.isArrowFunction(arg)) {\n return buildExtractedPureFn(arg, PURE_SERVER_FN_NAMESPACE, undefined, false, sourceFile, filePath, userProvidedName);\n }\n\n // Full PureFnDef object: pureServerFn({ pureFn: ..., namespace: ..., fnName: ... })\n if (ts.isObjectLiteralExpression(arg)) {\n return extractPureFnDefFromObjectLiteral(arg, sourceFile, filePath, userProvidedName);\n }\n\n throw new PurityError(\n 'pureServerFn() first argument must be a function, an object literal (PureFnDef), or a variable referencing one',\n filePath,\n call.arguments[0].getStart(sourceFile)\n );\n}\n\n/** Extracts the mapper function from a mapFrom(source, mapper) call expression */\nfunction extractDataFromMapFromCallAST(\n call: ts.CallExpression,\n sourceFile: ts.SourceFile,\n filePath: string,\n noViteClient = false\n): ExtractedPureFn {\n // Accept 2 or 3 arguments: mapFrom(source, mapper) or mapFrom(source, mapper, 'name') (user-provided name or already transformed)\n if (call.arguments.length < 2 || call.arguments.length > 3) {\n throw new PurityError(\n 'mapFrom() requires 2 or 3 arguments: a SubRequest source, a mapper function, and an optional name/bodyHash string',\n filePath,\n call.getStart(sourceFile)\n );\n }\n\n // Extract user-provided name from 3rd argument if present\n let userProvidedName: string | undefined;\n if (call.arguments.length === 3) {\n const nameArg = call.arguments[2];\n if (!ts.isStringLiteral(nameArg)) {\n throw new PurityError(\n 'mapFrom() third argument (name/bodyHash) must be a string literal',\n filePath,\n nameArg.getStart(sourceFile)\n );\n }\n if (nameArg.text.length === 0) {\n throw new PurityError(\n 'mapFrom() third argument (name/bodyHash) must not be an empty string',\n filePath,\n nameArg.getStart(sourceFile)\n );\n }\n userProvidedName = nameArg.text;\n } else if (noViteClient) {\n throw new PurityError(\n 'mapFrom() requires a name as the third argument (string literal) when noViteClient is enabled',\n filePath,\n call.getStart(sourceFile)\n );\n }\n\n let arg = call.arguments[1]; // mapper is the 2nd argument\n\n // If the argument is a variable reference, resolve it to its initializer\n if (ts.isIdentifier(arg)) {\n const resolved = resolveVariableInitializer(arg.text, sourceFile);\n if (!resolved) {\n if (isImportedIdentifier(arg.text, sourceFile)) {\n throw new PurityError(\n `mapFrom() mapper argument \"${arg.text}\" is imported from another module. Pure functions must be defined inline or as a variable in the same file`,\n filePath,\n arg.getStart(sourceFile)\n );\n }\n throw new PurityError(\n `mapFrom() mapper argument \"${arg.text}\" could not be resolved to a variable declaration in this file. Pure functions must be defined inline or as a variable in the same file`,\n filePath,\n arg.getStart(sourceFile)\n );\n }\n arg = resolved;\n }\n\n // Mapper must be a function expression or arrow function\n if (ts.isFunctionExpression(arg) || ts.isArrowFunction(arg)) {\n return buildExtractedPureFn(arg, PURE_SERVER_FN_NAMESPACE, undefined, false, sourceFile, filePath, userProvidedName);\n }\n\n throw new PurityError(\n 'mapFrom() second argument (mapper) must be a function expression or arrow function',\n filePath,\n call.arguments[1].getStart(sourceFile)\n );\n}\n\n/** Extracts data from a registerPureFnFactory(namespace, functionID, factoryFn) call expression */\nfunction extractDataFromRegisterPureFnFactoryAST(\n call: ts.CallExpression,\n sourceFile: ts.SourceFile,\n filePath: string\n): ExtractedPureFn {\n // Accept 3 or 4 arguments: registerPureFnFactory(ns, id, fn) or registerPureFnFactory(ns, id, fn, parsedFn)\n if (call.arguments.length < 3 || call.arguments.length > 4) {\n throw new PurityError(\n 'registerPureFnFactory() requires 3 or 4 arguments: namespace, functionID, factoryFn, and optional parsedFn',\n filePath,\n call.getStart(sourceFile)\n );\n }\n\n // 1st arg: namespace (string literal)\n const nsArg = call.arguments[0];\n if (!ts.isStringLiteral(nsArg)) {\n throw new PurityError(\n 'registerPureFnFactory() first argument (namespace) must be a string literal',\n filePath,\n nsArg.getStart(sourceFile)\n );\n }\n const namespace = nsArg.text;\n\n // 2nd arg: functionID (string literal)\n const idArg = call.arguments[1];\n if (!ts.isStringLiteral(idArg)) {\n throw new PurityError(\n 'registerPureFnFactory() second argument (functionID) must be a string literal',\n filePath,\n idArg.getStart(sourceFile)\n );\n }\n const fnName = idArg.text;\n\n // 3rd arg: factoryFn (function expression or arrow function)\n const fnArg = call.arguments[2];\n if (ts.isIdentifier(fnArg)) {\n if (isImportedIdentifier(fnArg.text, sourceFile)) {\n throw new PurityError(\n `registerPureFnFactory() third argument \"${fnArg.text}\" is imported from another module. The factory function must be defined inline`,\n filePath,\n fnArg.getStart(sourceFile)\n );\n }\n throw new PurityError(\n `registerPureFnFactory() third argument \"${fnArg.text}\" could not be resolved. The factory function must be defined inline as a function expression or arrow function`,\n filePath,\n fnArg.getStart(sourceFile)\n );\n }\n if (!ts.isFunctionExpression(fnArg) && !ts.isArrowFunction(fnArg)) {\n throw new PurityError(\n 'registerPureFnFactory() third argument (factoryFn) must be a function expression or arrow function',\n filePath,\n fnArg.getStart(sourceFile)\n );\n }\n\n // Extract parameter names\n const paramNames = fnArg.parameters.map((param) => {\n if (!ts.isIdentifier(param.name)) {\n throw new PurityError(\n 'Factory function parameters must be simple identifiers (no destructuring)',\n filePath,\n param.getStart(sourceFile)\n );\n }\n return param.name.text;\n });\n\n // Get the function body\n const bodyNode = fnArg.body;\n const bodyText = getBodyText(bodyNode, sourceFile);\n\n // Normalize body for hashing (collapse whitespace)\n const normalizedBody = bodyText.replace(/[ \\t]+/g, ' ').trim();\n const bodyHash = createHash('sha256')\n .update(namespace + fnName + normalizedBody)\n .digest('base64url')\n .slice(0, BODY_HASH_LENGTH);\n\n return {\n namespace,\n fnName,\n paramNames,\n fnBody: bodyText,\n bodyHash,\n dependencies: new Set(),\n sourceFile: filePath,\n isFactory: true, // registerPureFnFactory always registers factory functions\n };\n}\n\n/** Checks if an identifier name is imported from another module */\nfunction isImportedIdentifier(name: string, sourceFile: ts.SourceFile): boolean {\n for (const statement of sourceFile.statements) {\n if (!ts.isImportDeclaration(statement) || !statement.importClause) continue;\n const clause = statement.importClause;\n\n // Default import: import foo from '...'\n if (clause.name && clause.name.text === name) return true;\n\n if (clause.namedBindings) {\n // Namespace import: import * as foo from '...'\n if (ts.isNamespaceImport(clause.namedBindings) && clause.namedBindings.name.text === name) return true;\n\n // Named import: import { foo } from '...' or import { bar as foo } from '...'\n if (ts.isNamedImports(clause.namedBindings)) {\n for (const element of clause.namedBindings.elements) {\n if (element.name.text === name) return true;\n }\n }\n }\n }\n return false;\n}\n\n/** Resolves a variable name to its initializer expression within the source file */\nfunction resolveVariableInitializer(name: string, sourceFile: ts.SourceFile): ts.Expression | undefined {\n let result: ts.Expression | undefined;\n\n function visit(node: ts.Node): void {\n if (result) return;\n if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.name.text === name && node.initializer) {\n result = node.initializer;\n return;\n }\n ts.forEachChild(node, visit);\n }\n\n visit(sourceFile);\n return result;\n}\n\n/** Extracts PureFnDef data from an object literal AST node */\nfunction extractPureFnDefFromObjectLiteral(\n objLiteral: ts.ObjectLiteralExpression,\n sourceFile: ts.SourceFile,\n filePath: string,\n userProvidedName?: string\n): ExtractedPureFn {\n let pureFn: ts.FunctionExpression | ts.ArrowFunction | undefined;\n let namespace: string = PURE_SERVER_FN_NAMESPACE;\n let fnName: string | undefined;\n let isFactory = false;\n\n // Extract properties from the object literal\n for (const prop of objLiteral.properties) {\n if (!ts.isPropertyAssignment(prop)) continue;\n\n const propName = ts.isIdentifier(prop.name) ? prop.name.text : undefined;\n if (!propName) continue;\n\n switch (propName) {\n case 'pureFn': {\n const initializer = prop.initializer;\n if (ts.isFunctionExpression(initializer) || ts.isArrowFunction(initializer)) {\n pureFn = initializer;\n } else if (ts.isIdentifier(initializer)) {\n if (isImportedIdentifier(initializer.text, sourceFile)) {\n throw new PurityError(\n `pureFn property \"${initializer.text}\" is imported from another module. Pure functions must be defined inline or as a variable in the same file`,\n filePath,\n prop.initializer.getStart(sourceFile)\n );\n }\n throw new PurityError(\n `pureFn property \"${initializer.text}\" could not be resolved. Pure functions must be defined inline or as a variable in the same file`,\n filePath,\n prop.initializer.getStart(sourceFile)\n );\n } else {\n throw new PurityError(\n 'pureFn property must be a function expression or arrow function',\n filePath,\n prop.initializer.getStart(sourceFile)\n );\n }\n break;\n }\n case 'namespace':\n if (ts.isStringLiteral(prop.initializer)) {\n namespace = prop.initializer.text;\n } else {\n throw new PurityError(\n 'namespace property must be a string literal',\n filePath,\n prop.initializer.getStart(sourceFile)\n );\n }\n break;\n case 'fnName':\n if (ts.isStringLiteral(prop.initializer)) {\n fnName = prop.initializer.text;\n } else {\n throw new PurityError(\n 'fnName property must be a string literal',\n filePath,\n prop.initializer.getStart(sourceFile)\n );\n }\n break;\n case 'isFactory':\n if (prop.initializer.kind === ts.SyntaxKind.TrueKeyword) {\n isFactory = true;\n } else if (prop.initializer.kind === ts.SyntaxKind.FalseKeyword) {\n isFactory = false;\n } else {\n throw new PurityError(\n 'isFactory property must be a boolean literal',\n filePath,\n prop.initializer.getStart(sourceFile)\n );\n }\n break;\n }\n }\n\n if (!pureFn) {\n throw new PurityError('PureFnDef must have a pureFn property', filePath, objLiteral.getStart(sourceFile));\n }\n\n // For PureFnDef path: if no explicit fnName, try function.name fallback (set to 'useFunction' sentinel)\n const explicitFnName = fnName ?? (ts.isFunctionExpression(pureFn) && pureFn.name ? pureFn.name.text : undefined);\n return buildExtractedPureFn(pureFn, namespace, explicitFnName, isFactory, sourceFile, filePath, userProvidedName);\n}\n\n/** Common extraction logic: validates purity, computes hash, builds ExtractedPureFn */\nfunction buildExtractedPureFn(\n fnNode: ts.FunctionExpression | ts.ArrowFunction,\n namespace: string,\n explicitFnName: string | undefined,\n isFactory: boolean,\n sourceFile: ts.SourceFile,\n filePath: string,\n userProvidedName?: string\n): ExtractedPureFn {\n // Extract parameter names\n const paramNames = fnNode.parameters.map((param) => {\n if (!ts.isIdentifier(param.name)) {\n throw new PurityError(\n 'Pure function parameters must be simple identifiers (no destructuring)',\n filePath,\n param.getStart(sourceFile)\n );\n }\n return param.name.text;\n });\n\n // Get the function body\n const bodyNode = fnNode.body;\n\n // Validate purity\n const fnTypeLabel = isFactory ? 'factory functions' : 'pure functions';\n validatePurity(bodyNode, new Set(paramNames), explicitFnName, sourceFile, filePath, fnTypeLabel);\n\n // Get the body text\n const bodyText = getBodyText(bodyNode, sourceFile);\n\n // When user provides a name, use it as both bodyHash and fnName (skip hash computation)\n if (userProvidedName) {\n return {\n namespace,\n fnName: userProvidedName,\n paramNames,\n fnBody: bodyText,\n bodyHash: userProvidedName,\n dependencies: new Set(),\n sourceFile: filePath,\n isFactory,\n };\n }\n\n // Normalize body for hashing (collapse whitespace)\n const normalizedBody = bodyText.replace(/[ \\t]+/g, ' ').trim();\n const bodyHash = createHash('sha256')\n .update(namespace + normalizedBody)\n .digest('base64url')\n .slice(0, BODY_HASH_LENGTH);\n\n // Use explicit fnName if provided, otherwise default to bodyHash\n const fnName = explicitFnName || bodyHash;\n\n return {\n namespace,\n fnName,\n paramNames,\n fnBody: bodyText,\n bodyHash,\n dependencies: new Set(),\n sourceFile: filePath,\n isFactory,\n };\n}\n\n/** Gets the body text from a function body node */\nfunction getBodyText(body: ts.Node, sourceFile: ts.SourceFile): string {\n if (ts.isBlock(body)) {\n // Block body: { statements }\n const fullText = body.getText(sourceFile);\n return fullText.slice(1, -1).trim();\n } else {\n // Expression body (arrow function): return the expression wrapped in return\n return `return ${body.getText(sourceFile)}`;\n }\n}\n\n/** Validates that a function body is pure by traversing its AST */\nfunction validatePurity(\n body: ts.Node,\n localScope: Set<string>,\n fnName: string | undefined,\n sourceFile: ts.SourceFile,\n filePath: string,\n fnTypeLabel = 'pure functions'\n): void {\n // Collect all locally declared variables\n collectLocalDeclarations(body, localScope);\n\n // Add the function name to local scope (for recursion) if it exists\n if (fnName) localScope.add(fnName);\n\n // Traverse the AST and check for purity violations\n function checkNode(node: ts.Node): void {\n // Check for 'this' keyword\n if (node.kind === ts.SyntaxKind.ThisKeyword) {\n throw new PurityError(`'this' is not allowed in ${fnTypeLabel}`, filePath, node.getStart(sourceFile));\n }\n\n // Check for 'await' expression\n if (ts.isAwaitExpression(node)) {\n throw new PurityError(`async/await is not allowed in ${fnTypeLabel}`, filePath, node.getStart(sourceFile));\n }\n\n // Check for 'yield' keyword\n if (node.kind === ts.SyntaxKind.YieldKeyword) {\n throw new PurityError(`generators are not allowed in ${fnTypeLabel}`, filePath, node.getStart(sourceFile));\n }\n\n // Check for dynamic import\n if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.ImportKeyword) {\n throw new PurityError(`Dynamic import() is not allowed in ${fnTypeLabel}`, filePath, node.getStart(sourceFile));\n }\n\n // Check for identifier references\n if (ts.isIdentifier(node)) {\n const name = node.text;\n\n // Skip if it's a property access (e.g., obj.prop - we only care about 'obj')\n if (ts.isPropertyAccessExpression(node.parent) && node.parent.name === node) {\n ts.forEachChild(node, checkNode);\n return;\n }\n\n // Skip if it's a property name in object literal\n if (ts.isPropertyAssignment(node.parent) && node.parent.name === node) {\n ts.forEachChild(node, checkNode);\n return;\n }\n\n // Skip if it's a shorthand property assignment name\n if (ts.isShorthandPropertyAssignment(node.parent) && node.parent.name === node) {\n // But we still need to check the value reference\n if (!localScope.has(name) && !ALLOWED_GLOBALS.has(name)) {\n throw new PurityError(\n `Closure variable \"${name}\" is not allowed in ${fnTypeLabel}. ${fnTypeLabel[0].toUpperCase() + fnTypeLabel.slice(1)} cannot access outer scope variables.`,\n filePath,\n node.getStart(sourceFile)\n );\n }\n ts.forEachChild(node, checkNode);\n return;\n }\n\n // Check for forbidden identifiers\n if (FORBIDDEN_IDENTIFIERS.has(name)) {\n throw new PurityError(`${name} is not allowed in ${fnTypeLabel}`, filePath, node.getStart(sourceFile));\n }\n\n // Check for closure variables (not local, not allowed global)\n if (!localScope.has(name) && !ALLOWED_GLOBALS.has(name)) {\n throw new PurityError(\n `Closure variable \"${name}\" is not allowed in ${fnTypeLabel}. ${fnTypeLabel[0].toUpperCase() + fnTypeLabel.slice(1)} cannot access outer scope variables.`,\n filePath,\n node.getStart(sourceFile)\n );\n }\n }\n\n ts.forEachChild(node, checkNode);\n }\n\n checkNode(body);\n}\n\n/** Collects all locally declared variable names from a node */\nfunction collectLocalDeclarations(node: ts.Node, scope: Set<string>): void {\n function visit(n: ts.Node): void {\n // Variable declarations: const x = ..., let y = ..., var z = ...\n if (ts.isVariableDeclaration(n)) {\n collectBindingNames(n.name, scope);\n }\n\n // Function declarations: function foo() {}\n if (ts.isFunctionDeclaration(n) && n.name) {\n scope.add(n.name.text);\n return;\n }\n\n // Function expressions: const foo = function bar() {}\n if (ts.isFunctionExpression(n) && n.name) {\n scope.add(n.name.text);\n n.parameters.forEach((p) => collectBindingNames(p.name, scope));\n return;\n }\n\n // Arrow functions: (x) => ...\n if (ts.isArrowFunction(n)) {\n n.parameters.forEach((p) => collectBindingNames(p.name, scope));\n return;\n }\n\n // For-of/for-in loop variables\n if (ts.isForOfStatement(n) || ts.isForInStatement(n)) {\n if (ts.isVariableDeclarationList(n.initializer)) {\n n.initializer.declarations.forEach((d) => collectBindingNames(d.name, scope));\n }\n }\n\n // Catch clause variable\n if (ts.isCatchClause(n) && n.variableDeclaration) {\n collectBindingNames(n.variableDeclaration.name, scope);\n }\n\n ts.forEachChild(n, visit);\n }\n\n visit(node);\n}\n\n/** Collects binding names from a binding pattern (handles destructuring) */\nfunction collectBindingNames(name: ts.BindingName, scope: Set<string>): void {\n if (ts.isIdentifier(name)) {\n scope.add(name.text);\n } else if (ts.isObjectBindingPattern(name)) {\n name.elements.forEach((el) => collectBindingNames(el.name, scope));\n } else if (ts.isArrayBindingPattern(name)) {\n name.elements.forEach((el) => {\n if (ts.isBindingElement(el)) {\n collectBindingNames(el.name, scope);\n }\n });\n }\n}\n\n/** Error thrown when a purity violation is detected */\nexport class PurityError extends Error {\n constructor(\n message: string,\n public readonly filePath: string,\n public readonly position: number\n ) {\n super(`${message} (in ${filePath} at position ${position})`);\n this.name = 'PurityError';\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { mionVitePlugin, mionVitePlugin as mionPlugin, serverReady } from './mionVitePlugin.ts';
|
|
2
|
+
export type { MionPluginOptions } from './mionVitePlugin.ts';
|
|
3
|
+
export type { AOTCacheOptions, MionServerConfig, ServerPureFunctionsOptions as PureFunctionsPluginOptions, DeepkitTypeOptions, } from './types.ts';
|
|
4
|
+
export { cjsPackageJsonPlugin } from './cjsPackageJsonPlugin.ts';
|
|
5
|
+
export { VIRTUAL_AOT_JIT_FNS, VIRTUAL_AOT_PURE_FNS, VIRTUAL_AOT_ROUTER_CACHE, VIRTUAL_SERVER_PURE_FNS as VIRTUAL_PURE_FUNCTIONS, } from './constants.ts';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { mionVitePlugin, mionVitePlugin as mionVitePlugin2, serverReady } from "./mionVitePlugin.js";
|
|
2
|
+
import { cjsPackageJsonPlugin } from "./cjsPackageJsonPlugin.js";
|
|
3
|
+
import { VIRTUAL_AOT_JIT_FNS, VIRTUAL_AOT_PURE_FNS, VIRTUAL_AOT_ROUTER_CACHE, VIRTUAL_SERVER_PURE_FNS } from "./constants.js";
|
|
4
|
+
export {
|
|
5
|
+
VIRTUAL_AOT_JIT_FNS,
|
|
6
|
+
VIRTUAL_AOT_PURE_FNS,
|
|
7
|
+
VIRTUAL_AOT_ROUTER_CACHE,
|
|
8
|
+
VIRTUAL_SERVER_PURE_FNS as VIRTUAL_PURE_FUNCTIONS,
|
|
9
|
+
cjsPackageJsonPlugin,
|
|
10
|
+
mionVitePlugin as mionPlugin,
|
|
11
|
+
mionVitePlugin2 as mionVitePlugin,
|
|
12
|
+
serverReady
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ServerPureFunctionsOptions, DeepkitTypeOptions, AOTCacheOptions, MionServerConfig } from './types.ts';
|
|
2
|
+
export interface MionPluginOptions {
|
|
3
|
+
serverPureFunctions?: ServerPureFunctionsOptions;
|
|
4
|
+
runTypes?: DeepkitTypeOptions;
|
|
5
|
+
aotCaches?: AOTCacheOptions | true;
|
|
6
|
+
server?: MionServerConfig;
|
|
7
|
+
}
|
|
8
|
+
export declare function mionVitePlugin(options: MionPluginOptions): {
|
|
9
|
+
name: string;
|
|
10
|
+
enforce: "pre";
|
|
11
|
+
config(config: any): void;
|
|
12
|
+
configResolved(config: any): void;
|
|
13
|
+
buildStart(): Promise<void>;
|
|
14
|
+
configureServer(server: any): void;
|
|
15
|
+
resolveId(id: any): string | null;
|
|
16
|
+
load(id: any): Promise<string | {
|
|
17
|
+
code: string;
|
|
18
|
+
syntheticNamedExports: boolean;
|
|
19
|
+
} | null>;
|
|
20
|
+
transform(code: string, fileName: string): {
|
|
21
|
+
code: string;
|
|
22
|
+
map: string | undefined;
|
|
23
|
+
} | null;
|
|
24
|
+
buildEnd(): void;
|
|
25
|
+
closeBundle(): Promise<void>;
|
|
26
|
+
handleHotUpdate({ file, server }: {
|
|
27
|
+
file: any;
|
|
28
|
+
server: any;
|
|
29
|
+
}): any[] | undefined;
|
|
30
|
+
};
|
|
31
|
+
export declare function parseVueModuleId(id: string): {
|
|
32
|
+
basePath: string;
|
|
33
|
+
lang: string | null;
|
|
34
|
+
} | null;
|
|
35
|
+
export declare function isIncluded(filePath: string, include: string[], exclude: string[]): boolean;
|
|
36
|
+
export declare const serverReady: Promise<void>;
|
|
@@ -0,0 +1,387 @@
|
|
|
1
|
+
import { resolve } from "path";
|
|
2
|
+
import * as ts from "typescript";
|
|
3
|
+
import { createDeepkitConfig, createPureFnTransformerFactory } from "./transformers.js";
|
|
4
|
+
import { scanClientSource } from "./extractPureFn.js";
|
|
5
|
+
import { generateServerPureFnsVirtualModule } from "./virtualModule.js";
|
|
6
|
+
import { resolveVirtualId, VIRTUAL_SERVER_PURE_FNS, REFLECTION_MODULES, VIRTUAL_STUB_PREFIX } from "./constants.js";
|
|
7
|
+
import { generateAOTCaches, logAOTCaches, waitForServer, generateNoopCombinedModule, generateCombinedCachesModule, generateNoopModule, generateRouterCacheModule, generatePureFnsModule, generateJitFnsModule, loadSSRRouterAndGenerateAOTCaches, killPersistentChild } from "./aotCacheGenerator.js";
|
|
8
|
+
import { updateDiskCache, getOrGenerateAOTCaches, resolveCacheDir } from "./aotDiskCache.js";
|
|
9
|
+
function isRunningAsChild() {
|
|
10
|
+
return process.env.MION_COMPILE === "onlyAOT" || process.env.MION_COMPILE === "serve";
|
|
11
|
+
}
|
|
12
|
+
function mionVitePlugin(options) {
|
|
13
|
+
let extractedFns = null;
|
|
14
|
+
const pureFnOptions = options.serverPureFunctions;
|
|
15
|
+
const runTypesOptions = options.runTypes;
|
|
16
|
+
const aotOptions = options.aotCaches === true ? {} : options.aotCaches;
|
|
17
|
+
const serverConfig = options.server;
|
|
18
|
+
const deepkitConfig = runTypesOptions ? createDeepkitConfig(runTypesOptions) : null;
|
|
19
|
+
const defaultCompilerOptions = {
|
|
20
|
+
target: ts.ScriptTarget.ESNext,
|
|
21
|
+
module: ts.ModuleKind.ESNext
|
|
22
|
+
};
|
|
23
|
+
let pureServerFnCount = 0;
|
|
24
|
+
let registerPureFnFactoryCount = 0;
|
|
25
|
+
let pureFnFilesCount = 0;
|
|
26
|
+
let aotData = null;
|
|
27
|
+
let aotGenerationPromise = null;
|
|
28
|
+
let aotCacheDir = "";
|
|
29
|
+
let ssrLoadModule = null;
|
|
30
|
+
const ssrEnabled = serverConfig?.mode === "viteSSR";
|
|
31
|
+
let ssrInitPromise = null;
|
|
32
|
+
let persistentChild = null;
|
|
33
|
+
let cleanupRegistered = false;
|
|
34
|
+
const { aotVirtualModules, aotResolvedIds } = buildAOTVirtualModuleMaps(aotOptions?.customVirtualModuleId);
|
|
35
|
+
async function cleanupChild() {
|
|
36
|
+
if (persistentChild) {
|
|
37
|
+
await killPersistentChild(persistentChild);
|
|
38
|
+
persistentChild = null;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
function registerCleanupHandlers() {
|
|
42
|
+
if (cleanupRegistered) return;
|
|
43
|
+
cleanupRegistered = true;
|
|
44
|
+
const onExit = () => {
|
|
45
|
+
if (persistentChild && !persistentChild.killed) {
|
|
46
|
+
persistentChild.kill("SIGTERM");
|
|
47
|
+
persistentChild = null;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
process.on("exit", onExit);
|
|
51
|
+
process.on("SIGINT", onExit);
|
|
52
|
+
process.on("SIGTERM", onExit);
|
|
53
|
+
}
|
|
54
|
+
return {
|
|
55
|
+
name: "mion",
|
|
56
|
+
enforce: "pre",
|
|
57
|
+
// literal type required: inferred 'string' is not assignable to Vite's 'pre' | 'post'
|
|
58
|
+
config(config) {
|
|
59
|
+
if (aotOptions?.excludeReflection && !isRunningAsChild()) {
|
|
60
|
+
const aliases = config.resolve?.alias;
|
|
61
|
+
if (aliases && !Array.isArray(aliases)) {
|
|
62
|
+
for (const mod of REFLECTION_MODULES) {
|
|
63
|
+
delete aliases[mod];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
configResolved(config) {
|
|
69
|
+
if (aotOptions) {
|
|
70
|
+
aotCacheDir = resolveCacheDir(aotOptions, config.cacheDir);
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
async buildStart() {
|
|
74
|
+
if (serverConfig && !isRunningAsChild() && !ssrEnabled) {
|
|
75
|
+
if (serverConfig.port) process.env.MION_TEST_PORT = String(serverConfig.port);
|
|
76
|
+
try {
|
|
77
|
+
console.log("[mion] Generating AOT caches...");
|
|
78
|
+
const resultPromise = getOrGenerateAOTCaches(serverConfig, aotOptions, aotCacheDir);
|
|
79
|
+
aotGenerationPromise = resultPromise.then((r) => r.data);
|
|
80
|
+
const result = await resultPromise;
|
|
81
|
+
aotData = result.data;
|
|
82
|
+
console.log("[mion] AOT caches generated successfully");
|
|
83
|
+
logAOTCaches(aotData);
|
|
84
|
+
if (result.childProcess) {
|
|
85
|
+
persistentChild = result.childProcess;
|
|
86
|
+
registerCleanupHandlers();
|
|
87
|
+
console.log(`[mion] Server process persisted (pid: ${persistentChild.pid})`);
|
|
88
|
+
}
|
|
89
|
+
if (serverConfig.port && serverConfig.mode === "IPC") {
|
|
90
|
+
const timeout = serverConfig.waitTimeout ?? 3e4;
|
|
91
|
+
console.log(`[mion] Waiting for server on port ${serverConfig.port}...`);
|
|
92
|
+
waitForServer(serverConfig.port, timeout).then(() => {
|
|
93
|
+
console.log(`[mion] Server ready on port ${serverConfig.port}`);
|
|
94
|
+
onServerReady();
|
|
95
|
+
}).catch((err) => {
|
|
96
|
+
console.error(`[mion] ${err instanceof Error ? err.message : String(err)}`);
|
|
97
|
+
});
|
|
98
|
+
} else {
|
|
99
|
+
onServerReady();
|
|
100
|
+
}
|
|
101
|
+
} catch (err) {
|
|
102
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
103
|
+
throw new Error(`[mion] Failed to generate AOT caches: ${message}`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
configureServer(server) {
|
|
108
|
+
if (!ssrEnabled || !serverConfig) return;
|
|
109
|
+
ssrLoadModule = (url) => server.ssrLoadModule(url);
|
|
110
|
+
const startServerScript = resolve(serverConfig.startServerScript);
|
|
111
|
+
let nodeRequestHandler = null;
|
|
112
|
+
let basePath = null;
|
|
113
|
+
let initFailed = false;
|
|
114
|
+
console.log("[mion] Generating SSR AOT caches...");
|
|
115
|
+
ssrInitPromise = loadSSRRouterAndGenerateAOTCaches(ssrLoadModule, startServerScript).then(async (data) => {
|
|
116
|
+
aotData = data;
|
|
117
|
+
aotGenerationPromise = Promise.resolve(data);
|
|
118
|
+
console.log("[mion] SSR AOT caches generated successfully");
|
|
119
|
+
logAOTCaches(data);
|
|
120
|
+
for (const resolvedId of aotResolvedIds.keys()) {
|
|
121
|
+
const mod = server.moduleGraph.getModuleById(resolvedId);
|
|
122
|
+
if (mod) server.moduleGraph.invalidateModule(mod);
|
|
123
|
+
}
|
|
124
|
+
const routerModule = await server.ssrLoadModule("@mionjs/router");
|
|
125
|
+
const opts = routerModule.getRouterOptions();
|
|
126
|
+
basePath = "/" + (opts.basePath || "").replace(/^\//, "");
|
|
127
|
+
const platformNode = await server.ssrLoadModule("@mionjs/platform-node");
|
|
128
|
+
nodeRequestHandler = platformNode.httpRequestHandler;
|
|
129
|
+
console.log("[mion] Dev server proxy initialized");
|
|
130
|
+
onServerReady();
|
|
131
|
+
}).catch((err) => {
|
|
132
|
+
initFailed = true;
|
|
133
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
134
|
+
console.error(`[mion] Failed to initialize SSR: ${message}`);
|
|
135
|
+
});
|
|
136
|
+
server.middlewares.use(async (req, res, next) => {
|
|
137
|
+
try {
|
|
138
|
+
if (!basePath && !initFailed) await ssrInitPromise;
|
|
139
|
+
if (!basePath || !req.url?.startsWith(basePath)) return next();
|
|
140
|
+
if (nodeRequestHandler) {
|
|
141
|
+
nodeRequestHandler(req, res);
|
|
142
|
+
} else {
|
|
143
|
+
res.statusCode = 503;
|
|
144
|
+
res.end("mion API failed to initialize");
|
|
145
|
+
}
|
|
146
|
+
} catch (err) {
|
|
147
|
+
console.error("[mion] Dev server proxy error:", err);
|
|
148
|
+
if (!res.writableEnded) {
|
|
149
|
+
res.statusCode = 500;
|
|
150
|
+
res.end("Internal Server Error");
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
},
|
|
155
|
+
resolveId(id) {
|
|
156
|
+
if (id === VIRTUAL_SERVER_PURE_FNS) return resolveVirtualId(id);
|
|
157
|
+
if (aotVirtualModules.has(id)) return resolveVirtualId(id);
|
|
158
|
+
if (aotOptions?.excludeReflection && !isRunningAsChild() && REFLECTION_MODULES.includes(id)) {
|
|
159
|
+
return resolveVirtualId(VIRTUAL_STUB_PREFIX + id);
|
|
160
|
+
}
|
|
161
|
+
return null;
|
|
162
|
+
},
|
|
163
|
+
async load(id) {
|
|
164
|
+
if (id === resolveVirtualId(VIRTUAL_SERVER_PURE_FNS)) {
|
|
165
|
+
if (!pureFnOptions) return generateServerPureFnsVirtualModule([]);
|
|
166
|
+
if (!extractedFns) extractedFns = scanClientSource(pureFnOptions);
|
|
167
|
+
return generateServerPureFnsVirtualModule(extractedFns);
|
|
168
|
+
}
|
|
169
|
+
const aotType = aotResolvedIds.get(id);
|
|
170
|
+
if (aotType) {
|
|
171
|
+
const initPromise = ssrInitPromise || aotGenerationPromise;
|
|
172
|
+
if (!aotData && initPromise) await initPromise;
|
|
173
|
+
switch (aotType) {
|
|
174
|
+
case "jit-fns": {
|
|
175
|
+
if (!aotData) return generateNoopModule("No-op: AOT JIT caches not generated");
|
|
176
|
+
return generateJitFnsModule(aotData.jitFnsCode);
|
|
177
|
+
}
|
|
178
|
+
case "pure-fns": {
|
|
179
|
+
if (!aotData) return generateNoopModule("No-op: AOT pure fns not generated");
|
|
180
|
+
return generatePureFnsModule(aotData.pureFnsCode);
|
|
181
|
+
}
|
|
182
|
+
case "router-cache": {
|
|
183
|
+
if (!aotData) return generateNoopModule("No-op: AOT router cache not generated");
|
|
184
|
+
return generateRouterCacheModule(aotData.routerCacheCode);
|
|
185
|
+
}
|
|
186
|
+
case "caches": {
|
|
187
|
+
if (!aotData) return generateNoopCombinedModule();
|
|
188
|
+
return generateCombinedCachesModule();
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
for (const mod of REFLECTION_MODULES) {
|
|
193
|
+
if (id === resolveVirtualId(VIRTUAL_STUB_PREFIX + mod)) {
|
|
194
|
+
return { code: "export default {}", syntheticNamedExports: true };
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
return null;
|
|
198
|
+
},
|
|
199
|
+
transform(code, fileName) {
|
|
200
|
+
const vueInfo = parseVueModuleId(fileName);
|
|
201
|
+
const basePath = fileName.includes("?") ? fileName.slice(0, fileName.indexOf("?")) : fileName;
|
|
202
|
+
const filterPath = vueInfo ? vueInfo.basePath : basePath;
|
|
203
|
+
if (basePath.endsWith(".vue") && !vueInfo) return null;
|
|
204
|
+
const lang = vueInfo?.lang || "ts";
|
|
205
|
+
const tsFileName = vueInfo ? `${vueInfo.basePath}.${lang}` : fileName;
|
|
206
|
+
const isTsx = tsFileName.endsWith(".tsx") || tsFileName.endsWith(".jsx");
|
|
207
|
+
const hasPureFns = code.includes("pureServerFn") || code.includes("registerPureFnFactory") || code.includes("mapFrom");
|
|
208
|
+
const needsDeepkit = deepkitConfig ? deepkitConfig.filter(filterPath) : false;
|
|
209
|
+
if (!hasPureFns && !needsDeepkit) return null;
|
|
210
|
+
const before = [];
|
|
211
|
+
const after = [];
|
|
212
|
+
const collected = hasPureFns ? [] : void 0;
|
|
213
|
+
if (hasPureFns) {
|
|
214
|
+
before.push(createPureFnTransformerFactory(code, tsFileName, collected, pureFnOptions?.noViteClient));
|
|
215
|
+
}
|
|
216
|
+
if (deepkitConfig) after.push(...deepkitConfig.afterTransformers);
|
|
217
|
+
if (needsDeepkit) before.push(...deepkitConfig.beforeTransformers);
|
|
218
|
+
const baseCompilerOptions = deepkitConfig?.compilerOptions ?? defaultCompilerOptions;
|
|
219
|
+
const compilerOptions = isTsx ? { ...baseCompilerOptions, jsx: ts.JsxEmit.ReactJSX } : baseCompilerOptions;
|
|
220
|
+
const result = ts.transpileModule(code, {
|
|
221
|
+
compilerOptions,
|
|
222
|
+
fileName: tsFileName,
|
|
223
|
+
transformers: { before, after }
|
|
224
|
+
});
|
|
225
|
+
if (collected && collected.length > 0) {
|
|
226
|
+
pureFnFilesCount++;
|
|
227
|
+
for (const fn of collected) {
|
|
228
|
+
if (fn.isFactory) registerPureFnFactoryCount++;
|
|
229
|
+
else pureServerFnCount++;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return { code: result.outputText, map: result.sourceMapText };
|
|
233
|
+
},
|
|
234
|
+
buildEnd() {
|
|
235
|
+
if (pureServerFnCount > 0 || registerPureFnFactoryCount > 0) {
|
|
236
|
+
const total = pureServerFnCount + registerPureFnFactoryCount;
|
|
237
|
+
const parts = [
|
|
238
|
+
pureServerFnCount > 0 ? `${pureServerFnCount} pureServerFn` : "",
|
|
239
|
+
registerPureFnFactoryCount > 0 ? `${registerPureFnFactoryCount} registerPureFnFactory` : ""
|
|
240
|
+
].filter(Boolean);
|
|
241
|
+
console.log(`[mion] Injected ${total} pure functions across ${pureFnFilesCount} files (${parts.join(", ")})`);
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
async closeBundle() {
|
|
245
|
+
await cleanupChild();
|
|
246
|
+
},
|
|
247
|
+
handleHotUpdate({ file, server }) {
|
|
248
|
+
if (pureFnOptions) {
|
|
249
|
+
const clientSrcPath = resolve(pureFnOptions.clientSrcPath);
|
|
250
|
+
if (file.startsWith(clientSrcPath)) {
|
|
251
|
+
const include = pureFnOptions.include || ["**/*.ts", "**/*.tsx", "**/*.vue"];
|
|
252
|
+
const exclude = pureFnOptions.exclude || ["../node_modules/**", "**/.dist/**", "**/dist/**"];
|
|
253
|
+
if (isIncluded(file, include, exclude)) {
|
|
254
|
+
extractedFns = null;
|
|
255
|
+
const mod = server.moduleGraph.getModuleById(resolveVirtualId(VIRTUAL_SERVER_PURE_FNS));
|
|
256
|
+
if (mod) {
|
|
257
|
+
server.moduleGraph.invalidateModule(mod);
|
|
258
|
+
return [mod];
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (serverConfig && !isRunningAsChild()) {
|
|
264
|
+
const serverDir = resolve(serverConfig.startServerScript, "..");
|
|
265
|
+
if (file.startsWith(serverDir)) {
|
|
266
|
+
const killPromise = cleanupChild();
|
|
267
|
+
const regeneratePromise = ssrEnabled && ssrLoadModule ? (
|
|
268
|
+
// SSR mode: reset router and re-init via ssrLoadModule
|
|
269
|
+
(async () => {
|
|
270
|
+
const routerModule = await ssrLoadModule("@mionjs/router");
|
|
271
|
+
routerModule.resetRouter();
|
|
272
|
+
return loadSSRRouterAndGenerateAOTCaches(
|
|
273
|
+
ssrLoadModule,
|
|
274
|
+
resolve(serverConfig.startServerScript)
|
|
275
|
+
);
|
|
276
|
+
})()
|
|
277
|
+
) : (
|
|
278
|
+
// IPC mode: wait for old child to die, then spawn new
|
|
279
|
+
killPromise.then(() => generateAOTCaches(serverConfig))
|
|
280
|
+
);
|
|
281
|
+
aotGenerationPromise = regeneratePromise.then((r) => "data" in r ? r.data : r);
|
|
282
|
+
regeneratePromise.then((result) => {
|
|
283
|
+
const data = "data" in result ? result.data : result;
|
|
284
|
+
aotData = data;
|
|
285
|
+
logAOTCaches(data);
|
|
286
|
+
if ("childProcess" in result && result.childProcess) {
|
|
287
|
+
persistentChild = result.childProcess;
|
|
288
|
+
console.log(`[mion] Server process re-persisted (pid: ${persistentChild.pid})`);
|
|
289
|
+
}
|
|
290
|
+
if (serverConfig.port && serverConfig.mode === "IPC") {
|
|
291
|
+
const timeout = serverConfig.waitTimeout ?? 3e4;
|
|
292
|
+
console.log(`[mion] Waiting for restarted server on port ${serverConfig.port}...`);
|
|
293
|
+
waitForServer(serverConfig.port, timeout).then(() => {
|
|
294
|
+
console.log(`[mion] Restarted server ready on port ${serverConfig.port}`);
|
|
295
|
+
onServerReady();
|
|
296
|
+
}).catch((err) => {
|
|
297
|
+
console.error(`[mion] ${err instanceof Error ? err.message : String(err)}`);
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
if (!ssrEnabled) updateDiskCache(serverConfig, aotOptions, data, aotCacheDir);
|
|
301
|
+
let invalidatedCount = 0;
|
|
302
|
+
for (const resolvedId of aotResolvedIds.keys()) {
|
|
303
|
+
const mod = server.moduleGraph.getModuleById(resolvedId);
|
|
304
|
+
if (mod) {
|
|
305
|
+
server.moduleGraph.invalidateModule(mod);
|
|
306
|
+
invalidatedCount++;
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
if (invalidatedCount > 0) {
|
|
310
|
+
console.log("[mion] AOT caches regenerated, invalidating virtual modules");
|
|
311
|
+
}
|
|
312
|
+
}).catch((err) => {
|
|
313
|
+
console.error("[mion] Failed to regenerate AOT caches:", err.message);
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
return void 0;
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
function parseVueModuleId(id) {
|
|
322
|
+
const qIdx = id.indexOf("?");
|
|
323
|
+
if (qIdx === -1) return null;
|
|
324
|
+
const basePath = id.slice(0, qIdx);
|
|
325
|
+
if (!basePath.endsWith(".vue")) return null;
|
|
326
|
+
const params = new URLSearchParams(id.slice(qIdx));
|
|
327
|
+
if (!params.has("vue") || params.get("type") !== "script") return null;
|
|
328
|
+
return { basePath, lang: params.get("lang") };
|
|
329
|
+
}
|
|
330
|
+
function isIncluded(filePath, include, exclude) {
|
|
331
|
+
const vueInfo = parseVueModuleId(filePath);
|
|
332
|
+
const effectivePath = vueInfo ? vueInfo.basePath : filePath;
|
|
333
|
+
const isTs = /\.(ts|tsx|js|jsx)$/.test(effectivePath);
|
|
334
|
+
const isVue = effectivePath.endsWith(".vue");
|
|
335
|
+
const isDir = effectivePath.endsWith("/");
|
|
336
|
+
if (!isTs && !isVue && !isDir) return false;
|
|
337
|
+
for (const pattern of exclude) {
|
|
338
|
+
if (matchGlob(effectivePath, pattern)) return false;
|
|
339
|
+
}
|
|
340
|
+
return true;
|
|
341
|
+
}
|
|
342
|
+
function matchGlob(filePath, pattern) {
|
|
343
|
+
if (pattern.startsWith("**/")) {
|
|
344
|
+
const suffix = pattern.slice(3);
|
|
345
|
+
return filePath.includes(suffix.replace(/\*/g, ""));
|
|
346
|
+
}
|
|
347
|
+
const regex = new RegExp("^" + pattern.replace(/\*\*/g, ".*").replace(/\*/g, "[^/]*") + "$");
|
|
348
|
+
return regex.test(filePath);
|
|
349
|
+
}
|
|
350
|
+
const AOT_MODULE_TYPES = ["jit-fns", "pure-fns", "router-cache", "caches"];
|
|
351
|
+
function buildAOTVirtualModuleMaps(customVirtualModuleId) {
|
|
352
|
+
const aotVirtualModules = /* @__PURE__ */ new Map();
|
|
353
|
+
const aotResolvedIds = /* @__PURE__ */ new Map();
|
|
354
|
+
for (const type of AOT_MODULE_TYPES) {
|
|
355
|
+
const defaultId = `virtual:mion-aot/${type}`;
|
|
356
|
+
aotVirtualModules.set(defaultId, type);
|
|
357
|
+
aotResolvedIds.set(resolveVirtualId(defaultId), type);
|
|
358
|
+
if (customVirtualModuleId) {
|
|
359
|
+
const customId = `virtual:${customVirtualModuleId}/${type}`;
|
|
360
|
+
aotVirtualModules.set(customId, type);
|
|
361
|
+
aotResolvedIds.set(resolveVirtualId(customId), type);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
return { aotVirtualModules, aotResolvedIds };
|
|
365
|
+
}
|
|
366
|
+
const READY_KEY = /* @__PURE__ */ Symbol.for("mion.serverReady");
|
|
367
|
+
function getOrCreateServerReady() {
|
|
368
|
+
if (!globalThis[READY_KEY]) {
|
|
369
|
+
let _resolve;
|
|
370
|
+
globalThis[READY_KEY] = {
|
|
371
|
+
promise: new Promise((r) => {
|
|
372
|
+
_resolve = r;
|
|
373
|
+
}),
|
|
374
|
+
resolve: () => _resolve()
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
return globalThis[READY_KEY];
|
|
378
|
+
}
|
|
379
|
+
const serverReady = getOrCreateServerReady().promise;
|
|
380
|
+
const onServerReady = getOrCreateServerReady().resolve;
|
|
381
|
+
export {
|
|
382
|
+
isIncluded,
|
|
383
|
+
mionVitePlugin,
|
|
384
|
+
parseVueModuleId,
|
|
385
|
+
serverReady
|
|
386
|
+
};
|
|
387
|
+
//# sourceMappingURL=mionVitePlugin.js.map
|