zynapse 0.1.0
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 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +51 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/schema/client_side.d.ts +9 -0
- package/dist/schema/client_side.d.ts.map +1 -0
- package/dist/schema/client_side.js +308 -0
- package/dist/schema/client_side.js.map +1 -0
- package/dist/schema/index.d.ts +60 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +41 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/server/connection.d.ts +22 -0
- package/dist/server/connection.d.ts.map +1 -0
- package/dist/server/connection.js +83 -0
- package/dist/server/connection.js.map +1 -0
- package/dist/server/index.d.ts +38 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +234 -0
- package/dist/server/index.js.map +1 -0
- package/package.json +56 -0
package/README.md
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# zynapse
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { parseArgs } from "util";
|
|
3
|
+
import { GenerateCode } from "../schema/client_side";
|
|
4
|
+
import { readdirSync, rm } from "fs";
|
|
5
|
+
const { values: { inputFile, outputFolder }, } = parseArgs({
|
|
6
|
+
args: Bun.argv || process.argv,
|
|
7
|
+
allowPositionals: true,
|
|
8
|
+
options: {
|
|
9
|
+
inputFile: {
|
|
10
|
+
type: "string",
|
|
11
|
+
short: "I",
|
|
12
|
+
},
|
|
13
|
+
outputFolder: {
|
|
14
|
+
type: "string",
|
|
15
|
+
short: "O",
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
if (!inputFile || !outputFolder) {
|
|
20
|
+
throw new Error("One or more arguments are missing");
|
|
21
|
+
}
|
|
22
|
+
console.log("Code gen started", process.cwd());
|
|
23
|
+
// Find the file and dynamically import it
|
|
24
|
+
const fullPath = path.join(process.cwd(), inputFile);
|
|
25
|
+
const file = (await import(fullPath)).default;
|
|
26
|
+
// Remove old files.
|
|
27
|
+
const oldFilesDirectory = path.join(process.cwd(), outputFolder);
|
|
28
|
+
const files = readdirSync(oldFilesDirectory);
|
|
29
|
+
for (const file of files) {
|
|
30
|
+
const toDelete = path.join(oldFilesDirectory, file);
|
|
31
|
+
rm(toDelete, (err) => {
|
|
32
|
+
if (err) {
|
|
33
|
+
console.log(`Error con deleting file ${file}, ${err}`);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
console.log("Successfully deleted", file);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
// TODO: Add some sort of validation to make sure the mentioned file is actually a schema
|
|
41
|
+
const services_buffers = await GenerateCode(file);
|
|
42
|
+
let total_bytes = 0;
|
|
43
|
+
for (const service_buf of services_buffers) {
|
|
44
|
+
const full_filename = path.join(process.cwd(), outputFolder, service_buf.filename);
|
|
45
|
+
const fHandle = Bun.file(full_filename);
|
|
46
|
+
const bytes = await fHandle.write(service_buf.code);
|
|
47
|
+
console.log(`${bytes} written to ${full_filename}`);
|
|
48
|
+
total_bytes += bytes;
|
|
49
|
+
}
|
|
50
|
+
console.log(`${total_bytes} total bytes written`);
|
|
51
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAEA,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAiC,WAAW,EAAE,EAAE,EAAE,MAAM,IAAI,CAAC;AAEpE,MAAM,EACL,MAAM,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,GACnC,GAAG,SAAS,CAAC;IACb,IAAI,EAAE,GAAG,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI;IAC9B,gBAAgB,EAAE,IAAI;IACtB,OAAO,EAAE;QACR,SAAS,EAAE;YACV,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,GAAG;SACV;QACD,YAAY,EAAE;YACb,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,GAAG;SACV;KACD;CACD,CAAC,CAAC;AAEH,IAAI,CAAC,SAAS,IAAI,CAAC,YAAY,EAAE,CAAC;IACjC,MAAM,IAAI,KAAK,CAAC,mCAAmC,CAAC,CAAC;AACtD,CAAC;AAED,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;AAC/C,0CAA0C;AAE1C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;AACrD,MAAM,IAAI,GAAG,CAAC,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;AAE9C,oBAAoB;AACpB,MAAM,iBAAiB,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,YAAY,CAAC,CAAC;AACjE,MAAM,KAAK,GAAG,WAAW,CAAC,iBAAiB,CAAC,CAAC;AAC7C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;IAC1B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,IAAI,CAAC,CAAC;IACpD,EAAE,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC;QACrB,IAAI,GAAG,EAAE,CAAC;YACT,OAAO,CAAC,GAAG,CAAC,2BAA2B,IAAI,KAAK,GAAG,EAAE,CAAC,CAAC;QACxD,CAAC;aAAM,CAAC;YACP,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,IAAI,CAAC,CAAC;QAC3C,CAAC;IAAA,CACD,CAAC,CAAC;AACJ,CAAC;AAED,yFAAyF;AAEzF,MAAM,gBAAgB,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,CAAC;AAElD,IAAI,WAAW,GAAG,CAAC,CAAC;AACpB,KAAK,MAAM,WAAW,IAAI,gBAAgB,EAAE,CAAC;IAC5C,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAC9B,OAAO,CAAC,GAAG,EAAE,EACb,YAAY,EACZ,WAAW,CAAC,QAAQ,CACpB,CAAC;IACF,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAExC,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,eAAe,aAAa,EAAE,CAAC,CAAC;IACpD,WAAW,IAAI,KAAK,CAAC;AACtB,CAAC;AAED,OAAO,CAAC,GAAG,CAAC,GAAG,WAAW,sBAAsB,CAAC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { APISchema } from ".";
|
|
2
|
+
type ServiceCode = {
|
|
3
|
+
filename: string;
|
|
4
|
+
code: string;
|
|
5
|
+
};
|
|
6
|
+
type SchemaCodes = Array<ServiceCode>;
|
|
7
|
+
export declare function GenerateCode(schema: APISchema): Promise<SchemaCodes>;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=client_side.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client_side.d.ts","sourceRoot":"","sources":["../../src/schema/client_side.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAW,MAAM,GAAG,CAAC;AAgUvC,KAAK,WAAW,GAAG;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAWtD,KAAK,WAAW,GAAG,KAAK,CAAC,WAAW,CAAC,CAAC;AAEtC,wBAAsB,YAAY,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAwB1E"}
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { zodToTs, printNode, createTypeAlias } from "zod-to-ts";
|
|
2
|
+
import * as prettier from "prettier";
|
|
3
|
+
import ztj from "zod-to-json-schema";
|
|
4
|
+
import jtz from "json-schema-to-zod";
|
|
5
|
+
const buffer = `
|
|
6
|
+
import * as React from "react"
|
|
7
|
+
import {
|
|
8
|
+
useQuery,
|
|
9
|
+
useMutation,
|
|
10
|
+
|
|
11
|
+
} from "@tanstack/react-query";\n\n
|
|
12
|
+
`;
|
|
13
|
+
function getOutputAlias(proc, parentService) {
|
|
14
|
+
const outputTypeIdentifier = `${parentService.name}${proc.name}OutputType`;
|
|
15
|
+
const { node } = zodToTs(proc.output, outputTypeIdentifier);
|
|
16
|
+
const alias = createTypeAlias(node, outputTypeIdentifier);
|
|
17
|
+
const stringifiedAlias = printNode(alias);
|
|
18
|
+
return { outputTypeIdentifier, stringifiedAlias };
|
|
19
|
+
}
|
|
20
|
+
async function mutationProcedureCodeGen(proc, parentService) {
|
|
21
|
+
const { outputTypeIdentifier, stringifiedAlias } = getOutputAlias(proc, parentService);
|
|
22
|
+
const inputAliasIdentifier = `${parentService.name}${proc.name}InputSchema`;
|
|
23
|
+
const schema = ztj(proc.input, {
|
|
24
|
+
errorMessages: true,
|
|
25
|
+
markdownDescription: true,
|
|
26
|
+
});
|
|
27
|
+
// @ts-ignore
|
|
28
|
+
const zodCode = jtz(schema, {
|
|
29
|
+
withJsdocs: true,
|
|
30
|
+
name: inputAliasIdentifier,
|
|
31
|
+
});
|
|
32
|
+
let buff = `export ${stringifiedAlias}\nexport ${zodCode}\nexport function use${parentService.name}${proc.name}Mutation`;
|
|
33
|
+
buff += `(extraOptions?: Omit<UseMutationOptions<${outputTypeIdentifier}, Error, z.infer<typeof ${inputAliasIdentifier}>, unknown>, "mutationFn">) {
|
|
34
|
+
/*${proc.description}*/
|
|
35
|
+
return useMutation({
|
|
36
|
+
...extraOptions,
|
|
37
|
+
mutationFn: async (args: z.infer<typeof ${inputAliasIdentifier}>) => {
|
|
38
|
+
const validationResult = await ${inputAliasIdentifier}.safeParseAsync(args)
|
|
39
|
+
if (validationResult.error) {
|
|
40
|
+
console.error("Error on validating mutation input ", validationResult.error)
|
|
41
|
+
throw new Error(validationResult.error.message)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
const response = await fetch("/_api",{
|
|
46
|
+
method: "POST",
|
|
47
|
+
body: JSON.stringify({
|
|
48
|
+
service: '${parentService.name}',
|
|
49
|
+
procedure: '${proc.name}',
|
|
50
|
+
data: validationResult.data
|
|
51
|
+
}),
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
if (!response.ok) {
|
|
55
|
+
let backendErrorMessage = ""
|
|
56
|
+
try {
|
|
57
|
+
backendErrorMessage = await response.text()
|
|
58
|
+
} catch {
|
|
59
|
+
backendErrorMessage = "No Error message returned from backen"
|
|
60
|
+
}
|
|
61
|
+
throw new Error("Mutation: ${proc.name} Non ok response: " + backendErrorMessage)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
const rawResponse = await response.json()
|
|
66
|
+
|
|
67
|
+
return rawResponse["data"] as ${outputTypeIdentifier}
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
|
|
71
|
+
}`;
|
|
72
|
+
return await prettier.format(buff, { parser: "babel-ts" });
|
|
73
|
+
}
|
|
74
|
+
async function subscriptionProcedureCodeGen(proc, parentService) {
|
|
75
|
+
const { outputTypeIdentifier, stringifiedAlias } = getOutputAlias(proc, parentService);
|
|
76
|
+
const inputIdentifier = `${parentService.name}${proc.name}SubscriptionInputSchema`;
|
|
77
|
+
const jsonSchema = ztj(proc.input, {
|
|
78
|
+
errorMessages: true,
|
|
79
|
+
markdownDescription: true,
|
|
80
|
+
});
|
|
81
|
+
// @ts-ignore
|
|
82
|
+
const schema = jtz(jsonSchema, {
|
|
83
|
+
withJsdocs: true,
|
|
84
|
+
name: inputIdentifier,
|
|
85
|
+
});
|
|
86
|
+
let buff = `export ${schema}\nexport ${stringifiedAlias}\n\nexport function use${parentService.name}${proc.name}Subscription`;
|
|
87
|
+
buff += `(args: z.infer<typeof ${inputIdentifier}>,extraOptions?: {
|
|
88
|
+
onError?: (errorMessage: string) => void; // Callback that executes when there's an error
|
|
89
|
+
onClose?: () => void; // Callback that executes when the connection has been closed by the server
|
|
90
|
+
})`;
|
|
91
|
+
buff += "{\n";
|
|
92
|
+
buff += `/*${proc.description}*/\n`;
|
|
93
|
+
// Initial setup of state.
|
|
94
|
+
buff += `const sourceRef = useRef<EventSource>();\n`;
|
|
95
|
+
buff += `const [messages, setMessages] = useState<Array<${outputTypeIdentifier}>>([]);\n`;
|
|
96
|
+
buff += `const [isConnected, setIsConnected] = useState<boolean>(false);\n`;
|
|
97
|
+
// Use effect main logic.
|
|
98
|
+
buff += `useEffect(() => {
|
|
99
|
+
if (
|
|
100
|
+
sourceRef.current &&
|
|
101
|
+
sourceRef.current?.readyState === sourceRef.current?.OPEN
|
|
102
|
+
) {
|
|
103
|
+
// The connection is already stablished.
|
|
104
|
+
} else {
|
|
105
|
+
const targetURL = new URL("/_api", window.location.origin);
|
|
106
|
+
const fullPayload = {
|
|
107
|
+
service: "${parentService.name}",
|
|
108
|
+
procedure: "${proc.name}",
|
|
109
|
+
data: args,
|
|
110
|
+
};
|
|
111
|
+
const stringifiedArguments = JSON.stringify(fullPayload);
|
|
112
|
+
const encodedArguments = encodeURIComponent(stringifiedArguments);
|
|
113
|
+
targetURL.searchParams.set("payload", encodedArguments);
|
|
114
|
+
|
|
115
|
+
const source = new EventSource(targetURL);
|
|
116
|
+
sourceRef.current = source;
|
|
117
|
+
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const aborter = new AbortController();
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
sourceRef.current.addEventListener(
|
|
124
|
+
"open",
|
|
125
|
+
() => {
|
|
126
|
+
setIsConnected(true);
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
signal: aborter.signal,
|
|
130
|
+
},
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
sourceRef.current.addEventListener(
|
|
134
|
+
"error",
|
|
135
|
+
() => {
|
|
136
|
+
if (extraOptions?.onError) {
|
|
137
|
+
extraOptions.onError("Failed to connect.");
|
|
138
|
+
}
|
|
139
|
+
setIsConnected(false);
|
|
140
|
+
console.warn("No errror handler has been set for the event source");
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
signal: aborter.signal,
|
|
144
|
+
},
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
sourceRef.current.addEventListener(
|
|
148
|
+
"content",
|
|
149
|
+
(ev) => {
|
|
150
|
+
try {
|
|
151
|
+
const data = JSON.parse(ev.data)
|
|
152
|
+
setMessages((prev) => [...prev, data]);
|
|
153
|
+
} catch {
|
|
154
|
+
if (extraOptions?.onError) {
|
|
155
|
+
extraOptions.onError("Failed to decode data")
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
signal: aborter.signal,
|
|
161
|
+
},
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
sourceRef.current.addEventListener(
|
|
165
|
+
"close",
|
|
166
|
+
() => {
|
|
167
|
+
sourceRef.current?.close();
|
|
168
|
+
if (extraOptions?.onClose) {
|
|
169
|
+
extraOptions.onClose();
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
signal: aborter.signal,
|
|
174
|
+
},
|
|
175
|
+
);
|
|
176
|
+
|
|
177
|
+
return () => {
|
|
178
|
+
aborter.abort();
|
|
179
|
+
};
|
|
180
|
+
}, [extraOptions, args]);
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
return {
|
|
184
|
+
messages,
|
|
185
|
+
isConnected,
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
`;
|
|
189
|
+
return await prettier.format(buff, { parser: "babel-ts" });
|
|
190
|
+
}
|
|
191
|
+
async function queryProcedureCodeGen(proc, parentService) {
|
|
192
|
+
// Extract the output typeAlias
|
|
193
|
+
const { outputTypeIdentifier, stringifiedAlias } = getOutputAlias(proc, parentService);
|
|
194
|
+
const inputIdentifier = `${parentService.name}${proc.name}QueryInputSchema`;
|
|
195
|
+
const schema = ztj(proc.input, {
|
|
196
|
+
errorMessages: true,
|
|
197
|
+
markdownDescription: true,
|
|
198
|
+
});
|
|
199
|
+
// @ts-ignore
|
|
200
|
+
const jsonSchema = jtz(schema, {
|
|
201
|
+
withJsdocs: true,
|
|
202
|
+
name: inputIdentifier,
|
|
203
|
+
});
|
|
204
|
+
let buff = `export ${jsonSchema}\nexport ${stringifiedAlias}\n\nexport function use${parentService.name}${proc.name}Query`;
|
|
205
|
+
const extraOptionsType = `Omit<UseQueryOptions<${outputTypeIdentifier}, Error, ${outputTypeIdentifier}, Array<string | z.infer<typeof ${inputIdentifier}>>>, "queryKey" | "queryFn">`;
|
|
206
|
+
buff += `(args: z.infer<typeof ${inputIdentifier}>, extraOptions?: ${extraOptionsType})`;
|
|
207
|
+
// Actual logic of the buffer here
|
|
208
|
+
buff += "{\n";
|
|
209
|
+
buff += `/*${proc.description}*/\n`;
|
|
210
|
+
// Form the keys array with args included
|
|
211
|
+
const staticKeys = [parentService.name, proc.name];
|
|
212
|
+
buff += `\treturn useQuery({queryKey: [${staticKeys.map((k) => `"${k}"`).join(", ")}, args],
|
|
213
|
+
queryFn: async () => {
|
|
214
|
+
const validationResult = await ${inputIdentifier}.safeParseAsync(args)
|
|
215
|
+
if (validationResult.error) {
|
|
216
|
+
console.error("Error on input validation of ${proc.name}", validationResult.error)
|
|
217
|
+
throw new Error(validationResult.error.message)
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
|
|
222
|
+
const response = await fetch('/_api', {
|
|
223
|
+
method: "POST",
|
|
224
|
+
body: JSON.stringify({
|
|
225
|
+
service: '${parentService.name}',
|
|
226
|
+
procedure: '${proc.name}',
|
|
227
|
+
data: validationResult.data
|
|
228
|
+
}),
|
|
229
|
+
})
|
|
230
|
+
|
|
231
|
+
if (!response.ok) {
|
|
232
|
+
let backendErrorMessage = ""
|
|
233
|
+
try {
|
|
234
|
+
backendErrorMessage = await response.text()
|
|
235
|
+
} catch {
|
|
236
|
+
backendErrorMessage = "No Error message returned from backen"
|
|
237
|
+
}
|
|
238
|
+
throw new Error("Query: ${proc.name} Non ok response: " + backendErrorMessage)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const rawResponse = await response.json()
|
|
242
|
+
return rawResponse["data"] as ${outputTypeIdentifier}
|
|
243
|
+
},
|
|
244
|
+
...extraOptions
|
|
245
|
+
}
|
|
246
|
+
)`;
|
|
247
|
+
buff += "}";
|
|
248
|
+
return await prettier.format(buff, { parser: "babel-ts" });
|
|
249
|
+
}
|
|
250
|
+
async function GenerateServiceCode(service) {
|
|
251
|
+
const serviceBuffers = [];
|
|
252
|
+
for (const [pName, proc] of Object.entries(service.procedures)) {
|
|
253
|
+
let procedureCode = "";
|
|
254
|
+
if (proc.method === "MUTATION") {
|
|
255
|
+
procedureCode = await mutationProcedureCodeGen(proc, service);
|
|
256
|
+
}
|
|
257
|
+
else if (proc.method === "QUERY") {
|
|
258
|
+
procedureCode = await queryProcedureCodeGen(proc, service);
|
|
259
|
+
}
|
|
260
|
+
else if (proc.method === "SUBSCRIPTION") {
|
|
261
|
+
procedureCode = await subscriptionProcedureCodeGen(proc, service);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
console.error("UNKOWN METHOD!");
|
|
265
|
+
throw new Error("unk method");
|
|
266
|
+
}
|
|
267
|
+
serviceBuffers.push(procedureCode);
|
|
268
|
+
}
|
|
269
|
+
return serviceBuffers;
|
|
270
|
+
}
|
|
271
|
+
function serviceHasMethod(service, method) {
|
|
272
|
+
for (const [, proc] of Object.entries(service.procedures)) {
|
|
273
|
+
if (proc.method === method) {
|
|
274
|
+
return true;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return false;
|
|
278
|
+
}
|
|
279
|
+
async function getServiceCode(service, code) {
|
|
280
|
+
const prettified = await prettier.format(code, { parser: "babel-ts" });
|
|
281
|
+
return {
|
|
282
|
+
filename: service.name.toLowerCase() + ".service.ts",
|
|
283
|
+
code: code,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
export async function GenerateCode(schema) {
|
|
287
|
+
const out = [];
|
|
288
|
+
for (const [key, service] of Object.entries(schema.services)) {
|
|
289
|
+
let finalBuffer = ``;
|
|
290
|
+
if (serviceHasMethod(service, "MUTATION")) {
|
|
291
|
+
finalBuffer += `import {useMutation, UseMutationOptions} from "@tanstack/react-query";\n`;
|
|
292
|
+
}
|
|
293
|
+
if (serviceHasMethod(service, "QUERY")) {
|
|
294
|
+
finalBuffer += `import {useQuery, UseQueryOptions} from "@tanstack/react-query";\n`;
|
|
295
|
+
}
|
|
296
|
+
if (serviceHasMethod(service, "SUBSCRIPTION")) {
|
|
297
|
+
finalBuffer += `import { useEffect, useRef, useState } from "react";\n`;
|
|
298
|
+
}
|
|
299
|
+
finalBuffer += 'import {z} from "zod"\n\n';
|
|
300
|
+
const buffers = await GenerateServiceCode(service);
|
|
301
|
+
finalBuffer += `// ---- Service Name: ${service.name} ----\n`;
|
|
302
|
+
finalBuffer += buffers.join("\n");
|
|
303
|
+
finalBuffer += "//----";
|
|
304
|
+
out.push(await getServiceCode(service, finalBuffer));
|
|
305
|
+
}
|
|
306
|
+
return out;
|
|
307
|
+
}
|
|
308
|
+
//# sourceMappingURL=client_side.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client_side.js","sourceRoot":"","sources":["../../src/schema/client_side.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
export type ProcedureType = `MUTATION` | `QUERY` | `SUBSCRIPTION`;
|
|
3
|
+
/**
|
|
4
|
+
* Represents a single procedure.
|
|
5
|
+
*/
|
|
6
|
+
export interface Procedure<TMethod extends ProcedureType = ProcedureType, TInput extends z.Schema = z.AnyZodObject, TOuput extends z.Schema = z.AnyZodObject> {
|
|
7
|
+
// The name of the procdedure, must be unique and URI safe.
|
|
8
|
+
name: string;
|
|
9
|
+
// A description of what the procedure is supposed to do
|
|
10
|
+
description: string;
|
|
11
|
+
// The method to be used for the procedure
|
|
12
|
+
method: TMethod;
|
|
13
|
+
// If the method requires an input.
|
|
14
|
+
input: TInput;
|
|
15
|
+
// The output of the endpoint
|
|
16
|
+
output: TOuput;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Router, a container for multiple procedures. It can have a middleware which will run before each procedure.
|
|
20
|
+
*/
|
|
21
|
+
type ServiceProcedures = {
|
|
22
|
+
[procName: string]: Procedure<ProcedureType, any, any>;
|
|
23
|
+
};
|
|
24
|
+
export declare class Service<TProcedures extends ServiceProcedures = {
|
|
25
|
+
[a: string]: Procedure<ProcedureType>;
|
|
26
|
+
}> {
|
|
27
|
+
middlewareDescription?: string | undefined;
|
|
28
|
+
name: string;
|
|
29
|
+
procedures: TProcedures;
|
|
30
|
+
constructor(name: string);
|
|
31
|
+
setMiddlewareDescription(middlewareDescription: string): this;
|
|
32
|
+
// Method to add a procedure - MUTATES the current instance
|
|
33
|
+
addProcedure<M extends ProcedureType, N extends string,
|
|
34
|
+
// Ensure Desc matches the Procedure interface (string | undefined if optional)
|
|
35
|
+
Desc extends string, // Or string | undefined if description is optional
|
|
36
|
+
I extends z.Schema, O extends z.Schema>(procDefinition: {
|
|
37
|
+
method: M;
|
|
38
|
+
name: N;
|
|
39
|
+
description: Desc; // Match interface (required or optional)
|
|
40
|
+
input: I;
|
|
41
|
+
output: O;
|
|
42
|
+
}): Service<
|
|
43
|
+
// The return *type* reflects the added procedure
|
|
44
|
+
TProcedures & {
|
|
45
|
+
[K in N]: Procedure<M, I, O> & {
|
|
46
|
+
method: M;
|
|
47
|
+
name: N;
|
|
48
|
+
description: Desc;
|
|
49
|
+
};
|
|
50
|
+
}>;
|
|
51
|
+
getProcedure<PName extends keyof TProcedures>(name: PName): TProcedures[PName];
|
|
52
|
+
}
|
|
53
|
+
export declare class APISchema<TServices extends Record<string, Service<any>> = {
|
|
54
|
+
[serviceName: string]: Service<any>;
|
|
55
|
+
}> {
|
|
56
|
+
services: TServices;
|
|
57
|
+
constructor(services?: TServices);
|
|
58
|
+
}
|
|
59
|
+
export {};
|
|
60
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,OAAO,GAAG,cAAc,CAAC;AAElE;;GAEG;AACH,MAAM,WAAW,SAAS,CACzB,OAAO,SAAS,aAAa,GAAG,aAAa,EAC7C,MAAM,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,YAAY,EACxC,MAAM,SAAS,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,YAAY;IAExC,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IAEb,wDAAwD;IACxD,WAAW,EAAE,MAAM,CAAC;IAEpB,0CAA0C;IAC1C,MAAM,EAAE,OAAO,CAAC;IAEhB,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;IAEd,6BAA6B;IAC7B,MAAM,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AAEH,KAAK,iBAAiB,GAAG;IACxB,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC,aAAa,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;CACvD,CAAC;AAOF,qBAAa,OAAO,CACnB,WAAW,SAAS,iBAAiB,GAAG;IACvC,CAAC,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC,aAAa,CAAC,CAAC;CACtC;IAED,qBAAqB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3C,IAAI,EAAE,MAAM,CAAM;IAClB,UAAU,EAAE,WAAW,CAAC;IACxB,YAAY,IAAI,EAAE,MAAM,EAIvB;IAED,wBAAwB,CAAC,qBAAqB,EAAE,MAAM,QAGrD;IAED,2DAA2D;IAC3D,YAAY,CACX,CAAC,SAAS,aAAa,EACvB,CAAC,SAAS,MAAM;IAChB,+EAA+E;IAC/E,IAAI,SAAS,MAAM,EAAE,mDAAmD;IACxE,CAAC,SAAS,CAAC,CAAC,MAAM,EAClB,CAAC,SAAS,CAAC,CAAC,MAAM,EACjB,cAAc,EAAE;QACjB,MAAM,EAAE,CAAC,CAAC;QACV,IAAI,EAAE,CAAC,CAAC;QACR,WAAW,EAAE,IAAI,CAAC,CAAC,yCAAyC;QAC5D,KAAK,EAAE,CAAC,CAAC;QACT,MAAM,EAAE,CAAC,CAAC;KACV,GAAG,OAAO;IACV,iDAAiD;IACjD,WAAW,GAAG;SAEZ,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,GAAG;YAAE,MAAM,EAAE,CAAC,CAAC;YAAC,IAAI,EAAE,CAAC,CAAC;YAAC,WAAW,EAAE,IAAI,CAAA;SAAE;KACxE,CACD,CA6BA;IAED,YAAY,CAAC,KAAK,SAAS,MAAM,WAAW,EAC3C,IAAI,EAAE,KAAK,GACT,WAAW,CAAC,KAAK,CAAC,CAIpB;CACD;AAED,qBAAa,SAAS,CACrB,SAAS,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,GAAG;IAChD,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;CACpC;IAEM,QAAQ,EAAE,SAAS,CAAC;IAE3B,YAAY,QAAQ,GAAE,SAA2B,EAEhD;CACD"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export class Service {
|
|
2
|
+
middlewareDescription;
|
|
3
|
+
name = "";
|
|
4
|
+
procedures;
|
|
5
|
+
constructor(name) {
|
|
6
|
+
this.name = name;
|
|
7
|
+
this.procedures = {};
|
|
8
|
+
}
|
|
9
|
+
setMiddlewareDescription(middlewareDescription) {
|
|
10
|
+
this.middlewareDescription = middlewareDescription;
|
|
11
|
+
return this;
|
|
12
|
+
}
|
|
13
|
+
// Method to add a procedure - MUTATES the current instance
|
|
14
|
+
addProcedure(procDefinition) {
|
|
15
|
+
// Create the procedure object explicitly matching the target type structure
|
|
16
|
+
const newProcedure = {
|
|
17
|
+
// Spread the definition to copy properties, ensuring all are included
|
|
18
|
+
...procDefinition,
|
|
19
|
+
};
|
|
20
|
+
// Mutate the internal procedures map.
|
|
21
|
+
// Use a type assertion on `this.procedures` because we're adding a property
|
|
22
|
+
// dynamically. Treat it as a general record for the assignment.
|
|
23
|
+
this.procedures[procDefinition.name] = newProcedure;
|
|
24
|
+
// Return the *same instance* ('this') but CAST its type using 'as'.
|
|
25
|
+
// This tells TypeScript to treat 'this' going forward *as if* it has the
|
|
26
|
+
// new, more specific type that includes the added procedure.
|
|
27
|
+
return this;
|
|
28
|
+
}
|
|
29
|
+
getProcedure(name) {
|
|
30
|
+
// Access using the potentially broader type ServiceProcedures
|
|
31
|
+
// Or just directly access: this.procedures[name as keyof TProcedures]
|
|
32
|
+
return this.procedures[name];
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export class APISchema {
|
|
36
|
+
services;
|
|
37
|
+
constructor(services = {}) {
|
|
38
|
+
this.services = services;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"AAyCA,MAAM,OAAO,OAAO;IAKnB,qBAAqB,CAAsB;IAC3C,IAAI,GAAW,EAAE,CAAC;IAClB,UAAU,CAAc;IACxB,YAAY,IAAY,EAAE;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QAEjB,IAAI,CAAC,UAAU,GAAG,EAAiB,CAAC;IAAA,CACpC;IAED,wBAAwB,CAAC,qBAA6B,EAAE;QACvD,IAAI,CAAC,qBAAqB,GAAG,qBAAqB,CAAC;QACnD,OAAO,IAAI,CAAC;IAAA,CACZ;IAED,2DAA2D;IAC3D,YAAY,CAOV,cAMD,EAMC;QACD,4EAA4E;QAC5E,MAAM,YAAY,GAId;YACH,sEAAsE;YACtE,GAAG,cAAc;SACjB,CAAC;QAEF,sCAAsC;QACtC,4EAA4E;QAC5E,gEAAgE;QAC/D,IAAI,CAAC,UAAgC,CAAC,cAAc,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC;QAE3E,oEAAoE;QACpE,yEAAyE;QACzE,6DAA6D;QAE7D,OAAO,IAQN,CAAC;IAAA,CACF;IAED,YAAY,CACX,IAAW,EACU;QACrB,8DAA8D;QAC9D,sEAAsE;QACtE,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAAA,CAC7B;CACD;AAED,MAAM,OAAO,SAAS;IAKd,QAAQ,CAAY;IAE3B,YAAY,QAAQ,GAAc,EAAe,EAAE;QAClD,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAAA,CACzB;CACD"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Procedure, ProcedureType } from "../schema";
|
|
2
|
+
import type { z } from "zod";
|
|
3
|
+
export declare class Connection {
|
|
4
|
+
stream: ReadableStream<string>;
|
|
5
|
+
streamController: Bun.ReadableStreamController<string>;
|
|
6
|
+
constructor();
|
|
7
|
+
getStream(): ReadableStream<string>;
|
|
8
|
+
}
|
|
9
|
+
export declare class ConnectionWritter<P extends Procedure<ProcedureType, any, any>> {
|
|
10
|
+
private connection;
|
|
11
|
+
private procedureDefinition;
|
|
12
|
+
private closeFn;
|
|
13
|
+
private enqueueFn;
|
|
14
|
+
private closed;
|
|
15
|
+
private keepaliveInterval;
|
|
16
|
+
private _onCloseInternalCallback;
|
|
17
|
+
constructor(conn: Connection, procDefinition: P);
|
|
18
|
+
close(): Promise<void>;
|
|
19
|
+
write(message: z.infer<P["output"]>): Promise<void>;
|
|
20
|
+
onClose(callback: () => void): void;
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=connection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.d.ts","sourceRoot":"","sources":["../../src/server/connection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1D,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,qBAAa,UAAU;IACtB,MAAM,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IAC/B,gBAAgB,EAAE,GAAG,CAAC,wBAAwB,CAAC,MAAM,CAAC,CAAC;IACvD,cAYC;IAED,SAAS,2BAKR;CACD;AAED,qBAAa,iBAAiB,CAAC,CAAC,SAAS,SAAS,CAAC,aAAa,EAAE,GAAG,EAAE,GAAG,CAAC;IAC1E,OAAO,CAAC,UAAU,CAAa;IAC/B,OAAO,CAAC,mBAAmB,CAAI;IAC/B,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,SAAS,CAA8C;IAC/D,OAAO,CAAC,MAAM,CAAU;IAExB,OAAO,CAAC,iBAAiB,CAAQ;IACjC,OAAO,CAAC,wBAAwB,CAA2B;IAC3D,YAAY,IAAI,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC,EAc9C;IAEK,KAAK,kBAqBV;IAEK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,iBAkBxC;IAED,OAAO,CAAC,QAAQ,EAAE,MAAM,IAAI,QAE3B;CACD"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
export class Connection {
|
|
2
|
+
stream;
|
|
3
|
+
streamController;
|
|
4
|
+
constructor() {
|
|
5
|
+
let controllerToBeSet;
|
|
6
|
+
this.stream = new ReadableStream({
|
|
7
|
+
start(controller) {
|
|
8
|
+
controllerToBeSet = controller;
|
|
9
|
+
controller.enqueue(": Connected\n\n");
|
|
10
|
+
},
|
|
11
|
+
});
|
|
12
|
+
if (!controllerToBeSet) {
|
|
13
|
+
throw new Error("No controller has been captured");
|
|
14
|
+
}
|
|
15
|
+
this.streamController = controllerToBeSet;
|
|
16
|
+
}
|
|
17
|
+
getStream() {
|
|
18
|
+
if (this.stream === undefined) {
|
|
19
|
+
throw new Error("No stream has been stablished");
|
|
20
|
+
}
|
|
21
|
+
return this.stream;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export class ConnectionWritter {
|
|
25
|
+
connection;
|
|
26
|
+
procedureDefinition;
|
|
27
|
+
closeFn;
|
|
28
|
+
enqueueFn;
|
|
29
|
+
closed;
|
|
30
|
+
keepaliveInterval;
|
|
31
|
+
_onCloseInternalCallback;
|
|
32
|
+
constructor(conn, procDefinition) {
|
|
33
|
+
this.connection = conn;
|
|
34
|
+
this.procedureDefinition = procDefinition;
|
|
35
|
+
this.closeFn = this.connection.streamController.close.bind(this.connection.streamController);
|
|
36
|
+
this.enqueueFn = this.connection.streamController.enqueue.bind(this.connection.streamController);
|
|
37
|
+
this.closed = false;
|
|
38
|
+
this.keepaliveInterval = setInterval(() => {
|
|
39
|
+
this.enqueueFn(`: keepalive\n\n`);
|
|
40
|
+
}, 30_000);
|
|
41
|
+
}
|
|
42
|
+
async close() {
|
|
43
|
+
if (this.closed) {
|
|
44
|
+
console.log("The connection has been already closed");
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
this.enqueueFn(`event: close\ndata: close\n\n`);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
console.log("[ZYNAPSE SUBSCRIPTION] Failed to send close connection event, has the connection already closed?");
|
|
52
|
+
}
|
|
53
|
+
clearInterval(this.keepaliveInterval);
|
|
54
|
+
if (this._onCloseInternalCallback) {
|
|
55
|
+
this._onCloseInternalCallback();
|
|
56
|
+
}
|
|
57
|
+
this.closeFn();
|
|
58
|
+
this.closed = true;
|
|
59
|
+
}
|
|
60
|
+
async write(message) {
|
|
61
|
+
if (this.closed) {
|
|
62
|
+
throw new Error("Attepted to write on closed connection.");
|
|
63
|
+
}
|
|
64
|
+
/* Write a message to the connection */
|
|
65
|
+
if (this.connection.streamController === undefined) {
|
|
66
|
+
console.error(new Error("Connection not found."));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
const payload = JSON.stringify(message);
|
|
71
|
+
const buff = `event: content\ndata: ${payload}\n\n`;
|
|
72
|
+
this.enqueueFn(buff);
|
|
73
|
+
}
|
|
74
|
+
catch (e) {
|
|
75
|
+
console.log("Error at write method.", e);
|
|
76
|
+
// this.connection.streamController.enqueue(`event: error\ndata: ${e}\n\n`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
onClose(callback) {
|
|
80
|
+
this._onCloseInternalCallback = callback;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection.js","sourceRoot":"","sources":["../../src/server/connection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { BunRequest } from "bun";
|
|
2
|
+
import { APISchema, Service, type Procedure, type ProcedureType } from "../schema";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
import { ConnectionWritter } from "./connection";
|
|
5
|
+
type ContextType = Map<string, any>;
|
|
6
|
+
type SubscriptionHandler<P extends Procedure<ProcedureType, any, any>> = (args: z.infer<P["input"]>, request: BunRequest, context: ContextType, // Information that the middleware is capable of passing to the handler
|
|
7
|
+
connection: ConnectionWritter<P>) => Promise<undefined>;
|
|
8
|
+
type NormalProcedureHandler<P extends Procedure<ProcedureType, any, any>> = (args: z.infer<P["input"]>, request: BunRequest, context: ContextType) => Promise<z.infer<P["output"]>>;
|
|
9
|
+
type ProcedureHandler<P extends Procedure<ProcedureType, any, any>> = P["method"] extends `SUBSCRIPTION` ? SubscriptionHandler<P> : NormalProcedureHandler<P>;
|
|
10
|
+
type FullImplementation<SchemaT extends APISchema> = {
|
|
11
|
+
[ServiceName in keyof SchemaT["services"]]: ServiceImplementationHandlers<SchemaT["services"][ServiceName]>;
|
|
12
|
+
};
|
|
13
|
+
export type MiddlewareFunction = (req: BunRequest, procedureName: string, // The procedure name being executed.
|
|
14
|
+
context: ContextType) => Promise<void>;
|
|
15
|
+
type ServiceImplementationHandlers<ServiceT extends Service> = {
|
|
16
|
+
[ProcName in keyof ServiceT["procedures"]]: ProcedureHandler<ServiceT["procedures"][ProcName]>;
|
|
17
|
+
};
|
|
18
|
+
export declare class ServiceImplementationBuilder<ServiceT extends Service> {
|
|
19
|
+
middleware: MiddlewareFunction | undefined;
|
|
20
|
+
handlers: Partial<ServiceImplementationHandlers<ServiceT>>;
|
|
21
|
+
serviceSchema: ServiceT;
|
|
22
|
+
constructor(serviceSchema: ServiceT);
|
|
23
|
+
registerProcedureImplementation<ProcName extends keyof ServiceT["procedures"]>(procedureName: ProcName, handler: ProcedureHandler<ServiceT["procedures"][ProcName]>): this;
|
|
24
|
+
setMiddleware(middleware: MiddlewareFunction): this;
|
|
25
|
+
build(): ServiceImplementationHandlers<ServiceT>;
|
|
26
|
+
}
|
|
27
|
+
export declare class Server<SchemaT extends APISchema> {
|
|
28
|
+
schema: SchemaT;
|
|
29
|
+
implementation: FullImplementation<SchemaT>;
|
|
30
|
+
private _server;
|
|
31
|
+
private connectionPool;
|
|
32
|
+
constructor(schema: SchemaT, implementation: FullImplementation<SchemaT>);
|
|
33
|
+
private buildHandler;
|
|
34
|
+
start(port?: number): void;
|
|
35
|
+
stop(): Promise<void>;
|
|
36
|
+
}
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,KAAK,CAAC;AACtC,OAAO,EACN,SAAS,EACT,OAAO,EACP,KAAK,SAAS,EACd,KAAK,aAAa,EAClB,MAAM,WAAW,CAAC;AACnB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAAc,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAE7D,KAAK,WAAW,GAAG,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAEpC,KAAK,mBAAmB,CAAC,CAAC,SAAS,SAAS,CAAC,aAAa,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CACxE,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EACzB,OAAO,EAAE,UAAU,EACnB,OAAO,EAAE,WAAW,EAAE,uEAAuE;AAC7F,UAAU,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAC5B,OAAO,CAAC,SAAS,CAAC,CAAC;AAExB,KAAK,sBAAsB,CAAC,CAAC,SAAS,SAAS,CAAC,aAAa,EAAE,GAAG,EAAE,GAAG,CAAC,IAAI,CAC3E,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EACzB,OAAO,EAAE,UAAU,EACnB,OAAO,EAAE,WAAW,KAChB,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAEnC,KAAK,gBAAgB,CAAC,CAAC,SAAS,SAAS,CAAC,aAAa,EAAE,GAAG,EAAE,GAAG,CAAC,IACjE,CAAC,CAAC,QAAQ,CAAC,SAAS,cAAc,GAC/B,mBAAmB,CAAC,CAAC,CAAC,GACtB,sBAAsB,CAAC,CAAC,CAAC,CAAC;AAI9B,KAAK,kBAAkB,CAAC,OAAO,SAAS,SAAS,IAAI;KACnD,WAAW,IAAI,MAAM,OAAO,CAAC,UAAU,CAAC,GAAG,6BAA6B,CACxE,OAAO,CAAC,UAAU,CAAC,CAAC,WAAW,CAAC,CAChC;CACD,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG,CAChC,GAAG,EAAE,UAAU,EACf,aAAa,EAAE,MAAM,EAAE,qCAAqC;AAC5D,OAAO,EAAE,WAAW,KAChB,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB,KAAK,6BAA6B,CAAC,QAAQ,SAAS,OAAO,IAAI;KAC7D,QAAQ,IAAI,MAAM,QAAQ,CAAC,YAAY,CAAC,GAAG,gBAAgB,CAC3D,QAAQ,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,CAChC;CACD,CAAC;AAEF,qBAAa,4BAA4B,CAAC,QAAQ,SAAS,OAAO;IACjE,UAAU,EAAE,kBAAkB,GAAG,SAAS,CAAa;IACvD,QAAQ,EAAE,OAAO,CAAC,6BAA6B,CAAC,QAAQ,CAAC,CAAC,CAAM;IAChE,aAAa,EAAE,QAAQ,CAAC;IACxB,YAAY,aAAa,EAAE,QAAQ,EAElC;IAED,+BAA+B,CAC9B,QAAQ,SAAS,MAAM,QAAQ,CAAC,YAAY,CAAC,EAE7C,aAAa,EAAE,QAAQ,EACvB,OAAO,EAAE,gBAAgB,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,CAAC,QAI3D;IAED,aAAa,CAAC,UAAU,EAAE,kBAAkB,QAG3C;IAED,KAAK,IAAI,6BAA6B,CAAC,QAAQ,CAAC,CAsD/C;CACD;AAyBD,qBAAa,MAAM,CAAC,OAAO,SAAS,SAAS;IAC5C,MAAM,EAAE,OAAO,CAAC;IAChB,cAAc,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC;IAC5C,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,cAAc,CAEpB;IACF,YAAY,MAAM,EAAE,OAAO,EAAE,cAAc,EAAE,kBAAkB,CAAC,OAAO,CAAC,EAIvE;IAED,OAAO,CAAC,YAAY;IAkKpB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,QAgClB;IAEK,IAAI,kBAeT;CACD"}
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
import "../schema";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { Connection, ConnectionWritter } from "./connection";
|
|
4
|
+
async function* x() { }
|
|
5
|
+
export class ServiceImplementationBuilder {
|
|
6
|
+
middleware = undefined;
|
|
7
|
+
handlers = {};
|
|
8
|
+
serviceSchema;
|
|
9
|
+
constructor(serviceSchema) {
|
|
10
|
+
this.serviceSchema = serviceSchema;
|
|
11
|
+
}
|
|
12
|
+
registerProcedureImplementation(procedureName, handler) {
|
|
13
|
+
this.handlers[procedureName] = handler;
|
|
14
|
+
return this;
|
|
15
|
+
}
|
|
16
|
+
setMiddleware(middleware) {
|
|
17
|
+
this.middleware = middleware;
|
|
18
|
+
return this;
|
|
19
|
+
}
|
|
20
|
+
build() {
|
|
21
|
+
const requiredProcedureNames = Object.keys(this.serviceSchema.procedures);
|
|
22
|
+
const implementedProcedureNames = Object.keys(this.handlers);
|
|
23
|
+
const missingProcedures = requiredProcedureNames.filter((pName) => !implementedProcedureNames.includes(pName));
|
|
24
|
+
if (missingProcedures.length > 0) {
|
|
25
|
+
throw new Error(`Service implementation for "${this.serviceSchema.name}" is incomplete. Missing procedures: ${missingProcedures.join(", ")}`);
|
|
26
|
+
}
|
|
27
|
+
const extraProcedures = implementedProcedureNames.filter((pName) => !requiredProcedureNames.includes(pName));
|
|
28
|
+
if (extraProcedures.length > 0) {
|
|
29
|
+
// This case is less likely if using registerProcedureImplementation correctly
|
|
30
|
+
// due to the keyof constraint, but good for robustness.
|
|
31
|
+
console.warn(`Service implementation for "${this.serviceSchema.name}" has extra procedure handlers defined that are not in the schema: ${extraProcedures.join(", ")}`);
|
|
32
|
+
}
|
|
33
|
+
if (this.serviceSchema.middlewareDescription !== undefined &&
|
|
34
|
+
this.middleware === undefined) {
|
|
35
|
+
throw new Error(`A middleware for the service ${this.serviceSchema.name} is required but has not been implemented.`);
|
|
36
|
+
}
|
|
37
|
+
const finalHandlers = { ...this.handlers };
|
|
38
|
+
// Add middleware if defined
|
|
39
|
+
const result = {
|
|
40
|
+
...(this.middleware && { middleware: this.middleware }),
|
|
41
|
+
// Spread the required handlers (already checked for existence)
|
|
42
|
+
...finalHandlers,
|
|
43
|
+
}; // Assert final type
|
|
44
|
+
// Final check to ensure all required keys are present after assembly
|
|
45
|
+
for (const pName of requiredProcedureNames) {
|
|
46
|
+
if (!result[pName]) {
|
|
47
|
+
// This should ideally not happen if the logic above is correct, but acts as a safeguard.
|
|
48
|
+
throw new Error(`Internal error during build: Procedure "${pName}" handler missing in final object for service "${this.serviceSchema.name}".`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const RequestBodySchema = z.object({
|
|
55
|
+
procedure: z.string({ message: "Procedure is not present in the body" }),
|
|
56
|
+
service: z.string({ message: "Service is not present in the body" }),
|
|
57
|
+
data: z.custom((d) => d !== undefined && d !== null, {
|
|
58
|
+
message: "Data must be present",
|
|
59
|
+
}),
|
|
60
|
+
});
|
|
61
|
+
async function* generatorTransform(inp) {
|
|
62
|
+
try {
|
|
63
|
+
for await (const chunk of inp) {
|
|
64
|
+
yield `event: content\ndata: ${JSON.stringify(chunk)}\n\n`;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
catch (e) {
|
|
68
|
+
console.log("Error at iterator.", e);
|
|
69
|
+
yield `event: error\ndata: ${e}\n\n`;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
export class Server {
|
|
73
|
+
schema;
|
|
74
|
+
implementation;
|
|
75
|
+
_server;
|
|
76
|
+
connectionPool;
|
|
77
|
+
constructor(schema, implementation) {
|
|
78
|
+
this.schema = schema;
|
|
79
|
+
this.implementation = implementation;
|
|
80
|
+
this.connectionPool = [];
|
|
81
|
+
}
|
|
82
|
+
buildHandler() {
|
|
83
|
+
return async (request) => {
|
|
84
|
+
// Only open under _api, if not, then close the connection
|
|
85
|
+
const urlObject = new URL(request.url);
|
|
86
|
+
if (urlObject.pathname.split("/")[1] !== "_api") {
|
|
87
|
+
console.log("[ZYNAPSE] The base url of the requested resource is invalid.");
|
|
88
|
+
return new Response(null, {
|
|
89
|
+
status: 400,
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
// Parse the request body
|
|
93
|
+
try {
|
|
94
|
+
let body;
|
|
95
|
+
if (urlObject.searchParams.has("payload")) {
|
|
96
|
+
const p = urlObject.searchParams.get("payload");
|
|
97
|
+
const decodedBody = decodeURIComponent(p);
|
|
98
|
+
body = JSON.parse(decodedBody);
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
body = await request.json();
|
|
102
|
+
}
|
|
103
|
+
const parsedBody = await RequestBodySchema.safeParseAsync(body);
|
|
104
|
+
if (parsedBody.success === false) {
|
|
105
|
+
return new Response(parsedBody.error.message, {
|
|
106
|
+
status: 400,
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
// Now, lets check if we have that procedure.
|
|
110
|
+
const serviceDefinition = this.schema.services[parsedBody.data.service];
|
|
111
|
+
const implementationHandler = this.implementation[parsedBody.data.service];
|
|
112
|
+
if (implementationHandler === undefined ||
|
|
113
|
+
serviceDefinition === undefined) {
|
|
114
|
+
console.error(`[ZYNAPSE] The service ${parsedBody.data.service} doesn't exist`);
|
|
115
|
+
return new Response(`The service ${parsedBody.data.service} doesn't exist`, {
|
|
116
|
+
status: 404,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
// Before proceding to the final execution, lets check if we have the procedure that the client is asking.
|
|
120
|
+
const procedureHandler = implementationHandler[parsedBody.data.procedure];
|
|
121
|
+
const procedureDefinition = serviceDefinition.getProcedure(parsedBody.data.procedure);
|
|
122
|
+
if (procedureHandler === undefined ||
|
|
123
|
+
procedureDefinition === undefined) {
|
|
124
|
+
console.log(`[ZYNAPSE] The procedure ${parsedBody.data.procedure} doesn't exist`);
|
|
125
|
+
return new Response(`The procedure ${parsedBody.data.procedure} doesn't exist`, {
|
|
126
|
+
status: 404,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
// Validate the procedure input
|
|
130
|
+
const parsedArgumentsResult = await procedureDefinition.input.safeParseAsync(parsedBody.data.data);
|
|
131
|
+
if (parsedArgumentsResult.success === false) {
|
|
132
|
+
console.log(`[ZYNAPSE] The input has failed the validation: ${parsedArgumentsResult.error.message}`);
|
|
133
|
+
return new Response(`The input has failed the validation: ${parsedArgumentsResult.error.message}`, {
|
|
134
|
+
status: 400,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
const ctx = new Map();
|
|
138
|
+
// Now, run the middleware if it exists
|
|
139
|
+
if (implementationHandler.middleware !== undefined) {
|
|
140
|
+
console.log("[ZYNAPSE] Running middleware");
|
|
141
|
+
try {
|
|
142
|
+
await implementationHandler.middleware(request, procedureDefinition.name, ctx);
|
|
143
|
+
}
|
|
144
|
+
catch (e) {
|
|
145
|
+
console.log("[ZYNAPSE] Error on middleware", e);
|
|
146
|
+
return new Response(undefined, {
|
|
147
|
+
status: 500,
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
try {
|
|
152
|
+
if (procedureDefinition.method === "SUBSCRIPTION") {
|
|
153
|
+
const conn = new Connection();
|
|
154
|
+
const connWritter = new ConnectionWritter(conn, procedureDefinition);
|
|
155
|
+
request.signal.addEventListener("abort", async () => {
|
|
156
|
+
await connWritter.close();
|
|
157
|
+
});
|
|
158
|
+
this.connectionPool.push(connWritter);
|
|
159
|
+
procedureHandler(parsedArgumentsResult.data, request, ctx, connWritter).catch((e) => {
|
|
160
|
+
console.error(`[ZYNAPSE] [${procedureDefinition.name}-${procedureDefinition.method}] ${e}`);
|
|
161
|
+
});
|
|
162
|
+
return new Response(conn.getStream(), {
|
|
163
|
+
headers: {
|
|
164
|
+
"Content-Type": "text/event-stream",
|
|
165
|
+
"Access-Control-Allow-Origin": "*", // NOTE: Temporal patch to be able to test in localhost
|
|
166
|
+
},
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
const output = await procedureHandler(parsedArgumentsResult.data, request, ctx);
|
|
170
|
+
return new Response(JSON.stringify({
|
|
171
|
+
data: output,
|
|
172
|
+
}), {
|
|
173
|
+
status: 200,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
catch (e) {
|
|
177
|
+
console.error("[ZYNAPSE] The handler threw an error", e);
|
|
178
|
+
return new Response(`The endpoint returned an error ${e}`, {
|
|
179
|
+
status: 500,
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
catch (e) {
|
|
184
|
+
console.log("[ZYNAPSE] The body could not be parsed into JSON", e);
|
|
185
|
+
return new Response("Request cannot be parsed at the moment", {
|
|
186
|
+
status: 500,
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
start(port) {
|
|
192
|
+
if (this._server !== undefined) {
|
|
193
|
+
throw new Error("Cannot start 2 instances of the same server");
|
|
194
|
+
}
|
|
195
|
+
const _port = port || 3000;
|
|
196
|
+
const handler = this.buildHandler();
|
|
197
|
+
this._server = Bun.serve({
|
|
198
|
+
port: _port,
|
|
199
|
+
idleTimeout: 45,
|
|
200
|
+
routes: {
|
|
201
|
+
"/_api": handler,
|
|
202
|
+
},
|
|
203
|
+
async fetch(req) {
|
|
204
|
+
console.log(`[ZYNAPSE] Invalid request received. ${req.url}`);
|
|
205
|
+
return new Response(null, {
|
|
206
|
+
status: 404,
|
|
207
|
+
});
|
|
208
|
+
},
|
|
209
|
+
});
|
|
210
|
+
const stopServer = async () => {
|
|
211
|
+
await this.stop();
|
|
212
|
+
};
|
|
213
|
+
process.on("SIGTERM", stopServer);
|
|
214
|
+
process.on("SIGINT", stopServer);
|
|
215
|
+
process.on("SIGKILL", stopServer);
|
|
216
|
+
process.on("SIGHUP", stopServer);
|
|
217
|
+
console.log(`[ZYNAPSE] Listening on ${_port}`);
|
|
218
|
+
}
|
|
219
|
+
async stop() {
|
|
220
|
+
if (this._server === undefined) {
|
|
221
|
+
console.log("[ZYNAPSE] Nothing to stop");
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
console.log(`[ZYNAPSE] Closing ${this.connectionPool.length} connections`);
|
|
225
|
+
for (const conn of this.connectionPool) {
|
|
226
|
+
await conn.close();
|
|
227
|
+
}
|
|
228
|
+
console.log("[ZYNAPSE] All connections has been closed.");
|
|
229
|
+
await this._server.stop();
|
|
230
|
+
console.log("[ZYNAPSE] Server stopped");
|
|
231
|
+
process.exit(0);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/server/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "zynapse",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "A TypeScript library providing a schema-based API system with type-safe server implementations",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/schema/index.js",
|
|
7
|
+
"module": "./dist/schema/index.js",
|
|
8
|
+
"types": "./dist/schema/index.d.ts",
|
|
9
|
+
"exports": {
|
|
10
|
+
"./schema": {
|
|
11
|
+
"types": "./dist/schema/index.d.ts",
|
|
12
|
+
"import": "./dist/schema/index.js",
|
|
13
|
+
"default": "./dist/schema/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./server": {
|
|
16
|
+
"types": "./dist/server/index.d.ts",
|
|
17
|
+
"import": "./dist/server/index.js",
|
|
18
|
+
"default": "./dist/server/index.js"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"bin": {
|
|
22
|
+
"zynapse-cli": "./dist/cli/index.js"
|
|
23
|
+
},
|
|
24
|
+
"files": [
|
|
25
|
+
"dist",
|
|
26
|
+
"README.md",
|
|
27
|
+
"LICENSE"
|
|
28
|
+
],
|
|
29
|
+
"scripts": {
|
|
30
|
+
"build": "tsgo -p tsconfig.build.json",
|
|
31
|
+
"prepublishOnly": "bun run build",
|
|
32
|
+
"test": "bun test"
|
|
33
|
+
},
|
|
34
|
+
"keywords": [
|
|
35
|
+
"typescript",
|
|
36
|
+
"api",
|
|
37
|
+
"schema",
|
|
38
|
+
"zod",
|
|
39
|
+
"type-safe"
|
|
40
|
+
],
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/bun": "^1.3.2",
|
|
43
|
+
"@typescript/native-preview": "^7.0.0-dev.20250606.1",
|
|
44
|
+
"typescript": "^5.7.2"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"typescript": "^5"
|
|
48
|
+
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"json-schema-to-zod": "^2.6.1",
|
|
51
|
+
"prettier": "^3.5.3",
|
|
52
|
+
"zod": "^3.24.3",
|
|
53
|
+
"zod-to-json-schema": "^3.24.6",
|
|
54
|
+
"zod-to-ts": "^1.2.0"
|
|
55
|
+
}
|
|
56
|
+
}
|