okai 0.0.5 → 0.0.8

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/client.js ADDED
@@ -0,0 +1,39 @@
1
+ import { leftPart } from "./utils.js";
2
+ export function parseTsdHeader(tsd) {
3
+ const header = tsd.includes('/*prompt:')
4
+ ? leftPart(tsd, '*/').replace('/*prompt:', '').trim()
5
+ : null;
6
+ if (!header)
7
+ return null;
8
+ const lines = header.split('\n');
9
+ const to = { prompt: '', api: '' };
10
+ for (const line of lines) {
11
+ if (line.startsWith('api:')) {
12
+ to.api = line.replace('api:', '').trim();
13
+ }
14
+ else if (line.startsWith('migration:')) {
15
+ to.migration = line.replace('migration:', '').trim();
16
+ }
17
+ else if (!to.api && !to.migration && line.trim()) {
18
+ to.prompt += line.trim() + '\n';
19
+ }
20
+ }
21
+ if (!to.api)
22
+ return null;
23
+ to.prompt = to.prompt.trim();
24
+ to.api = to.api.trim();
25
+ if (to.migration)
26
+ to.migration = to.migration.trim();
27
+ return to;
28
+ }
29
+ export function toTsdHeader(header) {
30
+ const sb = [
31
+ `/*prompt: ${header.prompt}`,
32
+ `api: ${header.api}`,
33
+ ];
34
+ if (header.migration) {
35
+ sb.push(`migration: ${header.migration}`);
36
+ }
37
+ sb.push('*/');
38
+ return sb.join('\n');
39
+ }
@@ -0,0 +1,123 @@
1
+ import { getGroupName, splitCase } from "./utils.js";
2
+ import { CSharpGenerator } from "./cs-gen.js";
3
+ export class CSharpApiGenerator extends CSharpGenerator {
4
+ toApiClass(op) {
5
+ const cls = op.request;
6
+ const sb = [];
7
+ let clsDef = `public class ${cls.name}`;
8
+ let doesExtend = false;
9
+ if (cls.inherits) {
10
+ this.addNamespace(cls.inherits.namespace);
11
+ clsDef += ` : ${this.toTypeRef(cls.inherits)}`;
12
+ doesExtend = true;
13
+ }
14
+ if (cls.implements?.length) {
15
+ clsDef += (cls.inherits ? ', ' : ' : ') + `${cls.implements.map(x => this.toTypeRef(x)).join(', ')}`;
16
+ doesExtend = true;
17
+ }
18
+ if (!cls.inherits?.name.startsWith('QueryDb`') && !cls.inherits?.name.startsWith('QueryData`')) {
19
+ if (op.returnType || op.returnsVoid) {
20
+ clsDef += (doesExtend ? `, ` : ` : `) + (op.returnType
21
+ ? `IReturn<${this.toTypeRef(op.returnType)}>`
22
+ : `IReturnVoid`);
23
+ }
24
+ }
25
+ if (op.tags?.length) {
26
+ for (const tag of op.tags) {
27
+ sb.push(`[Tag("${tag}")]`);
28
+ }
29
+ }
30
+ if (op.requiredRoles?.length) {
31
+ const adminRole = op.requiredRoles.includes('Admin');
32
+ if (adminRole) {
33
+ sb.push(`[ValidateIsAdmin]`);
34
+ }
35
+ const roles = op.requiredRoles.filter(r => r !== 'Admin');
36
+ if (roles.length) {
37
+ sb.push(`[ValidateHasRole("${roles[0]}")]`);
38
+ }
39
+ }
40
+ else if (op.requiresAuth) {
41
+ sb.push(`[ValidateIsAuthenticated]`);
42
+ }
43
+ if (cls.description) {
44
+ sb.push(`[Api("${cls.description}")]`);
45
+ }
46
+ for (const attr of cls.attributes ?? []) {
47
+ sb.push(this.toAttribtue(attr));
48
+ }
49
+ if (op.routes?.length) {
50
+ for (const route of op.routes) {
51
+ sb.push(`[Route("${route.path}", "${route.verbs ?? "POST"}")]`);
52
+ }
53
+ }
54
+ sb.push(clsDef);
55
+ sb.push('{');
56
+ for (const prop of cls.properties) {
57
+ this.addNamespace(prop.namespace);
58
+ if (prop.description) {
59
+ if (!prop.description.includes('\n')) {
60
+ sb.push(` [ApiMember(Description="${prop.description.replace(/"/g, '\\"')}")]`);
61
+ }
62
+ else {
63
+ sb.push(` [ApiMember(Description=\n` +
64
+ ` """\n` +
65
+ ` ${prop.description.replaceAll('\n', '\n ')}\n` +
66
+ ` """)]`);
67
+ }
68
+ }
69
+ for (const attr of prop.attributes ?? []) {
70
+ const def = this.toAttribtue(attr);
71
+ sb.push(` ${def}`);
72
+ }
73
+ const propType = { name: prop.type, namespace: prop.namespace, genericArgs: prop.genericArgs };
74
+ sb.push(` public ${this.toTypeRef(propType)} ${prop.name} { get; set; }`);
75
+ }
76
+ sb.push('}');
77
+ return sb.join('\n');
78
+ }
79
+ generate(ast) {
80
+ const groupName = getGroupName(ast);
81
+ const friendlyGroupName = splitCase(groupName);
82
+ ast.operations.forEach(op => {
83
+ if (!op.tags)
84
+ op.tags = [];
85
+ op.tags.push(friendlyGroupName);
86
+ });
87
+ this.namespaces = Array.from(ast.namespaces);
88
+ this.apis = ast.operations.map(x => this.toApiClass(x));
89
+ this.classes = ast.types.filter(t => !t.isEnum).map(x => this.toClass(x));
90
+ this.enums = ast.types.filter(t => t.isEnum).map(x => this.toEnum(x));
91
+ const fileName = groupName + '.cs';
92
+ const sb = [];
93
+ for (const ns of this.namespaces) {
94
+ sb.push(`using ${ns};`);
95
+ }
96
+ sb.push('');
97
+ sb.push(`namespace MyApp.ServiceModel;`);
98
+ sb.push('');
99
+ if (this.apis.length) {
100
+ for (const cls of this.apis) {
101
+ sb.push(cls);
102
+ sb.push('');
103
+ }
104
+ sb.push('');
105
+ }
106
+ if (this.classes.length) {
107
+ for (const cls of this.classes) {
108
+ sb.push(cls);
109
+ sb.push('');
110
+ }
111
+ sb.push('');
112
+ }
113
+ if (this.enums.length) {
114
+ for (const cls of this.enums) {
115
+ sb.push(cls);
116
+ sb.push('');
117
+ }
118
+ sb.push('');
119
+ }
120
+ const cs = sb.join('\n');
121
+ return { [`MyApp.ServiceModel/${fileName}`]: cs };
122
+ }
123
+ }