okai 0.0.20 → 0.0.23
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/api.d.ts +352 -0
- package/dist/cs-apis.js +2 -0
- package/dist/cs-ast.js +278 -72
- package/dist/cs-gen.js +1 -1
- package/dist/index.js +49 -14
- package/dist/ts-parser.js +3 -2
- package/dist/tsd-gen.js +50 -23
- package/dist/utils.js +10 -2
- package/package.json +2 -2
package/dist/api.d.ts
ADDED
@@ -0,0 +1,352 @@
|
|
1
|
+
declare global {
|
2
|
+
export class AuditBase {
|
3
|
+
createdDate: Date
|
4
|
+
createdBy: string
|
5
|
+
modifiedDate: Date
|
6
|
+
modifiedBy: string
|
7
|
+
deletedDate?: Date
|
8
|
+
deletedBy?: string
|
9
|
+
}
|
10
|
+
|
11
|
+
export type TypeOf = `typeof(${string})`
|
12
|
+
export type InputAttrOptions = { type?:string, value?:string, placeholder?:string, help?:string, label?:string, title?:string, size?:string,
|
13
|
+
pattern?:string, readOnly?:boolean, required?:boolean, disabled?:boolean, autocomplete?:string, autofocus?:string,
|
14
|
+
min?:string, max?:string, step?:string, minLength?:number, maxLength?:number, accept?:string, capture?:string, multiple?:boolean,
|
15
|
+
allowableValues?:string[], allowableValuesEnum?:TypeOf, options?:string, ignore?:boolean, evalAllowableValues?:string, evalAllowableEntries?:string, }
|
16
|
+
export type ScriptValueOptions = { value?: any, expression?: string, eval?: string, noCache?: boolean }
|
17
|
+
|
18
|
+
type ClassDecoratorDef = (
|
19
|
+
target: any,
|
20
|
+
context: ClassDecoratorContext
|
21
|
+
) => void
|
22
|
+
|
23
|
+
type ClassFieldDecoratorDef = (
|
24
|
+
target: any,
|
25
|
+
context: ClassFieldDecoratorContext
|
26
|
+
) => void
|
27
|
+
|
28
|
+
type ClassOrFieldDecoratorDef = (
|
29
|
+
target: any,
|
30
|
+
context: ClassDecoratorContext | ClassFieldDecoratorContext
|
31
|
+
) => void
|
32
|
+
|
33
|
+
export function validateRequest(validator:string) : ClassDecoratorDef
|
34
|
+
export function validateIsAuthenticated() : ClassDecoratorDef
|
35
|
+
export function validateIsAdmin() : ClassDecoratorDef
|
36
|
+
export function validateAuthSecret() : ClassDecoratorDef
|
37
|
+
export function validateHasRole(role:string) : ClassDecoratorDef
|
38
|
+
export function validateHasRoles(roles:string[]) : ClassDecoratorDef
|
39
|
+
export function validateHasPermission(permission:string) : ClassDecoratorDef
|
40
|
+
export function validateHasPermissions(permissions:string[]) : ClassDecoratorDef
|
41
|
+
export function validateHasClaim(claim:string) : ClassDecoratorDef
|
42
|
+
export function validateHasScope(scope:string) : ClassDecoratorDef
|
43
|
+
export function validateApiKey(scope?:string) : ClassDecoratorDef
|
44
|
+
|
45
|
+
export function schema(schema:string) : ClassDecoratorDef
|
46
|
+
export function compositeKey(columns:string[]) : ClassDecoratorDef
|
47
|
+
export function compositeIndex(unique:boolean, columns:string[]) : ClassDecoratorDef
|
48
|
+
export function preCreateTable(sql:string) : ClassDecoratorDef
|
49
|
+
export function preDropTable(sql:string) : ClassDecoratorDef
|
50
|
+
export function postCreateTable(sql:string) : ClassDecoratorDef
|
51
|
+
export function postDropTable(sql:string) : ClassDecoratorDef
|
52
|
+
|
53
|
+
export function api(description:string, opt?:{ bodyParameter?:number, requestContentType?:string, isRequired?:boolean }) : ClassDecoratorDef
|
54
|
+
export function apiResponse(statusCode:number, description:string, opt?:{ isDefaultResponse?:boolean, responseType?:TypeOf }) : ClassDecoratorDef
|
55
|
+
|
56
|
+
export function dataContract() : ClassDecoratorDef
|
57
|
+
export function route(path:string, opt?:{ summary?:string, notes?:string, verbs?:string, priority?:number, matches?:string, }) : ClassDecoratorDef
|
58
|
+
export function icon(opt?:{ svg?:string, uri?:string, alt?:string, cls?:string, }) : ClassDecoratorDef
|
59
|
+
export function field(opt?:InputAttrOptions & { name?:string, fieldCss?:string, inputCss?:string, labelCss?:string, }) : ClassDecoratorDef
|
60
|
+
export function tag(name:string) : ClassDecoratorDef
|
61
|
+
export function worker(name:string) : ClassDecoratorDef
|
62
|
+
export function notes(notes:string) : ClassDecoratorDef
|
63
|
+
export function namedConnection(name:string) : ClassDecoratorDef
|
64
|
+
|
65
|
+
export enum QueryTerm { Default = 0, And = 1, Or = 2, Ensure = 3, }
|
66
|
+
export function queryDb(defaultTerm:QueryTerm) : ClassDecoratorDef
|
67
|
+
export function queryData(defaultTerm:QueryTerm) : ClassDecoratorDef
|
68
|
+
export function autoFilter(term:QueryTerm, field?:string, opt?:{ operand?:string, template?:string, valueFormat:string }) : ClassDecoratorDef
|
69
|
+
export function autoPopulate(field?:string, opt?:ScriptValueOptions) : ClassDecoratorDef
|
70
|
+
export class SqlTemplate {
|
71
|
+
static IsNull: string
|
72
|
+
static IsNotNull: string
|
73
|
+
static GreaterThanOrEqual: string
|
74
|
+
static GreaterThan: string
|
75
|
+
static LessThan: string
|
76
|
+
static LessThanOrEqual: string
|
77
|
+
static NotEqual: string
|
78
|
+
static CaseSensitiveLike: string
|
79
|
+
static CaseInsensitiveLike: string
|
80
|
+
}
|
81
|
+
|
82
|
+
export function alias(table:string) : ClassOrFieldDecoratorDef
|
83
|
+
export function meta(name:string,value:string) : ClassOrFieldDecoratorDef
|
84
|
+
export function priority(value:string) : ClassOrFieldDecoratorDef
|
85
|
+
|
86
|
+
// Enum decorators
|
87
|
+
export function flags() : ClassDecoratorDef
|
88
|
+
export function enumMember(opt:{ value:string }) : ClassFieldDecoratorDef
|
89
|
+
|
90
|
+
export function validate(validator:string) : ClassFieldDecoratorDef
|
91
|
+
export function validateNull() : ClassFieldDecoratorDef
|
92
|
+
export function validateEmpty() : ClassFieldDecoratorDef
|
93
|
+
export function validateEmail() : ClassFieldDecoratorDef
|
94
|
+
export function validateNotNull() : ClassFieldDecoratorDef
|
95
|
+
export function validateNotEmpty() : ClassFieldDecoratorDef
|
96
|
+
export function validateCreditCard() : ClassFieldDecoratorDef
|
97
|
+
export function validateLength(min:number, max:number) : ClassFieldDecoratorDef
|
98
|
+
export function validateExactLength(length:number) : ClassFieldDecoratorDef
|
99
|
+
export function validateMinimumLength(min:number) : ClassFieldDecoratorDef
|
100
|
+
export function validateMaximumLength(max:number) : ClassFieldDecoratorDef
|
101
|
+
export function validateLessThanLength(value:number) : ClassFieldDecoratorDef
|
102
|
+
export function validateLessThanOrEqual(value:number) : ClassFieldDecoratorDef
|
103
|
+
export function validateGreaterThanLength(value:number) : ClassFieldDecoratorDef
|
104
|
+
export function validateGreaterThanOrEqual(value:number) : ClassFieldDecoratorDef
|
105
|
+
export function validateScalePrecision(scale:number, precision:number) : ClassFieldDecoratorDef
|
106
|
+
export function validateRegularExpression(pattern:string) : ClassFieldDecoratorDef
|
107
|
+
export function validateEqualExpression(value:string|number|boolean) : ClassFieldDecoratorDef
|
108
|
+
export function validateNotEqualExpression(value:string|number|boolean) : ClassFieldDecoratorDef
|
109
|
+
export function validateInclusiveBetween(from:string|number,to:string|number) : ClassFieldDecoratorDef
|
110
|
+
export function validateExclusiveBetween(from:string|number,to:string|number) : ClassFieldDecoratorDef
|
111
|
+
|
112
|
+
export function allowReset() : ClassFieldDecoratorDef
|
113
|
+
export function denyReset() : ClassFieldDecoratorDef
|
114
|
+
|
115
|
+
export function primaryKey() : ClassFieldDecoratorDef
|
116
|
+
export function autoId() : ClassFieldDecoratorDef
|
117
|
+
export function autoIncrement() : ClassFieldDecoratorDef
|
118
|
+
export function belongTo(BelongToTableType:TypeOf) : ClassFieldDecoratorDef
|
119
|
+
export function index(opt?:{ name?:string, unique?:boolean, clustered?:boolean, nonClustered?:boolean, }) : ClassFieldDecoratorDef
|
120
|
+
export function compute() : ClassFieldDecoratorDef
|
121
|
+
export function computed() : ClassFieldDecoratorDef
|
122
|
+
export function persisted() : ClassFieldDecoratorDef
|
123
|
+
export function uniqueConstraint(columns:string[]) : ClassFieldDecoratorDef
|
124
|
+
export function addColumn() : ClassFieldDecoratorDef
|
125
|
+
export function removeColumn() : ClassFieldDecoratorDef
|
126
|
+
export function checkConstraint(constraint:string) : ClassFieldDecoratorDef
|
127
|
+
export function customField(sql:string, order?:number) : ClassFieldDecoratorDef
|
128
|
+
export function customSelect(sql:string) : ClassFieldDecoratorDef
|
129
|
+
export function customInsert(sql:string) : ClassFieldDecoratorDef
|
130
|
+
export function customUpdate(sql:string) : ClassFieldDecoratorDef
|
131
|
+
export function decimalLength(precision:number, scale?:number) : ClassFieldDecoratorDef
|
132
|
+
export function Default(value:string|number|boolean) : ClassFieldDecoratorDef
|
133
|
+
export function description(description:string) : ClassFieldDecoratorDef
|
134
|
+
export function enumAsInt() : ClassFieldDecoratorDef
|
135
|
+
export function excludeMetadata() : ClassFieldDecoratorDef
|
136
|
+
export function excludeFromDescription() : ClassFieldDecoratorDef
|
137
|
+
export function explicitAutoQuery() : ClassFieldDecoratorDef
|
138
|
+
export type foreignKeyBehavior = "NO ACTION"|"RESTRICT"|"SET NULL"|"SET DEFAULT"|"CASCADE"
|
139
|
+
export function foreignKey(type:string, opt?:{ onDelete?:foreignKeyBehavior, onUpdate?:foreignKeyBehavior, foreignKeyName?:string }) : ClassFieldDecoratorDef
|
140
|
+
export function ignore() : ClassFieldDecoratorDef
|
141
|
+
export function ignoreOnUpdate() : ClassFieldDecoratorDef
|
142
|
+
export function ignoreOnInsert() : ClassFieldDecoratorDef
|
143
|
+
export function ignoreDataMember() : ClassFieldDecoratorDef
|
144
|
+
export function reference() : ClassFieldDecoratorDef
|
145
|
+
export function referenceField(model:TypeOf, id?:string, field?:string) : ClassFieldDecoratorDef
|
146
|
+
export function references(type:TypeOf) : ClassFieldDecoratorDef
|
147
|
+
export function required() : ClassFieldDecoratorDef
|
148
|
+
export function returnOnInsert() : ClassFieldDecoratorDef
|
149
|
+
export function rowVersion() : ClassFieldDecoratorDef
|
150
|
+
export function unique() : ClassFieldDecoratorDef
|
151
|
+
|
152
|
+
export enum ValueStyle { Single, Multiple, List, }
|
153
|
+
export function queryDbField(opt?:{ term:QueryTerm, operand?:string, template?:string, field?:string, valueFormat?:string, valueStyle?:ValueStyle, valueArity?:number }) : ClassFieldDecoratorDef
|
154
|
+
export function queryDataField(opt?:{ term:QueryTerm, condition?:string, field?:string }) : ClassFieldDecoratorDef
|
155
|
+
|
156
|
+
export enum AutoUpdateStyle { Always, NonDefaults }
|
157
|
+
export function autoUpdate(style:AutoUpdateStyle) : ClassFieldDecoratorDef
|
158
|
+
export function autoDefault(opt:ScriptValueOptions) : ClassFieldDecoratorDef
|
159
|
+
export function autoMap(to:string) : ClassFieldDecoratorDef
|
160
|
+
export function autoIgnore() : ClassFieldDecoratorDef
|
161
|
+
export function autoApply(name:string, args?:string[]) : ClassFieldDecoratorDef
|
162
|
+
|
163
|
+
export function apiMember(opt?:{ name?:string, verb?:string, parameterType?:string, description?:string, dataType?:string,
|
164
|
+
format?:string, isRequired?:boolean, isOptional?:boolean, allowMultiple?:boolean, route?:string, excludeInSchema?:boolean
|
165
|
+
}) : ClassFieldDecoratorDef
|
166
|
+
export function apiAllowableValues(name:string, opt?:{ type?:"RANGE"|"LIST", min?:number, max?:number, values?:string[] }) : ClassFieldDecoratorDef
|
167
|
+
|
168
|
+
export function dataMember(opt?:{ name?:string, order?:number, isRequired?:boolean }) : ClassFieldDecoratorDef
|
169
|
+
export function input(opt?:InputAttrOptions) : ClassFieldDecoratorDef
|
170
|
+
export function fieldCss(opt?:{ field?:string, input?:string, label?:string, }) : ClassFieldDecoratorDef
|
171
|
+
export function explorerCss(opt?:{ form?:string, fieldset?:string, field?:string, }) : ClassFieldDecoratorDef
|
172
|
+
export function locodeCss(opt?:{ form?:string, fieldset?:string, field?:string, }) : ClassFieldDecoratorDef
|
173
|
+
export function uploadTo(location:string) : ClassFieldDecoratorDef
|
174
|
+
export function ref(opt?:{ modelType?:TypeOf, model?:string, refId?:string, refLabel?:string, selfId?:string, queryType?:TypeOf, none?:boolean, }) : ClassFieldDecoratorDef
|
175
|
+
export type FormatMethods = "currency"|"bytes"|"icon"|"iconRounded"|"attachment"|"link"|"linkMailTo"|"linkTel"|"enumFlags"|"hidden"
|
176
|
+
export function format(method:FormatMethods, opt?:{ options?:string, locale?:string }) : ClassFieldDecoratorDef
|
177
|
+
|
178
|
+
export enum IntlFormat { Number, DateTime, RelativeTime }
|
179
|
+
export enum NumberStyle { Undefined=0, Decimal, Currency, Percent, Unit, }
|
180
|
+
export enum DateStyle { Undefined=0, Full, Long, Medium, Short, }
|
181
|
+
export enum TimeStyle { Undefined=0, Full, Long, Medium, Short, }
|
182
|
+
export enum Numeric { Undefined=0, Always, Auto, }
|
183
|
+
|
184
|
+
export enum DatePart { Undefined=0, Numeric, Digits2, }
|
185
|
+
export enum DateMonth { Undefined=0, Numeric, Digits2, Narrow, Short, Long, }
|
186
|
+
export enum DateText { Undefined=0, Narrow, Short, Long }
|
187
|
+
|
188
|
+
export enum CurrencyDisplay { Undefined=0, Symbol, NarrowSymbol, Code, Name, }
|
189
|
+
export enum CurrencySign { Undefined=0, Accounting, Standard, }
|
190
|
+
export enum SignDisplay { Undefined=0, Always, Auto, ExceptZero, Negative, Never, }
|
191
|
+
export enum RoundingMode { Undefined=0, Ceil, Floor, Expand, Trunc, HalfCeil, HalfFloor, HalfExpand, HalfTrunc, HalfEven, }
|
192
|
+
|
193
|
+
export enum UnitDisplay { Undefined=0, Long, Short, Narrow }
|
194
|
+
export enum Notation { Undefined=0, Standard, Scientific, Engineering, Compact, }
|
195
|
+
|
196
|
+
export type IntlOptions = { locale?:string, options?:string, number?:NumberStyle, date?:DateStyle, time?:TimeStyle, numeric?:Numeric,
|
197
|
+
currency?:string, currencyDisplay?:CurrencyDisplay, currencySign?:CurrencySign, signDisplay?:SignDisplay, roundingMode?:RoundingMode,
|
198
|
+
unit?:string, unitDisplay?:UnitDisplay, notation?:Notation,
|
199
|
+
minimumIntegerDigits?:number, minimumFractionDigits?:number, maximumFractionDigits?:number, minimumSignificantDigits?:number, maximumSignificantDigits?:number, fractionalSecondDigits?:number,
|
200
|
+
weekday?:DateText, era?:DateText, year?:DatePart, month?:DateMonth, day?:DatePart, hour?:DatePart, minute?:DatePart, second?:DatePart,
|
201
|
+
timeZoneName?:DateText, timeZone?:string, hour12?:boolean
|
202
|
+
}
|
203
|
+
|
204
|
+
export function intl(type:IntlFormat, opt?:IntlOptions) : ClassFieldDecoratorDef
|
205
|
+
export function intlNumber(number?:NumberStyle) : ClassFieldDecoratorDef
|
206
|
+
export function intlDateTime(date?:DateStyle, time?:TimeStyle) : ClassFieldDecoratorDef
|
207
|
+
export function intlRelativeTime(numeric?:Numeric) : ClassFieldDecoratorDef
|
208
|
+
|
209
|
+
//RequestAttrs & TypeAttrs & DataModelAttrs & RequestPropAttrs & DataModelPropAttrs
|
210
|
+
export class All {
|
211
|
+
// RequestAttrs
|
212
|
+
api:typeof api
|
213
|
+
apiResponse:typeof apiResponse
|
214
|
+
validateRequest:typeof validateRequest
|
215
|
+
validateIsAuthenticated:typeof validateIsAuthenticated
|
216
|
+
validateIsAdmin:typeof validateIsAdmin
|
217
|
+
validateAuthSecret:typeof validateAuthSecret
|
218
|
+
validateHasRole:typeof validateHasRole
|
219
|
+
validateHasRoles:typeof validateHasRoles
|
220
|
+
validateHasPermission:typeof validateHasPermission
|
221
|
+
validateHasPermissions:typeof validateHasPermissions
|
222
|
+
validateHasClaim:typeof validateHasClaim
|
223
|
+
validateHasScope:typeof validateHasScope
|
224
|
+
validateApiKey:typeof validateApiKey
|
225
|
+
|
226
|
+
queryDb:typeof queryDb
|
227
|
+
queryData:typeof queryData
|
228
|
+
autoFilter:typeof autoFilter
|
229
|
+
autoPopulate:typeof autoPopulate
|
230
|
+
|
231
|
+
route:typeof route
|
232
|
+
field:typeof field
|
233
|
+
tag:typeof tag
|
234
|
+
notes:typeof notes
|
235
|
+
|
236
|
+
// Type and Attrs
|
237
|
+
dataContract:typeof dataContract
|
238
|
+
|
239
|
+
// DataModelAttrs
|
240
|
+
schema:typeof schema
|
241
|
+
compositeKey:typeof compositeKey
|
242
|
+
preCreateTable:typeof preCreateTable
|
243
|
+
preDropTable:typeof preDropTable
|
244
|
+
postCreateTable:typeof postCreateTable
|
245
|
+
postDropTable:typeof postDropTable
|
246
|
+
|
247
|
+
namedConnection:typeof namedConnection
|
248
|
+
icon:typeof icon
|
249
|
+
|
250
|
+
// Class or Field Attrs
|
251
|
+
alias:typeof alias
|
252
|
+
meta:typeof meta // Type
|
253
|
+
flags:typeof flags // Enum
|
254
|
+
|
255
|
+
// RequestPropAttrs
|
256
|
+
validate:typeof validate
|
257
|
+
validateNull:typeof validateNull
|
258
|
+
validateEmpty:typeof validateEmpty
|
259
|
+
validateEmail:typeof validateEmail
|
260
|
+
validateNotNull:typeof validateNotNull
|
261
|
+
validateNotEmpty:typeof validateNotEmpty
|
262
|
+
validateCreditCard:typeof validateCreditCard
|
263
|
+
validateLength:typeof validateLength
|
264
|
+
validateExactLength:typeof validateExactLength
|
265
|
+
validateMinimumLength:typeof validateMinimumLength
|
266
|
+
validateMaximumLength:typeof validateMaximumLength
|
267
|
+
validateLessThanLength:typeof validateLessThanLength
|
268
|
+
validateLessThanOrEqual:typeof validateLessThanOrEqual
|
269
|
+
validateGreaterThanLength:typeof validateGreaterThanLength
|
270
|
+
validateGreaterThanOrEqual:typeof validateGreaterThanOrEqual
|
271
|
+
validateScalePrecision:typeof validateScalePrecision
|
272
|
+
validateRegularExpression:typeof validateRegularExpression
|
273
|
+
validateEqualExpression:typeof validateEqualExpression
|
274
|
+
validateNotEqualExpression:typeof validateNotEqualExpression
|
275
|
+
validateInclusiveBetween:typeof validateInclusiveBetween
|
276
|
+
validateExclusiveBetween:typeof validateExclusiveBetween
|
277
|
+
allowReset:typeof allowReset
|
278
|
+
denyReset:typeof denyReset
|
279
|
+
|
280
|
+
queryDbField:typeof queryDbField
|
281
|
+
queryDataField:typeof queryDataField
|
282
|
+
autoUpdate:typeof autoUpdate
|
283
|
+
autoDefault:typeof autoDefault
|
284
|
+
autoMap:typeof autoMap
|
285
|
+
autoIgnore:typeof autoIgnore
|
286
|
+
autoApply:typeof autoApply
|
287
|
+
|
288
|
+
apiMember:typeof apiMember
|
289
|
+
apiAllowableValues:typeof apiAllowableValues
|
290
|
+
dataMember:typeof dataMember
|
291
|
+
input:typeof input
|
292
|
+
fieldCss:typeof fieldCss
|
293
|
+
uploadTo:typeof uploadTo
|
294
|
+
|
295
|
+
enumMember:typeof enumMember
|
296
|
+
|
297
|
+
// DataModelPropAttrs
|
298
|
+
// alias:typeof alias
|
299
|
+
// meta:typeof meta
|
300
|
+
priority:typeof priority
|
301
|
+
|
302
|
+
primaryKey:typeof primaryKey
|
303
|
+
autoId:typeof autoId
|
304
|
+
autoIncrement:typeof autoIncrement
|
305
|
+
index:typeof index
|
306
|
+
compute:typeof compute
|
307
|
+
computed:typeof computed
|
308
|
+
persisted:typeof persisted
|
309
|
+
uniqueConstraint:typeof uniqueConstraint
|
310
|
+
addColumn:typeof addColumn
|
311
|
+
removeColumn:typeof removeColumn
|
312
|
+
belongTo:typeof belongTo
|
313
|
+
checkConstraint:typeof checkConstraint
|
314
|
+
customField:typeof customField
|
315
|
+
customSelect:typeof customSelect
|
316
|
+
customInsert:typeof customInsert
|
317
|
+
customUpdate:typeof customUpdate
|
318
|
+
decimalLength:typeof decimalLength
|
319
|
+
Default:typeof Default
|
320
|
+
description:typeof description
|
321
|
+
enumAsInt:typeof enumAsInt
|
322
|
+
excludeMetadata:typeof excludeMetadata
|
323
|
+
excludeFromDescription:typeof excludeFromDescription
|
324
|
+
explicitAutoQuery:typeof explicitAutoQuery
|
325
|
+
foreignKey:typeof foreignKey
|
326
|
+
ignore:typeof ignore
|
327
|
+
ignoreOnUpdate:typeof ignoreOnUpdate
|
328
|
+
ignoreOnInsert:typeof ignoreOnInsert
|
329
|
+
ignoreDataMember:typeof ignoreDataMember
|
330
|
+
reference:typeof reference
|
331
|
+
referenceField:typeof referenceField
|
332
|
+
references:typeof references
|
333
|
+
required:typeof required
|
334
|
+
returnOnInsert:typeof returnOnInsert
|
335
|
+
rowVersion:typeof rowVersion
|
336
|
+
unique:typeof unique
|
337
|
+
|
338
|
+
ref:typeof ref
|
339
|
+
format:typeof format
|
340
|
+
intl:typeof intl
|
341
|
+
intlNumber:typeof intlNumber
|
342
|
+
intlDateTime:typeof intlDateTime
|
343
|
+
intlRelativeTime:typeof intlRelativeTime
|
344
|
+
}
|
345
|
+
export const Read : All
|
346
|
+
export const Write : All
|
347
|
+
export const Create : All
|
348
|
+
export const Update : All
|
349
|
+
export const Delete : All
|
350
|
+
}
|
351
|
+
|
352
|
+
export {}
|
package/dist/cs-apis.js
CHANGED
@@ -80,6 +80,8 @@ export class CSharpApiGenerator extends CSharpGenerator {
|
|
80
80
|
const groupName = getGroupName(ast);
|
81
81
|
const friendlyGroupName = splitCase(groupName);
|
82
82
|
ast.operations.forEach(op => {
|
83
|
+
if (op.request.attributes?.find(x => x.name === 'Tag'))
|
84
|
+
return;
|
83
85
|
if (!op.tags)
|
84
86
|
op.tags = [];
|
85
87
|
op.tags.push(friendlyGroupName);
|
package/dist/cs-ast.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { plural, toPascalCase } from "./utils.js";
|
1
|
+
import { leftPart, plural, rightPart, toPascalCase } from "./utils.js";
|
2
2
|
import { Icons } from "./icons.js";
|
3
3
|
const sys = (name, genericArgs) => ({ name, namespace: "System", genericArgs });
|
4
4
|
const sysObj = sys("object");
|
@@ -34,6 +34,129 @@ export class CSharpAst {
|
|
34
34
|
commonValueTypes = [
|
35
35
|
"int", "Int32", "long", "Int64", "string",
|
36
36
|
];
|
37
|
+
requestAttrs = [
|
38
|
+
'api',
|
39
|
+
'apiResponse',
|
40
|
+
'validateRequest',
|
41
|
+
'validateIsAuthenticated',
|
42
|
+
'validateIsAdmin',
|
43
|
+
'validateAuthSecret',
|
44
|
+
'validateHasRole',
|
45
|
+
'validateHasRoles',
|
46
|
+
'validateHasPermission',
|
47
|
+
'validateHasPermissions',
|
48
|
+
'validateHasClaim',
|
49
|
+
'validateHasScope',
|
50
|
+
'validateApiKey',
|
51
|
+
'queryDb',
|
52
|
+
'queryData',
|
53
|
+
'autoFilter',
|
54
|
+
'autoPopulate',
|
55
|
+
'route',
|
56
|
+
'field',
|
57
|
+
'tag',
|
58
|
+
'notes',
|
59
|
+
'meta',
|
60
|
+
'dataContract',
|
61
|
+
].map(x => x.toLowerCase());
|
62
|
+
modelAttrs = [
|
63
|
+
'schema',
|
64
|
+
'compositeKey',
|
65
|
+
'preCreateTable',
|
66
|
+
'preDropTable',
|
67
|
+
'postCreateTable',
|
68
|
+
'postDropTable',
|
69
|
+
'namedConnection',
|
70
|
+
'alias',
|
71
|
+
'icon',
|
72
|
+
'meta',
|
73
|
+
'dataContract',
|
74
|
+
].map(x => x.toLowerCase());
|
75
|
+
requestPropAttrs = [
|
76
|
+
'validate',
|
77
|
+
'validateNull',
|
78
|
+
'validateEmpty',
|
79
|
+
'validateEmail',
|
80
|
+
'validateNotNull',
|
81
|
+
'validateNotEmpty',
|
82
|
+
'validateCreditCard',
|
83
|
+
'validateLength',
|
84
|
+
'validateExactLength',
|
85
|
+
'validateMinimumLength',
|
86
|
+
'validateMaximumLength',
|
87
|
+
'validateLessThanLength',
|
88
|
+
'validateLessThanOrEqual',
|
89
|
+
'validateGreaterThanLength',
|
90
|
+
'validateGreaterThanOrEqual',
|
91
|
+
'validateScalePrecision',
|
92
|
+
'validateRegularExpression',
|
93
|
+
'validateEqualExpression',
|
94
|
+
'validateNotEqualExpression',
|
95
|
+
'validateInclusiveBetween',
|
96
|
+
'validateExclusiveBetween',
|
97
|
+
'allowReset',
|
98
|
+
'denyReset',
|
99
|
+
'queryDbField',
|
100
|
+
'queryDataField',
|
101
|
+
'autoUpdate',
|
102
|
+
'autoDefault',
|
103
|
+
'autoMap',
|
104
|
+
'autoIgnore',
|
105
|
+
'autoApply',
|
106
|
+
'apiMember',
|
107
|
+
'apiAllowableValues',
|
108
|
+
'dataMember',
|
109
|
+
'input',
|
110
|
+
'fieldCss',
|
111
|
+
'uploadTo',
|
112
|
+
].map(x => x.toLowerCase());
|
113
|
+
modelPropAttrs = [
|
114
|
+
'alias',
|
115
|
+
'meta',
|
116
|
+
'priority',
|
117
|
+
'primaryKey',
|
118
|
+
'autoId',
|
119
|
+
'autoIncrement',
|
120
|
+
'index',
|
121
|
+
'compute',
|
122
|
+
'computed',
|
123
|
+
'persisted',
|
124
|
+
'uniqueConstraint',
|
125
|
+
'addColumn',
|
126
|
+
'removeColumn',
|
127
|
+
'belongTo',
|
128
|
+
'checkConstraint',
|
129
|
+
'customField',
|
130
|
+
'customSelect',
|
131
|
+
'customInsert',
|
132
|
+
'customUpdate',
|
133
|
+
'decimalLength',
|
134
|
+
'Default',
|
135
|
+
'description',
|
136
|
+
'enumAsInt',
|
137
|
+
'excludeMetadata',
|
138
|
+
'excludeFromDescription',
|
139
|
+
'explicitAutoQuery',
|
140
|
+
'foreignKey',
|
141
|
+
'ignore',
|
142
|
+
'ignoreOnUpdate',
|
143
|
+
'ignoreOnInsert',
|
144
|
+
'ignoreDataMember',
|
145
|
+
'reference',
|
146
|
+
'referenceField',
|
147
|
+
'references',
|
148
|
+
'required',
|
149
|
+
'returnOnInsert',
|
150
|
+
'rowVersion',
|
151
|
+
'unique',
|
152
|
+
'dataMember',
|
153
|
+
'ref',
|
154
|
+
'format',
|
155
|
+
'intl',
|
156
|
+
'intlNumber',
|
157
|
+
'intlDateTime',
|
158
|
+
'intlRelativeTime',
|
159
|
+
].map(x => x.toLowerCase());
|
37
160
|
unwrap(type) {
|
38
161
|
if (type.endsWith("?")) {
|
39
162
|
return type.substring(0, type.length - 1);
|
@@ -76,19 +199,26 @@ export class CSharpAst {
|
|
76
199
|
return this.typeMap[type] ?? { name: type, namespace: "MyApp" };
|
77
200
|
}
|
78
201
|
csharpAttribute(attr) {
|
79
|
-
const
|
202
|
+
const attrName = attr.name.includes('.')
|
203
|
+
? rightPart(attr.name, '.')
|
204
|
+
: attr.name;
|
205
|
+
const to = { name: toPascalCase(attrName) };
|
80
206
|
const attrType = (value) => typeof value == 'string'
|
81
|
-
? (
|
207
|
+
? ((value.startsWith('typeof(') || value.startsWith('nameof(')) && value.endsWith(')')
|
208
|
+
? "constant" :
|
209
|
+
value.match(/^[A-Z][A-Za-z0-9_]+\.[A-Z][A-Za-z0-9_]+$/) //Axx.Bxx
|
210
|
+
? "constant"
|
211
|
+
: "string")
|
82
212
|
: typeof value == "object"
|
83
213
|
? (value instanceof Date ? "string" : Array.isArray(value) ? "array" : "object")
|
84
214
|
: typeof value;
|
85
215
|
if (attr.constructorArgs?.length) {
|
86
216
|
to.constructorArgs = attr.constructorArgs.map(x => {
|
87
|
-
const type = attrType(x
|
217
|
+
const type = attrType(x);
|
88
218
|
return {
|
89
219
|
name: 'String',
|
90
220
|
type,
|
91
|
-
value: `${x
|
221
|
+
value: `${x}`
|
92
222
|
};
|
93
223
|
});
|
94
224
|
}
|
@@ -102,21 +232,27 @@ export class CSharpAst {
|
|
102
232
|
};
|
103
233
|
});
|
104
234
|
}
|
235
|
+
if (attr.name.includes('.')) {
|
236
|
+
to.namespace = leftPart(attr.name, '.');
|
237
|
+
}
|
105
238
|
return to;
|
106
239
|
}
|
107
240
|
addMetadataType(cls) {
|
108
241
|
const type = {
|
109
242
|
name: this.toCsName(cls.name),
|
110
243
|
namespace: "MyApp",
|
111
|
-
description: cls.comment,
|
112
244
|
properties: cls.properties.map(p => {
|
113
245
|
const type = this.csharpType(p.type, p.name);
|
114
246
|
const prop = {
|
115
247
|
name: this.toCsName(p.name),
|
116
248
|
type: p.optional ? this.nullable(type.name) : type.name,
|
117
|
-
namespace: type.namespace,
|
118
|
-
description: p.comment,
|
119
249
|
};
|
250
|
+
if (type.namespace) {
|
251
|
+
prop.namespace = type.namespace;
|
252
|
+
}
|
253
|
+
if (p.comment) {
|
254
|
+
prop.description = p.comment;
|
255
|
+
}
|
120
256
|
if (prop.name === 'Id') {
|
121
257
|
prop.isPrimaryKey = true;
|
122
258
|
}
|
@@ -145,6 +281,12 @@ export class CSharpAst {
|
|
145
281
|
return prop;
|
146
282
|
}),
|
147
283
|
};
|
284
|
+
if (cls.comment) {
|
285
|
+
type.description = cls.comment;
|
286
|
+
}
|
287
|
+
if (cls.extends) {
|
288
|
+
type.inherits = { name: this.toCsName(cls.extends) };
|
289
|
+
}
|
148
290
|
if (cls.annotations?.length) {
|
149
291
|
type.attributes = cls.annotations.map(x => this.csharpAttribute(x));
|
150
292
|
}
|
@@ -389,6 +531,47 @@ export class CSharpAst {
|
|
389
531
|
}
|
390
532
|
}
|
391
533
|
}
|
534
|
+
attrsFor(dtoType, attrs) {
|
535
|
+
const requestAttrs = this.requestAttrs;
|
536
|
+
const requestPropAttrs = this.requestPropAttrs;
|
537
|
+
const modelAttrs = this.modelAttrs;
|
538
|
+
const modelPropAttrs = this.modelPropAttrs;
|
539
|
+
function shouldInclude(attr, dtoType) {
|
540
|
+
const ns = attr.namespace;
|
541
|
+
if (ns) {
|
542
|
+
if (ns == "All")
|
543
|
+
return true;
|
544
|
+
if (ns == "Read")
|
545
|
+
return dtoType == "Read";
|
546
|
+
if (ns == "Create")
|
547
|
+
return dtoType == "Create";
|
548
|
+
if (ns == "Update")
|
549
|
+
return dtoType == "Update";
|
550
|
+
if (ns == "Delete")
|
551
|
+
return dtoType == "Delete";
|
552
|
+
if (ns == "Write")
|
553
|
+
return ["Create", "Update", "Delete"].includes(dtoType);
|
554
|
+
}
|
555
|
+
else {
|
556
|
+
const isRequest = dtoType != "Model";
|
557
|
+
const nameLower = attr.name.toLowerCase();
|
558
|
+
if (isRequest) {
|
559
|
+
return requestAttrs.includes(nameLower) || requestPropAttrs.includes(nameLower);
|
560
|
+
}
|
561
|
+
else {
|
562
|
+
return modelAttrs.includes(nameLower) || modelPropAttrs.includes(nameLower);
|
563
|
+
}
|
564
|
+
}
|
565
|
+
return true;
|
566
|
+
}
|
567
|
+
const to = [];
|
568
|
+
for (const attr of attrs || []) {
|
569
|
+
if (shouldInclude(attr, dtoType)) {
|
570
|
+
to.push(attr);
|
571
|
+
}
|
572
|
+
}
|
573
|
+
return to;
|
574
|
+
}
|
392
575
|
createAutoCrudApis() {
|
393
576
|
for (const type of this.classes) {
|
394
577
|
const hasPk = type.properties?.some(x => x.isPrimaryKey);
|
@@ -408,21 +591,19 @@ export class CSharpAst {
|
|
408
591
|
name: "FieldCss",
|
409
592
|
args: [{ name: "Field", type: "string", value: "col-span-12" }]
|
410
593
|
}];
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
{
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
]
|
425
|
-
: [];
|
594
|
+
function onlyAttrs(attrs, only) {
|
595
|
+
if (!attrs)
|
596
|
+
return;
|
597
|
+
return attrs.filter(x => only.includes(x.name));
|
598
|
+
}
|
599
|
+
const idsProp = pk
|
600
|
+
? {
|
601
|
+
name: `${pk.name}s`,
|
602
|
+
type: "List`1?",
|
603
|
+
namespace: "System.Collections.Generic",
|
604
|
+
genericArgs: [pk.type]
|
605
|
+
}
|
606
|
+
: undefined;
|
426
607
|
if (!queryApi) {
|
427
608
|
queryApi = {
|
428
609
|
method: "GET",
|
@@ -436,7 +617,16 @@ export class CSharpAst {
|
|
436
617
|
namespace: "ServiceStack",
|
437
618
|
genericArgs: [type.name]
|
438
619
|
},
|
439
|
-
properties:
|
620
|
+
properties: pk
|
621
|
+
? [
|
622
|
+
Object.assign({}, pk, {
|
623
|
+
type: `${this.nullable(pk.type)}`,
|
624
|
+
attributes: onlyAttrs(pk.attributes, this.requestPropAttrs),
|
625
|
+
}),
|
626
|
+
idsProp
|
627
|
+
]
|
628
|
+
: [],
|
629
|
+
attributes: this.attrsFor("Read", type.attributes),
|
440
630
|
},
|
441
631
|
returnType: {
|
442
632
|
name: "QueryResponse`1",
|
@@ -446,17 +636,17 @@ export class CSharpAst {
|
|
446
636
|
dataModel,
|
447
637
|
};
|
448
638
|
if (isAuditBase) {
|
449
|
-
if (!queryApi.request.attributes)
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
}
|
639
|
+
if (!queryApi.request.attributes?.find(x => x.name === 'AutoApply')) {
|
640
|
+
// [AutoApply(Behavior.AuditQuery)]
|
641
|
+
queryApi.request.attributes.push({
|
642
|
+
name: "AutoApply",
|
643
|
+
constructorArgs: [{
|
644
|
+
name: "name",
|
645
|
+
type: "constant",
|
646
|
+
value: "Behavior.AuditQuery"
|
647
|
+
}]
|
648
|
+
});
|
649
|
+
}
|
460
650
|
}
|
461
651
|
this.result.operations.push(queryApi);
|
462
652
|
}
|
@@ -464,7 +654,6 @@ export class CSharpAst {
|
|
464
654
|
let createApi = this.result.operations.find(x => x.request.name === createName);
|
465
655
|
if (!createApi) {
|
466
656
|
const ignorePropsWithAttrs = ['AutoIncrement', 'Reference'];
|
467
|
-
const ignoreAttrs = [];
|
468
657
|
createApi = {
|
469
658
|
method: "POST",
|
470
659
|
actions: ["ANY"],
|
@@ -481,8 +670,9 @@ export class CSharpAst {
|
|
481
670
|
type: x.isPrimaryKey
|
482
671
|
? x.type
|
483
672
|
: `${x.type}`,
|
484
|
-
attributes: x.attributes
|
673
|
+
attributes: onlyAttrs(x.attributes, this.requestPropAttrs),
|
485
674
|
})),
|
675
|
+
attributes: this.attrsFor("Create", type.attributes),
|
486
676
|
},
|
487
677
|
returnType: {
|
488
678
|
name: "IdResponse",
|
@@ -512,17 +702,17 @@ export class CSharpAst {
|
|
512
702
|
}
|
513
703
|
if (isAuditBase) {
|
514
704
|
createApi.requiresAuth = true;
|
515
|
-
if (!createApi.request.attributes)
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
}
|
705
|
+
if (!createApi.request.attributes?.find(x => x.name === 'AutoApply')) {
|
706
|
+
// [AutoApply(Behavior.AuditCreate)]
|
707
|
+
createApi.request.attributes.push({
|
708
|
+
name: "AutoApply",
|
709
|
+
constructorArgs: [{
|
710
|
+
name: "name",
|
711
|
+
type: "constant",
|
712
|
+
value: "Behavior.AuditCreate"
|
713
|
+
}]
|
714
|
+
});
|
715
|
+
}
|
526
716
|
}
|
527
717
|
this.result.operations.push(createApi);
|
528
718
|
}
|
@@ -545,8 +735,9 @@ export class CSharpAst {
|
|
545
735
|
type: x.isPrimaryKey
|
546
736
|
? x.type
|
547
737
|
: `${this.nullable(x.type)}`,
|
548
|
-
attributes: x.attributes?.filter(a => !ignoreAttrs.includes(a.name)),
|
738
|
+
attributes: onlyAttrs(x.attributes?.filter(a => !ignoreAttrs.includes(a.name)), this.requestPropAttrs),
|
549
739
|
})),
|
740
|
+
attributes: this.attrsFor("Update", type.attributes),
|
550
741
|
},
|
551
742
|
returnType: {
|
552
743
|
name: "IdResponse",
|
@@ -565,17 +756,17 @@ export class CSharpAst {
|
|
565
756
|
}
|
566
757
|
if (isAuditBase) {
|
567
758
|
updateApi.requiresAuth = true;
|
568
|
-
if (!updateApi.request.attributes)
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
}
|
759
|
+
if (!updateApi.request.attributes?.find(x => x.name === 'AutoApply')) {
|
760
|
+
// [AutoApply(Behavior.AuditModify)]
|
761
|
+
updateApi.request.attributes.push({
|
762
|
+
name: "AutoApply",
|
763
|
+
constructorArgs: [{
|
764
|
+
name: "name",
|
765
|
+
type: "constant",
|
766
|
+
value: "Behavior.AuditModify"
|
767
|
+
}]
|
768
|
+
});
|
769
|
+
}
|
579
770
|
}
|
580
771
|
this.result.operations.push(updateApi);
|
581
772
|
}
|
@@ -593,29 +784,43 @@ export class CSharpAst {
|
|
593
784
|
namespace: "ServiceStack",
|
594
785
|
genericArgs: [type.name]
|
595
786
|
}],
|
596
|
-
properties:
|
787
|
+
properties: pk
|
788
|
+
? [
|
789
|
+
Object.assign({}, pk, {
|
790
|
+
type: `${this.nullable(pk.type)}`,
|
791
|
+
attributes: onlyAttrs(pk.attributes, this.requestPropAttrs),
|
792
|
+
}),
|
793
|
+
idsProp
|
794
|
+
]
|
795
|
+
: [],
|
796
|
+
attributes: this.attrsFor("Delete", type.attributes),
|
597
797
|
},
|
598
798
|
returnsVoid: true,
|
599
799
|
dataModel,
|
600
800
|
};
|
601
801
|
if (isAuditBase) {
|
602
802
|
deleteApi.requiresAuth = true;
|
603
|
-
if (!deleteApi.request.attributes)
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
}
|
803
|
+
if (!deleteApi.request.attributes?.find(x => x.name === 'AutoApply')) {
|
804
|
+
// [AutoApply(Behavior.AuditSoftDelete)]
|
805
|
+
deleteApi.request.attributes.push({
|
806
|
+
name: "AutoApply",
|
807
|
+
constructorArgs: [{
|
808
|
+
name: "name",
|
809
|
+
type: "constant",
|
810
|
+
value: "Behavior.AuditSoftDelete"
|
811
|
+
}]
|
812
|
+
});
|
813
|
+
}
|
614
814
|
}
|
615
815
|
this.result.operations.push(deleteApi);
|
616
816
|
}
|
617
817
|
}
|
618
818
|
}
|
819
|
+
filterModelAttributes() {
|
820
|
+
for (const type of this.classes) {
|
821
|
+
type.attributes = this.attrsFor("Model", type.attributes);
|
822
|
+
}
|
823
|
+
}
|
619
824
|
// Add Icon for BuiltIn UIs and AutoQueryGrid to known type names
|
620
825
|
addIconsToKnownTypes() {
|
621
826
|
for (const type of this.typesWithPrimaryKeys) {
|
@@ -696,6 +901,7 @@ export class CSharpAst {
|
|
696
901
|
this.hideReferenceProperties();
|
697
902
|
this.replaceUserReferencesWithAuditTables();
|
698
903
|
this.createAutoCrudApis();
|
904
|
+
this.filterModelAttributes();
|
699
905
|
}
|
700
906
|
parse(ast) {
|
701
907
|
const classes = ast.classes.concat(ast.interfaces);
|
package/dist/cs-gen.js
CHANGED
package/dist/index.js
CHANGED
@@ -57,7 +57,7 @@ function parseArgs(...args) {
|
|
57
57
|
break;
|
58
58
|
}
|
59
59
|
}
|
60
|
-
else if (ret.type === "help" && ["help", "info", "init", "ls", "rm", "update", "accept"].includes(arg)) {
|
60
|
+
else if (ret.type === "help" && ["help", "info", "init", "ls", "add", "rm", "update", "accept"].includes(arg)) {
|
61
61
|
if (arg == "help")
|
62
62
|
ret.type = "help";
|
63
63
|
else if (arg == "info")
|
@@ -82,6 +82,10 @@ function parseArgs(...args) {
|
|
82
82
|
ret.type = "list";
|
83
83
|
ret.list = args[++i];
|
84
84
|
}
|
85
|
+
else if (arg == "add") {
|
86
|
+
ret.type = "add";
|
87
|
+
ret.add = args[++i];
|
88
|
+
}
|
85
89
|
else if (arg == "accept") {
|
86
90
|
ret.type = "accept";
|
87
91
|
ret.accept = args[++i];
|
@@ -150,18 +154,19 @@ export async function cli(cmdArgs) {
|
|
150
154
|
if (command.unknown?.length) {
|
151
155
|
console.log(`Unknown Command: ${command.script} ${command.unknown.join(' ')}\n`);
|
152
156
|
}
|
157
|
+
const bin = script.padStart(7, ' ');
|
153
158
|
console.log(`Usage:
|
154
|
-
${
|
159
|
+
${bin} <prompt> Generate new TypeScript Data Models, C# APIs and Migrations from prompt
|
155
160
|
-m, -models <model,> Specify up to 5 LLM models to generate .d.ts Data Models
|
156
161
|
-l, -license <LC-xxx> Specify valid license certificate or key to use premium models
|
157
162
|
|
158
|
-
${
|
163
|
+
${bin} <models>.d.ts Regenerate C# *.cs files for Data Models defined in the TypeScript .d.ts file
|
159
164
|
-w, -watch Watch for changes to <models>.d.ts and regenerate *.cs on save
|
160
165
|
|
161
|
-
${
|
162
|
-
${
|
163
|
-
${
|
164
|
-
${
|
166
|
+
${bin} rm <models>.d.ts Remove <models>.d.ts and its generated *.cs files
|
167
|
+
${bin} ls models Display list of available premium LLM models
|
168
|
+
${bin} init Initialize okai.json with project info to override default paths
|
169
|
+
${bin} info Display current project info
|
165
170
|
|
166
171
|
Options:
|
167
172
|
-v, -verbose Display verbose logging
|
@@ -207,6 +212,24 @@ Options:
|
|
207
212
|
process.exit(0);
|
208
213
|
}
|
209
214
|
}
|
215
|
+
if (command.type === "add") {
|
216
|
+
if (command.add == "types" || command.add?.startsWith("api")) {
|
217
|
+
const apiFile = path.join(import.meta.dirname, 'api.d.ts');
|
218
|
+
if (!fs.existsSync(apiFile)) {
|
219
|
+
console.log(`Could not find: ${apiFile}`);
|
220
|
+
process.exit(1);
|
221
|
+
}
|
222
|
+
const toFile = path.join(info.serviceModelDir, 'api.d.ts');
|
223
|
+
fs.copyFileSync(apiFile, toFile);
|
224
|
+
console.log(`Added: ${toFile}`);
|
225
|
+
process.exit(0);
|
226
|
+
}
|
227
|
+
else {
|
228
|
+
console.log(`Unknown add command: ${command.add}`);
|
229
|
+
console.log(`Usage: add types`);
|
230
|
+
process.exit(1);
|
231
|
+
}
|
232
|
+
}
|
210
233
|
function assertTsdPath(tsdFile) {
|
211
234
|
const tryPaths = [
|
212
235
|
path.join(process.cwd(), tsdFile),
|
@@ -319,6 +342,13 @@ Options:
|
|
319
342
|
}
|
320
343
|
fs.unlinkSync(tsdPath);
|
321
344
|
console.log(`Removed: ${tsdPath}`);
|
345
|
+
const serviceModelDir = path.dirname(tsdPath);
|
346
|
+
const tsds = fs.readdirSync(serviceModelDir).filter(x => x.endsWith('.d.ts'));
|
347
|
+
if (tsds.length == 1 && tsds[0] == 'api.d.ts') {
|
348
|
+
const typesApiPath = path.join(serviceModelDir, 'api.d.ts');
|
349
|
+
fs.unlinkSync(typesApiPath);
|
350
|
+
console.log(`Removed: ${typesApiPath}`);
|
351
|
+
}
|
322
352
|
process.exit(0);
|
323
353
|
}
|
324
354
|
if (command.type == "accept") {
|
@@ -607,15 +637,18 @@ function chooseFile(ctx, info, gist, comamnd) {
|
|
607
637
|
const migrationFileName = path.basename(migrationPath);
|
608
638
|
const migrationCls = leftPart(migrationFileName, '.');
|
609
639
|
const migrationContent = replaceMyApp(csMigrationFiles[Object.keys(csMigrationFiles)[0]].replaceAll('Migration1000', migrationCls), info.projectName);
|
610
|
-
const sb = [
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
640
|
+
const sb = [
|
641
|
+
`/// <reference path="./api.d.ts" />`,
|
642
|
+
`/*prompt: ${titleBar.content.replaceAll('/*', '').replaceAll('*/', '')}`,
|
643
|
+
`api: ~/${path.join(relativeServiceModelDir, apiFileName)}`,
|
644
|
+
`migration: ~/${path.join(relativeMigrationDir, migrationFileName)}`,
|
645
|
+
`*/`,
|
646
|
+
'',
|
647
|
+
tsd,
|
648
|
+
];
|
617
649
|
const tsdContent = sb.join('\n');
|
618
650
|
const tsdFileName = `${groupName}.d.ts`;
|
651
|
+
const typesApiPath = path.join(info.slnDir, relativeServiceModelDir, `api.d.ts`);
|
619
652
|
const fullTsdPath = path.join(info.slnDir, relativeServiceModelDir, tsdFileName);
|
620
653
|
const fullApiPath = path.join(info.slnDir, relativeServiceModelDir, apiFileName);
|
621
654
|
const fullMigrationPath = path.join(info.slnDir, relativeMigrationDir, migrationFileName);
|
@@ -634,6 +667,8 @@ function chooseFile(ctx, info, gist, comamnd) {
|
|
634
667
|
fs.writeFileSync(fullMigrationPath, migrationContent, { encoding: 'utf-8' });
|
635
668
|
console.log(`Saved: ${fullMigrationPath}`);
|
636
669
|
}
|
670
|
+
const apiFile = path.join(import.meta.dirname, 'api.d.ts');
|
671
|
+
fs.writeFileSync(typesApiPath, fs.readFileSync(apiFile, 'utf-8'));
|
637
672
|
const script = path.basename(process.argv[1]);
|
638
673
|
console.log(`\nTo regenerate classes, update '${tsdFileName}' then run:`);
|
639
674
|
console.log(`$ ${script} ${tsdFileName}`);
|
package/dist/ts-parser.js
CHANGED
@@ -4,7 +4,8 @@ export class TypeScriptParser {
|
|
4
4
|
static ENUM_PATTERN = /enum\s+(\w+)\s*{([^}]*)}/g;
|
5
5
|
static PROPERTY_PATTERN = /(?:(?<modifier>private|public|protected|readonly)\s+)*(?<name>\w+)(?<optional>\?)?\s*:\s*(?<type>[\w<>[\],\s]+)(?<union>\|\s*[\w<>[\],|,\s]+)?\s*;?/;
|
6
6
|
static ENUM_MEMBER_PATTERN = /(\w+)\s*(?:=\s*("[^"]*"|'[^']*'|\d+|[^,\n]+))?\s*/;
|
7
|
-
static ANNOTATION_PATTERN =
|
7
|
+
// private static readonly ANNOTATION_PATTERN = /@(\w+\.?\w*)\s*\((.*)\)/
|
8
|
+
static ANNOTATION_PATTERN = /@([A-Za-z_][A-Za-z0-9_]*\.?[A-Za-z_]?[A-Za-z0-9_]*)\s*\((.*)\)/;
|
8
9
|
classes = [];
|
9
10
|
interfaces = [];
|
10
11
|
enums = [];
|
@@ -260,7 +261,7 @@ export class TypeScriptParser {
|
|
260
261
|
}
|
261
262
|
export function parseAnnotation(annotation) {
|
262
263
|
// Match @name and everything inside ()
|
263
|
-
const regex = /@(\w
|
264
|
+
const regex = /@(\w+\.?\w*)\s*\((.*)\)/;
|
264
265
|
const match = annotation.match(regex);
|
265
266
|
if (!match)
|
266
267
|
return null;
|
package/dist/tsd-gen.js
CHANGED
@@ -32,6 +32,12 @@ export class TsdGenerator {
|
|
32
32
|
return `${prefix}@${attr.name}(${sbArgs.join(',')})`;
|
33
33
|
}
|
34
34
|
toInterface(ast) {
|
35
|
+
return this.toType(ast, 'interface');
|
36
|
+
}
|
37
|
+
toClass(ast) {
|
38
|
+
return this.toType(ast, 'class');
|
39
|
+
}
|
40
|
+
toType(ast, type) {
|
35
41
|
const sb = [];
|
36
42
|
if (ast.comment) {
|
37
43
|
sb.push(ast.comment.split('\n').map(x => `// ${x}`).join('\n'));
|
@@ -42,7 +48,7 @@ export class TsdGenerator {
|
|
42
48
|
}
|
43
49
|
}
|
44
50
|
const extend = ast.extends ? ` extends ${ast.extends}` : '';
|
45
|
-
sb.push(`export
|
51
|
+
sb.push(`export ${type} ${ast.name}${extend} {`);
|
46
52
|
for (const prop of ast.properties) {
|
47
53
|
if (prop.comment) {
|
48
54
|
sb.push(prop.comment.split('\n').map(x => ` // ${x}`).join('\n'));
|
@@ -76,7 +82,7 @@ export class TsdGenerator {
|
|
76
82
|
sb.push('}');
|
77
83
|
return sb.join('\n');
|
78
84
|
}
|
79
|
-
generate(ast) {
|
85
|
+
generate(ast, type = 'interface') {
|
80
86
|
this.ast = ast;
|
81
87
|
const sb = [];
|
82
88
|
for (const cls of ast.enums ?? []) {
|
@@ -84,12 +90,12 @@ export class TsdGenerator {
|
|
84
90
|
sb.push('');
|
85
91
|
}
|
86
92
|
for (const cls of ast.interfaces ?? []) {
|
87
|
-
sb.push(this.
|
93
|
+
sb.push(this.toType(cls, type));
|
88
94
|
sb.push('');
|
89
95
|
}
|
90
96
|
for (const cls of ast.classes ?? []) {
|
91
97
|
const iface = this.clsToInterface(cls);
|
92
|
-
sb.push(this.
|
98
|
+
sb.push(this.toType(iface, type));
|
93
99
|
sb.push('');
|
94
100
|
}
|
95
101
|
const tsd = sb.join('\n');
|
@@ -97,29 +103,50 @@ export class TsdGenerator {
|
|
97
103
|
}
|
98
104
|
}
|
99
105
|
export class TsdDataModelGenerator extends TsdGenerator {
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
106
|
+
duplicateTypePropMap = {
|
107
|
+
note: 'content',
|
108
|
+
};
|
109
|
+
convertType(type) {
|
110
|
+
type.name = toPascalCase(type.name);
|
111
|
+
type.properties?.forEach(prop => {
|
112
|
+
prop.name = toCamelCase(prop.name);
|
113
|
+
if (prop.type.startsWith('Array<')) {
|
114
|
+
const elType = prop.type.slice('Array<'.length, -1);
|
115
|
+
prop.type = elType + '[]';
|
116
|
+
}
|
117
|
+
if (prop.type === 'User') {
|
118
|
+
prop.name = 'userId';
|
119
|
+
prop.type = 'string';
|
120
|
+
}
|
121
|
+
if (prop.type === 'User[]') {
|
122
|
+
if (prop.name.endsWith('s')) {
|
123
|
+
prop.name = prop.name.slice(0, -1) + 'Ids';
|
113
124
|
}
|
114
|
-
|
125
|
+
prop.type = 'string[]';
|
126
|
+
}
|
127
|
+
});
|
128
|
+
this.rewriteDuplicateTypePropNames(type);
|
129
|
+
this.rewriteSelfReferencingIds(type);
|
130
|
+
}
|
131
|
+
rewriteDuplicateTypePropNames(type) {
|
132
|
+
const duplicateProp = type.properties?.find(x => toPascalCase(x.name) === type.name);
|
133
|
+
if (duplicateProp) {
|
134
|
+
const newName = this.duplicateTypePropMap[duplicateProp.name] ?? 'value';
|
135
|
+
duplicateProp.name = newName;
|
115
136
|
}
|
137
|
+
}
|
138
|
+
rewriteSelfReferencingIds(type) {
|
139
|
+
const selfRefId = type.properties?.find(x => x.name.toLowerCase() === `${type.name}id`.toLowerCase());
|
140
|
+
if (selfRefId) {
|
141
|
+
selfRefId.name = `parentId`;
|
142
|
+
}
|
143
|
+
}
|
144
|
+
generate(ast) {
|
116
145
|
ast.classes?.forEach(cls => {
|
117
|
-
|
118
|
-
convertProps(cls.properties);
|
146
|
+
this.convertType(cls);
|
119
147
|
});
|
120
148
|
ast.interfaces?.forEach(cls => {
|
121
|
-
|
122
|
-
convertProps(cls.properties);
|
149
|
+
this.convertType(cls);
|
123
150
|
});
|
124
151
|
ast.enums?.forEach(e => {
|
125
152
|
e.name = toPascalCase(e.name);
|
@@ -133,6 +160,6 @@ export class TsdDataModelGenerator extends TsdGenerator {
|
|
133
160
|
if (ast.interfaces) {
|
134
161
|
ast.interfaces = ast.interfaces.filter(x => x.name !== 'User');
|
135
162
|
}
|
136
|
-
return super.generate(ast);
|
163
|
+
return super.generate(ast, "class");
|
137
164
|
}
|
138
165
|
}
|
package/dist/utils.js
CHANGED
@@ -113,6 +113,14 @@ export function leftPart(s, needle) {
|
|
113
113
|
? s
|
114
114
|
: s.substring(0, pos);
|
115
115
|
}
|
116
|
+
export function rightPart(s, needle) {
|
117
|
+
if (s == null)
|
118
|
+
return null;
|
119
|
+
let pos = s.indexOf(needle);
|
120
|
+
return pos == -1
|
121
|
+
? s
|
122
|
+
: s.substring(pos + needle.length);
|
123
|
+
}
|
116
124
|
export function splitCase(t) {
|
117
125
|
return typeof t != 'string' ? t : t.replace(/([A-Z]|[0-9]+)/g, ' $1').replace(/_/g, ' ').trim();
|
118
126
|
}
|
@@ -126,13 +134,13 @@ export function tsdWithPrompt(tsd, prompt) {
|
|
126
134
|
return `/*prompt: ${prompt}\n*/\n\n${tsd}`;
|
127
135
|
}
|
128
136
|
export function tsdWithoutPrompt(tsd) {
|
129
|
-
return tsd.
|
137
|
+
return tsd.includes('/*prompt:')
|
130
138
|
? tsd.substring(tsd.indexOf('*/') + 2).trim()
|
131
139
|
: tsd;
|
132
140
|
}
|
133
141
|
export function parseTsdHeader(tsd) {
|
134
142
|
const header = tsd.includes('/*prompt:')
|
135
|
-
? leftPart(tsd, '
|
143
|
+
? leftPart(rightPart(tsd, '/*prompt:'), '*/').trim()
|
136
144
|
: null;
|
137
145
|
if (!header)
|
138
146
|
return null;
|
package/package.json
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
{
|
2
2
|
"name": "okai",
|
3
3
|
"type": "module",
|
4
|
-
"version": "0.0.
|
4
|
+
"version": "0.0.23",
|
5
5
|
"bin": "./dist/okai.js",
|
6
6
|
"main": "./dist/index.js",
|
7
7
|
"module": "./dist/index.js",
|
@@ -12,7 +12,7 @@
|
|
12
12
|
"import": "./dist/index.js"
|
13
13
|
},
|
14
14
|
"scripts": {
|
15
|
-
"build": "bun run clean && tsc && chmod +x ./dist/okai.js",
|
15
|
+
"build": "bun run clean && tsc && shx cp ./src/api.d.ts ./dist && chmod +x ./dist/okai.js",
|
16
16
|
"build-bun": "bun run clean && bun build.ts",
|
17
17
|
"clean": "shx rm -rf ./dist",
|
18
18
|
"test": "bun test --",
|