zero-com 1.12.2 → 1.13.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 +33 -1
- package/lib/common.d.ts +2 -0
- package/lib/common.js +28 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -212,6 +212,37 @@ When `getFullName` is called from the client:
|
|
|
212
212
|
4. `getFirstName` executes directly (no transport) with the same context
|
|
213
213
|
5. Both functions can access `context()` with the same data
|
|
214
214
|
|
|
215
|
+
## File boundary rule
|
|
216
|
+
|
|
217
|
+
Any file that contains `func()` exports is treated as a **server-only module**. On the client build the plugin replaces the **entire file** with lightweight RPC stubs — only the `func()` exports survive, everything else in that file is discarded.
|
|
218
|
+
|
|
219
|
+
This means you must not mix `func()` declarations with client-side code (state, UI utilities, etc.) in the same file. The pattern is the same as Next.js `"use server"` files: one side of the boundary per file.
|
|
220
|
+
|
|
221
|
+
**Wrong** — `connect` will be `undefined` on the client because the whole file is replaced:
|
|
222
|
+
|
|
223
|
+
```ts
|
|
224
|
+
// store.ts ❌
|
|
225
|
+
import { func } from 'zero-com'
|
|
226
|
+
import { createStore } from './create-store'
|
|
227
|
+
|
|
228
|
+
export const { connect, useStore } = createStore(...) // lost on client
|
|
229
|
+
|
|
230
|
+
export const getPhones = func(async () => { ... })
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Right** — separate the RPC calls from client state:
|
|
234
|
+
|
|
235
|
+
```ts
|
|
236
|
+
// funcs.ts ✅ (replaced with stubs on client)
|
|
237
|
+
import { func } from 'zero-com'
|
|
238
|
+
export const getPhones = func(async () => { ... })
|
|
239
|
+
|
|
240
|
+
// store.ts ✅ (untouched on client)
|
|
241
|
+
import { createStore } from './create-store'
|
|
242
|
+
export const { connect, useStore } = createStore(...)
|
|
243
|
+
export * from './funcs'
|
|
244
|
+
```
|
|
245
|
+
|
|
215
246
|
## Plugin options
|
|
216
247
|
|
|
217
248
|
| Option | Type | Description |
|
|
@@ -301,7 +332,8 @@ export const getPhones = func(async (name: string) => {
|
|
|
301
332
|
// server.ts
|
|
302
333
|
import express from 'express';
|
|
303
334
|
import { handle } from 'zero-com';
|
|
304
|
-
|
|
335
|
+
// No manual imports needed — the plugin automatically registers all func() files
|
|
336
|
+
// when it transforms any file that calls handle()
|
|
305
337
|
|
|
306
338
|
const app = express();
|
|
307
339
|
app.use(express.json());
|
package/lib/common.d.ts
CHANGED
|
@@ -38,6 +38,8 @@ export declare const buildRegistry: (contextDir: string, registry: ServerFuncReg
|
|
|
38
38
|
export declare const updateRegistryForFile: (filePath: string, contextDir: string, registry: ServerFuncRegistry, project?: Project) => void;
|
|
39
39
|
export declare const getImportedServerFunctions: (sourceFile: SourceFile, registry: ServerFuncRegistry) => Map<string, ServerFuncInfo>;
|
|
40
40
|
export declare const collectCallSiteReplacements: (sourceFile: SourceFile, importedFuncs: Map<string, ServerFuncInfo>) => Replacement[];
|
|
41
|
+
export declare const hasHandleCall: (sourceFile: SourceFile) => boolean;
|
|
42
|
+
export declare const generateRegistryRequires: (registry: ServerFuncRegistry) => string;
|
|
41
43
|
export declare const collectHandleCallReplacements: (sourceFile: SourceFile) => Replacement[];
|
|
42
44
|
export declare const collectSendCallReplacements: (sourceFile: SourceFile) => Replacement[];
|
|
43
45
|
export declare const collectFuncCallReplacements: (sourceFile: SourceFile) => Replacement[];
|
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.generateClientStubs = exports.appendRegistryCode = exports.applyReplacementsWithMap = exports.collectFuncCallReplacements = exports.collectSendCallReplacements = exports.collectHandleCallReplacements = exports.collectCallSiteReplacements = exports.getImportedServerFunctions = exports.updateRegistryForFile = exports.buildRegistry = exports.mightNeedTransform = 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.generateRegistryRequires = exports.hasHandleCall = exports.collectCallSiteReplacements = exports.getImportedServerFunctions = exports.updateRegistryForFile = exports.buildRegistry = exports.mightNeedTransform = 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"));
|
|
@@ -213,6 +213,27 @@ const collectCallSiteReplacements = (sourceFile, importedFuncs) => {
|
|
|
213
213
|
return replacements;
|
|
214
214
|
};
|
|
215
215
|
exports.collectCallSiteReplacements = collectCallSiteReplacements;
|
|
216
|
+
const hasHandleCall = (sourceFile) => {
|
|
217
|
+
let found = false;
|
|
218
|
+
sourceFile.forEachDescendant((node) => {
|
|
219
|
+
if (found)
|
|
220
|
+
return;
|
|
221
|
+
if (node.getKind() !== ts_morph_1.SyntaxKind.CallExpression)
|
|
222
|
+
return;
|
|
223
|
+
const callExpr = node;
|
|
224
|
+
if ((0, exports.isFromLibrary)(callExpr, exports.LIBRARY_NAME) && getCalleeName(callExpr) === exports.HANDLE_NAME) {
|
|
225
|
+
found = true;
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
return found;
|
|
229
|
+
};
|
|
230
|
+
exports.hasHandleCall = hasHandleCall;
|
|
231
|
+
const generateRegistryRequires = (registry) => {
|
|
232
|
+
return Array.from(registry.keys())
|
|
233
|
+
.map(fp => `require(${JSON.stringify(fp)});`)
|
|
234
|
+
.join('\n');
|
|
235
|
+
};
|
|
236
|
+
exports.generateRegistryRequires = generateRegistryRequires;
|
|
216
237
|
const collectHandleCallReplacements = (sourceFile) => {
|
|
217
238
|
const replacements = [];
|
|
218
239
|
sourceFile.forEachDescendant((node) => {
|
|
@@ -352,9 +373,14 @@ const transformSourceFile = (filePath, content, registry, options = {}, project)
|
|
|
352
373
|
}
|
|
353
374
|
return { content: (0, exports.appendRegistryCode)(sourceFile, fileRegistry), transformed: true };
|
|
354
375
|
}
|
|
376
|
+
const isHandleFile = target === 'server' && (0, exports.hasHandleCall)(sourceFile);
|
|
355
377
|
if (replacements.length > 0) {
|
|
356
378
|
const { code, map } = (0, exports.applyReplacementsWithMap)(content, replacements, filePath);
|
|
357
|
-
|
|
379
|
+
const finalContent = isHandleFile ? (0, exports.generateRegistryRequires)(registry) + '\n' + code : code;
|
|
380
|
+
return { content: finalContent, transformed: true, map };
|
|
381
|
+
}
|
|
382
|
+
if (isHandleFile) {
|
|
383
|
+
return { content: (0, exports.generateRegistryRequires)(registry) + '\n' + content, transformed: true };
|
|
358
384
|
}
|
|
359
385
|
return { content, transformed: false };
|
|
360
386
|
};
|