zero-com 1.13.1 → 1.13.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 +34 -0
- package/lib/runtime.d.ts +1 -0
- package/lib/runtime.js +19 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -212,6 +212,40 @@ 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
|
+
## Calling server functions outside handle()
|
|
216
|
+
|
|
217
|
+
Server functions can be called from any server-side code, not only through the RPC path. This is useful for server-side-only integrations like authentication callbacks, cron jobs, or webhook handlers.
|
|
218
|
+
|
|
219
|
+
```typescript
|
|
220
|
+
// pages/api/auth/[...nextauth].ts (Next.js example)
|
|
221
|
+
import { getUserByCredentials } from '../../../server/auth/funcs'
|
|
222
|
+
|
|
223
|
+
const user = await getUserByCredentials(email, password)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
When called outside `handle()`, the function executes directly with no context. If the function calls `context()` internally, it throws:
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
Error: context() called outside of a server function
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
Use `runWithContext` to provide a context in those cases:
|
|
233
|
+
|
|
234
|
+
```typescript
|
|
235
|
+
import { runWithContext } from 'zero-com'
|
|
236
|
+
|
|
237
|
+
const authorize = async (credentials) => {
|
|
238
|
+
return runWithContext({}, async () => {
|
|
239
|
+
const user = await getUserByCredentials(credentials.email, credentials.password)
|
|
240
|
+
return user ?? null
|
|
241
|
+
})
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
`runWithContext` accepts any object as the context value, which will be returned by `context()` inside any server function called within the callback.
|
|
246
|
+
|
|
247
|
+
When called inside `handle()`, context is propagated automatically to the function and any nested `func()` calls, same as the normal RPC path.
|
|
248
|
+
|
|
215
249
|
## File boundary rule
|
|
216
250
|
|
|
217
251
|
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.
|
package/lib/runtime.d.ts
CHANGED
|
@@ -11,4 +11,5 @@ declare global {
|
|
|
11
11
|
export declare function context<T = unknown>(): T;
|
|
12
12
|
export declare function func<F extends (...args: any[]) => any>(fn: F): F;
|
|
13
13
|
export declare const handle: (funcId: string, ctx: any, args: any[]) => any;
|
|
14
|
+
export declare const runWithContext: <T>(ctx: any, fn: () => T) => T;
|
|
14
15
|
export declare const call: (fn: (funcId: string, args: any[]) => any) => void;
|
package/lib/runtime.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.call = exports.handle = void 0;
|
|
3
|
+
exports.call = exports.runWithContext = exports.handle = void 0;
|
|
4
4
|
exports.context = context;
|
|
5
5
|
exports.func = func;
|
|
6
6
|
// Context storage - only available on server (Node.js)
|
|
@@ -36,7 +36,11 @@ function context() {
|
|
|
36
36
|
return ctx;
|
|
37
37
|
}
|
|
38
38
|
// Default server-side implementation: call directly from registry
|
|
39
|
-
// This enables server functions to call other server functions without transport
|
|
39
|
+
// This enables server functions to call other server functions without transport.
|
|
40
|
+
// If a request context exists (set by handle()), it is propagated automatically.
|
|
41
|
+
// If there is no context (e.g. called from NextAuth or other server-only code that
|
|
42
|
+
// does not go through handle()), the function is called directly — context() will
|
|
43
|
+
// throw inside the function only if the function actually tries to use it.
|
|
40
44
|
if (typeof globalThis.ZERO_COM_CLIENT_CALL === 'undefined') {
|
|
41
45
|
globalThis.ZERO_COM_CLIENT_CALL = (funcId, args) => {
|
|
42
46
|
var _a;
|
|
@@ -44,13 +48,13 @@ if (typeof globalThis.ZERO_COM_CLIENT_CALL === 'undefined') {
|
|
|
44
48
|
if (!storage) {
|
|
45
49
|
throw new Error('Server function called on client without transport configured. Call call() first.');
|
|
46
50
|
}
|
|
47
|
-
const ctx = storage.getStore();
|
|
48
|
-
if (ctx === undefined) {
|
|
49
|
-
throw new Error('Server function called outside of request context');
|
|
50
|
-
}
|
|
51
51
|
const fn = (_a = globalThis.ZERO_COM_SERVER_REGISTRY) === null || _a === void 0 ? void 0 : _a[funcId];
|
|
52
52
|
if (!fn)
|
|
53
53
|
throw new Error(`Function not found: ${funcId}`);
|
|
54
|
+
const ctx = storage.getStore();
|
|
55
|
+
if (ctx !== undefined) {
|
|
56
|
+
return storage.run(ctx, () => fn(...args));
|
|
57
|
+
}
|
|
54
58
|
return fn(...args);
|
|
55
59
|
};
|
|
56
60
|
}
|
|
@@ -74,6 +78,15 @@ const handle = (funcId, ctx, args) => {
|
|
|
74
78
|
return storage.run(ctx, () => fn(...args));
|
|
75
79
|
};
|
|
76
80
|
exports.handle = handle;
|
|
81
|
+
// Run a callback within a context, making context() available inside it.
|
|
82
|
+
// Use this in server-only code that does not go through handle() (e.g. auth callbacks).
|
|
83
|
+
const runWithContext = (ctx, fn) => {
|
|
84
|
+
const storage = getContextStorage();
|
|
85
|
+
if (!storage)
|
|
86
|
+
throw new Error('runWithContext() is only available on the server');
|
|
87
|
+
return storage.run(ctx, fn);
|
|
88
|
+
};
|
|
89
|
+
exports.runWithContext = runWithContext;
|
|
77
90
|
// Client calls this to set up transport (overrides default server-side behavior)
|
|
78
91
|
// In production mode: transformed by plugin to assignment
|
|
79
92
|
const call = (fn) => {
|