UNPKG

seia.js

Version:

Lightweight SSR framework for React Server Components

165 lines (164 loc) 5.51 kB
import { relative } from 'node:path'; import { generate } from 'astring'; import sum from 'hash-sum'; import { name } from '../package.js'; import { changeExtension } from '../utils-path.js'; import { isObject } from '../utils.js'; export const injectClient = ({ clientBoundaries, config })=>{ return { name: 'seia:inject-client', resolveId (source) { if (source.endsWith('\0client.js')) return { id: '\0client.js', moduleSideEffects: true }; }, load (id) { if (id === '\0client.js') { const rawAst = injectManifest(clientBoundaries.map((path)=>[ '_' + sum(path), path ]), config); const ast = injectSpan(rawAst); // TODO: well... sourcemap issue again. const code = generate(ast); return { code }; } } }; }; const dummySpan = { start: 0, end: 0 }; const s = (v)=>({ ...v, ...dummySpan }); const injectSpan = (node)=>{ if (Array.isArray(node)) return node.map(injectSpan); if (isObject(node)) { for(const key in node){ if (!Object.hasOwn(node, key)) continue; const value = node[key]; node[key] = injectSpan(value); } return s(node); } return node; }; const injectManifest = (manifestArray, { paths: { src } })=>({ type: 'Program', sourceType: 'module', body: [ { type: 'ImportDeclaration', specifiers: [ { type: 'ImportSpecifier', local: { type: 'Identifier', name: 'initClientModuleMap' }, imported: { type: 'Identifier', name: 'initClientModuleMap' } }, { type: 'ImportSpecifier', local: { type: 'Identifier', name: 'run' }, imported: { type: 'Identifier', name: 'run' } } ], source: { type: 'Literal', value: `${name}/client` } }, ...manifestArray.map(([id, path])=>({ type: 'ImportDeclaration', specifiers: [ { type: 'ImportNamespaceSpecifier', local: { type: 'Identifier', name: id } } ], source: { type: 'Literal', value: path } })), { type: 'VariableDeclaration', declarations: [ { type: 'VariableDeclarator', id: { type: 'Identifier', name: 'clientModuleMap' }, init: { type: 'ObjectExpression', properties: manifestArray.map(([id, path])=>({ type: 'Property', key: { type: 'Literal', value: './' + changeExtension(relative(src, path), '.js') }, value: { type: 'Identifier', name: id }, kind: 'init', method: false, shorthand: false, computed: false })) } } ], kind: 'const' }, { type: 'ExpressionStatement', expression: { type: 'CallExpression', callee: { type: 'Identifier', name: 'initClientModuleMap' }, arguments: [ { type: 'Identifier', name: 'clientModuleMap' } ], optional: false } }, { type: 'ExpressionStatement', expression: { type: 'CallExpression', callee: { type: 'Identifier', name: 'run' }, arguments: [], optional: false } } ] });