@seam-rpc/server 4.3.21 → 5.0.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/dist/bin/generate.js +27 -6
- package/dist/index copy.d.ts +84 -0
- package/dist/index copy.js +254 -0
- package/dist/index.d.ts +37 -29
- package/dist/index.js +171 -189
- package/dist/router.d.ts +14 -0
- package/dist/router.js +197 -0
- package/package.json +1 -1
- package/dist/bin/gen-client.js +0 -193
- package/dist/bin/gen-config.js +0 -44
- package/dist/test.d.ts +0 -2
- package/dist/test.js +0 -56
- package/dist/validation.js +0 -54
package/dist/bin/gen-client.js
DELETED
|
@@ -1,193 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import path from "path";
|
|
3
|
-
import fg from "fast-glob";
|
|
4
|
-
import ts from "typescript";
|
|
5
|
-
import * as z from "zod";
|
|
6
|
-
import { zodToTs, createAuxiliaryTypeStore, printNode } from "zod-to-ts";
|
|
7
|
-
import { existsSync, writeFileSync } from "fs";
|
|
8
|
-
export async function genClient() {
|
|
9
|
-
const args = process.argv;
|
|
10
|
-
let config;
|
|
11
|
-
if (args.length == 3) {
|
|
12
|
-
// Use config
|
|
13
|
-
// Check if config exists
|
|
14
|
-
if (!fs.existsSync("./seam-rpc.config.json"))
|
|
15
|
-
return console.error("\x1b[31mCommand arguments omitted and no config file found.\x1b[0m\n"
|
|
16
|
-
+ "Either define a config file with \x1b[36mseam-rpc gen-config\x1b[0m or generate the client files using \x1b[36mseam-rpc gen-client <input-files> <output-folder> [global-types-file]\x1b[0m.");
|
|
17
|
-
// Load config from config file
|
|
18
|
-
config = JSON.parse(fs.readFileSync("./seam-rpc.config.json", "utf-8"));
|
|
19
|
-
}
|
|
20
|
-
else if (args.length == 5 || args.length == 6) {
|
|
21
|
-
// Use command args
|
|
22
|
-
// Load config from command args
|
|
23
|
-
config = {
|
|
24
|
-
inputFiles: args[3],
|
|
25
|
-
outputFolder: args[4]
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
// Invalid command usage
|
|
30
|
-
return console.error("Usage: seam-rpc gen-client <input-files> <output-folder>");
|
|
31
|
-
}
|
|
32
|
-
const inputFiles = await fg(config.inputFiles);
|
|
33
|
-
const outputPath = path.resolve(config.outputFolder);
|
|
34
|
-
const rootPath = path.resolve(".");
|
|
35
|
-
try {
|
|
36
|
-
const outputFiles = [];
|
|
37
|
-
for (const inputFile of inputFiles) {
|
|
38
|
-
// console.log(getProcedureInfo(inputFile));
|
|
39
|
-
const outputFile = await generateClientFile(inputFile, outputPath);
|
|
40
|
-
outputFiles.push(removeRootPath(outputFile, rootPath));
|
|
41
|
-
}
|
|
42
|
-
console.log("\x1b[32m%s\x1b[0m\n\x1b[36m%s\x1b[0m", `✅ Successfully generated client files at ${removeRootPath(outputPath, rootPath)}`, `${outputFiles.join("\n")}`);
|
|
43
|
-
}
|
|
44
|
-
catch (err) {
|
|
45
|
-
console.error("❌ Failed to generate client file:", err.message);
|
|
46
|
-
process.exit(1);
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
// interface ProcedureInfo {
|
|
50
|
-
// name: string;
|
|
51
|
-
// inputType: string;
|
|
52
|
-
// outputType: string;
|
|
53
|
-
// comments: string;
|
|
54
|
-
// }
|
|
55
|
-
// export function getProcedureInfo(filePath: string): ProcedureInfo[] {
|
|
56
|
-
// const fullPath = path.resolve(filePath);
|
|
57
|
-
// const sourceText = fs.readFileSync(fullPath, "utf8");
|
|
58
|
-
// const sourceFile = ts.createSourceFile(
|
|
59
|
-
// fullPath,
|
|
60
|
-
// sourceText,
|
|
61
|
-
// ts.ScriptTarget.Latest,
|
|
62
|
-
// true,
|
|
63
|
-
// ts.ScriptKind.TS
|
|
64
|
-
// );
|
|
65
|
-
// const procedures: ProcedureInfo[] = [];
|
|
66
|
-
// function visit(node: ts.Node) {
|
|
67
|
-
// // Look for const assignments
|
|
68
|
-
// if (ts.isVariableStatement(node)) {
|
|
69
|
-
// node.declarationList.declarations.forEach((decl) => {
|
|
70
|
-
// if (ts.isIdentifier(decl.name) && decl.initializer) {
|
|
71
|
-
// let varName = decl.name.text;
|
|
72
|
-
// let inputType = "";
|
|
73
|
-
// let outputType = "";
|
|
74
|
-
// let comments = "";
|
|
75
|
-
// const jsDocs = ts.getJSDocCommentsAndTags(node); // node = VariableStatement
|
|
76
|
-
// // Get JSDoc comments
|
|
77
|
-
// if (jsDocs.length > 0) {
|
|
78
|
-
// comments = jsDocs.map(doc => doc.getText()).join("\n");
|
|
79
|
-
// }
|
|
80
|
-
// // Check for chain calls: .input(...).output(...)
|
|
81
|
-
// if (ts.isCallExpression(decl.initializer) || ts.isPropertyAccessExpression(decl.initializer)) {
|
|
82
|
-
// function extractChain(expr: ts.Expression) {
|
|
83
|
-
// if (ts.isCallExpression(expr)) {
|
|
84
|
-
// if (ts.isPropertyAccessExpression(expr.expression)) {
|
|
85
|
-
// const propName = expr.expression.name.text;
|
|
86
|
-
// if (propName === "input" && expr.arguments.length > 0) {
|
|
87
|
-
// inputType = expr.arguments[0].getText();
|
|
88
|
-
// } else if (propName === "output" && expr.arguments.length > 0) {
|
|
89
|
-
// outputType = expr.arguments[0].getText();
|
|
90
|
-
// }
|
|
91
|
-
// extractChain(expr.expression.expression);
|
|
92
|
-
// }
|
|
93
|
-
// } else if (ts.isPropertyAccessExpression(expr)) {
|
|
94
|
-
// extractChain(expr.expression);
|
|
95
|
-
// }
|
|
96
|
-
// }
|
|
97
|
-
// extractChain(decl.initializer);
|
|
98
|
-
// }
|
|
99
|
-
// if (inputType || outputType || comments) {
|
|
100
|
-
// procedures.push({ name: varName, inputType, outputType, comments });
|
|
101
|
-
// }
|
|
102
|
-
// }
|
|
103
|
-
// });
|
|
104
|
-
// }
|
|
105
|
-
// ts.forEachChild(node, visit);
|
|
106
|
-
// }
|
|
107
|
-
// visit(sourceFile);
|
|
108
|
-
// return procedures;
|
|
109
|
-
// }
|
|
110
|
-
function removeRootPath(path, rootPath) {
|
|
111
|
-
return "." + path.slice(rootPath.length);
|
|
112
|
-
}
|
|
113
|
-
async function generateClientFile(sourcePath, outputPath) {
|
|
114
|
-
const sourceFile = path.resolve(process.cwd(), sourcePath);
|
|
115
|
-
if (!existsSync(sourceFile)) {
|
|
116
|
-
console.error(`File ${sourceFile} not found`);
|
|
117
|
-
process.exit(1);
|
|
118
|
-
}
|
|
119
|
-
const module = await import("file://" + sourceFile);
|
|
120
|
-
const procedures = module.default;
|
|
121
|
-
const routerName = path.basename(sourceFile, path.extname(sourceFile));
|
|
122
|
-
let fileContent = `/* Auto-generated by SeamRPC - DO NOT EDIT */
|
|
123
|
-
|
|
124
|
-
import { callApi } from \"@seam-rpc/client\";
|
|
125
|
-
|
|
126
|
-
`;
|
|
127
|
-
// Parse the source file using TypeScript API
|
|
128
|
-
const program = ts.createProgram([sourceFile], {});
|
|
129
|
-
const tsFile = program.getSourceFile(sourceFile);
|
|
130
|
-
// Helper to get JSDoc comment for a variable
|
|
131
|
-
function getJsDocComment(node) {
|
|
132
|
-
const jsDocs = node.jsDoc;
|
|
133
|
-
if (!jsDocs || jsDocs.length === 0)
|
|
134
|
-
return "";
|
|
135
|
-
return jsDocs.map(doc => doc.comment).filter(Boolean).join("\n");
|
|
136
|
-
}
|
|
137
|
-
const functions = [];
|
|
138
|
-
for (const [procName, proc] of Object.entries(procedures)) {
|
|
139
|
-
// Input
|
|
140
|
-
const input = [];
|
|
141
|
-
if (proc._def.input) {
|
|
142
|
-
for (const [paramName, param] of Object.entries(proc._def.input)) {
|
|
143
|
-
input.push(`${paramName}${param instanceof z.ZodOptional ? "?" : ""}: ${convert(param)}`);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
// Output
|
|
147
|
-
const returnType = proc._def.output ? convert(proc._def.output) : "void";
|
|
148
|
-
// Input
|
|
149
|
-
const hasInput = input.length != 0;
|
|
150
|
-
const params = hasInput ? `input: { ${input.join(", ")} }` : "";
|
|
151
|
-
// Function body
|
|
152
|
-
const body = `return callApi("${routerName}", "${procName}"${hasInput ? ", input" : ""});`;
|
|
153
|
-
// Comments
|
|
154
|
-
let comments = "";
|
|
155
|
-
ts.forEachChild(tsFile, node => {
|
|
156
|
-
if (ts.isVariableStatement(node)) {
|
|
157
|
-
node.declarationList.declarations.forEach(decl => {
|
|
158
|
-
console.log(decl.name.getText(), procName);
|
|
159
|
-
if (decl.name.getText() === procName) {
|
|
160
|
-
const doc = getJsDocComment(decl);
|
|
161
|
-
if (doc)
|
|
162
|
-
comments = `/** ${doc} */\n`;
|
|
163
|
-
}
|
|
164
|
-
});
|
|
165
|
-
}
|
|
166
|
-
});
|
|
167
|
-
const func = `${comments}export function ${procName}(${params}): Promise<${returnType}> { ${body} }`;
|
|
168
|
-
functions.push(func);
|
|
169
|
-
}
|
|
170
|
-
fileContent += functions.join("\n\n");
|
|
171
|
-
writeFileSync(`${outputPath}/${routerName}.ts`, fileContent, "utf-8");
|
|
172
|
-
return sourceFile;
|
|
173
|
-
}
|
|
174
|
-
function convert(schema) {
|
|
175
|
-
const auxiliaryTypeStore = createAuxiliaryTypeStore();
|
|
176
|
-
const { node } = zodToTs(schema, { auxiliaryTypeStore });
|
|
177
|
-
return printNode(node);
|
|
178
|
-
}
|
|
179
|
-
// function zodToTs(schema: z.ZodType): { value: string, definition?: string } {
|
|
180
|
-
// if (schema instanceof z.ZodString) {
|
|
181
|
-
// return { value: "string" };
|
|
182
|
-
// }
|
|
183
|
-
// if (schema instanceof z.ZodNumber) {
|
|
184
|
-
// return { value: "number" };
|
|
185
|
-
// }
|
|
186
|
-
// if (schema instanceof z.ZodArray) {
|
|
187
|
-
// return { value: zodToTs(schema.def.type) + "[]" };
|
|
188
|
-
// }
|
|
189
|
-
// if (schema instanceof z.ZodOptional) {
|
|
190
|
-
// return {value: };
|
|
191
|
-
// }
|
|
192
|
-
// return { value: "any" };
|
|
193
|
-
// }
|
package/dist/bin/gen-config.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import fs from "fs";
|
|
2
|
-
import readline from "readline";
|
|
3
|
-
export async function genConfig() {
|
|
4
|
-
const args = process.argv;
|
|
5
|
-
let inputFiles = "./src/api/*";
|
|
6
|
-
let outputFolder = "../client/src/api";
|
|
7
|
-
if (args.length == 5) {
|
|
8
|
-
inputFiles = args[3];
|
|
9
|
-
outputFolder = args[4];
|
|
10
|
-
}
|
|
11
|
-
else if (args.length > 3) {
|
|
12
|
-
return console.error("Usage: seam-rpc gen-config [input-files] [output-folder]");
|
|
13
|
-
}
|
|
14
|
-
if (fs.existsSync("./seam-rpc.config.json")) {
|
|
15
|
-
const rl = readline.createInterface({
|
|
16
|
-
input: process.stdin,
|
|
17
|
-
output: process.stdout,
|
|
18
|
-
});
|
|
19
|
-
rl.question("Config file already exists. Do you want to overwrite it? [Y/n] ", answer => {
|
|
20
|
-
if (answer && answer.toLowerCase() != "y" && answer.toLowerCase() != "yes") {
|
|
21
|
-
console.log("Operation canceled.");
|
|
22
|
-
process.exit(0);
|
|
23
|
-
}
|
|
24
|
-
rl.close();
|
|
25
|
-
generateConfig();
|
|
26
|
-
});
|
|
27
|
-
}
|
|
28
|
-
else {
|
|
29
|
-
generateConfig();
|
|
30
|
-
}
|
|
31
|
-
function generateConfig() {
|
|
32
|
-
const config = {
|
|
33
|
-
inputFiles,
|
|
34
|
-
outputFolder
|
|
35
|
-
};
|
|
36
|
-
try {
|
|
37
|
-
fs.writeFileSync("./seam-rpc.config.json", JSON.stringify(config, null, 4), "utf-8");
|
|
38
|
-
}
|
|
39
|
-
catch (e) {
|
|
40
|
-
console.log("\x1b[31mFailed to generate config file ./seam-rpc.config.json\x1b[0m\n" + e);
|
|
41
|
-
}
|
|
42
|
-
console.log(`\x1b[32mSuccessfully generated config file ./seam-rpc.config.json\x1b[0m`);
|
|
43
|
-
}
|
|
44
|
-
}
|
package/dist/test.d.ts
DELETED
package/dist/test.js
DELETED
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
import { zodToTs, createAuxiliaryTypeStore, printNode } from "zod-to-ts";
|
|
2
|
-
import * as z from "zod";
|
|
3
|
-
import ts from "typescript";
|
|
4
|
-
export function convert(schema) {
|
|
5
|
-
const store = createAuxiliaryTypeStore();
|
|
6
|
-
const { node } = zodToTs(schema, {
|
|
7
|
-
auxiliaryTypeStore: store,
|
|
8
|
-
});
|
|
9
|
-
const typeAlias = ts.factory.createTypeAliasDeclaration([ts.factory.createModifier(ts.SyntaxKind.ExportKeyword)], ts.factory.createIdentifier("GeneratedType"), undefined, node);
|
|
10
|
-
const file = ts.createSourceFile("types.ts", "", ts.ScriptTarget.Latest, false, ts.ScriptKind.TS);
|
|
11
|
-
const printer = ts.createPrinter({
|
|
12
|
-
newLine: ts.NewLineKind.LineFeed,
|
|
13
|
-
removeComments: false,
|
|
14
|
-
});
|
|
15
|
-
return printer.printNode(ts.EmitHint.Unspecified, typeAlias, file);
|
|
16
|
-
}
|
|
17
|
-
function convert2(schema) {
|
|
18
|
-
const store = createAuxiliaryTypeStore();
|
|
19
|
-
const { node } = zodToTs(schema, { auxiliaryTypeStore: store });
|
|
20
|
-
return printNode(node);
|
|
21
|
-
}
|
|
22
|
-
console.log(convert2(z.object({
|
|
23
|
-
user: z.object({
|
|
24
|
-
email: z.string(),
|
|
25
|
-
id: z.string(),
|
|
26
|
-
createdAt: z.date(),
|
|
27
|
-
firstName: z.string(),
|
|
28
|
-
lastName: z.string(),
|
|
29
|
-
trackingStartDate: z.string(),
|
|
30
|
-
trackingWorkItemId: z.string(),
|
|
31
|
-
}),
|
|
32
|
-
roles: z.object({
|
|
33
|
-
id: z.string(),
|
|
34
|
-
name: z.string(),
|
|
35
|
-
createdAt: z.date(),
|
|
36
|
-
permissions: z.number().array(),
|
|
37
|
-
projectId: z.string(),
|
|
38
|
-
}),
|
|
39
|
-
workItems: z.object({
|
|
40
|
-
id: z.string(),
|
|
41
|
-
createdAt: z.date(),
|
|
42
|
-
date: z.date(),
|
|
43
|
-
link: z.string(),
|
|
44
|
-
title: z.string(),
|
|
45
|
-
description: z.string(),
|
|
46
|
-
projectId: z.string(),
|
|
47
|
-
authorId: z.string(),
|
|
48
|
-
durationMethod: z.string(),
|
|
49
|
-
startTime: z.number(),
|
|
50
|
-
endTime: z.number(),
|
|
51
|
-
duration: z.number(),
|
|
52
|
-
labels: z.string(),
|
|
53
|
-
updatedAt: z.string(),
|
|
54
|
-
projectMemberId: z.string(),
|
|
55
|
-
})
|
|
56
|
-
})));
|
package/dist/validation.js
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
export class ValString {
|
|
2
|
-
constructor(value) {
|
|
3
|
-
this._isValid = true;
|
|
4
|
-
this._value = value;
|
|
5
|
-
}
|
|
6
|
-
get isValid() {
|
|
7
|
-
return this._isValid;
|
|
8
|
-
}
|
|
9
|
-
min(value) {
|
|
10
|
-
if (this._isValid)
|
|
11
|
-
this._isValid = this._value.length >= value;
|
|
12
|
-
return this;
|
|
13
|
-
}
|
|
14
|
-
max(value) {
|
|
15
|
-
if (this._isValid)
|
|
16
|
-
this._isValid = this._value.length <= value;
|
|
17
|
-
return this;
|
|
18
|
-
}
|
|
19
|
-
length(value) {
|
|
20
|
-
if (this._isValid)
|
|
21
|
-
this._isValid = this._value.length == value;
|
|
22
|
-
return this;
|
|
23
|
-
}
|
|
24
|
-
startsWith(value) {
|
|
25
|
-
if (this._isValid)
|
|
26
|
-
this._isValid = this._value.startsWith(value);
|
|
27
|
-
return this;
|
|
28
|
-
}
|
|
29
|
-
endsWith(value) {
|
|
30
|
-
if (this._isValid)
|
|
31
|
-
this._isValid = this._value.endsWith(value);
|
|
32
|
-
return this;
|
|
33
|
-
}
|
|
34
|
-
includes(value) {
|
|
35
|
-
if (this._isValid)
|
|
36
|
-
this._isValid = this._value.includes(value);
|
|
37
|
-
return this;
|
|
38
|
-
}
|
|
39
|
-
regex(regExpr) {
|
|
40
|
-
// if (this._isValid)
|
|
41
|
-
// this._isValid = this._value.startsWith(value);
|
|
42
|
-
return this;
|
|
43
|
-
}
|
|
44
|
-
email() {
|
|
45
|
-
return this;
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
function createUser(name, age, data) {
|
|
49
|
-
name.min(3).max(50);
|
|
50
|
-
age.gte(1).lt(150);
|
|
51
|
-
data.description?.max(250);
|
|
52
|
-
}
|
|
53
|
-
function validate(data) {
|
|
54
|
-
}
|