okai 0.0.22 → 0.0.24
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 +1 -7
- package/dist/cs-ast.js +374 -85
- package/dist/cs-gen.js +1 -1
- package/dist/index.js +42 -8
- package/dist/ts-parser.js +3 -2
- package/dist/tsd-gen.js +11 -5
- 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 validateLessThan(value:number) : ClassFieldDecoratorDef
|
102
|
+
export function validateLessThanOrEqual(value:number) : ClassFieldDecoratorDef
|
103
|
+
export function validateGreaterThan(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
|
+
validateLessThan:typeof validateLessThan
|
268
|
+
validateLessThanOrEqual:typeof validateLessThanOrEqual
|
269
|
+
validateGreaterThan:typeof validateGreaterThan
|
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
@@ -1,4 +1,4 @@
|
|
1
|
-
import { getGroupName
|
1
|
+
import { getGroupName } from "./utils.js";
|
2
2
|
import { CSharpGenerator } from "./cs-gen.js";
|
3
3
|
export class CSharpApiGenerator extends CSharpGenerator {
|
4
4
|
toApiClass(op) {
|
@@ -78,12 +78,6 @@ export class CSharpApiGenerator extends CSharpGenerator {
|
|
78
78
|
}
|
79
79
|
generate(ast) {
|
80
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
81
|
this.namespaces = Array.from(ast.namespaces);
|
88
82
|
this.apis = ast.operations.map(x => this.toApiClass(x));
|
89
83
|
this.classes = ast.types.filter(t => !t.isEnum).map(x => this.toClass(x));
|
package/dist/cs-ast.js
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import { plural, toPascalCase } from "./utils.js";
|
1
|
+
import { getGroupName, leftPart, plural, rightPart, splitCase, 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,153 @@ 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
|
+
'validateLessThan',
|
88
|
+
'validateLessThanOrEqual',
|
89
|
+
'validateGreaterThan',
|
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
|
+
get requestPropAttrsWithoutValidators() {
|
114
|
+
return this.requestPropAttrs.filter(x => !x.startsWith('validate'));
|
115
|
+
}
|
116
|
+
modelPropAttrs = [
|
117
|
+
'alias',
|
118
|
+
'meta',
|
119
|
+
'priority',
|
120
|
+
'primaryKey',
|
121
|
+
'autoId',
|
122
|
+
'autoIncrement',
|
123
|
+
'index',
|
124
|
+
'compute',
|
125
|
+
'computed',
|
126
|
+
'persisted',
|
127
|
+
'uniqueConstraint',
|
128
|
+
'addColumn',
|
129
|
+
'removeColumn',
|
130
|
+
'belongTo',
|
131
|
+
'checkConstraint',
|
132
|
+
'customField',
|
133
|
+
'customSelect',
|
134
|
+
'customInsert',
|
135
|
+
'customUpdate',
|
136
|
+
'decimalLength',
|
137
|
+
'Default',
|
138
|
+
'description',
|
139
|
+
'enumAsInt',
|
140
|
+
'excludeMetadata',
|
141
|
+
'excludeFromDescription',
|
142
|
+
'explicitAutoQuery',
|
143
|
+
'foreignKey',
|
144
|
+
'ignore',
|
145
|
+
'ignoreOnUpdate',
|
146
|
+
'ignoreOnInsert',
|
147
|
+
'ignoreDataMember',
|
148
|
+
'reference',
|
149
|
+
'referenceField',
|
150
|
+
'references',
|
151
|
+
'required',
|
152
|
+
'returnOnInsert',
|
153
|
+
'rowVersion',
|
154
|
+
'unique',
|
155
|
+
'dataMember',
|
156
|
+
'ref',
|
157
|
+
'format',
|
158
|
+
'intl',
|
159
|
+
'intlNumber',
|
160
|
+
'intlDateTime',
|
161
|
+
'intlRelativeTime',
|
162
|
+
].map(x => x.toLowerCase());
|
163
|
+
// Ignore properties with these attributes on APIs
|
164
|
+
ignoreCreateProps = [
|
165
|
+
'autoIncrement',
|
166
|
+
'references',
|
167
|
+
'compute',
|
168
|
+
'computed',
|
169
|
+
].map(x => x.toLowerCase());
|
170
|
+
ignoreUpdateProps = [
|
171
|
+
'references',
|
172
|
+
'compute',
|
173
|
+
'computed',
|
174
|
+
].map(x => x.toLowerCase());
|
175
|
+
// Validators that should be on Create but not optional Update APIs
|
176
|
+
ignoreUpdateValidators = [
|
177
|
+
'validateNull',
|
178
|
+
'validateNotNull',
|
179
|
+
'validateEmpty',
|
180
|
+
'validateNotEmpty',
|
181
|
+
].map(x => x.toLowerCase());
|
182
|
+
ignoreReadValidators = this.requestPropAttrs.filter(x => x.startsWith('validate')).map(x => x.toLowerCase());
|
183
|
+
ignoreDeleteValidators = this.requestPropAttrs.filter(x => x.startsWith('validate')).map(x => x.toLowerCase());
|
37
184
|
unwrap(type) {
|
38
185
|
if (type.endsWith("?")) {
|
39
186
|
return type.substring(0, type.length - 1);
|
@@ -76,19 +223,26 @@ export class CSharpAst {
|
|
76
223
|
return this.typeMap[type] ?? { name: type, namespace: "MyApp" };
|
77
224
|
}
|
78
225
|
csharpAttribute(attr) {
|
79
|
-
const
|
226
|
+
const attrName = attr.name.includes('.')
|
227
|
+
? rightPart(attr.name, '.')
|
228
|
+
: attr.name;
|
229
|
+
const to = { name: toPascalCase(attrName) };
|
80
230
|
const attrType = (value) => typeof value == 'string'
|
81
|
-
? (
|
231
|
+
? ((value.startsWith('typeof(') || value.startsWith('nameof(')) && value.endsWith(')')
|
232
|
+
? "constant" :
|
233
|
+
value.match(/^[A-Z][A-Za-z0-9_]+\.[A-Z][A-Za-z0-9_]+$/) //Axx.Bxx
|
234
|
+
? "constant"
|
235
|
+
: "string")
|
82
236
|
: typeof value == "object"
|
83
237
|
? (value instanceof Date ? "string" : Array.isArray(value) ? "array" : "object")
|
84
238
|
: typeof value;
|
85
239
|
if (attr.constructorArgs?.length) {
|
86
240
|
to.constructorArgs = attr.constructorArgs.map(x => {
|
87
|
-
const type = attrType(x
|
241
|
+
const type = attrType(x);
|
88
242
|
return {
|
89
243
|
name: 'String',
|
90
244
|
type,
|
91
|
-
value: `${x
|
245
|
+
value: `${x}`
|
92
246
|
};
|
93
247
|
});
|
94
248
|
}
|
@@ -102,21 +256,27 @@ export class CSharpAst {
|
|
102
256
|
};
|
103
257
|
});
|
104
258
|
}
|
259
|
+
if (attr.name.includes('.')) {
|
260
|
+
to.namespace = leftPart(attr.name, '.');
|
261
|
+
}
|
105
262
|
return to;
|
106
263
|
}
|
107
264
|
addMetadataType(cls) {
|
108
265
|
const type = {
|
109
266
|
name: this.toCsName(cls.name),
|
110
267
|
namespace: "MyApp",
|
111
|
-
description: cls.comment,
|
112
268
|
properties: cls.properties.map(p => {
|
113
269
|
const type = this.csharpType(p.type, p.name);
|
114
270
|
const prop = {
|
115
271
|
name: this.toCsName(p.name),
|
116
272
|
type: p.optional ? this.nullable(type.name) : type.name,
|
117
|
-
namespace: type.namespace,
|
118
|
-
description: p.comment,
|
119
273
|
};
|
274
|
+
if (type.namespace) {
|
275
|
+
prop.namespace = type.namespace;
|
276
|
+
}
|
277
|
+
if (p.comment) {
|
278
|
+
prop.description = p.comment;
|
279
|
+
}
|
120
280
|
if (prop.name === 'Id') {
|
121
281
|
prop.isPrimaryKey = true;
|
122
282
|
}
|
@@ -145,6 +305,12 @@ export class CSharpAst {
|
|
145
305
|
return prop;
|
146
306
|
}),
|
147
307
|
};
|
308
|
+
if (cls.comment) {
|
309
|
+
type.description = cls.comment;
|
310
|
+
}
|
311
|
+
if (cls.extends) {
|
312
|
+
type.inherits = { name: this.toCsName(cls.extends) };
|
313
|
+
}
|
148
314
|
if (cls.annotations?.length) {
|
149
315
|
type.attributes = cls.annotations.map(x => this.csharpAttribute(x));
|
150
316
|
}
|
@@ -389,7 +555,86 @@ export class CSharpAst {
|
|
389
555
|
}
|
390
556
|
}
|
391
557
|
}
|
558
|
+
onlyAttrs(attrs, only) {
|
559
|
+
if (!attrs)
|
560
|
+
return;
|
561
|
+
return attrs.filter(x => only.includes(x.name.toLowerCase()));
|
562
|
+
}
|
563
|
+
attrsFor(dtoType, attrType, attrs) {
|
564
|
+
const requestAttrs = this.requestAttrs;
|
565
|
+
const requestPropAttrs = this.requestPropAttrs;
|
566
|
+
const modelAttrs = this.modelAttrs;
|
567
|
+
const modelPropAttrs = this.modelPropAttrs;
|
568
|
+
const isRequest = ["Read", "Create", "Update", "Delete"].includes(dtoType);
|
569
|
+
const validAttrs = attrType === "Type"
|
570
|
+
? isRequest
|
571
|
+
? requestAttrs
|
572
|
+
: modelAttrs
|
573
|
+
: isRequest
|
574
|
+
? requestPropAttrs
|
575
|
+
: modelPropAttrs;
|
576
|
+
const ignoreValidators = attrType === "Prop"
|
577
|
+
? dtoType === "Update"
|
578
|
+
? this.ignoreUpdateValidators
|
579
|
+
: dtoType === "Read"
|
580
|
+
? this.ignoreReadValidators
|
581
|
+
: dtoType === "Delete"
|
582
|
+
? this.ignoreDeleteValidators
|
583
|
+
: []
|
584
|
+
: [];
|
585
|
+
function shouldInclude(attr, dtoType) {
|
586
|
+
if (!validAttrs.includes(attr.name.toLowerCase()))
|
587
|
+
return false;
|
588
|
+
const ns = attr.namespace;
|
589
|
+
if (ns) {
|
590
|
+
if (ns == "All")
|
591
|
+
return true;
|
592
|
+
if (ns == "Read")
|
593
|
+
return dtoType == "Read";
|
594
|
+
if (ns == "Create")
|
595
|
+
return dtoType == "Create";
|
596
|
+
if (ns == "Update")
|
597
|
+
return dtoType == "Update";
|
598
|
+
if (ns == "Delete")
|
599
|
+
return dtoType == "Delete";
|
600
|
+
if (ns == "Write")
|
601
|
+
return ["Create", "Update", "Delete"].includes(dtoType);
|
602
|
+
return false;
|
603
|
+
}
|
604
|
+
else {
|
605
|
+
const nameLower = attr.name.toLowerCase();
|
606
|
+
if (isRequest) {
|
607
|
+
if (attrType === "Type") {
|
608
|
+
return requestAttrs.includes(nameLower);
|
609
|
+
}
|
610
|
+
else if (attrType === "Prop") {
|
611
|
+
if (ignoreValidators.length && ignoreValidators.includes(nameLower))
|
612
|
+
return false;
|
613
|
+
return requestPropAttrs.includes(nameLower);
|
614
|
+
}
|
615
|
+
}
|
616
|
+
else {
|
617
|
+
if (attrType === "Type") {
|
618
|
+
return modelAttrs.includes(nameLower);
|
619
|
+
}
|
620
|
+
else if (attrType === "Prop") {
|
621
|
+
return modelPropAttrs.includes(nameLower);
|
622
|
+
}
|
623
|
+
}
|
624
|
+
}
|
625
|
+
return true;
|
626
|
+
}
|
627
|
+
const to = [];
|
628
|
+
for (const attr of attrs || []) {
|
629
|
+
if (shouldInclude(attr, dtoType)) {
|
630
|
+
to.push(attr);
|
631
|
+
}
|
632
|
+
}
|
633
|
+
return to;
|
634
|
+
}
|
392
635
|
createAutoCrudApis() {
|
636
|
+
const groupName = getGroupName(this.result);
|
637
|
+
const friendlyGroupName = splitCase(groupName);
|
393
638
|
for (const type of this.classes) {
|
394
639
|
const hasPk = type.properties?.some(x => x.isPrimaryKey);
|
395
640
|
if (!hasPk)
|
@@ -400,6 +645,12 @@ export class CSharpAst {
|
|
400
645
|
const pk = type.properties?.find(x => x.isPrimaryKey);
|
401
646
|
const dataModel = { name: type.name, namespace: type.name };
|
402
647
|
const isAuditBase = type.inherits?.name === 'AuditBase';
|
648
|
+
const existingTag = type.attributes?.find(x => x.name.toLowerCase() === 'tag');
|
649
|
+
const tags = !existingTag ? [friendlyGroupName] : undefined;
|
650
|
+
const emptyTag = existingTag?.constructorArgs?.[0]?.value === '';
|
651
|
+
if (emptyTag) {
|
652
|
+
type.attributes = type.attributes.filter(x => x !== existingTag);
|
653
|
+
}
|
403
654
|
const inputTagAttrs = [{
|
404
655
|
name: "Input",
|
405
656
|
args: [{ name: "Type", type: "string", value: "tag" }]
|
@@ -408,21 +659,14 @@ export class CSharpAst {
|
|
408
659
|
name: "FieldCss",
|
409
660
|
args: [{ name: "Field", type: "string", value: "col-span-12" }]
|
410
661
|
}];
|
411
|
-
const
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
name: `${pk.name}s`,
|
420
|
-
type: "List`1?",
|
421
|
-
namespace: "System.Collections.Generic",
|
422
|
-
genericArgs: [pk.type]
|
423
|
-
}
|
424
|
-
]
|
425
|
-
: [];
|
662
|
+
const idsProp = pk
|
663
|
+
? {
|
664
|
+
name: `${pk.name}s`,
|
665
|
+
type: "List`1?",
|
666
|
+
namespace: "System.Collections.Generic",
|
667
|
+
genericArgs: [pk.type]
|
668
|
+
}
|
669
|
+
: undefined;
|
426
670
|
if (!queryApi) {
|
427
671
|
queryApi = {
|
428
672
|
method: "GET",
|
@@ -436,7 +680,16 @@ export class CSharpAst {
|
|
436
680
|
namespace: "ServiceStack",
|
437
681
|
genericArgs: [type.name]
|
438
682
|
},
|
439
|
-
properties:
|
683
|
+
properties: pk
|
684
|
+
? [
|
685
|
+
Object.assign({}, pk, {
|
686
|
+
type: this.nullable(pk.type),
|
687
|
+
attributes: this.attrsFor("Read", "Prop", pk.attributes),
|
688
|
+
}),
|
689
|
+
idsProp
|
690
|
+
]
|
691
|
+
: [],
|
692
|
+
attributes: this.attrsFor("Read", "Type", type.attributes),
|
440
693
|
},
|
441
694
|
returnType: {
|
442
695
|
name: "QueryResponse`1",
|
@@ -446,25 +699,23 @@ export class CSharpAst {
|
|
446
699
|
dataModel,
|
447
700
|
};
|
448
701
|
if (isAuditBase) {
|
449
|
-
if (!queryApi.request.attributes)
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
}
|
702
|
+
if (!queryApi.request.attributes?.find(x => x.name === 'AutoApply')) {
|
703
|
+
// [AutoApply(Behavior.AuditQuery)]
|
704
|
+
queryApi.request.attributes.push({
|
705
|
+
name: "AutoApply",
|
706
|
+
constructorArgs: [{
|
707
|
+
name: "name",
|
708
|
+
type: "constant",
|
709
|
+
value: "Behavior.AuditQuery"
|
710
|
+
}]
|
711
|
+
});
|
712
|
+
}
|
460
713
|
}
|
461
714
|
this.result.operations.push(queryApi);
|
462
715
|
}
|
463
716
|
let createName = `Create${type.name}`;
|
464
717
|
let createApi = this.result.operations.find(x => x.request.name === createName);
|
465
718
|
if (!createApi) {
|
466
|
-
const ignorePropsWithAttrs = ['AutoIncrement', 'Reference'];
|
467
|
-
const ignoreAttrs = [];
|
468
719
|
createApi = {
|
469
720
|
method: "POST",
|
470
721
|
actions: ["ANY"],
|
@@ -477,12 +728,13 @@ export class CSharpAst {
|
|
477
728
|
genericArgs: [type.name]
|
478
729
|
}],
|
479
730
|
properties: type.properties
|
480
|
-
.filter(x => !x.attributes?.some(a =>
|
731
|
+
.filter(x => !x.attributes?.some(a => this.ignoreCreateProps.includes(a.name.toLowerCase()))).map(x => Object.assign({}, x, {
|
481
732
|
type: x.isPrimaryKey
|
482
733
|
? x.type
|
483
734
|
: `${x.type}`,
|
484
|
-
attributes:
|
735
|
+
attributes: this.attrsFor("Create", "Prop", x.attributes),
|
485
736
|
})),
|
737
|
+
attributes: this.attrsFor("Create", "Type", type.attributes),
|
486
738
|
},
|
487
739
|
returnType: {
|
488
740
|
name: "IdResponse",
|
@@ -494,42 +746,50 @@ export class CSharpAst {
|
|
494
746
|
if (prop.isRequired) {
|
495
747
|
if (!prop.attributes)
|
496
748
|
prop.attributes = [];
|
749
|
+
var hasAnyValidateAttrs = prop.attributes.some(x => x.name.toLowerCase().startsWith('validate'));
|
497
750
|
if (prop.type === 'string') {
|
498
|
-
|
499
|
-
|
500
|
-
|
751
|
+
if (!hasAnyValidateAttrs) {
|
752
|
+
prop.attributes.push({
|
753
|
+
name: "ValidateNotEmpty",
|
754
|
+
});
|
755
|
+
}
|
501
756
|
}
|
502
757
|
else if (this.integerTypes.includes(prop.type)) {
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
758
|
+
if (!hasAnyValidateAttrs) {
|
759
|
+
prop.attributes.push({
|
760
|
+
name: "ValidateGreaterThan",
|
761
|
+
constructorArgs: [{ name: "value", type: "int", value: "0" }]
|
762
|
+
});
|
763
|
+
}
|
507
764
|
}
|
508
765
|
else if (prop.type === 'List`1' && this.commonValueTypes.includes(prop.genericArgs[0])) {
|
509
766
|
prop.attributes.push(...inputTagAttrs);
|
510
767
|
}
|
768
|
+
const emptyValidateAttr = prop.attributes.find(x => x.name.toLowerCase() === 'validate');
|
769
|
+
if (emptyValidateAttr && emptyValidateAttr.constructorArgs?.[0]?.value === '') {
|
770
|
+
prop.attributes = prop.attributes.filter(x => x !== emptyValidateAttr);
|
771
|
+
}
|
511
772
|
}
|
512
773
|
}
|
513
774
|
if (isAuditBase) {
|
514
775
|
createApi.requiresAuth = true;
|
515
|
-
if (!createApi.request.attributes)
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
}
|
776
|
+
if (!createApi.request.attributes?.find(x => x.name === 'AutoApply')) {
|
777
|
+
// [AutoApply(Behavior.AuditCreate)]
|
778
|
+
createApi.request.attributes.push({
|
779
|
+
name: "AutoApply",
|
780
|
+
constructorArgs: [{
|
781
|
+
name: "name",
|
782
|
+
type: "constant",
|
783
|
+
value: "Behavior.AuditCreate"
|
784
|
+
}]
|
785
|
+
});
|
786
|
+
}
|
526
787
|
}
|
527
788
|
this.result.operations.push(createApi);
|
528
789
|
}
|
529
790
|
let updateName = `Update${type.name}`;
|
530
791
|
let updateApi = this.result.operations.find(x => x.request.name === updateName);
|
531
792
|
if (!updateApi) {
|
532
|
-
const ignoreAttrs = ['AutoIncrement'];
|
533
793
|
updateApi = {
|
534
794
|
method: "PATCH",
|
535
795
|
actions: ["ANY"],
|
@@ -541,12 +801,13 @@ export class CSharpAst {
|
|
541
801
|
namespace: "ServiceStack",
|
542
802
|
genericArgs: [type.name]
|
543
803
|
}],
|
544
|
-
properties: type.properties?.filter(x => !x.attributes?.some(x => x.name
|
804
|
+
properties: type.properties?.filter(x => !x.attributes?.some(x => this.ignoreUpdateProps.includes(x.name.toLowerCase()))).map(x => Object.assign({}, x, {
|
545
805
|
type: x.isPrimaryKey
|
546
806
|
? x.type
|
547
807
|
: `${this.nullable(x.type)}`,
|
548
|
-
attributes:
|
808
|
+
attributes: this.attrsFor("Update", "Prop", x.attributes),
|
549
809
|
})),
|
810
|
+
attributes: this.attrsFor("Update", "Type", type.attributes),
|
550
811
|
},
|
551
812
|
returnType: {
|
552
813
|
name: "IdResponse",
|
@@ -565,17 +826,17 @@ export class CSharpAst {
|
|
565
826
|
}
|
566
827
|
if (isAuditBase) {
|
567
828
|
updateApi.requiresAuth = true;
|
568
|
-
if (!updateApi.request.attributes)
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
}
|
829
|
+
if (!updateApi.request.attributes?.find(x => x.name === 'AutoApply')) {
|
830
|
+
// [AutoApply(Behavior.AuditModify)]
|
831
|
+
updateApi.request.attributes.push({
|
832
|
+
name: "AutoApply",
|
833
|
+
constructorArgs: [{
|
834
|
+
name: "name",
|
835
|
+
type: "constant",
|
836
|
+
value: "Behavior.AuditModify"
|
837
|
+
}]
|
838
|
+
});
|
839
|
+
}
|
579
840
|
}
|
580
841
|
this.result.operations.push(updateApi);
|
581
842
|
}
|
@@ -593,29 +854,50 @@ export class CSharpAst {
|
|
593
854
|
namespace: "ServiceStack",
|
594
855
|
genericArgs: [type.name]
|
595
856
|
}],
|
596
|
-
properties:
|
857
|
+
properties: pk
|
858
|
+
? [
|
859
|
+
Object.assign({}, pk, {
|
860
|
+
type: this.nullable(pk.type),
|
861
|
+
attributes: this.attrsFor("Delete", "Prop", pk.attributes),
|
862
|
+
}),
|
863
|
+
idsProp
|
864
|
+
]
|
865
|
+
: [],
|
866
|
+
attributes: this.attrsFor("Delete", "Type", type.attributes),
|
597
867
|
},
|
598
868
|
returnsVoid: true,
|
599
869
|
dataModel,
|
600
870
|
};
|
601
871
|
if (isAuditBase) {
|
602
872
|
deleteApi.requiresAuth = true;
|
603
|
-
if (!deleteApi.request.attributes)
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
}
|
873
|
+
if (!deleteApi.request.attributes?.find(x => x.name === 'AutoApply')) {
|
874
|
+
// [AutoApply(Behavior.AuditSoftDelete)]
|
875
|
+
deleteApi.request.attributes.push({
|
876
|
+
name: "AutoApply",
|
877
|
+
constructorArgs: [{
|
878
|
+
name: "name",
|
879
|
+
type: "constant",
|
880
|
+
value: "Behavior.AuditSoftDelete"
|
881
|
+
}]
|
882
|
+
});
|
883
|
+
}
|
614
884
|
}
|
615
885
|
this.result.operations.push(deleteApi);
|
616
886
|
}
|
617
887
|
}
|
618
888
|
}
|
889
|
+
filterModelAttributes() {
|
890
|
+
for (const type of this.classes) {
|
891
|
+
if (type.attributes?.length) {
|
892
|
+
type.attributes = this.attrsFor("Model", "Type", type.attributes);
|
893
|
+
}
|
894
|
+
type.properties?.forEach(p => {
|
895
|
+
if (p.attributes?.length) {
|
896
|
+
p.attributes = this.attrsFor("Model", "Prop", p.attributes);
|
897
|
+
}
|
898
|
+
});
|
899
|
+
}
|
900
|
+
}
|
619
901
|
// Add Icon for BuiltIn UIs and AutoQueryGrid to known type names
|
620
902
|
addIconsToKnownTypes() {
|
621
903
|
for (const type of this.typesWithPrimaryKeys) {
|
@@ -623,8 +905,14 @@ export class CSharpAst {
|
|
623
905
|
if (icon) {
|
624
906
|
if (!type.attributes)
|
625
907
|
type.attributes = [];
|
626
|
-
|
627
|
-
|
908
|
+
const existingIcon = type.attributes.find(x => x.name === 'Icon');
|
909
|
+
if (existingIcon) {
|
910
|
+
// remove empty icon
|
911
|
+
if (existingIcon.constructorArgs?.[0]?.value === '') {
|
912
|
+
type.attributes = type.attributes.filter(x => x !== existingIcon);
|
913
|
+
}
|
914
|
+
return;
|
915
|
+
}
|
628
916
|
type.attributes.push({
|
629
917
|
name: "Icon",
|
630
918
|
args: [{ name: "Svg", type: "string", value: icon }]
|
@@ -696,6 +984,7 @@ export class CSharpAst {
|
|
696
984
|
this.hideReferenceProperties();
|
697
985
|
this.replaceUserReferencesWithAuditTables();
|
698
986
|
this.createAutoCrudApis();
|
987
|
+
this.filterModelAttributes();
|
699
988
|
}
|
700
989
|
parse(ast) {
|
701
990
|
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];
|
@@ -208,6 +212,24 @@ Options:
|
|
208
212
|
process.exit(0);
|
209
213
|
}
|
210
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
|
+
}
|
211
233
|
function assertTsdPath(tsdFile) {
|
212
234
|
const tryPaths = [
|
213
235
|
path.join(process.cwd(), tsdFile),
|
@@ -320,6 +342,13 @@ Options:
|
|
320
342
|
}
|
321
343
|
fs.unlinkSync(tsdPath);
|
322
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
|
+
}
|
323
352
|
process.exit(0);
|
324
353
|
}
|
325
354
|
if (command.type == "accept") {
|
@@ -608,15 +637,18 @@ function chooseFile(ctx, info, gist, comamnd) {
|
|
608
637
|
const migrationFileName = path.basename(migrationPath);
|
609
638
|
const migrationCls = leftPart(migrationFileName, '.');
|
610
639
|
const migrationContent = replaceMyApp(csMigrationFiles[Object.keys(csMigrationFiles)[0]].replaceAll('Migration1000', migrationCls), info.projectName);
|
611
|
-
const sb = [
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
|
616
|
-
|
617
|
-
|
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
|
+
];
|
618
649
|
const tsdContent = sb.join('\n');
|
619
650
|
const tsdFileName = `${groupName}.d.ts`;
|
651
|
+
const typesApiPath = path.join(info.slnDir, relativeServiceModelDir, `api.d.ts`);
|
620
652
|
const fullTsdPath = path.join(info.slnDir, relativeServiceModelDir, tsdFileName);
|
621
653
|
const fullApiPath = path.join(info.slnDir, relativeServiceModelDir, apiFileName);
|
622
654
|
const fullMigrationPath = path.join(info.slnDir, relativeMigrationDir, migrationFileName);
|
@@ -635,6 +667,8 @@ function chooseFile(ctx, info, gist, comamnd) {
|
|
635
667
|
fs.writeFileSync(fullMigrationPath, migrationContent, { encoding: 'utf-8' });
|
636
668
|
console.log(`Saved: ${fullMigrationPath}`);
|
637
669
|
}
|
670
|
+
const apiFile = path.join(import.meta.dirname, 'api.d.ts');
|
671
|
+
fs.writeFileSync(typesApiPath, fs.readFileSync(apiFile, 'utf-8'));
|
638
672
|
const script = path.basename(process.argv[1]);
|
639
673
|
console.log(`\nTo regenerate classes, update '${tsdFileName}' then run:`);
|
640
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');
|
@@ -154,6 +160,6 @@ export class TsdDataModelGenerator extends TsdGenerator {
|
|
154
160
|
if (ast.interfaces) {
|
155
161
|
ast.interfaces = ast.interfaces.filter(x => x.name !== 'User');
|
156
162
|
}
|
157
|
-
return super.generate(ast);
|
163
|
+
return super.generate(ast, "class");
|
158
164
|
}
|
159
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.24",
|
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 --",
|