spiceflow 0.0.7 → 1.0.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 -171
- package/dist/client/errors.d.ts +7 -0
- package/dist/client/errors.d.ts.map +1 -0
- package/dist/client/errors.js +18 -0
- package/dist/client/errors.js.map +1 -0
- package/dist/client/index.d.ts +15 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +376 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/types.d.ts +87 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +2 -0
- package/dist/client/types.js.map +1 -0
- package/dist/client/utils.d.ts +2 -0
- package/dist/client/utils.d.ts.map +1 -0
- package/dist/client/utils.js +9 -0
- package/dist/client/utils.js.map +1 -0
- package/dist/client/ws.d.ts +15 -0
- package/dist/client/ws.d.ts.map +1 -0
- package/dist/client/ws.js +51 -0
- package/dist/client/ws.js.map +1 -0
- package/dist/client.test.d.ts +2 -0
- package/dist/client.test.d.ts.map +1 -0
- package/dist/client.test.js +237 -0
- package/dist/client.test.js.map +1 -0
- package/dist/elysia-fork/context.d.ts +87 -0
- package/dist/elysia-fork/context.d.ts.map +1 -0
- package/dist/elysia-fork/context.js +2 -0
- package/dist/elysia-fork/context.js.map +1 -0
- package/dist/elysia-fork/error.d.ts +246 -0
- package/dist/elysia-fork/error.d.ts.map +1 -0
- package/dist/elysia-fork/error.js +195 -0
- package/dist/elysia-fork/error.js.map +1 -0
- package/dist/elysia-fork/types.d.ts +570 -0
- package/dist/elysia-fork/types.d.ts.map +1 -0
- package/dist/elysia-fork/types.js +3 -0
- package/dist/elysia-fork/types.js.map +1 -0
- package/dist/elysia-fork/utils.d.ts +134 -0
- package/dist/elysia-fork/utils.d.ts.map +1 -0
- package/dist/elysia-fork/utils.js +70 -0
- package/dist/elysia-fork/utils.js.map +1 -0
- package/dist/index.d.ts +2 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -22
- package/dist/index.js.map +1 -1
- package/dist/spiceflow.d.ts +237 -0
- package/dist/spiceflow.d.ts.map +1 -0
- package/dist/spiceflow.js +484 -0
- package/dist/spiceflow.js.map +1 -0
- package/dist/spiceflow.test.d.ts +2 -0
- package/dist/spiceflow.test.d.ts.map +1 -0
- package/dist/spiceflow.test.js +225 -0
- package/dist/spiceflow.test.js.map +1 -0
- package/dist/stream.test.d.ts +2 -0
- package/dist/stream.test.d.ts.map +1 -0
- package/dist/stream.test.js +286 -0
- package/dist/stream.test.js.map +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +4 -20
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +17 -46
- package/dist/utils.js.map +1 -1
- package/package.json +12 -37
- package/src/client/errors.ts +21 -0
- package/src/client/index.ts +541 -0
- package/src/client/types.ts +233 -0
- package/src/client/utils.ts +7 -0
- package/src/client/ws.ts +99 -0
- package/src/client.test.ts +235 -0
- package/src/elysia-fork/context.ts +196 -0
- package/src/elysia-fork/error.ts +293 -0
- package/src/elysia-fork/types.ts +1353 -0
- package/src/elysia-fork/utils.ts +85 -0
- package/src/index.ts +2 -34
- package/src/spiceflow.test.ts +290 -0
- package/src/spiceflow.ts +1251 -0
- package/src/stream.test.ts +342 -0
- package/src/types.ts +0 -0
- package/src/utils.ts +21 -70
- package/context.d.ts +0 -2
- package/context.js +0 -1
- package/dist/babel.test.d.ts +0 -2
- package/dist/babel.test.d.ts.map +0 -1
- package/dist/babel.test.js +0 -27
- package/dist/babel.test.js.map +0 -1
- package/dist/babelDebugOutputs.d.ts +0 -9
- package/dist/babelDebugOutputs.d.ts.map +0 -1
- package/dist/babelDebugOutputs.js +0 -34
- package/dist/babelDebugOutputs.js.map +0 -1
- package/dist/babelTransformRpc.d.ts +0 -19
- package/dist/babelTransformRpc.d.ts.map +0 -1
- package/dist/babelTransformRpc.js +0 -285
- package/dist/babelTransformRpc.js.map +0 -1
- package/dist/browser.d.ts +0 -8
- package/dist/browser.d.ts.map +0 -1
- package/dist/browser.js +0 -126
- package/dist/browser.js.map +0 -1
- package/dist/build.d.ts +0 -13
- package/dist/build.d.ts.map +0 -1
- package/dist/build.js +0 -230
- package/dist/build.js.map +0 -1
- package/dist/cli.d.ts +0 -3
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -111
- package/dist/cli.js.map +0 -1
- package/dist/context-internal.d.ts +0 -20
- package/dist/context-internal.d.ts.map +0 -1
- package/dist/context-internal.js +0 -16
- package/dist/context-internal.js.map +0 -1
- package/dist/context.d.ts +0 -2
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js +0 -2
- package/dist/context.js.map +0 -1
- package/dist/expose.d.ts +0 -6
- package/dist/expose.d.ts.map +0 -1
- package/dist/expose.js +0 -32
- package/dist/expose.js.map +0 -1
- package/dist/headers.d.ts +0 -2
- package/dist/headers.d.ts.map +0 -1
- package/dist/headers.js +0 -18
- package/dist/headers.js.map +0 -1
- package/dist/jsonRpc.d.ts +0 -32
- package/dist/jsonRpc.d.ts.map +0 -1
- package/dist/jsonRpc.js +0 -3
- package/dist/jsonRpc.js.map +0 -1
- package/dist/server.d.ts +0 -32
- package/dist/server.d.ts.map +0 -1
- package/dist/server.js +0 -292
- package/dist/server.js.map +0 -1
- package/headers.d.ts +0 -2
- package/headers.js +0 -1
- package/sdk-template/package.json +0 -22
- package/sdk-template/src/index.ts +0 -2
- package/sdk-template/src/v1/example.ts +0 -5
- package/sdk-template/src/v1/generator.ts +0 -12
- package/sdk-template/tsconfig.json +0 -16
- package/src/babel.test.ts +0 -35
- package/src/babelDebugOutputs.ts +0 -56
- package/src/babelTransformRpc.ts +0 -394
- package/src/browser.ts +0 -141
- package/src/build.ts +0 -298
- package/src/cli.ts +0 -132
- package/src/context-internal.ts +0 -36
- package/src/context.ts +0 -5
- package/src/expose.ts +0 -34
- package/src/headers.ts +0 -19
- package/src/jsonRpc.ts +0 -43
- package/src/server.ts +0 -384
package/src/babelTransformRpc.ts
DELETED
|
@@ -1,394 +0,0 @@
|
|
|
1
|
-
import * as babel from '@babel/core';
|
|
2
|
-
import generate from '@babel/generator';
|
|
3
|
-
import { parse, parseExpression } from '@babel/parser';
|
|
4
|
-
import type * as types from '@babel/types';
|
|
5
|
-
import fs from 'fs';
|
|
6
|
-
import path from 'path';
|
|
7
|
-
import { WrapMethodMeta } from './server.js';
|
|
8
|
-
import { annotateAsPure, directive, logger, removeExtension } from './utils.js';
|
|
9
|
-
|
|
10
|
-
type Babel = { types: typeof types };
|
|
11
|
-
|
|
12
|
-
function isAllowedTsExportDeclaration(
|
|
13
|
-
declaration: babel.NodePath<babel.types.Declaration | null | undefined>,
|
|
14
|
-
): boolean {
|
|
15
|
-
return (
|
|
16
|
-
declaration.isTSTypeAliasDeclaration() ||
|
|
17
|
-
declaration.isTSInterfaceDeclaration()
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const allowedExports = new Set([
|
|
22
|
-
'revalidate', //
|
|
23
|
-
'preferredRegion',
|
|
24
|
-
'runtime',
|
|
25
|
-
'maxDuration',
|
|
26
|
-
'fetchCache',
|
|
27
|
-
'dynamic',
|
|
28
|
-
'dynamicParams',
|
|
29
|
-
'GET',
|
|
30
|
-
'HEAD',
|
|
31
|
-
]);
|
|
32
|
-
|
|
33
|
-
function getConfigObjectExpression(
|
|
34
|
-
variable: babel.NodePath<babel.types.VariableDeclarator>,
|
|
35
|
-
) {
|
|
36
|
-
const identifier = variable.get('id');
|
|
37
|
-
const init = variable.get('init');
|
|
38
|
-
if (
|
|
39
|
-
identifier.isIdentifier() &&
|
|
40
|
-
identifier.node.name === 'config' &&
|
|
41
|
-
init.isObjectExpression()
|
|
42
|
-
) {
|
|
43
|
-
const isEdge = isEdgeInConfig(init);
|
|
44
|
-
return {
|
|
45
|
-
isEdge,
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
if (identifier.isIdentifier() && identifier.node.name === 'runtime') {
|
|
49
|
-
const isEdge = init.isStringLiteral({ value: 'edge' });
|
|
50
|
-
return {
|
|
51
|
-
isEdge,
|
|
52
|
-
};
|
|
53
|
-
}
|
|
54
|
-
return null;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export function getConfigObject(program: babel.NodePath<babel.types.Program>) {
|
|
58
|
-
for (const statement of program.get('body')) {
|
|
59
|
-
if (statement.isExportNamedDeclaration()) {
|
|
60
|
-
const declaration = statement.get('declaration');
|
|
61
|
-
if (declaration.isVariableDeclaration()) {
|
|
62
|
-
for (const variable of declaration.get('declarations')) {
|
|
63
|
-
const configObject = getConfigObjectExpression(variable);
|
|
64
|
-
if (configObject) {
|
|
65
|
-
return configObject;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
return;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
function isServerAction(program: babel.NodePath<babel.types.Program>): boolean {
|
|
75
|
-
const dir = program.node.directives?.find(
|
|
76
|
-
(x) => x.value?.value === directive,
|
|
77
|
-
);
|
|
78
|
-
return !!dir;
|
|
79
|
-
// https://regex101.com/r/Wm6UvV/1
|
|
80
|
-
// return /^("|')poor man's use server("|')(;?)\n/m.test(code);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
function hasWrapMethod(program: babel.NodePath<babel.types.Program>) {
|
|
84
|
-
// check if there is a function export called wrapMethod
|
|
85
|
-
for (const statement of program.get('body')) {
|
|
86
|
-
// also check the export { wrapMethod }
|
|
87
|
-
if (statement.isExportNamedDeclaration()) {
|
|
88
|
-
for (const specifier of statement.get('specifiers')) {
|
|
89
|
-
if (
|
|
90
|
-
specifier.node.exported.type === 'Identifier' &&
|
|
91
|
-
specifier.node.exported.name === 'wrapMethod'
|
|
92
|
-
) {
|
|
93
|
-
return true;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
if (statement.isExportNamedDeclaration()) {
|
|
98
|
-
const declaration = statement.get('declaration');
|
|
99
|
-
if (declaration.isFunctionDeclaration()) {
|
|
100
|
-
const identifier = declaration.get('id');
|
|
101
|
-
if (identifier.node?.name === 'wrapMethod') {
|
|
102
|
-
return true;
|
|
103
|
-
}
|
|
104
|
-
} else if (declaration.isVariableDeclaration()) {
|
|
105
|
-
for (const variable of declaration.get('declarations')) {
|
|
106
|
-
const id = variable.get('id');
|
|
107
|
-
if (id.isIdentifier() && id.node.name === 'wrapMethod') {
|
|
108
|
-
return true;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// return (
|
|
116
|
-
// /export\s+function\s+wrapMethod\s*\(/m.test(code) ||
|
|
117
|
-
// /export\s+(let|const)\s+wrapMethod\s*/m.test(code) ||
|
|
118
|
-
// // https://regex101.com/r/nRaEVs/1
|
|
119
|
-
// /export\s+\{[^}]*wrapMethod/m.test(code)
|
|
120
|
-
// );
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export function isEdgeInConfig(
|
|
124
|
-
configObject?: babel.NodePath<babel.types.ObjectExpression>,
|
|
125
|
-
): boolean {
|
|
126
|
-
if (!configObject) {
|
|
127
|
-
return false;
|
|
128
|
-
}
|
|
129
|
-
for (const property of configObject.get('properties')) {
|
|
130
|
-
if (!property.isObjectProperty()) {
|
|
131
|
-
continue;
|
|
132
|
-
}
|
|
133
|
-
const key = property.get('key');
|
|
134
|
-
const value = property.get('value');
|
|
135
|
-
|
|
136
|
-
if (
|
|
137
|
-
property.isObjectProperty() &&
|
|
138
|
-
key.isIdentifier({ name: 'runtime' }) &&
|
|
139
|
-
value.isStringLiteral({ value: 'edge' })
|
|
140
|
-
) {
|
|
141
|
-
return true;
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
return false;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
export interface PluginOptions {
|
|
148
|
-
isServer: boolean;
|
|
149
|
-
rootDir: string;
|
|
150
|
-
onMethod?: (method: WrapMethodMeta) => void;
|
|
151
|
-
url?: string;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
export default function (
|
|
155
|
-
{ types: t }: Babel,
|
|
156
|
-
{ rootDir, onMethod, isServer, url: rpcUrl }: PluginOptions,
|
|
157
|
-
): babel.PluginObj {
|
|
158
|
-
return {
|
|
159
|
-
visitor: {
|
|
160
|
-
Program(program, state) {
|
|
161
|
-
const { filename } = this.file.opts;
|
|
162
|
-
|
|
163
|
-
if (!filename) {
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
const { isEdge } = getConfigObject(program) || {
|
|
168
|
-
isEdge: false,
|
|
169
|
-
};
|
|
170
|
-
|
|
171
|
-
const isAction = isServerAction(program);
|
|
172
|
-
|
|
173
|
-
if (!isAction) {
|
|
174
|
-
logger.log(`Skipping ${filename} because it's not an action`);
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
logger.log(
|
|
179
|
-
`Processing ${filename} as a ${
|
|
180
|
-
isServer ? 'server' : 'client'
|
|
181
|
-
} action`,
|
|
182
|
-
);
|
|
183
|
-
|
|
184
|
-
const hasWrap = hasWrapMethod(program);
|
|
185
|
-
|
|
186
|
-
const rel = path.relative(rootDir, filename);
|
|
187
|
-
|
|
188
|
-
const rpcRelativePath = rel
|
|
189
|
-
.replace(/\.[j|t]sx?$/, '')
|
|
190
|
-
// remove /pages at the start
|
|
191
|
-
.replace(/^src\//, '')
|
|
192
|
-
.replace(/\/index$/, '');
|
|
193
|
-
let rpcPath = rpcUrl
|
|
194
|
-
? new URL(rpcRelativePath, rpcUrl).toString()
|
|
195
|
-
: '/' + rpcRelativePath;
|
|
196
|
-
|
|
197
|
-
const rpcMethodNames: string[] = [];
|
|
198
|
-
|
|
199
|
-
const createRpcMethodIdentifier =
|
|
200
|
-
program.scope.generateUidIdentifier('createRpcMethod');
|
|
201
|
-
|
|
202
|
-
const createRpcMethod = (
|
|
203
|
-
rpcMethod:
|
|
204
|
-
| babel.types.ArrowFunctionExpression
|
|
205
|
-
| babel.types.FunctionExpression,
|
|
206
|
-
meta: WrapMethodMeta,
|
|
207
|
-
) => {
|
|
208
|
-
return t.callExpression(createRpcMethodIdentifier, [
|
|
209
|
-
rpcMethod,
|
|
210
|
-
parseExpression(JSON.stringify(meta)),
|
|
211
|
-
|
|
212
|
-
parseExpression(
|
|
213
|
-
hasWrap
|
|
214
|
-
? `typeof wrapMethod === 'function' ? wrapMethod : undefined`
|
|
215
|
-
: 'null',
|
|
216
|
-
),
|
|
217
|
-
]);
|
|
218
|
-
};
|
|
219
|
-
|
|
220
|
-
const generators = new Map<string, boolean>();
|
|
221
|
-
for (const statement of program.get('body')) {
|
|
222
|
-
if (statement.isExportNamedDeclaration()) {
|
|
223
|
-
// check if function is async generator
|
|
224
|
-
|
|
225
|
-
const declaration = statement.get('declaration');
|
|
226
|
-
if (isAllowedTsExportDeclaration(declaration)) {
|
|
227
|
-
// ignore
|
|
228
|
-
} else if (declaration.isFunctionDeclaration()) {
|
|
229
|
-
const identifier = declaration.get('id');
|
|
230
|
-
const methodName = identifier.node?.name;
|
|
231
|
-
if (methodName === 'wrapMethod') {
|
|
232
|
-
continue;
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
const isGenerator = !!declaration.node.generator;
|
|
236
|
-
generators.set(methodName!, isGenerator);
|
|
237
|
-
if (!declaration.node.async) {
|
|
238
|
-
throw declaration.buildCodeFrameError(
|
|
239
|
-
'rpc exports must be async functions',
|
|
240
|
-
);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
if (methodName) {
|
|
244
|
-
rpcMethodNames.push(methodName);
|
|
245
|
-
if (isServer) {
|
|
246
|
-
// replace with wrapped
|
|
247
|
-
statement.replaceWith(
|
|
248
|
-
t.exportNamedDeclaration(
|
|
249
|
-
t.variableDeclaration('const', [
|
|
250
|
-
t.variableDeclarator(
|
|
251
|
-
t.identifier(methodName),
|
|
252
|
-
createRpcMethod(t.toExpression(declaration.node), {
|
|
253
|
-
name: methodName,
|
|
254
|
-
pathname: rpcPath,
|
|
255
|
-
isGenerator,
|
|
256
|
-
}),
|
|
257
|
-
),
|
|
258
|
-
]),
|
|
259
|
-
),
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
} else if (
|
|
264
|
-
declaration.isVariableDeclaration() &&
|
|
265
|
-
declaration.node.kind === 'const'
|
|
266
|
-
) {
|
|
267
|
-
for (const variable of declaration.get('declarations')) {
|
|
268
|
-
const init = variable.get('init');
|
|
269
|
-
|
|
270
|
-
if (getConfigObjectExpression(variable)) {
|
|
271
|
-
continue;
|
|
272
|
-
}
|
|
273
|
-
const node = variable.get('id');
|
|
274
|
-
|
|
275
|
-
if (node.isIdentifier() && allowedExports.has(node.node.name)) {
|
|
276
|
-
continue;
|
|
277
|
-
}
|
|
278
|
-
if (getConfigObjectExpression(variable)) {
|
|
279
|
-
// ignore, this is the only allowed non-function export
|
|
280
|
-
continue;
|
|
281
|
-
}
|
|
282
|
-
if (
|
|
283
|
-
init.isFunctionExpression() ||
|
|
284
|
-
init.isArrowFunctionExpression()
|
|
285
|
-
) {
|
|
286
|
-
const { id } = variable.node;
|
|
287
|
-
if (t.isIdentifier(id)) {
|
|
288
|
-
const methodName = id.name;
|
|
289
|
-
if (methodName === 'wrapMethod') {
|
|
290
|
-
continue;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
if (!init.node.async) {
|
|
294
|
-
throw init.buildCodeFrameError(
|
|
295
|
-
'rpc exports must be async functions',
|
|
296
|
-
);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
if (t.isIdentifier(id)) {
|
|
300
|
-
const methodName = id.name;
|
|
301
|
-
if (methodName === 'wrapMethod') {
|
|
302
|
-
continue;
|
|
303
|
-
}
|
|
304
|
-
const isGenerator = !!init.node.generator;
|
|
305
|
-
generators.set(methodName!, isGenerator);
|
|
306
|
-
rpcMethodNames.push(methodName);
|
|
307
|
-
if (isServer) {
|
|
308
|
-
init.replaceWith(
|
|
309
|
-
createRpcMethod(init.node, {
|
|
310
|
-
name: methodName,
|
|
311
|
-
pathname: rpcPath,
|
|
312
|
-
isGenerator,
|
|
313
|
-
}),
|
|
314
|
-
);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
} else {
|
|
318
|
-
throw variable.buildCodeFrameError(
|
|
319
|
-
'rpc exports must be static functions',
|
|
320
|
-
);
|
|
321
|
-
}
|
|
322
|
-
}
|
|
323
|
-
} else {
|
|
324
|
-
for (const specifier of statement.get('specifiers')) {
|
|
325
|
-
if (
|
|
326
|
-
specifier?.node?.exported.type === 'Identifier' &&
|
|
327
|
-
specifier?.node?.exported.name === 'wrapMethod'
|
|
328
|
-
) {
|
|
329
|
-
continue;
|
|
330
|
-
}
|
|
331
|
-
throw specifier.buildCodeFrameError(
|
|
332
|
-
'rpc exports must be static functions',
|
|
333
|
-
);
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
} else if (statement.isExportDefaultDeclaration()) {
|
|
337
|
-
throw statement.buildCodeFrameError(
|
|
338
|
-
'default exports are not allowed in rpc routes',
|
|
339
|
-
);
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
if (!isServer) {
|
|
344
|
-
// Clear the whole body
|
|
345
|
-
out: for (const statement of program.get('body')) {
|
|
346
|
-
// don't remove if it's an export with name is config or runtime
|
|
347
|
-
if (statement.isExportNamedDeclaration()) {
|
|
348
|
-
const declaration = statement.get('declaration');
|
|
349
|
-
if (declaration.isVariableDeclaration()) {
|
|
350
|
-
for (const variable of declaration.get('declarations')) {
|
|
351
|
-
const configObject = getConfigObjectExpression(variable);
|
|
352
|
-
if (configObject) {
|
|
353
|
-
continue out;
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
statement.remove();
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
const outFile = path.resolve(
|
|
362
|
-
rootDir,
|
|
363
|
-
'../browser',
|
|
364
|
-
path.relative(rootDir, filename),
|
|
365
|
-
);
|
|
366
|
-
program.node.directives = [];
|
|
367
|
-
program.pushContainer('body', [
|
|
368
|
-
...(parse(
|
|
369
|
-
`import { createRpcFetcher } from 'spiceflow/dist/browser.js';\n` +
|
|
370
|
-
`import * as methods from './${
|
|
371
|
-
removeExtension(
|
|
372
|
-
path.relative(path.dirname(outFile), filename),
|
|
373
|
-
) + '.js'
|
|
374
|
-
}'`,
|
|
375
|
-
{ sourceType: 'module' },
|
|
376
|
-
).program.body as any),
|
|
377
|
-
...rpcMethodNames.map((name) => {
|
|
378
|
-
const isGenerator = !!generators.get(name);
|
|
379
|
-
onMethod?.({ name, pathname: rpcPath, isGenerator });
|
|
380
|
-
return parse(
|
|
381
|
-
`export const ${name}: typeof methods['${name}'] = createRpcFetcher({ url: ${JSON.stringify(
|
|
382
|
-
rpcPath,
|
|
383
|
-
)}, method: ${JSON.stringify(
|
|
384
|
-
name,
|
|
385
|
-
)}, isGenerator: ${isGenerator} });`,
|
|
386
|
-
{ sourceType: 'module', plugins: ['typescript'] },
|
|
387
|
-
).program.body[0];
|
|
388
|
-
}),
|
|
389
|
-
]);
|
|
390
|
-
}
|
|
391
|
-
},
|
|
392
|
-
},
|
|
393
|
-
};
|
|
394
|
-
}
|
package/src/browser.ts
DELETED
|
@@ -1,141 +0,0 @@
|
|
|
1
|
-
import { EventSourceParserStream } from 'eventsource-parser/stream';
|
|
2
|
-
import { JsonRpcRequest, JsonRpcResponse } from './jsonRpc.js';
|
|
3
|
-
|
|
4
|
-
import superjson from 'superjson';
|
|
5
|
-
|
|
6
|
-
type NextRpcCall = (...params: any[]) => any | AsyncGenerator<any>;
|
|
7
|
-
|
|
8
|
-
let nextId = 1;
|
|
9
|
-
|
|
10
|
-
export function createRpcFetcher({
|
|
11
|
-
url,
|
|
12
|
-
method,
|
|
13
|
-
isGenerator,
|
|
14
|
-
}: {
|
|
15
|
-
url: string;
|
|
16
|
-
method: string;
|
|
17
|
-
isGenerator?: boolean;
|
|
18
|
-
}): NextRpcCall {
|
|
19
|
-
const controller = new AbortController();
|
|
20
|
-
if (isGenerator) {
|
|
21
|
-
const generator = async function* rpcFetchGenerator(...args) {
|
|
22
|
-
const { json, meta } = superjson.serialize(args);
|
|
23
|
-
const res = await fetch(url, {
|
|
24
|
-
method: 'POST',
|
|
25
|
-
headers: {
|
|
26
|
-
Accept: 'text/event-stream',
|
|
27
|
-
'Content-Type': 'application/json',
|
|
28
|
-
},
|
|
29
|
-
signal: controller.signal,
|
|
30
|
-
body: JSON.stringify({
|
|
31
|
-
jsonrpc: '2.0',
|
|
32
|
-
id: nextId++,
|
|
33
|
-
method,
|
|
34
|
-
params: json as any[],
|
|
35
|
-
meta,
|
|
36
|
-
} satisfies JsonRpcRequest),
|
|
37
|
-
});
|
|
38
|
-
if (res.status >= 400) {
|
|
39
|
-
const json = await res.json();
|
|
40
|
-
await handleJsonrpcError({ status: res.status, json });
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
if (!res.body) {
|
|
44
|
-
throw new Error('No response body for generator action');
|
|
45
|
-
}
|
|
46
|
-
const eventStream = res.body
|
|
47
|
-
.pipeThrough(new TextDecoderStream())
|
|
48
|
-
.pipeThrough(new EventSourceParserStream())
|
|
49
|
-
.getReader();
|
|
50
|
-
let isClosed = false;
|
|
51
|
-
try {
|
|
52
|
-
while (true) {
|
|
53
|
-
const { value: event, done } = await eventStream.read();
|
|
54
|
-
|
|
55
|
-
if (done) {
|
|
56
|
-
isClosed = true;
|
|
57
|
-
break;
|
|
58
|
-
}
|
|
59
|
-
if (!event) continue;
|
|
60
|
-
|
|
61
|
-
if (event.data === '[DONE]') {
|
|
62
|
-
continue;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const json = JSON.parse(event.data);
|
|
66
|
-
|
|
67
|
-
const { jsonrpc, id, result, meta, error } = json as JsonRpcResponse;
|
|
68
|
-
await handleJsonrpcError({ status: res.status, json });
|
|
69
|
-
const deserialized = superjson.deserialize({
|
|
70
|
-
json: result,
|
|
71
|
-
meta,
|
|
72
|
-
});
|
|
73
|
-
yield deserialized;
|
|
74
|
-
}
|
|
75
|
-
} finally {
|
|
76
|
-
// if user calls return() in the generator, we need to close the stream
|
|
77
|
-
|
|
78
|
-
if (!isClosed) {
|
|
79
|
-
// if stream is still open, abort controller
|
|
80
|
-
controller.abort();
|
|
81
|
-
eventStream.cancel();
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
return generator;
|
|
87
|
-
}
|
|
88
|
-
async function rpcFetch(...args) {
|
|
89
|
-
const { json: argsJson, meta } = superjson.serialize(args);
|
|
90
|
-
const res = await fetch(url, {
|
|
91
|
-
method: 'POST',
|
|
92
|
-
body: JSON.stringify(
|
|
93
|
-
{
|
|
94
|
-
jsonrpc: '2.0',
|
|
95
|
-
id: nextId++,
|
|
96
|
-
method,
|
|
97
|
-
params: argsJson as any[],
|
|
98
|
-
meta,
|
|
99
|
-
} satisfies JsonRpcRequest,
|
|
100
|
-
null,
|
|
101
|
-
2,
|
|
102
|
-
),
|
|
103
|
-
headers: {
|
|
104
|
-
'content-type': 'application/json',
|
|
105
|
-
},
|
|
106
|
-
});
|
|
107
|
-
const json = await res.json();
|
|
108
|
-
await handleJsonrpcError({ status: res.status, json });
|
|
109
|
-
{
|
|
110
|
-
const deserialized = superjson.deserialize({
|
|
111
|
-
json: json.result,
|
|
112
|
-
meta: json.meta,
|
|
113
|
-
});
|
|
114
|
-
return deserialized as any;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
rpcFetch.abort = function abort() {
|
|
118
|
-
controller.abort();
|
|
119
|
-
};
|
|
120
|
-
return rpcFetch;
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
async function handleJsonrpcError({
|
|
124
|
-
status,
|
|
125
|
-
json,
|
|
126
|
-
}: {
|
|
127
|
-
status: number;
|
|
128
|
-
json: JsonRpcResponse;
|
|
129
|
-
}) {
|
|
130
|
-
if (status >= 400) {
|
|
131
|
-
const statusError = new Error('Unexpected HTTP status ' + status);
|
|
132
|
-
|
|
133
|
-
if (json?.error && typeof json.error?.message === 'string') {
|
|
134
|
-
let err = new Error(json.error.message);
|
|
135
|
-
Object.assign(err, json.error.data || {});
|
|
136
|
-
throw err;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
throw statusError;
|
|
140
|
-
}
|
|
141
|
-
}
|