zero-com 1.7.1 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/lib/common.d.ts +3 -0
- package/lib/common.js +12 -2
- package/lib/rollup.d.ts +3 -1
- package/lib/rollup.js +37 -3
- package/lib/turbopack-loader.d.ts +1 -0
- package/lib/turbopack-loader.js +6 -2
- package/lib/webpack-loader.d.ts +1 -0
- package/lib/webpack-loader.js +2 -1
- package/lib/webpack.js +6 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -217,6 +217,7 @@ When `getFullName` is called from the client:
|
|
|
217
217
|
| Option | Type | Description |
|
|
218
218
|
|-------------|-----------|-----------------------------------------------------------------------------|
|
|
219
219
|
| `development` | `boolean` | If `false`, will add internal variable renaming to the final bundle. |
|
|
220
|
+
| `target` | `'client' \| 'server'` | When `'client'`, server function files are replaced with lightweight RPC stubs containing no server dependencies. When `'server'`, full function bodies and registry code are preserved. When omitted, the Vite/Rollup plugin infers it from the `ssr` flag in the `transform` hook. |
|
|
220
221
|
|
|
221
222
|
## Complete Example
|
|
222
223
|
|
package/lib/common.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export type Replacement = {
|
|
|
7
7
|
};
|
|
8
8
|
export type Options = {
|
|
9
9
|
development?: boolean;
|
|
10
|
+
target?: 'client' | 'server';
|
|
10
11
|
};
|
|
11
12
|
export type ServerFuncInfo = {
|
|
12
13
|
funcId: string;
|
|
@@ -42,6 +43,7 @@ export declare const applyReplacementsWithMap: (source: string, replacements: Re
|
|
|
42
43
|
map: SourceMap;
|
|
43
44
|
};
|
|
44
45
|
export declare const appendRegistryCode: (sourceFile: SourceFile, fileRegistry: Map<string, ServerFuncInfo>) => string;
|
|
46
|
+
export declare const generateClientStubs: (fileRegistry: Map<string, ServerFuncInfo>) => string;
|
|
45
47
|
export type TransformResult = {
|
|
46
48
|
content: string;
|
|
47
49
|
transformed: boolean;
|
|
@@ -49,6 +51,7 @@ export type TransformResult = {
|
|
|
49
51
|
};
|
|
50
52
|
export type TransformOptions = {
|
|
51
53
|
development?: boolean;
|
|
54
|
+
target?: 'client' | 'server';
|
|
52
55
|
};
|
|
53
56
|
export declare const transformSourceFile: (filePath: string, content: string, registry: ServerFuncRegistry, options?: TransformOptions) => TransformResult;
|
|
54
57
|
export declare const emitToJs: (filePath: string, content: string) => string;
|
package/lib/common.js
CHANGED
|
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.applyReplacements = exports.emitToJs = exports.transformSourceFile = exports.appendRegistryCode = exports.applyReplacementsWithMap = exports.collectFuncCallReplacements = exports.collectSendCallReplacements = exports.collectHandleCallReplacements = exports.collectCallSiteReplacements = exports.getImportedServerFunctions = exports.buildRegistry = exports.createProject = exports.resolveFilePath = exports.isFromLibrary = exports.getReplacements = exports.generateCompilationId = exports.formatFuncIdName = exports.FILE_EXTENSIONS = exports.LIBRARY_NAME = exports.CALL_NAME = exports.HANDLE_NAME = exports.SERVER_FUNCTION_WRAPPER_NAME = exports.ZERO_COM_CONTEXT_STORAGE = exports.ZERO_COM_SERVER_REGISTRY = exports.ZERO_COM_CLIENT_CALL = void 0;
|
|
6
|
+
exports.applyReplacements = exports.emitToJs = exports.transformSourceFile = exports.generateClientStubs = exports.appendRegistryCode = exports.applyReplacementsWithMap = exports.collectFuncCallReplacements = exports.collectSendCallReplacements = exports.collectHandleCallReplacements = exports.collectCallSiteReplacements = exports.getImportedServerFunctions = exports.buildRegistry = exports.createProject = exports.resolveFilePath = exports.isFromLibrary = exports.getReplacements = exports.generateCompilationId = exports.formatFuncIdName = exports.FILE_EXTENSIONS = exports.LIBRARY_NAME = exports.CALL_NAME = exports.HANDLE_NAME = exports.SERVER_FUNCTION_WRAPPER_NAME = exports.ZERO_COM_CONTEXT_STORAGE = exports.ZERO_COM_SERVER_REGISTRY = exports.ZERO_COM_CLIENT_CALL = void 0;
|
|
7
7
|
const fs_1 = __importDefault(require("fs"));
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const magic_string_1 = __importDefault(require("magic-string"));
|
|
@@ -267,12 +267,22 @@ if (!globalThis.${exports.ZERO_COM_SERVER_REGISTRY}) globalThis.${exports.ZERO_C
|
|
|
267
267
|
${registrations}`;
|
|
268
268
|
};
|
|
269
269
|
exports.appendRegistryCode = appendRegistryCode;
|
|
270
|
+
const generateClientStubs = (fileRegistry) => {
|
|
271
|
+
const stubs = Array.from(fileRegistry.values())
|
|
272
|
+
.map(info => `export const ${info.exportName} = (...args) => globalThis.${exports.ZERO_COM_CLIENT_CALL}('${info.funcId}', args);`)
|
|
273
|
+
.join('\n');
|
|
274
|
+
return stubs;
|
|
275
|
+
};
|
|
276
|
+
exports.generateClientStubs = generateClientStubs;
|
|
270
277
|
const transformSourceFile = (filePath, content, registry, options = {}) => {
|
|
271
|
-
const { development = true } = options;
|
|
278
|
+
const { development = true, target } = options;
|
|
272
279
|
const project = (0, exports.createProject)();
|
|
273
280
|
const sourceFile = project.createSourceFile(filePath, content, { overwrite: true });
|
|
274
281
|
const fileRegistry = registry.get(filePath);
|
|
275
282
|
const isServerFunctionFile = fileRegistry && fileRegistry.size > 0;
|
|
283
|
+
if (target === 'client' && isServerFunctionFile) {
|
|
284
|
+
return { content: (0, exports.generateClientStubs)(fileRegistry), transformed: true };
|
|
285
|
+
}
|
|
276
286
|
const importedFuncs = (0, exports.getImportedServerFunctions)(sourceFile, registry);
|
|
277
287
|
// Don't transform calls to functions defined in the same file
|
|
278
288
|
if (isServerFunctionFile) {
|
package/lib/rollup.d.ts
CHANGED
package/lib/rollup.js
CHANGED
|
@@ -17,17 +17,30 @@ const fs_1 = __importDefault(require("fs"));
|
|
|
17
17
|
const path_1 = __importDefault(require("path"));
|
|
18
18
|
const common_1 = require("./common");
|
|
19
19
|
function zeroComRollupPlugin(options = {}) {
|
|
20
|
-
const { development = true } = options;
|
|
20
|
+
const { development = true, target } = options;
|
|
21
21
|
const compilationId = (0, common_1.generateCompilationId)();
|
|
22
22
|
const registry = new Map();
|
|
23
|
+
let isVite = false;
|
|
23
24
|
return {
|
|
24
25
|
name: 'zero-com-rollup-plugin',
|
|
26
|
+
// Vite-only hook — detect that we're running inside Vite
|
|
27
|
+
configResolved() {
|
|
28
|
+
isVite = true;
|
|
29
|
+
},
|
|
25
30
|
buildStart() {
|
|
26
31
|
(0, common_1.buildRegistry)(process.cwd(), registry);
|
|
27
|
-
|
|
32
|
+
for (const fileRegistry of registry.values()) {
|
|
33
|
+
for (const info of fileRegistry.values()) {
|
|
34
|
+
console.log(`[ZeroComRollupPlugin] ${info.funcId}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
28
37
|
},
|
|
38
|
+
// Rollup path: resolveId marks files, load transforms them.
|
|
39
|
+
// Skipped in Vite because meta doesn't propagate from resolveId to load.
|
|
29
40
|
resolveId(source, importer, opts) {
|
|
30
41
|
return __awaiter(this, void 0, void 0, function* () {
|
|
42
|
+
if (isVite)
|
|
43
|
+
return null;
|
|
31
44
|
if (!importer || (!source.startsWith('.') && !source.startsWith('/')))
|
|
32
45
|
return null;
|
|
33
46
|
const result = yield this.resolve(source, importer, Object.assign(Object.assign({}, opts), { skipSelf: true }));
|
|
@@ -43,16 +56,37 @@ function zeroComRollupPlugin(options = {}) {
|
|
|
43
56
|
},
|
|
44
57
|
load(id) {
|
|
45
58
|
var _a, _b, _c;
|
|
59
|
+
if (isVite)
|
|
60
|
+
return null;
|
|
46
61
|
if (!((_b = (_a = this.getModuleInfo(id)) === null || _a === void 0 ? void 0 : _a.meta) === null || _b === void 0 ? void 0 : _b.needsTransform) || !fs_1.default.existsSync(id))
|
|
47
62
|
return null;
|
|
48
63
|
const content = fs_1.default.readFileSync(id, 'utf8');
|
|
49
|
-
const result = (0, common_1.transformSourceFile)(id, content, registry, { development });
|
|
64
|
+
const result = (0, common_1.transformSourceFile)(id, content, registry, { development, target });
|
|
50
65
|
if (!result.transformed)
|
|
51
66
|
return null;
|
|
52
67
|
console.log(`[ZeroComRollupPlugin] Transformed: ${path_1.default.relative(process.cwd(), id)}`);
|
|
53
68
|
const code = (0, common_1.emitToJs)(id, result.content);
|
|
54
69
|
return { code, map: (_c = result.map) !== null && _c !== void 0 ? _c : null };
|
|
55
70
|
},
|
|
71
|
+
// Vite path: transform hook works reliably (no cross-hook meta needed).
|
|
72
|
+
// Returns transformed TypeScript — Vite's esbuild handles TS→JS.
|
|
73
|
+
transform(code, id, viteOptions) {
|
|
74
|
+
var _a;
|
|
75
|
+
if (!isVite)
|
|
76
|
+
return null;
|
|
77
|
+
if (id.includes('node_modules') || !/\.(ts|tsx|js|jsx|mjs)$/.test(id))
|
|
78
|
+
return null;
|
|
79
|
+
// Derive effective target: explicit option takes precedence, otherwise infer from Vite's ssr flag
|
|
80
|
+
const ssr = typeof viteOptions === 'object' && viteOptions !== null && 'ssr' in viteOptions
|
|
81
|
+
? viteOptions.ssr
|
|
82
|
+
: undefined;
|
|
83
|
+
const effectiveTarget = target !== null && target !== void 0 ? target : (ssr === false ? 'client' : ssr === true ? 'server' : undefined);
|
|
84
|
+
const result = (0, common_1.transformSourceFile)(id, code, registry, { development, target: effectiveTarget });
|
|
85
|
+
if (!result.transformed)
|
|
86
|
+
return null;
|
|
87
|
+
console.log(`[ZeroComRollupPlugin] Transformed: ${path_1.default.relative(process.cwd(), id)}`);
|
|
88
|
+
return { code: result.content, map: (_a = result.map) !== null && _a !== void 0 ? _a : null };
|
|
89
|
+
},
|
|
56
90
|
renderChunk(code) {
|
|
57
91
|
if (development)
|
|
58
92
|
return null;
|
|
@@ -2,5 +2,6 @@ import type { LoaderContext } from 'webpack';
|
|
|
2
2
|
export interface TurbopackLoaderOptions {
|
|
3
3
|
development?: boolean;
|
|
4
4
|
rootDir?: string;
|
|
5
|
+
target?: 'client' | 'server';
|
|
5
6
|
}
|
|
6
7
|
export default function turbopackLoader(this: LoaderContext<TurbopackLoaderOptions>, source: string): void;
|
package/lib/turbopack-loader.js
CHANGED
|
@@ -20,9 +20,13 @@ function turbopackLoader(source) {
|
|
|
20
20
|
cachedRegistry = new Map();
|
|
21
21
|
cachedRootDir = rootDir;
|
|
22
22
|
(0, common_1.buildRegistry)(rootDir, cachedRegistry);
|
|
23
|
-
|
|
23
|
+
for (const fileRegistry of cachedRegistry.values()) {
|
|
24
|
+
for (const info of fileRegistry.values()) {
|
|
25
|
+
console.log(`[TurbopackLoader] ${info.funcId}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
24
28
|
}
|
|
25
|
-
const result = (0, common_1.transformSourceFile)(filePath, source, cachedRegistry, { development });
|
|
29
|
+
const result = (0, common_1.transformSourceFile)(filePath, source, cachedRegistry, { development, target: options.target });
|
|
26
30
|
if (!result.transformed) {
|
|
27
31
|
this.callback(null, source);
|
|
28
32
|
return;
|
package/lib/webpack-loader.d.ts
CHANGED
|
@@ -3,5 +3,6 @@ import { ServerFuncRegistry } from './common';
|
|
|
3
3
|
export interface ZeroComLoaderOptions {
|
|
4
4
|
registry: ServerFuncRegistry;
|
|
5
5
|
development: boolean;
|
|
6
|
+
target?: 'client' | 'server';
|
|
6
7
|
}
|
|
7
8
|
export default function zeroComLoader(this: LoaderContext<ZeroComLoaderOptions>, source: string): void;
|
package/lib/webpack-loader.js
CHANGED
|
@@ -10,7 +10,8 @@ function zeroComLoader(source) {
|
|
|
10
10
|
const options = this.getOptions();
|
|
11
11
|
const filePath = this.resourcePath;
|
|
12
12
|
const result = (0, common_1.transformSourceFile)(filePath, source, options.registry, {
|
|
13
|
-
development: options.development
|
|
13
|
+
development: options.development,
|
|
14
|
+
target: options.target
|
|
14
15
|
});
|
|
15
16
|
if (!result.transformed) {
|
|
16
17
|
this.callback(null, source);
|
package/lib/webpack.js
CHANGED
|
@@ -14,7 +14,11 @@ class ZeroComWebpackPlugin {
|
|
|
14
14
|
// Build registry before compilation
|
|
15
15
|
compiler.hooks.beforeCompile.tap(pluginName, () => {
|
|
16
16
|
(0, common_1.buildRegistry)(compiler.context, this.registry);
|
|
17
|
-
|
|
17
|
+
for (const fileRegistry of this.registry.values()) {
|
|
18
|
+
for (const info of fileRegistry.values()) {
|
|
19
|
+
console.log(`[ZeroComWebpackPlugin] ${info.funcId}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
18
22
|
});
|
|
19
23
|
// Add loader rule for TypeScript/JavaScript files
|
|
20
24
|
const loaderPath = require.resolve('./webpack-loader');
|
|
@@ -24,7 +28,7 @@ class ZeroComWebpackPlugin {
|
|
|
24
28
|
enforce: 'pre',
|
|
25
29
|
use: [{
|
|
26
30
|
loader: loaderPath,
|
|
27
|
-
options: { registry: this.registry, development: this.options.development }
|
|
31
|
+
options: { registry: this.registry, development: this.options.development, target: this.options.target }
|
|
28
32
|
}]
|
|
29
33
|
};
|
|
30
34
|
compiler.options.module.rules.unshift(loaderRule);
|