phantom-build 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (94) hide show
  1. package/README.md +378 -0
  2. package/dist/analyzer.d.ts +11 -0
  3. package/dist/analyzer.d.ts.map +1 -0
  4. package/dist/analyzer.js +330 -0
  5. package/dist/analyzer.js.map +1 -0
  6. package/dist/ast-compat.d.ts +11 -0
  7. package/dist/ast-compat.d.ts.map +1 -0
  8. package/dist/ast-compat.js +84 -0
  9. package/dist/ast-compat.js.map +1 -0
  10. package/dist/classify/boundary.d.ts +30 -0
  11. package/dist/classify/boundary.d.ts.map +1 -0
  12. package/dist/classify/boundary.js +145 -0
  13. package/dist/classify/boundary.js.map +1 -0
  14. package/dist/classify/browser-globals.d.ts +29 -0
  15. package/dist/classify/browser-globals.d.ts.map +1 -0
  16. package/dist/classify/browser-globals.js +197 -0
  17. package/dist/classify/browser-globals.js.map +1 -0
  18. package/dist/classify/index.d.ts +14 -0
  19. package/dist/classify/index.d.ts.map +1 -0
  20. package/dist/classify/index.js +294 -0
  21. package/dist/classify/index.js.map +1 -0
  22. package/dist/classify/lazy-llm.d.ts +122 -0
  23. package/dist/classify/lazy-llm.d.ts.map +1 -0
  24. package/dist/classify/lazy-llm.js +142 -0
  25. package/dist/classify/lazy-llm.js.map +1 -0
  26. package/dist/classify/lazy.d.ts +23 -0
  27. package/dist/classify/lazy.d.ts.map +1 -0
  28. package/dist/classify/lazy.js +686 -0
  29. package/dist/classify/lazy.js.map +1 -0
  30. package/dist/classify/llm-client.d.ts +59 -0
  31. package/dist/classify/llm-client.d.ts.map +1 -0
  32. package/dist/classify/llm-client.js +193 -0
  33. package/dist/classify/llm-client.js.map +1 -0
  34. package/dist/classify/purity.d.ts +21 -0
  35. package/dist/classify/purity.d.ts.map +1 -0
  36. package/dist/classify/purity.js +47 -0
  37. package/dist/classify/purity.js.map +1 -0
  38. package/dist/classify/react-patterns.d.ts +15 -0
  39. package/dist/classify/react-patterns.d.ts.map +1 -0
  40. package/dist/classify/react-patterns.js +82 -0
  41. package/dist/classify/react-patterns.js.map +1 -0
  42. package/dist/classify/taint.d.ts +32 -0
  43. package/dist/classify/taint.d.ts.map +1 -0
  44. package/dist/classify/taint.js +68 -0
  45. package/dist/classify/taint.js.map +1 -0
  46. package/dist/cli.d.ts +3 -0
  47. package/dist/cli.d.ts.map +1 -0
  48. package/dist/cli.js +109 -0
  49. package/dist/cli.js.map +1 -0
  50. package/dist/extract/chunk-module.d.ts +20 -0
  51. package/dist/extract/chunk-module.d.ts.map +1 -0
  52. package/dist/extract/chunk-module.js +163 -0
  53. package/dist/extract/chunk-module.js.map +1 -0
  54. package/dist/extract/client-stub.d.ts +25 -0
  55. package/dist/extract/client-stub.d.ts.map +1 -0
  56. package/dist/extract/client-stub.js +233 -0
  57. package/dist/extract/client-stub.js.map +1 -0
  58. package/dist/extract/import-resolver.d.ts +20 -0
  59. package/dist/extract/import-resolver.d.ts.map +1 -0
  60. package/dist/extract/import-resolver.js +51 -0
  61. package/dist/extract/import-resolver.js.map +1 -0
  62. package/dist/extract/index.d.ts +20 -0
  63. package/dist/extract/index.d.ts.map +1 -0
  64. package/dist/extract/index.js +105 -0
  65. package/dist/extract/index.js.map +1 -0
  66. package/dist/extract/lazy-transform.d.ts +14 -0
  67. package/dist/extract/lazy-transform.d.ts.map +1 -0
  68. package/dist/extract/lazy-transform.js +473 -0
  69. package/dist/extract/lazy-transform.js.map +1 -0
  70. package/dist/index.d.ts +4 -0
  71. package/dist/index.d.ts.map +1 -0
  72. package/dist/index.js +3 -0
  73. package/dist/index.js.map +1 -0
  74. package/dist/plugin.d.ts +7 -0
  75. package/dist/plugin.d.ts.map +1 -0
  76. package/dist/plugin.js +535 -0
  77. package/dist/plugin.js.map +1 -0
  78. package/dist/runtime/index.d.ts +28 -0
  79. package/dist/runtime/index.d.ts.map +1 -0
  80. package/dist/runtime/index.js +73 -0
  81. package/dist/runtime/index.js.map +1 -0
  82. package/dist/types.d.ts +219 -0
  83. package/dist/types.d.ts.map +1 -0
  84. package/dist/types.js +2 -0
  85. package/dist/types.js.map +1 -0
  86. package/dist/vite.d.ts +3 -0
  87. package/dist/vite.d.ts.map +1 -0
  88. package/dist/vite.js +3 -0
  89. package/dist/vite.js.map +1 -0
  90. package/dist/webpack.d.ts +3 -0
  91. package/dist/webpack.d.ts.map +1 -0
  92. package/dist/webpack.js +3 -0
  93. package/dist/webpack.js.map +1 -0
  94. package/package.json +79 -0
