sonamu 0.7.16 → 0.7.18
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/ai/providers/rtzr/error.d.ts +1 -1
- package/dist/ai/providers/rtzr/error.d.ts.map +1 -1
- package/dist/api/config.d.ts +1 -0
- package/dist/api/config.d.ts.map +1 -1
- package/dist/api/config.js +1 -1
- package/dist/api/decorators.d.ts +1 -1
- package/dist/api/decorators.d.ts.map +1 -1
- package/dist/api/decorators.js +1 -1
- package/dist/api/sonamu.d.ts +3 -1
- package/dist/api/sonamu.d.ts.map +1 -1
- package/dist/api/sonamu.js +48 -38
- package/dist/syncer/checksum.d.ts +8 -3
- package/dist/syncer/checksum.d.ts.map +1 -1
- package/dist/syncer/checksum.js +17 -9
- package/dist/syncer/code-generator.js +7 -2
- package/dist/syncer/syncer.d.ts +6 -6
- package/dist/syncer/syncer.d.ts.map +1 -1
- package/dist/syncer/syncer.js +27 -13
- package/dist/template/implementations/model.template.js +5 -5
- package/dist/template/implementations/services.template.d.ts +17 -0
- package/dist/template/implementations/services.template.d.ts.map +1 -0
- package/dist/template/implementations/services.template.js +180 -0
- package/dist/template/implementations/view_form.template.js +2 -2
- package/dist/template/implementations/view_id_async_select.template.js +2 -2
- package/dist/template/implementations/view_list.template.js +5 -5
- package/dist/types/types.d.ts +2 -14
- package/dist/types/types.d.ts.map +1 -1
- package/dist/types/types.js +3 -15
- package/dist/ui/ai-api.d.ts +2 -0
- package/dist/ui/ai-api.d.ts.map +1 -1
- package/dist/ui/ai-api.js +43 -49
- package/dist/ui/ai-client.d.ts +10 -0
- package/dist/ui/ai-client.d.ts.map +1 -1
- package/dist/ui/ai-client.js +457 -437
- package/dist/ui/api.d.ts.map +1 -1
- package/dist/ui/api.js +3 -1
- package/dist/ui-web/assets/index-DFqVuxOB.js +92 -0
- package/dist/ui-web/index.html +1 -1
- package/package.json +9 -5
- package/src/api/config.ts +3 -0
- package/src/api/decorators.ts +6 -1
- package/src/api/sonamu.ts +68 -50
- package/src/shared/app.shared.ts.txt +1 -1
- package/src/shared/web.shared.ts.txt +0 -43
- package/src/syncer/checksum.ts +31 -9
- package/src/syncer/code-generator.ts +8 -1
- package/src/syncer/syncer.ts +38 -26
- package/src/template/implementations/model.template.ts +4 -4
- package/src/template/implementations/services.template.ts +265 -0
- package/src/template/implementations/view_form.template.ts +1 -1
- package/src/template/implementations/view_id_async_select.template.ts +1 -1
- package/src/template/implementations/view_list.template.ts +4 -4
- package/src/types/types.ts +2 -14
- package/src/ui/ai-api.ts +61 -60
- package/src/ui/ai-client.ts +535 -499
- package/src/ui/api.ts +3 -0
- package/src/ui/entity.instructions.md +536 -0
- package/dist/template/implementations/service.template.d.ts +0 -29
- package/dist/template/implementations/service.template.d.ts.map +0 -1
- package/dist/template/implementations/service.template.js +0 -202
- package/dist/ui-web/assets/index-BcbbB-BB.js +0 -95
- package/dist/ui-web/assets/provider-utils_false-BKJD46kk.js +0 -1
- package/dist/ui-web/assets/provider-utils_false-Bu5lmX18.js +0 -1
- package/src/template/implementations/service.template.ts +0 -328
|
@@ -1 +0,0 @@
|
|
|
1
|
-
throw new Error('Could not resolve "@valibot/to-json-schema" imported by "@ai-sdk/provider-utils".');
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
throw new Error('Could not resolve "effect" imported by "@ai-sdk/provider-utils".');
|
|
@@ -1,328 +0,0 @@
|
|
|
1
|
-
import assert from "assert";
|
|
2
|
-
import inflection from "inflection";
|
|
3
|
-
import { diff, group, sort, unique } from "radashi";
|
|
4
|
-
import {
|
|
5
|
-
apiParamToTsCode,
|
|
6
|
-
apiParamToTsCodeAsObject,
|
|
7
|
-
apiParamTypeToTsType,
|
|
8
|
-
unwrapPromiseOnce,
|
|
9
|
-
} from "../../api/code-converters";
|
|
10
|
-
import type { ExtendedApi } from "../../api/decorators";
|
|
11
|
-
import { Sonamu } from "../../api/sonamu";
|
|
12
|
-
import type { EntityNamesRecord } from "../../entity/entity-manager";
|
|
13
|
-
import { Naite } from "../../naite/naite";
|
|
14
|
-
import type { TemplateOptions } from "../../types/types";
|
|
15
|
-
import { type ApiParam, ApiParamType } from "../../types/types";
|
|
16
|
-
import { assertDefined } from "../../utils/utils";
|
|
17
|
-
import { Template } from "../template";
|
|
18
|
-
import { zodTypeToTsTypeDef } from "../zod-converter";
|
|
19
|
-
|
|
20
|
-
export class Template__service extends Template {
|
|
21
|
-
constructor() {
|
|
22
|
-
super("service");
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
getTargetAndPath(names: EntityNamesRecord) {
|
|
26
|
-
return {
|
|
27
|
-
target: ":target/src/services",
|
|
28
|
-
path: `${names.fs}/${names.fs}.service.ts`,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
render({ namesRecord }: TemplateOptions["service"]) {
|
|
33
|
-
Naite.t("render", { namesRecord });
|
|
34
|
-
|
|
35
|
-
const {
|
|
36
|
-
syncer: { apis },
|
|
37
|
-
} = Sonamu;
|
|
38
|
-
|
|
39
|
-
const apisForThisModel = apis.filter(
|
|
40
|
-
(api) =>
|
|
41
|
-
api.modelName === `${namesRecord.capital}Model` ||
|
|
42
|
-
api.modelName === `${namesRecord.capital}Frame`,
|
|
43
|
-
);
|
|
44
|
-
|
|
45
|
-
// 서비스 TypeSource
|
|
46
|
-
const { lines, importKeys } = this.getTypeSource(apisForThisModel);
|
|
47
|
-
|
|
48
|
-
// AxiosProgressEvent 있는지 확인
|
|
49
|
-
const hasAxiosProgressEvent = apis.find((api) =>
|
|
50
|
-
(api.options.clients ?? []).includes("axios-multipart"),
|
|
51
|
-
);
|
|
52
|
-
|
|
53
|
-
return {
|
|
54
|
-
...this.getTargetAndPath(namesRecord),
|
|
55
|
-
body: lines.join("\n"),
|
|
56
|
-
importKeys: importKeys.filter((key) => ["ListResult"].includes(key) === false),
|
|
57
|
-
customHeaders: [
|
|
58
|
-
`import { z } from 'zod';`,
|
|
59
|
-
`import qs from "qs";`,
|
|
60
|
-
`import useSWR, { type SWRResponse } from "swr";`,
|
|
61
|
-
`import { fetch, ListResult, SWRError, SwrOptions, handleConditional, swrPostFetcher, EventHandlers, SSEStreamOptions, useSSEStream } from '../sonamu.shared';`,
|
|
62
|
-
...(hasAxiosProgressEvent ? [`import { type AxiosProgressEvent } from 'axios';`] : []),
|
|
63
|
-
],
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
getTypeSource(apis: ExtendedApi[]): {
|
|
68
|
-
lines: string[];
|
|
69
|
-
importKeys: string[];
|
|
70
|
-
} {
|
|
71
|
-
const importKeys: string[] = [];
|
|
72
|
-
|
|
73
|
-
// 제네릭에서 선언한 타입, importKeys에서 제외 필요
|
|
74
|
-
let typeParamNames: string[] = [];
|
|
75
|
-
|
|
76
|
-
const groups = group(apis, (api) => api.modelName);
|
|
77
|
-
const body = Object.keys(groups)
|
|
78
|
-
.map((modelName) => {
|
|
79
|
-
const methods = groups[modelName];
|
|
80
|
-
assert(methods);
|
|
81
|
-
const methodCodes = methods
|
|
82
|
-
.map((api) => {
|
|
83
|
-
// 컨텍스트 제외된 파라미터 리스트
|
|
84
|
-
const paramsWithoutContext = api.parameters.filter(
|
|
85
|
-
(param) =>
|
|
86
|
-
!ApiParamType.isContext(param.type) &&
|
|
87
|
-
!ApiParamType.isRefKnex(param.type) &&
|
|
88
|
-
!(param.optional === true && param.name.startsWith("_")), // _로 시작하는 파라미터는 제외
|
|
89
|
-
);
|
|
90
|
-
|
|
91
|
-
// 파라미터 타입 정의
|
|
92
|
-
const typeParametersAsTsType = api.typeParameters
|
|
93
|
-
.map((typeParam) => {
|
|
94
|
-
return apiParamTypeToTsType(typeParam, importKeys);
|
|
95
|
-
})
|
|
96
|
-
.join(", ");
|
|
97
|
-
const typeParamsDef = typeParametersAsTsType ? `<${typeParametersAsTsType}>` : "";
|
|
98
|
-
typeParamNames = typeParamNames.concat(
|
|
99
|
-
api.typeParameters.map((typeParam) => typeParam.id),
|
|
100
|
-
);
|
|
101
|
-
|
|
102
|
-
// 파라미터 정의
|
|
103
|
-
const paramsDef = apiParamToTsCode(paramsWithoutContext, importKeys);
|
|
104
|
-
|
|
105
|
-
// 파라미터 정의 (객체 형태)
|
|
106
|
-
const paramsDefAsObject = apiParamToTsCodeAsObject(paramsWithoutContext, importKeys);
|
|
107
|
-
|
|
108
|
-
// 리턴 타입 정의
|
|
109
|
-
const returnTypeDef = apiParamTypeToTsType(
|
|
110
|
-
assertDefined(unwrapPromiseOnce(api.returnType)),
|
|
111
|
-
importKeys,
|
|
112
|
-
);
|
|
113
|
-
|
|
114
|
-
// 페이로드 데이터 정의
|
|
115
|
-
const payloadDef = `{ ${paramsWithoutContext.map((param) => param.name).join(", ")} }`;
|
|
116
|
-
|
|
117
|
-
// 기본 URL
|
|
118
|
-
const apiBaseUrl = `${Sonamu.config.api.route.prefix}${api.path}`;
|
|
119
|
-
|
|
120
|
-
const clients = api.options.clients ?? [];
|
|
121
|
-
return [
|
|
122
|
-
// 클라이언트별로 생성
|
|
123
|
-
...sort(clients, (client) => (client === "swr" ? 0 : 1)).map((client) => {
|
|
124
|
-
switch (client) {
|
|
125
|
-
case "axios":
|
|
126
|
-
return this.renderAxios(
|
|
127
|
-
api,
|
|
128
|
-
apiBaseUrl,
|
|
129
|
-
typeParamsDef,
|
|
130
|
-
paramsDef,
|
|
131
|
-
returnTypeDef,
|
|
132
|
-
payloadDef,
|
|
133
|
-
);
|
|
134
|
-
case "axios-multipart":
|
|
135
|
-
return this.renderAxiosMultipart(
|
|
136
|
-
api,
|
|
137
|
-
apiBaseUrl,
|
|
138
|
-
typeParamsDef,
|
|
139
|
-
paramsDef,
|
|
140
|
-
returnTypeDef,
|
|
141
|
-
paramsWithoutContext,
|
|
142
|
-
);
|
|
143
|
-
case "swr":
|
|
144
|
-
return this.renderSwr(
|
|
145
|
-
api,
|
|
146
|
-
apiBaseUrl,
|
|
147
|
-
typeParamsDef,
|
|
148
|
-
paramsDef,
|
|
149
|
-
returnTypeDef,
|
|
150
|
-
payloadDef,
|
|
151
|
-
);
|
|
152
|
-
case "window-fetch":
|
|
153
|
-
return this.renderWindowFetch(
|
|
154
|
-
api,
|
|
155
|
-
apiBaseUrl,
|
|
156
|
-
typeParamsDef,
|
|
157
|
-
paramsDef,
|
|
158
|
-
payloadDef,
|
|
159
|
-
);
|
|
160
|
-
default:
|
|
161
|
-
return `// Not supported ${inflection.camelize(client, true)} yet.`;
|
|
162
|
-
}
|
|
163
|
-
}),
|
|
164
|
-
// 스트리밍인 경우
|
|
165
|
-
...(api.streamOptions ? [this.renderStream(api, apiBaseUrl, paramsDefAsObject)] : []),
|
|
166
|
-
].join("\n");
|
|
167
|
-
})
|
|
168
|
-
.join("\n\n");
|
|
169
|
-
|
|
170
|
-
return `export namespace ${modelName.replace(/Model$/, "Service").replace(/Frame$/, "Service")} {
|
|
171
|
-
${methodCodes}
|
|
172
|
-
}`;
|
|
173
|
-
})
|
|
174
|
-
.join("\n\n");
|
|
175
|
-
|
|
176
|
-
return {
|
|
177
|
-
lines: [body],
|
|
178
|
-
importKeys: diff(unique(importKeys), typeParamNames),
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
renderAxios(
|
|
183
|
-
api: ExtendedApi,
|
|
184
|
-
apiBaseUrl: string,
|
|
185
|
-
typeParamsDef: string,
|
|
186
|
-
paramsDef: string,
|
|
187
|
-
returnTypeDef: string,
|
|
188
|
-
payloadDef: string,
|
|
189
|
-
) {
|
|
190
|
-
const methodNameAxios = api.options.resourceName
|
|
191
|
-
? `get${inflection.camelize(api.options.resourceName)}`
|
|
192
|
-
: api.methodName;
|
|
193
|
-
|
|
194
|
-
if (api.options.httpMethod === "GET") {
|
|
195
|
-
return `
|
|
196
|
-
export async function ${methodNameAxios}${typeParamsDef}(${paramsDef}): Promise<${returnTypeDef}> {
|
|
197
|
-
return fetch({
|
|
198
|
-
method: "GET",
|
|
199
|
-
url: \`${apiBaseUrl}?\${qs.stringify(${payloadDef})}\`,
|
|
200
|
-
${api.options.timeout ? `signal: AbortSignal.timeout(${api.options.timeout}),` : ""}
|
|
201
|
-
});
|
|
202
|
-
}
|
|
203
|
-
`.trim();
|
|
204
|
-
} else {
|
|
205
|
-
return `
|
|
206
|
-
export async function ${methodNameAxios}${typeParamsDef}(${paramsDef}): Promise<${returnTypeDef}> {
|
|
207
|
-
return fetch({
|
|
208
|
-
method: '${api.options.httpMethod}',
|
|
209
|
-
url: \`${apiBaseUrl}\`,
|
|
210
|
-
data: ${payloadDef},
|
|
211
|
-
${api.options.timeout ? `signal: AbortSignal.timeout(${api.options.timeout}),` : ""}
|
|
212
|
-
});
|
|
213
|
-
}
|
|
214
|
-
`.trim();
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
renderAxiosMultipart(
|
|
219
|
-
api: ExtendedApi,
|
|
220
|
-
apiBaseUrl: string,
|
|
221
|
-
typeParamsDef: string,
|
|
222
|
-
paramsDef: string,
|
|
223
|
-
returnTypeDef: string,
|
|
224
|
-
paramsWithoutContext: ApiParam[],
|
|
225
|
-
) {
|
|
226
|
-
const isMultiple = api.uploadOptions?.mode === "multiple";
|
|
227
|
-
const fileParamName = isMultiple ? "files" : "file";
|
|
228
|
-
const fileParamType = isMultiple ? "File[]" : "File";
|
|
229
|
-
|
|
230
|
-
const formDataDef = isMultiple
|
|
231
|
-
? [
|
|
232
|
-
`${fileParamName}.forEach(f => { formData.append("${fileParamName}", f) } ); `,
|
|
233
|
-
...paramsWithoutContext.map(
|
|
234
|
-
(param) => `formData.append('${param.name}', String(${param.name}));`,
|
|
235
|
-
),
|
|
236
|
-
].join("\n")
|
|
237
|
-
: [
|
|
238
|
-
`formData.append("${fileParamName}", ${fileParamName});`,
|
|
239
|
-
...paramsWithoutContext.map(
|
|
240
|
-
(param) => `formData.append('${param.name}', String(${param.name}));`,
|
|
241
|
-
),
|
|
242
|
-
].join("\n");
|
|
243
|
-
|
|
244
|
-
const paramsDefComma = paramsDef !== "" ? ", " : "";
|
|
245
|
-
return `
|
|
246
|
-
export async function ${api.methodName}${typeParamsDef}(
|
|
247
|
-
${paramsDef}${paramsDefComma}
|
|
248
|
-
${fileParamName}: ${fileParamType},
|
|
249
|
-
onUploadProgress?: (pe:AxiosProgressEvent) => void
|
|
250
|
-
): Promise<${returnTypeDef}> {
|
|
251
|
-
const formData = new FormData();
|
|
252
|
-
${formDataDef}
|
|
253
|
-
return fetch({
|
|
254
|
-
method: 'POST',
|
|
255
|
-
url: \`${apiBaseUrl}\`,
|
|
256
|
-
headers: {
|
|
257
|
-
"Content-Type": "multipart/form-data",
|
|
258
|
-
},
|
|
259
|
-
onUploadProgress,
|
|
260
|
-
data: formData,
|
|
261
|
-
${api.options.timeout ? `signal: AbortSignal.timeout(${api.options.timeout}),` : ""}
|
|
262
|
-
});
|
|
263
|
-
}
|
|
264
|
-
`.trim();
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
renderSwr(
|
|
268
|
-
api: ExtendedApi,
|
|
269
|
-
apiBaseUrl: string,
|
|
270
|
-
typeParamsDef: string,
|
|
271
|
-
paramsDef: string,
|
|
272
|
-
returnTypeDef: string,
|
|
273
|
-
payloadDef: string,
|
|
274
|
-
) {
|
|
275
|
-
const methodNameSwr = api.options.resourceName
|
|
276
|
-
? `use${inflection.camelize(api.options.resourceName)}`
|
|
277
|
-
: `use${inflection.camelize(api.methodName)}`;
|
|
278
|
-
return ` export function ${inflection.camelize(methodNameSwr, true)}${typeParamsDef}(${[
|
|
279
|
-
paramsDef,
|
|
280
|
-
"swrOptions?: SwrOptions",
|
|
281
|
-
]
|
|
282
|
-
.filter((p) => p !== "")
|
|
283
|
-
.join(",")}, ): SWRResponse<${returnTypeDef}, SWRError> {
|
|
284
|
-
return useSWR(handleConditional([
|
|
285
|
-
\`${apiBaseUrl}\`,
|
|
286
|
-
${payloadDef},
|
|
287
|
-
], swrOptions?.conditional)${api.options.httpMethod === "POST" ? ", swrPostFetcher" : ""}${
|
|
288
|
-
api.options.timeout ? `, { loadingTimeout: ${api.options.timeout} }` : ""
|
|
289
|
-
});
|
|
290
|
-
}`;
|
|
291
|
-
}
|
|
292
|
-
|
|
293
|
-
renderWindowFetch(
|
|
294
|
-
api: ExtendedApi,
|
|
295
|
-
apiBaseUrl: string,
|
|
296
|
-
typeParamsDef: string,
|
|
297
|
-
paramsDef: string,
|
|
298
|
-
payloadDef: string,
|
|
299
|
-
) {
|
|
300
|
-
return `
|
|
301
|
-
export async function ${api.methodName}${typeParamsDef}(${paramsDef}): Promise<Response> {
|
|
302
|
-
return window.fetch(\`${apiBaseUrl}?\${qs.stringify(${payloadDef})}\`${
|
|
303
|
-
api.options.timeout ? `, { signal: AbortSignal.timeout(${api.options.timeout}) }` : ""
|
|
304
|
-
});
|
|
305
|
-
}
|
|
306
|
-
`.trim();
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
renderStream(api: ExtendedApi, apiBaseUrl: string, paramsDefAsObject: string) {
|
|
310
|
-
if (!api.streamOptions) {
|
|
311
|
-
return "// streamOptions not found";
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
const methodNameStream = api.options.resourceName
|
|
315
|
-
? `use${inflection.camelize(api.options.resourceName)}`
|
|
316
|
-
: `use${inflection.camelize(api.methodName)}`;
|
|
317
|
-
const methodNameStreamCamelized = inflection.camelize(methodNameStream, true);
|
|
318
|
-
|
|
319
|
-
const eventsTypeDef = zodTypeToTsTypeDef(api.streamOptions.events);
|
|
320
|
-
|
|
321
|
-
return ` export function ${methodNameStreamCamelized}(
|
|
322
|
-
params: ${paramsDefAsObject},
|
|
323
|
-
handlers: EventHandlers<${eventsTypeDef} & { end?: () => void }>,
|
|
324
|
-
options: SSEStreamOptions) {
|
|
325
|
-
return useSSEStream<${eventsTypeDef}>(\`${apiBaseUrl}\`, params, handlers, options);
|
|
326
|
-
}`;
|
|
327
|
-
}
|
|
328
|
-
}
|