zero-com 1.6.2 → 1.6.3
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 -1
- package/lib/common.d.ts +1 -0
- package/lib/common.js +37 -4
- package/lib/runtime.js +5 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Zero-com
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The ~85 Bytes utility for transparently communicating client and server in full-stack projects through compile-time code transformation, with end-to-end static type checking.
|
|
4
4
|
|
|
5
5
|
## Table of Contents
|
|
6
6
|
|
package/lib/common.d.ts
CHANGED
|
@@ -32,6 +32,7 @@ export declare const getImportedServerFunctions: (sourceFile: SourceFile, regist
|
|
|
32
32
|
export declare const transformCallSites: (sourceFile: SourceFile, importedFuncs: Map<string, ServerFuncInfo>) => boolean;
|
|
33
33
|
export declare const transformHandleCalls: (sourceFile: SourceFile) => boolean;
|
|
34
34
|
export declare const transformSendCalls: (sourceFile: SourceFile) => boolean;
|
|
35
|
+
export declare const transformFuncCalls: (sourceFile: SourceFile) => boolean;
|
|
35
36
|
export declare const appendRegistryCode: (sourceFile: SourceFile, fileRegistry: Map<string, ServerFuncInfo>) => string;
|
|
36
37
|
export type TransformResult = {
|
|
37
38
|
content: 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.transformSendCalls = exports.transformHandleCalls = exports.transformCallSites = exports.getImportedServerFunctions = exports.buildRegistry = exports.createProject = exports.resolveFilePath = exports.isFromLibrary = exports.getReplacements = exports.generateCompilationId = exports.formatFuncIdName = exports.FILE_EXTENSIONS = exports.LIBRARY_NAME = exports.CONTEXT_TYPE_NAME = exports.EXEC_FUNC_NAME = exports.CALL_NAME = exports.HANDLE_NAME = exports.SERVER_FUNCTION_WRAPPER_NAME = exports.ZERO_COM_SERVER_REGISTRY = exports.ZERO_COM_CLIENT_CALL = void 0;
|
|
6
|
+
exports.applyReplacements = exports.emitToJs = exports.transformSourceFile = exports.appendRegistryCode = exports.transformFuncCalls = exports.transformSendCalls = exports.transformHandleCalls = exports.transformCallSites = exports.getImportedServerFunctions = exports.buildRegistry = exports.createProject = exports.resolveFilePath = exports.isFromLibrary = exports.getReplacements = exports.generateCompilationId = exports.formatFuncIdName = exports.FILE_EXTENSIONS = exports.LIBRARY_NAME = exports.CONTEXT_TYPE_NAME = exports.EXEC_FUNC_NAME = exports.CALL_NAME = exports.HANDLE_NAME = exports.SERVER_FUNCTION_WRAPPER_NAME = 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 ts_morph_1 = require("ts-morph");
|
|
@@ -208,13 +208,40 @@ const transformSendCalls = (sourceFile) => {
|
|
|
208
208
|
return modified;
|
|
209
209
|
};
|
|
210
210
|
exports.transformSendCalls = transformSendCalls;
|
|
211
|
+
// Transform func(fn) calls to just fn.
|
|
212
|
+
// The func() wrapper is only needed for type-level transformation (RemoveContextParam).
|
|
213
|
+
// At runtime, we just need the raw function. The registration code (appendRegistryCode)
|
|
214
|
+
// will set requireContext on the function based on compile-time analysis.
|
|
215
|
+
const transformFuncCalls = (sourceFile) => {
|
|
216
|
+
let modified = false;
|
|
217
|
+
sourceFile.forEachDescendant((node) => {
|
|
218
|
+
if (node.getKind() !== ts_morph_1.SyntaxKind.CallExpression)
|
|
219
|
+
return;
|
|
220
|
+
const callExpr = node;
|
|
221
|
+
if (!(0, exports.isFromLibrary)(callExpr, exports.LIBRARY_NAME) || getCalleeName(callExpr) !== exports.SERVER_FUNCTION_WRAPPER_NAME)
|
|
222
|
+
return;
|
|
223
|
+
const args = callExpr.getArguments();
|
|
224
|
+
if (args.length !== 1)
|
|
225
|
+
return;
|
|
226
|
+
// Replace func(fn) with just fn
|
|
227
|
+
callExpr.replaceWithText(args[0].getText());
|
|
228
|
+
modified = true;
|
|
229
|
+
});
|
|
230
|
+
return modified;
|
|
231
|
+
};
|
|
232
|
+
exports.transformFuncCalls = transformFuncCalls;
|
|
211
233
|
const appendRegistryCode = (sourceFile, fileRegistry) => {
|
|
234
|
+
// Generate registration code for each server function.
|
|
235
|
+
// We set requireContext based on compile-time analysis of the function's first parameter type.
|
|
236
|
+
// If the first param is context<T>, requireContext = true, otherwise false.
|
|
237
|
+
// This allows execFunc() at runtime to know whether to inject the context as the first argument.
|
|
212
238
|
const registrations = Array.from(fileRegistry.values())
|
|
213
|
-
.map(info => `globalThis.${exports.ZERO_COM_SERVER_REGISTRY}['${info.funcId}'] = ${info.exportName}`
|
|
214
|
-
.
|
|
239
|
+
.map(info => `globalThis.${exports.ZERO_COM_SERVER_REGISTRY}['${info.funcId}'] = ${info.exportName};\n` +
|
|
240
|
+
`${info.exportName}.requireContext = ${info.requireContext};`)
|
|
241
|
+
.join('\n');
|
|
215
242
|
return `${sourceFile.getFullText()}
|
|
216
243
|
if (!globalThis.${exports.ZERO_COM_SERVER_REGISTRY}) globalThis.${exports.ZERO_COM_SERVER_REGISTRY} = Object.create(null);
|
|
217
|
-
${registrations}
|
|
244
|
+
${registrations}`;
|
|
218
245
|
};
|
|
219
246
|
exports.appendRegistryCode = appendRegistryCode;
|
|
220
247
|
// Helper to ensure a specific named import exists
|
|
@@ -262,6 +289,12 @@ const transformSourceFile = (filePath, content, registry) => {
|
|
|
262
289
|
const callsTransformed = (0, exports.transformCallSites)(sourceFile, importedFuncs);
|
|
263
290
|
const handleTransformed = (0, exports.transformHandleCalls)(sourceFile);
|
|
264
291
|
const sendTransformed = (0, exports.transformSendCalls)(sourceFile);
|
|
292
|
+
// Transform func() calls in files that define server functions.
|
|
293
|
+
// This strips the func() wrapper since it's only needed for types.
|
|
294
|
+
let funcTransformed = false;
|
|
295
|
+
if (isServerFunctionFile) {
|
|
296
|
+
funcTransformed = (0, exports.transformFuncCalls)(sourceFile);
|
|
297
|
+
}
|
|
265
298
|
if (handleTransformed) {
|
|
266
299
|
ensureImport(sourceFile, exports.LIBRARY_NAME, exports.EXEC_FUNC_NAME);
|
|
267
300
|
}
|
package/lib/runtime.js
CHANGED
|
@@ -3,9 +3,11 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.call = exports.handle = exports.execFunc = void 0;
|
|
4
4
|
exports.func = func;
|
|
5
5
|
// Implementation
|
|
6
|
-
function
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
// User-facing function - transformed by plugin to just the inner function.
|
|
7
|
+
// The plugin also appends code to register the function and set requireContext based on
|
|
8
|
+
// compile-time analysis of whether the first parameter is context<T>.
|
|
9
|
+
function func(_fn) {
|
|
10
|
+
throw new Error('func() was not transformed. Ensure the zero-com plugin is configured.');
|
|
9
11
|
}
|
|
10
12
|
// Internal implementation - receives the actual function from registry
|
|
11
13
|
const execFunc = (sfn, ctx, args) => {
|