@@ -0,0 +1,51 @@
1
+ import { resolve, dirname } from 'node:path';
2
+ /**
3
+ * Resolve what the extracted segment needs: imports vs captured variables.
4
+ *
5
+ * ClassifiedSegment.dependencies merges fn.captured + fn.imported.
6
+ * We recover the split by matching back to the FunctionDependency via span,
7
+ * then cross-reference imported names against AnalyzedModule.imports.
8
+ *
9
+ * Relative import paths (./foo, ../bar) are rewritten to absolute paths
10
+ * so that chunk virtual modules (which have no filesystem location) can
11
+ * resolve their dependencies correctly.
12
+ */
13
+ export function resolveImports(segment, analyzed, sourceFilePath) {
14
+ const fnDep = analyzed.functions.find((fn) => fn.span.start === segment.span.start && fn.span.end === segment.span.end);
15
+ if (!fnDep) {
16
+ return { imports: [], capturedParams: segment.dependencies };
17
+ }
18
+ const capturedParams = fnDep.captured;
19
+ const importedNames = new Set(fnDep.imported);
20
+ // Group needed imports by source module
21
+ const importMap = new Map();
22
+ const sourceDir = dirname(sourceFilePath);
23
+ for (const imp of analyzed.imports) {
24
+ for (const spec of imp.specifiers) {
25
+ if (importedNames.has(spec.local)) {
26
+ // Rewrite relative imports to absolute paths for virtual module resolution
27
+ const resolvedSource = isRelativeImport(imp.source)
28
+ ? resolve(sourceDir, imp.source)
29
+ : imp.source;
30
+ let entry = importMap.get(resolvedSource);
31
+ if (!entry) {
32
+ entry = { source: resolvedSource, specifiers: [] };
33
+ importMap.set(resolvedSource, entry);
34
+ }
35
+ entry.specifiers.push(spec);
36
+ }
37
+ }
38
+ }
39
+ return {
40
+ imports: Array.from(importMap.values()),
41
+ capturedParams,
42
+ };
43
+ }
44
+ /**
45
+ * Check if an import specifier is a relative path (./foo or ../bar).
46
+ * Bare specifiers like 'react' or '@org/pkg' are NOT relative.
47
+ */
48
+ function isRelativeImport(source) {
49
+ return source.startsWith('./') || source.startsWith('../');
50
+ }
51
+ //# sourceMappingURL=import-resolver.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import-resolver.js","sourceRoot":"","sources":["../../src/extract/import-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAU7C;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAC5B,OAA0B,EAC1B,QAAwB,EACxB,cAAsB;IAEtB,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,CAAC,IAAI,CACnC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,OAAO,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,CACjF,CAAC;IAEF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,cAAc,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC;IAC/D,CAAC;IAED,MAAM,cAAc,GAAG,KAAK,CAAC,QAAQ,CAAC;IACtC,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAE9C,wCAAwC;IACxC,MAAM,SAAS,GAAG,IAAI,GAAG,EAAsB,CAAC;IAChD,MAAM,SAAS,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IAE1C,KAAK,MAAM,GAAG,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;QACnC,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;YAClC,IAAI,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBAClC,2EAA2E;gBAC3E,MAAM,cAAc,GAAG,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC;oBACjD,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,CAAC,MAAM,CAAC;oBAChC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC;gBAEf,IAAI,KAAK,GAAG,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;gBAC1C,IAAI,CAAC,KAAK,EAAE,CAAC;oBACX,KAAK,GAAG,EAAE,MAAM,EAAE,cAAc,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;oBACnD,SAAS,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,CAAC,CAAC;gBACvC,CAAC;gBACD,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC9B,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO;QACL,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC;QACvC,cAAc;KACf,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,gBAAgB,CAAC,MAAc;IACtC,OAAO,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { AnalyzedModule, ClassifiedSegment, LazyCandidate, SourceMapLike } from '../types.js';
2
+ export interface ExtractionResult {
3
+ clientCode: string;
4
+ clientMap: SourceMapLike;
5
+ chunkModules: Array<{
6
+ id: string;
7
+ code: string;
8
+ map: SourceMapLike;
9
+ }>;
10
+ }
11
+ /**
12
+ * Extract EventHandler segments from a module into lazy-loaded chunks.
13
+ *
14
+ * Returns null if no segments qualify for extraction,
15
+ * otherwise returns rewritten client code + chunk modules.
16
+ *
17
+ * Uses proper AST-based codegen with esrap — no source text splicing.
18
+ */
19
+ export declare function extractModule(analyzed: AnalyzedModule, segments: ClassifiedSegment[], _sourceCode: string, confidenceThreshold: number, sourceFilePath: string, lazyCandidates?: LazyCandidate[]): ExtractionResult | null;
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/extract/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,iBAAiB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAMnG,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,aAAa,CAAC;IACzB,YAAY,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,aAAa,CAAA;KAAE,CAAC,CAAC;CACvE;AAED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,cAAc,EACxB,QAAQ,EAAE,iBAAiB,EAAE,EAC7B,WAAW,EAAE,MAAM,EACnB,mBAAmB,EAAE,MAAM,EAC3B,cAAc,EAAE,MAAM,EACtB,cAAc,CAAC,EAAE,aAAa,EAAE,GAC/B,gBAAgB,GAAG,IAAI,CA6EzB"}
@@ -0,0 +1,105 @@
1
+ import { print } from 'esrap';
2
+ import tsx from 'esrap/languages/tsx';
3
+ import { resolveImports } from './import-resolver.js';
4
+ import { generateChunkModule } from './chunk-module.js';
5
+ import { replaceWithStub } from './client-stub.js';
6
+ import { applyLazyTransforms } from './lazy-transform.js';
7
+ /**
8
+ * Extract EventHandler segments from a module into lazy-loaded chunks.
9
+ *
10
+ * Returns null if no segments qualify for extraction,
11
+ * otherwise returns rewritten client code + chunk modules.
12
+ *
13
+ * Uses proper AST-based codegen with esrap — no source text splicing.
14
+ */
15
+ export function extractModule(analyzed, segments, _sourceCode, confidenceThreshold, sourceFilePath, lazyCandidates) {
16
+ const extractable = segments.filter((seg) => seg.classification === 'EventHandler' &&
17
+ seg.confidence >= confidenceThreshold);
18
+ const hasLazyTransforms = lazyCandidates && lazyCandidates.length > 0;
19
+ // Nothing to do if no handler extractions and no lazy transforms
20
+ if (extractable.length === 0 && !hasLazyTransforms)
21
+ return null;
22
+ // Deep-copy the full AST for client code mutation
23
+ const clientAST = structuredClone(analyzed.ast);
24
+ const chunkModules = [];
25
+ let extractedCount = 0;
26
+ for (const segment of extractable) {
27
+ // Find the AST node in the ORIGINAL tree (for chunk module generation)
28
+ const originalNode = findASTNode(analyzed.ast, segment.span);
29
+ if (!originalNode)
30
+ continue;
31
+ // Find the corresponding node in the CLONED tree (for client mutation)
32
+ const clientNode = findASTNode(clientAST, segment.span);
33
+ if (!clientNode)
34
+ continue;
35
+ // Separate captured vars from imports (rewrites relative paths to absolute)
36
+ const resolution = resolveImports(segment, analyzed, sourceFilePath);
37
+ // Generate the chunk module from the original (unmutated) AST
38
+ const chunkResult = generateChunkModule(segment, originalNode, resolution.imports, resolution.capturedParams, sourceFilePath, _sourceCode);
39
+ chunkModules.push({ id: segment.id, code: chunkResult.code, map: chunkResult.map });
40
+ // Mutate the client AST node — replace function body with lazy stub
41
+ replaceWithStub(clientNode, segment, resolution.capturedParams);
42
+ extractedCount++;
43
+ }
44
+ // Apply React.lazy + Suspense transforms (after handler extraction)
45
+ if (hasLazyTransforms) {
46
+ applyLazyTransforms(clientAST, lazyCandidates);
47
+ }
48
+ // Bail if neither handler extraction nor lazy transforms produced changes
49
+ if (extractedCount === 0 && !hasLazyTransforms)
50
+ return null;
51
+ // Prepend `import { __phantom_lazy } from 'phantom-build/runtime'` if handlers were extracted
52
+ if (extractedCount > 0) {
53
+ const lazyImport = {
54
+ type: 'ImportDeclaration',
55
+ specifiers: [{
56
+ type: 'ImportSpecifier',
57
+ imported: { type: 'Identifier', name: '__phantom_lazy' },
58
+ local: { type: 'Identifier', name: '__phantom_lazy' },
59
+ }],
60
+ source: { type: 'Literal', value: 'phantom-build/runtime' },
61
+ };
62
+ clientAST.body.unshift(lazyImport);
63
+ }
64
+ // Generate client code with esrap (including source map)
65
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any -- esrap tsx visitors expect TSESTree.Node, OXC produces compatible estree nodes
66
+ const result = print(clientAST, tsx(), {
67
+ sourceMapSource: sourceFilePath,
68
+ sourceMapContent: _sourceCode,
69
+ });
70
+ return { clientCode: result.code, clientMap: result.map, chunkModules };
71
+ }
72
+ // ── AST helpers ──────────────────────────────────────────────────────────
73
+ function findASTNode(root, span) {
74
+ let match = null;
75
+ walkNode(root, (node) => {
76
+ const n = node;
77
+ if (n.start !== span.start || n.end !== span.end)
78
+ return;
79
+ if (node.type === 'ArrowFunctionExpression' ||
80
+ node.type === 'FunctionExpression' ||
81
+ node.type === 'FunctionDeclaration') {
82
+ match = node;
83
+ }
84
+ });
85
+ return match;
86
+ }
87
+ function walkNode(node, callback) {
88
+ if (!node || typeof node !== 'object')
89
+ return;
90
+ if (Array.isArray(node)) {
91
+ for (const child of node)
92
+ walkNode(child, callback);
93
+ return;
94
+ }
95
+ const obj = node;
96
+ if (typeof obj.type !== 'string')
97
+ return;
98
+ callback(obj);
99
+ for (const key of Object.keys(obj)) {
100
+ if (key === 'type')
101
+ continue;
102
+ walkNode(obj[key], callback);
103
+ }
104
+ }
105
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/extract/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ import type { Program } from 'estree';
2
+ import type { LazyCandidate } from '../types.js';
3
+ /**
4
+ * Apply React.lazy + Suspense transforms to a cloned AST.
5
+ *
6
+ * Mutates the AST in place:
7
+ * 1. Rewrites component imports → React.lazy(() => import(...))
8
+ * 2. Wraps JSX usages in <Suspense fallback={null}>
9
+ * 3. Ensures `lazy` and `Suspense` are imported from 'react'
10
+ *
11
+ * Should be called on a structuredClone of the original AST.
12
+ */
13
+ export declare function applyLazyTransforms(ast: Program, candidates: LazyCandidate[]): void;
14
+ //# sourceMappingURL=lazy-transform.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lazy-transform.d.ts","sourceRoot":"","sources":["../../src/extract/lazy-transform.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,OAAO,EAYR,MAAM,QAAQ,CAAC;AAChB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAIjD;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,OAAO,EACZ,UAAU,EAAE,aAAa,EAAE,GAC1B,IAAI,CAiBN"}