sonamu 0.0.1

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.
Files changed (60) hide show
  1. package/.pnp.cjs +15552 -0
  2. package/.pnp.loader.mjs +285 -0
  3. package/.vscode/extensions.json +6 -0
  4. package/.vscode/settings.json +9 -0
  5. package/.yarnrc.yml +5 -0
  6. package/dist/bin/cli.d.ts +2 -0
  7. package/dist/bin/cli.d.ts.map +1 -0
  8. package/dist/bin/cli.js +123 -0
  9. package/dist/bin/cli.js.map +1 -0
  10. package/dist/index.js +34 -0
  11. package/package.json +60 -0
  12. package/src/api/caster.ts +72 -0
  13. package/src/api/code-converters.ts +552 -0
  14. package/src/api/context.ts +20 -0
  15. package/src/api/decorators.ts +63 -0
  16. package/src/api/index.ts +5 -0
  17. package/src/api/init.ts +128 -0
  18. package/src/bin/cli.ts +115 -0
  19. package/src/database/base-model.ts +287 -0
  20. package/src/database/db.ts +95 -0
  21. package/src/database/knex-plugins/knex-on-duplicate-update.ts +41 -0
  22. package/src/database/upsert-builder.ts +231 -0
  23. package/src/exceptions/error-handler.ts +29 -0
  24. package/src/exceptions/so-exceptions.ts +91 -0
  25. package/src/index.ts +17 -0
  26. package/src/shared/web.shared.ts.txt +119 -0
  27. package/src/smd/migrator.ts +1462 -0
  28. package/src/smd/smd-manager.ts +141 -0
  29. package/src/smd/smd-utils.ts +266 -0
  30. package/src/smd/smd.ts +533 -0
  31. package/src/syncer/index.ts +1 -0
  32. package/src/syncer/syncer.ts +1283 -0
  33. package/src/templates/base-template.ts +19 -0
  34. package/src/templates/generated.template.ts +247 -0
  35. package/src/templates/generated_http.template.ts +114 -0
  36. package/src/templates/index.ts +1 -0
  37. package/src/templates/init_enums.template.ts +71 -0
  38. package/src/templates/init_generated.template.ts +44 -0
  39. package/src/templates/init_types.template.ts +38 -0
  40. package/src/templates/model.template.ts +168 -0
  41. package/src/templates/model_test.template.ts +39 -0
  42. package/src/templates/service.template.ts +263 -0
  43. package/src/templates/smd.template.ts +49 -0
  44. package/src/templates/view_enums_buttonset.template.ts +34 -0
  45. package/src/templates/view_enums_dropdown.template.ts +67 -0
  46. package/src/templates/view_enums_select.template.ts +60 -0
  47. package/src/templates/view_form.template.ts +397 -0
  48. package/src/templates/view_id_all_select.template.ts +34 -0
  49. package/src/templates/view_id_async_select.template.ts +113 -0
  50. package/src/templates/view_list.template.ts +652 -0
  51. package/src/templates/view_list_columns.template.ts +59 -0
  52. package/src/templates/view_search_input.template.ts +67 -0
  53. package/src/testing/fixture-manager.ts +271 -0
  54. package/src/types/types.ts +668 -0
  55. package/src/typings/knex.d.ts +24 -0
  56. package/src/utils/controller.ts +21 -0
  57. package/src/utils/lodash-able.ts +11 -0
  58. package/src/utils/model.ts +33 -0
  59. package/src/utils/utils.ts +28 -0
  60. package/tsconfig.json +47 -0
