spiceflow 0.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 +178 -0
- package/context.d.ts +2 -0
- package/context.js +1 -0
- package/dist/babel.test.d.ts +2 -0
- package/dist/babel.test.d.ts.map +1 -0
- package/dist/babel.test.js +32 -0
- package/dist/babel.test.js.map +1 -0
- package/dist/babelDebugOutputs.d.ts +9 -0
- package/dist/babelDebugOutputs.d.ts.map +1 -0
- package/dist/babelDebugOutputs.js +40 -0
- package/dist/babelDebugOutputs.js.map +1 -0
- package/dist/babelTransformRpc.d.ts +17 -0
- package/dist/babelTransformRpc.d.ts.map +1 -0
- package/dist/babelTransformRpc.js +304 -0
- package/dist/babelTransformRpc.js.map +1 -0
- package/dist/browser.d.ts +8 -0
- package/dist/browser.d.ts.map +1 -0
- package/dist/browser.js +133 -0
- package/dist/browser.js.map +1 -0
- package/dist/build.d.ts +10 -0
- package/dist/build.d.ts.map +1 -0
- package/dist/build.js +253 -0
- package/dist/build.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +108 -0
- package/dist/cli.js.map +1 -0
- package/dist/context-internal.d.ts +20 -0
- package/dist/context-internal.d.ts.map +1 -0
- package/dist/context-internal.js +22 -0
- package/dist/context-internal.js.map +1 -0
- package/dist/context.d.ts +2 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +8 -0
- package/dist/context.js.map +1 -0
- package/dist/expose.d.ts +6 -0
- package/dist/expose.d.ts.map +1 -0
- package/dist/expose.js +39 -0
- package/dist/expose.js.map +1 -0
- package/dist/headers.d.ts +1 -0
- package/dist/headers.d.ts.map +1 -0
- package/dist/headers.js +18 -0
- package/dist/headers.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -0
- package/dist/jsonRpc.d.ts +32 -0
- package/dist/jsonRpc.d.ts.map +1 -0
- package/dist/jsonRpc.js +4 -0
- package/dist/jsonRpc.js.map +1 -0
- package/dist/server.d.ts +32 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +301 -0
- package/dist/server.js.map +1 -0
- package/dist/utils.d.ts +20 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +44 -0
- package/dist/utils.js.map +1 -0
- package/headers.d.ts +2 -0
- package/headers.js +1 -0
- package/package.json +56 -0
- package/sdk-template/package.json +22 -0
- package/sdk-template/src/index.ts +2 -0
- package/sdk-template/src/v1/example.ts +5 -0
- package/sdk-template/src/v1/generator.ts +12 -0
- package/sdk-template/tsconfig.json +16 -0
- package/src/babel.test.ts +35 -0
- package/src/babelDebugOutputs.ts +56 -0
- package/src/babelTransformRpc.ts +404 -0
- package/src/browser.ts +142 -0
- package/src/build.ts +303 -0
- package/src/cli.ts +118 -0
- package/src/context-internal.ts +36 -0
- package/src/context.ts +1 -0
- package/src/expose.ts +34 -0
- package/src/headers.ts +19 -0
- package/src/index.ts +42 -0
- package/src/jsonRpc.ts +43 -0
- package/src/server.ts +384 -0
- package/src/utils.ts +61 -0
package/src/jsonRpc.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// https://www.jsonrpc.org/specification
|
|
2
|
+
|
|
3
|
+
export type JsonRpcRequestId = string | number | null;
|
|
4
|
+
|
|
5
|
+
export type JsonValue =
|
|
6
|
+
| string
|
|
7
|
+
| number
|
|
8
|
+
| boolean
|
|
9
|
+
| null
|
|
10
|
+
| JsonValue[]
|
|
11
|
+
| { [key: string]: JsonValue };
|
|
12
|
+
|
|
13
|
+
export interface JsonRpcRequest {
|
|
14
|
+
jsonrpc: '2.0';
|
|
15
|
+
method: string;
|
|
16
|
+
params: JsonValue[];
|
|
17
|
+
meta?: any
|
|
18
|
+
id: JsonRpcRequestId;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface JsonRpcError {
|
|
22
|
+
code: number;
|
|
23
|
+
message: string;
|
|
24
|
+
data?: JsonValue;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface JsonRpcSuccessResponse {
|
|
28
|
+
jsonrpc: '2.0';
|
|
29
|
+
result: JsonValue;
|
|
30
|
+
error?: undefined;
|
|
31
|
+
id: JsonRpcRequestId;
|
|
32
|
+
meta?: any;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface JsonRpcErrorResponse {
|
|
36
|
+
jsonrpc: '2.0';
|
|
37
|
+
result?: undefined;
|
|
38
|
+
error: JsonRpcError;
|
|
39
|
+
id: JsonRpcRequestId;
|
|
40
|
+
meta?: any;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export type JsonRpcResponse = JsonRpcSuccessResponse | JsonRpcErrorResponse;
|
package/src/server.ts
ADDED
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
import { IncomingMessage, ServerResponse } from 'http';
|
|
2
|
+
import superjson from 'superjson';
|
|
3
|
+
import { asyncLocalStorage } from './context-internal';
|
|
4
|
+
import { JsonRpcRequest, JsonRpcResponse } from './jsonRpc';
|
|
5
|
+
import { jsonRpcError } from './utils';
|
|
6
|
+
|
|
7
|
+
export type Method<P extends any[], R> = (
|
|
8
|
+
...params: P
|
|
9
|
+
) => Promise<R> | AsyncIterable<R>;
|
|
10
|
+
export type WrapMethodMeta = {
|
|
11
|
+
name: string;
|
|
12
|
+
isGenerator: boolean;
|
|
13
|
+
pathname: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export interface WrapMethod {
|
|
17
|
+
<P extends any[], R = any>(
|
|
18
|
+
method: Method<P, R>,
|
|
19
|
+
meta: WrapMethodMeta,
|
|
20
|
+
): Method<P, R>;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function createRpcMethod<P extends any[], R>(
|
|
24
|
+
method: Method<P, R>,
|
|
25
|
+
meta: WrapMethodMeta,
|
|
26
|
+
customWrapRpcMethod: unknown,
|
|
27
|
+
): Method<P, R> {
|
|
28
|
+
let wrapped = method;
|
|
29
|
+
if (typeof customWrapRpcMethod === 'function') {
|
|
30
|
+
wrapped = customWrapRpcMethod(method, meta);
|
|
31
|
+
if (typeof wrapped !== 'function') {
|
|
32
|
+
throw new Error(
|
|
33
|
+
`wrapMethod didn't return a function, got "${typeof wrapped}"`,
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
} else if (
|
|
37
|
+
customWrapRpcMethod !== undefined &&
|
|
38
|
+
customWrapRpcMethod !== null
|
|
39
|
+
) {
|
|
40
|
+
throw new Error(
|
|
41
|
+
`Invalid wrapMethod type, expected "function", got "${typeof customWrapRpcMethod}"`,
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
return (...args) => wrapped(...args);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
type MethodsMap = {
|
|
48
|
+
[key: string]: () => Promise<{
|
|
49
|
+
[key: string]: Method<any, any>;
|
|
50
|
+
}>;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export function internalEdgeHandler({
|
|
54
|
+
methodsMap,
|
|
55
|
+
}: {
|
|
56
|
+
methodsMap: MethodsMap;
|
|
57
|
+
}) {
|
|
58
|
+
return async ({ req, basePath }: { req: Request; basePath: string }) => {
|
|
59
|
+
const body = await req.json();
|
|
60
|
+
const res = new Response();
|
|
61
|
+
const result = await asyncLocalStorage.run({ req, res }, () =>
|
|
62
|
+
handler({
|
|
63
|
+
methodsMap,
|
|
64
|
+
body,
|
|
65
|
+
pathname: new URL(req.url).pathname,
|
|
66
|
+
basePath,
|
|
67
|
+
method: req.method,
|
|
68
|
+
}),
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
if (isAsyncGenerator(result)) {
|
|
72
|
+
const encoder = new TextEncoder();
|
|
73
|
+
let generatorFinished = false;
|
|
74
|
+
|
|
75
|
+
req.signal.addEventListener('abort', () => {
|
|
76
|
+
if (!generatorFinished) {
|
|
77
|
+
console.log(`request aborted, cancelling generator`);
|
|
78
|
+
result.return?.(undefined);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
const readableStream = new ReadableStream(
|
|
82
|
+
{
|
|
83
|
+
start(controller) {},
|
|
84
|
+
async pull(controller) {
|
|
85
|
+
while (true) {
|
|
86
|
+
const { done, value } = await result.next();
|
|
87
|
+
if (done) {
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
controller.enqueue(
|
|
91
|
+
encoder.encode('data: ' + JSON.stringify(value.json) + '\n\n'),
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
generatorFinished = true;
|
|
95
|
+
controller.close();
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
cancel() {},
|
|
99
|
+
},
|
|
100
|
+
// { highWaterMark: 0 },
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
return new Response(readableStream, {
|
|
104
|
+
headers: {
|
|
105
|
+
'content-type': 'text/event-stream',
|
|
106
|
+
'cache-control': 'no-cache',
|
|
107
|
+
connection: 'keep-alive',
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const { status, json } = result;
|
|
113
|
+
return new Response(JSON.stringify(json, null, 2), {
|
|
114
|
+
status,
|
|
115
|
+
headers: res?.headers || {
|
|
116
|
+
'content-type': 'application/json',
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export function internalNodeJsHandler({
|
|
123
|
+
methodsMap,
|
|
124
|
+
}: {
|
|
125
|
+
methodsMap: MethodsMap;
|
|
126
|
+
}) {
|
|
127
|
+
return async ({
|
|
128
|
+
req,
|
|
129
|
+
res,
|
|
130
|
+
basePath,
|
|
131
|
+
}: {
|
|
132
|
+
req: IncomingMessage;
|
|
133
|
+
res: ServerResponse;
|
|
134
|
+
basePath: string;
|
|
135
|
+
}) => {
|
|
136
|
+
let body = req['body'];
|
|
137
|
+
if (body && typeof body === 'string') {
|
|
138
|
+
// if the sdk send a request without content-type header as json, it will be a string
|
|
139
|
+
body = JSON.parse(body);
|
|
140
|
+
}
|
|
141
|
+
if (!body) {
|
|
142
|
+
// if used outside of next.js, the body is not available
|
|
143
|
+
try {
|
|
144
|
+
body = await readReqJson(req);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
res.writeHead(400);
|
|
147
|
+
res.end(
|
|
148
|
+
JSON.stringify(
|
|
149
|
+
jsonRpcError({ message: 'Invalid body, must be JSON' }),
|
|
150
|
+
),
|
|
151
|
+
);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const result = await asyncLocalStorage.run({ req, res }, () =>
|
|
157
|
+
handler({
|
|
158
|
+
methodsMap,
|
|
159
|
+
body,
|
|
160
|
+
basePath,
|
|
161
|
+
pathname: req.url!,
|
|
162
|
+
method: req.method!,
|
|
163
|
+
}),
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
if (isAsyncGenerator(result)) {
|
|
167
|
+
res.writeHead(200, {
|
|
168
|
+
'content-type': 'text/event-stream',
|
|
169
|
+
'cache-control': 'no-cache',
|
|
170
|
+
connection: 'keep-alive',
|
|
171
|
+
// https://github.com/vercel/next.js/issues/9965#issuecomment-584319868
|
|
172
|
+
'content-encoding': 'none',
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
let generatorFinished = false;
|
|
176
|
+
// handle cancellation
|
|
177
|
+
res.on('close', () => {
|
|
178
|
+
if (!generatorFinished) {
|
|
179
|
+
console.log(`response closed, cancelling generator`);
|
|
180
|
+
(result as AsyncIterator<any>).return?.();
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
while (true) {
|
|
184
|
+
const { done, value } = await result.next();
|
|
185
|
+
if (done) {
|
|
186
|
+
break;
|
|
187
|
+
}
|
|
188
|
+
res.write('data: ' + JSON.stringify(value.json) + '\n\n');
|
|
189
|
+
}
|
|
190
|
+
generatorFinished = true;
|
|
191
|
+
|
|
192
|
+
res.end();
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
const { status, json } = result;
|
|
196
|
+
res.writeHead(status || 200).end(JSON.stringify(json, null, 2));
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function isAsyncGenerator(obj: any): obj is AsyncGenerator<any> {
|
|
201
|
+
return obj != null && typeof obj.next === 'function';
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const handler = async ({
|
|
205
|
+
method,
|
|
206
|
+
methodsMap,
|
|
207
|
+
basePath,
|
|
208
|
+
body,
|
|
209
|
+
pathname,
|
|
210
|
+
}: {
|
|
211
|
+
method: string;
|
|
212
|
+
basePath: string;
|
|
213
|
+
pathname: string;
|
|
214
|
+
methodsMap: MethodsMap;
|
|
215
|
+
body: JsonRpcRequest;
|
|
216
|
+
}) => {
|
|
217
|
+
if (!methodsMap) {
|
|
218
|
+
throw new Error('No methods found');
|
|
219
|
+
}
|
|
220
|
+
if (basePath && pathname.startsWith(basePath)) {
|
|
221
|
+
if (basePath.endsWith('/')) {
|
|
222
|
+
basePath = basePath.slice(0, -1);
|
|
223
|
+
}
|
|
224
|
+
pathname = pathname.slice(basePath.length);
|
|
225
|
+
}
|
|
226
|
+
if (method !== 'POST') {
|
|
227
|
+
return {
|
|
228
|
+
status: 405,
|
|
229
|
+
json: {
|
|
230
|
+
jsonrpc: '2.0',
|
|
231
|
+
id: null,
|
|
232
|
+
error: {
|
|
233
|
+
code: -32001,
|
|
234
|
+
message: 'Server error',
|
|
235
|
+
data: {
|
|
236
|
+
cause: `HTTP method "${method}" is not allowed`,
|
|
237
|
+
},
|
|
238
|
+
},
|
|
239
|
+
} satisfies JsonRpcResponse,
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
const { id, method: fn, params, meta: argsMeta } = body;
|
|
244
|
+
|
|
245
|
+
const mod = methodsMap[pathname] && (await methodsMap[pathname]());
|
|
246
|
+
if (!mod) {
|
|
247
|
+
return {
|
|
248
|
+
status: 400,
|
|
249
|
+
json: {
|
|
250
|
+
jsonrpc: '2.0',
|
|
251
|
+
id,
|
|
252
|
+
error: {
|
|
253
|
+
code: -32601,
|
|
254
|
+
message: 'Method not found',
|
|
255
|
+
data: {
|
|
256
|
+
cause: `Path "${pathname}" is not handled by any method`,
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
} satisfies JsonRpcResponse,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
const requestedMethod = mod[fn];
|
|
264
|
+
|
|
265
|
+
if (typeof requestedMethod !== 'function') {
|
|
266
|
+
return {
|
|
267
|
+
status: 400,
|
|
268
|
+
json: {
|
|
269
|
+
jsonrpc: '2.0',
|
|
270
|
+
id,
|
|
271
|
+
error: {
|
|
272
|
+
code: -32601,
|
|
273
|
+
message: 'Method not found',
|
|
274
|
+
data: {
|
|
275
|
+
cause: `Method "${fn}" is not a function, in ${Object.keys(
|
|
276
|
+
mod,
|
|
277
|
+
).join(', ')}`,
|
|
278
|
+
},
|
|
279
|
+
},
|
|
280
|
+
} satisfies JsonRpcResponse,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
try {
|
|
285
|
+
const args = superjson.deserialize({
|
|
286
|
+
json: params,
|
|
287
|
+
meta: argsMeta,
|
|
288
|
+
}) as any[];
|
|
289
|
+
const result = await requestedMethod(...args);
|
|
290
|
+
if (!isAsyncGenerator(result)) {
|
|
291
|
+
const { json, meta } = superjson.serialize(result);
|
|
292
|
+
|
|
293
|
+
return {
|
|
294
|
+
json: {
|
|
295
|
+
jsonrpc: '2.0',
|
|
296
|
+
id,
|
|
297
|
+
result: json as any,
|
|
298
|
+
meta,
|
|
299
|
+
} satisfies JsonRpcResponse,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
return (async function* () {
|
|
303
|
+
// send a response for each yielded value
|
|
304
|
+
|
|
305
|
+
try {
|
|
306
|
+
while (true) {
|
|
307
|
+
const { done, value } = await result.next();
|
|
308
|
+
if (done) {
|
|
309
|
+
break;
|
|
310
|
+
}
|
|
311
|
+
const { json, meta } = superjson.serialize(value);
|
|
312
|
+
|
|
313
|
+
yield {
|
|
314
|
+
json: {
|
|
315
|
+
jsonrpc: '2.0',
|
|
316
|
+
id,
|
|
317
|
+
result: json as any,
|
|
318
|
+
meta,
|
|
319
|
+
} satisfies JsonRpcResponse,
|
|
320
|
+
};
|
|
321
|
+
}
|
|
322
|
+
} catch (error) {
|
|
323
|
+
const {
|
|
324
|
+
name = 'RpcError',
|
|
325
|
+
message = `Invalid value thrown in "${method}", must be instance of Error`,
|
|
326
|
+
stack = undefined,
|
|
327
|
+
} = error instanceof Error ? error : {};
|
|
328
|
+
return {
|
|
329
|
+
json: {
|
|
330
|
+
jsonrpc: '2.0',
|
|
331
|
+
id,
|
|
332
|
+
error: {
|
|
333
|
+
code: 1,
|
|
334
|
+
message,
|
|
335
|
+
data: {
|
|
336
|
+
name,
|
|
337
|
+
...(process.env.NODE_ENV === 'production' ? {} : { stack }),
|
|
338
|
+
},
|
|
339
|
+
},
|
|
340
|
+
} satisfies JsonRpcResponse,
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
})();
|
|
344
|
+
} catch (error) {
|
|
345
|
+
const {
|
|
346
|
+
name = 'RpcError',
|
|
347
|
+
message = `Invalid value thrown in "${method}", must be instance of Error`,
|
|
348
|
+
stack = undefined,
|
|
349
|
+
} = error instanceof Error ? error : {};
|
|
350
|
+
return {
|
|
351
|
+
status: 502,
|
|
352
|
+
json: {
|
|
353
|
+
jsonrpc: '2.0',
|
|
354
|
+
id,
|
|
355
|
+
error: {
|
|
356
|
+
code: 1,
|
|
357
|
+
message,
|
|
358
|
+
data: {
|
|
359
|
+
name,
|
|
360
|
+
...(process.env.NODE_ENV === 'production' ? {} : { stack }),
|
|
361
|
+
},
|
|
362
|
+
},
|
|
363
|
+
} satisfies JsonRpcResponse,
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
|
|
368
|
+
function readReqJson(req: IncomingMessage) {
|
|
369
|
+
return new Promise((resolve, reject) => {
|
|
370
|
+
let data = '';
|
|
371
|
+
req.on('data', (chunk) => {
|
|
372
|
+
data += chunk;
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
req.on('end', () => {
|
|
376
|
+
try {
|
|
377
|
+
const parsedData = JSON.parse(data);
|
|
378
|
+
resolve(parsedData);
|
|
379
|
+
} catch (error) {
|
|
380
|
+
reject(error);
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
}
|
package/src/utils.ts
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { PluginPass, parse } from '@babel/core';
|
|
2
|
+
|
|
3
|
+
import { Node, types } from '@babel/core';
|
|
4
|
+
import { JsonRpcError, JsonRpcErrorResponse } from './jsonRpc';
|
|
5
|
+
|
|
6
|
+
const PURE_ANNOTATION = '#__PURE__';
|
|
7
|
+
|
|
8
|
+
export function annotateAsPure<N extends Node>(t: typeof types, node: N): N {
|
|
9
|
+
t.addComment(node, 'leading', PURE_ANNOTATION);
|
|
10
|
+
return node;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export type Literal =
|
|
14
|
+
| number
|
|
15
|
+
| string
|
|
16
|
+
| boolean
|
|
17
|
+
| { [key: string]: Literal }
|
|
18
|
+
| Literal[];
|
|
19
|
+
|
|
20
|
+
const enabled = !!process.env.DEBUG_ACTIONS;
|
|
21
|
+
export const logger = {
|
|
22
|
+
log(...args) {
|
|
23
|
+
enabled && console.log('[actions]:', ...args);
|
|
24
|
+
},
|
|
25
|
+
error(...args) {
|
|
26
|
+
enabled && console.log('[actions]:', ...args);
|
|
27
|
+
},
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export function getFileName(state: PluginPass) {
|
|
31
|
+
const { filename, cwd } = state;
|
|
32
|
+
|
|
33
|
+
if (!filename) {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
if (cwd && filename.startsWith(cwd)) {
|
|
38
|
+
return filename.slice(cwd.length + 1);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return filename;
|
|
42
|
+
}
|
|
43
|
+
export const directive = "use spiceflow"
|
|
44
|
+
|
|
45
|
+
export const serverEntryName = '_function_server_file';
|
|
46
|
+
|
|
47
|
+
export function jsonRpcError({
|
|
48
|
+
id = null,
|
|
49
|
+
message,
|
|
50
|
+
code = 1,
|
|
51
|
+
}): JsonRpcErrorResponse {
|
|
52
|
+
return {
|
|
53
|
+
jsonrpc: '2.0',
|
|
54
|
+
id,
|
|
55
|
+
error: {
|
|
56
|
+
code,
|
|
57
|
+
message,
|
|
58
|
+
data: null,
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|