@@ -0,0 +1,668 @@
1
+ import { z } from "zod";
2
+
3
+ /*
4
+ Enums
5
+ */
6
+ export type EnumsLabel<T extends string, L extends "ko" | "en"> = {
7
+ [key in T]: { [lang in L]: string };
8
+ };
9
+ export type EnumsLabelKo<T extends string> = EnumsLabel<T, "ko">;
10
+
11
+ /*
12
+ Custom Scalars
13
+ */
14
+ export const SQLDateTimeString = z
15
+ .string()
16
+ .regex(/([0-9]{4}-[0-9]{2}-[0-9]{2}( [0-9]{2}:[0-9]{2}:[0-9]{2})*)$/, {
17
+ message: "잘못된 SQLDate 타입",
18
+ })
19
+ .min(10)
20
+ .max(19)
21
+ .describe("SQLDateTimeString");
22
+ export type SQLDateTimeString = z.infer<typeof SQLDateTimeString>;
23
+
24
+ /*
25
+ Utility Types
26
+ */
27
+ export function zArrayable<T extends z.ZodTypeAny>(
28
+ shape: T
29
+ ): z.ZodUnion<[T, z.ZodArray<T, "many">]> {
30
+ return z.union([shape, shape.array()]);
31
+ }
32
+ export type DistributiveOmit<T, K extends keyof any> = T extends any
33
+ ? Omit<T, K>
34
+ : never;
35
+
36
+ /*
37
+ Model-Defintion
38
+ */
39
+ export type CommonProp = {
40
+ name: string;
41
+ nullable?: boolean;
42
+ index?: true | string[];
43
+ unique?: true | string[];
44
+ toFilter?: true;
45
+ desc?: string;
46
+ dbDefault?: string | number | { raw: string };
47
+ };
48
+ export type IntegerProp = CommonProp & {
49
+ type: "integer";
50
+ unsigned?: true;
51
+ };
52
+ export type BigIntegerProp = CommonProp & {
53
+ type: "bigInteger";
54
+ unsigned?: true;
55
+ };
56
+ export type TextProp = CommonProp & {
57
+ type: "text";
58
+ textType: "text" | "mediumtext" | "longtext";
59
+ };
60
+ export type StringProp = CommonProp & {
61
+ type: "string";
62
+ length: number;
63
+ };
64
+ export type EnumProp = CommonProp & {
65
+ type: "enum";
66
+ length: number;
67
+ id: string;
68
+ };
69
+ export type FloatProp = CommonProp & {
70
+ type: "float";
71
+ unsigned?: true;
72
+ };
73
+ export type DoubleProp = CommonProp & {
74
+ type: "double";
75
+ unsigned?: true;
76
+ };
77
+ export type DecimalProp = CommonProp & {
78
+ type: "decimal";
79
+ unsigned?: true;
80
+ };
81
+ export type BooleanProp = CommonProp & {
82
+ type: "boolean";
83
+ };
84
+ export type DateProp = CommonProp & {
85
+ type: "date";
86
+ };
87
+ export type DateTimeProp = CommonProp & {
88
+ type: "dateTime";
89
+ };
90
+ export type TimeProp = CommonProp & {
91
+ type: "time";
92
+ };
93
+ export type TimestampProp = CommonProp & {
94
+ type: "timestamp";
95
+ };
96
+ export type JsonProp = CommonProp & {
97
+ type: "json";
98
+ as: { ref: string } | z.ZodTypeAny;
99
+ };
100
+ export type UuidProp = CommonProp & {
101
+ type: "uuid";
102
+ };
103
+ export type VirtualProp = CommonProp & {
104
+ type: "virtual";
105
+ as: { ref: string } | z.ZodTypeAny;
106
+ };
107
+
108
+ export type RelationType =
109
+ | "HasMany"
110
+ | "BelongsToOne"
111
+ | "ManyToMany"
112
+ | "OneToOne";
113
+ export type RelationOn =
114
+ | "UPDATE"
115
+ | "CASCADE"
116
+ | "SET NULL"
117
+ | "NO ACTION"
118
+ | "SET DEFAULT"
119
+ | "RESTRICT";
120
+ type _RelationProp = {
121
+ type: "relation";
122
+ name: string;
123
+ with: string;
124
+ nullable?: boolean;
125
+ index?: true | string[];
126
+ unique?: true | string[];
127
+ toFilter?: true;
128
+ };
129
+ export type OneToOneRelationProp = _RelationProp & {
130
+ relationType: "OneToOne";
131
+ customJoinClause?: string;
132
+ } & (
133
+ | {
134
+ hasJoinColumn: true;
135
+ onUpdate: RelationOn;
136
+ onDelete: RelationOn;
137
+ }
138
+ | {
139
+ hasJoinColumn: false;
140
+ }
141
+ );
142
+ export type BelongsToOneRelationProp = _RelationProp & {
143
+ relationType: "BelongsToOne";
144
+ customJoinClause?: string;
145
+ onUpdate: RelationOn;
146
+ onDelete: RelationOn;
147
+ };
148
+ export type HasManyRelationProp = _RelationProp & {
149
+ relationType: "HasMany";
150
+ joinColumn: string;
151
+ };
152
+ export type ManyToManyRelationProp = _RelationProp & {
153
+ relationType: "ManyToMany";
154
+ joinTable: `${string}__${string}`;
155
+ onUpdate: RelationOn;
156
+ onDelete: RelationOn;
157
+ };
158
+ export type RelationProp =
159
+ | OneToOneRelationProp
160
+ | BelongsToOneRelationProp
161
+ | HasManyRelationProp
162
+ | ManyToManyRelationProp;
163
+
164
+ export type SMDProp =
165
+ | IntegerProp
166
+ | BigIntegerProp
167
+ | TextProp
168
+ | StringProp
169
+ | FloatProp
170
+ | DoubleProp
171
+ | DecimalProp
172
+ | BooleanProp
173
+ | DateProp
174
+ | DateTimeProp
175
+ | TimeProp
176
+ | TimestampProp
177
+ | JsonProp
178
+ | UuidProp
179
+ | EnumProp
180
+ | VirtualProp
181
+ | RelationProp;
182
+
183
+ export type SMDInput<T extends string> = {
184
+ id: string;
185
+ parentId?: string;
186
+ table?: string;
187
+ title?: string;
188
+ props?: SMDProp[];
189
+ subsets?: {
190
+ [subset: string]: T[];
191
+ };
192
+ };
193
+
194
+ /*
195
+ PropNode
196
+ */
197
+
198
+ export type SMDPropNode =
199
+ | {
200
+ nodeType: "plain";
201
+ prop: SMDProp;
202
+ }
203
+ | {
204
+ nodeType: "object" | "array";
205
+ prop?: SMDProp;
206
+ children: SMDPropNode[];
207
+ };
208
+
209
+ /*
210
+ Prop Type Guards
211
+ */
212
+ export function isIntegerProp(p: any): p is IntegerProp {
213
+ return p?.type === "integer";
214
+ }
215
+ export function isBigIntegerProp(p: any): p is BigIntegerProp {
216
+ return p?.type === "bigInteger";
217
+ }
218
+ export function isTextProp(p: any): p is TextProp {
219
+ return p?.type === "text";
220
+ }
221
+ export function isStringProp(p: any): p is StringProp {
222
+ return p?.type === "string";
223
+ }
224
+ export function isEnumProp(p: any): p is EnumProp {
225
+ return p?.type === "enum";
226
+ }
227
+ export function isFloatProp(p: any): p is FloatProp {
228
+ return p?.type === "float";
229
+ }
230
+ export function isDoubleProp(p: any): p is DoubleProp {
231
+ return p?.type === "double";
232
+ }
233
+ export function isDecimalProp(p: any): p is DecimalProp {
234
+ return p?.type === "decimal";
235
+ }
236
+ export function isBooleanProp(p: any): p is BooleanProp {
237
+ return p?.type === "boolean";
238
+ }
239
+ export function isDateProp(p: any): p is DateProp {
240
+ return p?.type === "date";
241
+ }
242
+ export function isDateTimeProp(p: any): p is DateTimeProp {
243
+ return p?.type === "dateTime";
244
+ }
245
+ export function isTimeProp(p: any): p is TimeProp {
246
+ return p?.type === "time";
247
+ }
248
+ export function isTimestampProp(p: any): p is TimestampProp {
249
+ return p?.type === "timestamp";
250
+ }
251
+ export function isJsonProp(p: any): p is JsonProp {
252
+ return p?.type === "json";
253
+ }
254
+ export function isUuidProp(p: any): p is UuidProp {
255
+ return p?.type === "uuid";
256
+ }
257
+ export function isVirtualProp(p: any): p is VirtualProp {
258
+ return p?.type === "virtual";
259
+ }
260
+ export function isRelationProp(p: any): p is RelationProp {
261
+ return p?.type === "relation";
262
+ }
263
+ export function isOneToOneRelationProp(p: any): p is OneToOneRelationProp {
264
+ return p?.relationType === "OneToOne";
265
+ }
266
+ export function isBelongsToOneRelationProp(
267
+ p: any
268
+ ): p is BelongsToOneRelationProp {
269
+ return p?.relationType === "BelongsToOne";
270
+ }
271
+ export function isHasManyRelationProp(p: any): p is HasManyRelationProp {
272
+ return p?.relationType === "HasMany";
273
+ }
274
+ export function isManyToManyRelationProp(p: any): p is ManyToManyRelationProp {
275
+ return p?.relationType === "ManyToMany";
276
+ }
277
+
278
+ type JoinClause =
279
+ | {
280
+ from: string;
281
+ to: string;
282
+ }
283
+ | {
284
+ custom: string;
285
+ };
286
+ export function isCustomJoinClause(p: any): p is { custom: string } {
287
+ return p?.custom;
288
+ }
289
+
290
+ /* 서브셋 */
291
+ type SubsetLoader = {
292
+ as: string;
293
+ table: string;
294
+ manyJoin: {
295
+ fromTable: string;
296
+ fromCol: string;
297
+ idField: string;
298
+ toTable: string;
299
+ toCol: string;
300
+ through?: {
301
+ table: string;
302
+ fromCol: string;
303
+ toCol: string;
304
+ };
305
+ };
306
+ oneJoins: ({
307
+ as: string;
308
+ join: "inner" | "outer";
309
+ table: string;
310
+ } & JoinClause)[];
311
+ select: string[];
312
+ loaders?: SubsetLoader[];
313
+ };
314
+ export type SubsetQuery = {
315
+ select: string[];
316
+ virtual: string[];
317
+ joins: ({
318
+ as: string;
319
+ join: "inner" | "outer";
320
+ table: string;
321
+ } & JoinClause)[];
322
+ loaders: SubsetLoader[];
323
+ };
324
+
325
+ /* Knex Migration */
326
+ export type KnexColumnType =
327
+ | "string"
328
+ | "text"
329
+ | "smalltext"
330
+ | "mediumtext"
331
+ | "longtext"
332
+ | "integer"
333
+ | "bigInteger"
334
+ | "decimal"
335
+ | "timestamp"
336
+ | "boolean"
337
+ | "foreign"
338
+ | "uuid"
339
+ | "json"
340
+ | "float"
341
+ | "date"
342
+ | "time"
343
+ | "dateTime";
344
+ export type MigrationColumn = {
345
+ name: string;
346
+ type: KnexColumnType;
347
+ nullable: boolean;
348
+ unsigned?: boolean;
349
+ length?: number;
350
+ defaultTo?: string | number;
351
+ };
352
+ export type MigrationIndex = {
353
+ columns: string[];
354
+ type: "unique" | "index";
355
+ name?: string;
356
+ };
357
+ export type MigrationForeign = {
358
+ columns: string[];
359
+ to: string;
360
+ onUpdate: RelationOn;
361
+ onDelete: RelationOn;
362
+ };
363
+ export type MigrationJoinTable = {
364
+ table: string;
365
+ indexes: MigrationIndex[];
366
+ columns: MigrationColumn[];
367
+ foreigns: MigrationForeign[];
368
+ };
369
+ export type MigrationSet = {
370
+ table: string;
371
+ columns: MigrationColumn[];
372
+ indexes: MigrationIndex[];
373
+ foreigns: MigrationForeign[];
374
+ };
375
+ export type MigrationSetAndJoinTable = MigrationSet & {
376
+ joinTables: MigrationJoinTable[];
377
+ };
378
+ export type GenMigrationCode = {
379
+ title: string;
380
+ table: string;
381
+ type: "normal" | "foreign";
382
+ formatted: string | null;
383
+ };
384
+
385
+ /* Api */
386
+ export type ApiParam = {
387
+ name: string;
388
+ type: ApiParamType;
389
+ optional: boolean;
390
+ defaultDef?: string;
391
+ };
392
+ export namespace ApiParamType {
393
+ export type Object = {
394
+ t: "object";
395
+ props: ApiParam[];
396
+ };
397
+ export type Union = {
398
+ t: "union";
399
+ types: ApiParamType[];
400
+ };
401
+ export type Intersection = {
402
+ t: "intersection";
403
+ types: ApiParamType[];
404
+ };
405
+ export type StringLiteral = {
406
+ t: "string-literal";
407
+ value: string;
408
+ };
409
+ export type NumericLiteral = {
410
+ t: "numeric-literal";
411
+ value: number;
412
+ };
413
+ export type Array = {
414
+ t: "array";
415
+ elementsType: ApiParamType;
416
+ };
417
+ export type Ref = {
418
+ t: "ref";
419
+ id: string;
420
+ args?: ApiParamType[];
421
+ };
422
+ export type IndexedAccess = {
423
+ t: "indexed-access";
424
+ object: ApiParamType;
425
+ index: ApiParamType;
426
+ };
427
+ export type TupleType = {
428
+ t: "tuple-type";
429
+ elements: ApiParamType[];
430
+ };
431
+ export type Pick = Ref & {
432
+ t: "ref";
433
+ id: "Pick";
434
+ };
435
+ export type Omit = Ref & {
436
+ t: "ref";
437
+ id: "Omit";
438
+ };
439
+ export type Partial = Ref & {
440
+ t: "ref";
441
+ id: "Partial";
442
+ };
443
+ export type Promise = Ref & {
444
+ t: "ref";
445
+ id: "Promise";
446
+ };
447
+ export type Context = Ref & {
448
+ t: "ref";
449
+ id: "Context";
450
+ };
451
+ export type TypeParam = {
452
+ t: "type-param";
453
+ id: string;
454
+ constraint?: ApiParamType;
455
+ };
456
+
457
+ export function isObject(v: any): v is ApiParamType.Object {
458
+ return v?.t === "object";
459
+ }
460
+ export function isUnion(v: any): v is ApiParamType.Union {
461
+ return v?.t === "union";
462
+ }
463
+ export function isIntersection(v: any): v is ApiParamType.Intersection {
464
+ return v?.t === "intersection";
465
+ }
466
+ export function isStringLiteral(v: any): v is ApiParamType.StringLiteral {
467
+ return v?.t === "string-literal";
468
+ }
469
+ export function isNumericLiteral(v: any): v is ApiParamType.NumericLiteral {
470
+ return v?.t === "numeric-literal";
471
+ }
472
+ export function isArray(v: any): v is ApiParamType.Array {
473
+ return v?.t === "array";
474
+ }
475
+ export function isRef(v: any): v is ApiParamType.Ref {
476
+ return v?.t === "ref";
477
+ }
478
+ export function isIndexedAccess(v: any): v is ApiParamType.IndexedAccess {
479
+ return v?.t === "indexed-access";
480
+ }
481
+ export function isTupleType(v: any): v is ApiParamType.TupleType {
482
+ return v?.t === "tuple-type";
483
+ }
484
+ export function isPick(v: any): v is ApiParamType.Pick {
485
+ return v?.t === "ref" && v.id === "Pick";
486
+ }
487
+ export function isOmit(v: any): v is ApiParamType.Omit {
488
+ return v?.t === "ref" && v.id === "Omit";
489
+ }
490
+ export function isPartial(v: any): v is ApiParamType.Partial {
491
+ return v?.t === "ref" && v.id === "Partial";
492
+ }
493
+ export function isPromise(v: any): v is ApiParamType.Promise {
494
+ return v?.t === "ref" && v.id === "Promise";
495
+ }
496
+ export function isContext(v: any): v is ApiParamType.Context {
497
+ return v?.t === "ref" && v.id === "Context";
498
+ }
499
+ export function isTypeParam(v: any): v is ApiParamType.TypeParam {
500
+ return v?.t === "type-param";
501
+ }
502
+ }
503
+ export type ApiParamType =
504
+ | "string"
505
+ | "number"
506
+ | "boolean"
507
+ | "null"
508
+ | "undefined"
509
+ | "void"
510
+ | "any"
511
+ | "unknown"
512
+ | "true"
513
+ | "false"
514
+ | ApiParamType.StringLiteral
515
+ | ApiParamType.NumericLiteral
516
+ | ApiParamType.Object
517
+ | ApiParamType.Union
518
+ | ApiParamType.Intersection
519
+ | ApiParamType.Array
520
+ | ApiParamType.Ref
521
+ | ApiParamType.IndexedAccess
522
+ | ApiParamType.TypeParam
523
+ | ApiParamType.TupleType;
524
+
525
+ /* Template */
526
+ // 셀프 참조 타입이므로 Zod 생략하고 직접 정의
527
+ export const RenderingNode = z.any();
528
+ export type RenderingNode = {
529
+ name: string;
530
+ label: string;
531
+ renderType:
532
+ | "string-plain"
533
+ | "string-image"
534
+ | "string-datetime"
535
+ | "number-plain"
536
+ | "number-id"
537
+ | "number-fk_id"
538
+ | "boolean"
539
+ | "enums"
540
+ | "array"
541
+ | "array-images"
542
+ | "object"
543
+ | "object-pick";
544
+ zodType: z.ZodTypeAny;
545
+ element?: RenderingNode;
546
+ children?: RenderingNode[];
547
+ config?: {
548
+ picked: string;
549
+ };
550
+ optional?: boolean;
551
+ nullable?: boolean;
552
+ };
553
+
554
+ export const TemplateOptions = z.object({
555
+ smd: z.object({
556
+ smdId: z.string(),
557
+ title: z.string(),
558
+ refCode: z.string().optional(),
559
+ }),
560
+ init_enums: z.object({
561
+ smdId: z.string(),
562
+ def: z.record(z.record(z.string())).optional(),
563
+ }),
564
+ init_types: z.object({
565
+ smdId: z.string(),
566
+ }),
567
+ init_generated: z.object({
568
+ smdId: z.string(),
569
+ }),
570
+ generated: z.object({
571
+ smdId: z.string(),
572
+ }),
573
+ generated_http: z.object({
574
+ smdId: z.string(),
575
+ }),
576
+ model: z.object({
577
+ smdId: z.string(),
578
+ defaultSearchField: z.string(),
579
+ defaultOrderBy: z.string(),
580
+ }),
581
+ model_test: z.object({
582
+ smdId: z.string(),
583
+ }),
584
+ bridge: z.object({
585
+ smdId: z.string(),
586
+ }),
587
+ service: z.object({
588
+ smdId: z.string(),
589
+ }),
590
+ view_list: z.object({
591
+ smdId: z.string(),
592
+ extra: z.unknown(),
593
+ }),
594
+ view_list_columns: z.object({
595
+ smdId: z.string(),
596
+ columns: z
597
+ .object({
598
+ name: z.string(),
599
+ label: z.string(),
600
+ tc: z.string(),
601
+ })
602
+ .array(),
603
+ columnImports: z.string(),
604
+ }),
605
+ view_search_input: z.object({
606
+ smdId: z.string(),
607
+ }),
608
+ view_form: z.object({
609
+ smdId: z.string(),
610
+ }),
611
+ view_id_all_select: z.object({
612
+ smdId: z.string(),
613
+ }),
614
+ view_id_async_select: z.object({
615
+ smdId: z.string(),
616
+ textField: z.string(),
617
+ }),
618
+ view_enums_select: z.object({
619
+ smdId: z.string(),
620
+ enumId: z.string(),
621
+ idConstant: z.string(),
622
+ }),
623
+ view_enums_dropdown: z.object({
624
+ smdId: z.string(),
625
+ enumId: z.string(),
626
+ idConstant: z.string(),
627
+ }),
628
+ view_enums_buttonset: z.object({
629
+ smdId: z.string(),
630
+ enumId: z.string(),
631
+ idConstant: z.string(),
632
+ }),
633
+ });
634
+ export type TemplateOptions = z.infer<typeof TemplateOptions>;
635
+
636
+ export const TemplateKey = z.enum([
637
+ "smd",
638
+ "init_enums",
639
+ "init_types",
640
+ "init_generated",
641
+ "generated",
642
+ "generated_http",
643
+ "model",
644
+ "model_test",
645
+ "bridge",
646
+ "service",
647
+ "view_list",
648
+ "view_list_columns",
649
+ "view_search_input",
650
+ "view_form",
651
+ "view_id_all_select",
652
+ "view_id_async_select",
653
+ "view_enums_select",
654
+ "view_enums_dropdown",
655
+ "view_enums_buttonset",
656
+ ]);
657
+ export type TemplateKey = z.infer<typeof TemplateKey>;
658
+
659
+ export const GenerateOptions = z.object({
660
+ overwrite: z.boolean().optional(),
661
+ });
662
+ export type GenerateOptions = z.infer<typeof GenerateOptions>;
663
+
664
+ export const PathAndCode = z.object({
665
+ path: z.string(),
666
+ code: z.string(),
667
+ });
668
+ export type PathAndCode = z.infer<typeof PathAndCode>;
@@ -0,0 +1,24 @@
1
+ import { Knex } from "knex";
2
+
3
+ declare module "knex" {
4
+ namespace Knex {
5
+ interface QueryBuilder {
6
+ onDuplicateUpdate<TRecord extends {}, TResult>(
7
+ ...columns: string[]
8
+ ): Knex.QueryBuilder<TRecord, TResult>;
9
+
10
+ columnInfo<TRecord>(
11
+ column?: keyof TRecord
12
+ ): Promise<Knex.ColumnInfo | ColumnInfosObj>;
13
+
14
+ whereBetween<TRecord, TResult>(
15
+ columnName: string,
16
+ range: readonly [any, any]
17
+ ): Knex.QueryBuilder;
18
+ }
19
+
20
+ type ColumnInfosObj = {
21
+ [columnName: string]: Knex.ColumnInfo;
22
+ };
23
+ }
24
+ }
@@ -0,0 +1,21 @@
1
+ export function isLocal(): boolean {
2
+ return process.env.LR === undefined || process.env.LR === "local";
3
+ }
4
+ export function isRemote(): boolean {
5
+ return process.env.LR === "remote";
6
+ }
7
+ export function isInDocker(): boolean {
8
+ return process.env.LR !== undefined;
9
+ }
10
+ export function isDaemonServer(): boolean {
11
+ return process.env.NODE_TYPE === "daemon";
12
+ }
13
+ export function isDevelopment(): boolean {
14
+ return isRemote() && process.env.NODE_ENV === "development";
15
+ }
16
+ export function isStaging(): boolean {
17
+ return isRemote() && process.env.NODE_ENV === "staging";
18
+ }
19
+ export function isProduction(): boolean {
20
+ return isRemote() && process.env.NODE_ENV === "production";
21
+ }
@@ -0,0 +1,11 @@
1
+ export function wrapIf(
2
+ source: string,
3
+ predicate: (str: string) => [boolean, string]
4
+ ): string {
5
+ const [ok, wrapped] = predicate(source);
6
+ return ok ? wrapped : source;
7
+ }
8
+
9
+ export function propIf(expression: boolean, obj: any) {
10
+ return expression ? obj : {};
11
+ }