@kinotic-ai/kinotic-cli 1.0.0

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 (82) hide show
  1. package/README.md +594 -0
  2. package/bin/dev.cmd +3 -0
  3. package/bin/dev.js +6 -0
  4. package/bin/run.cmd +3 -0
  5. package/bin/run.js +6 -0
  6. package/dist/commands/generate.d.ts +11 -0
  7. package/dist/commands/generate.js +36 -0
  8. package/dist/commands/initialize.d.ts +12 -0
  9. package/dist/commands/initialize.js +102 -0
  10. package/dist/commands/synchronize.d.ts +17 -0
  11. package/dist/commands/synchronize.js +154 -0
  12. package/dist/index.d.ts +1 -0
  13. package/dist/index.js +1 -0
  14. package/dist/internal/CodeGenerationService.d.ts +24 -0
  15. package/dist/internal/CodeGenerationService.js +256 -0
  16. package/dist/internal/Logger.d.ts +27 -0
  17. package/dist/internal/Logger.js +35 -0
  18. package/dist/internal/ProjectMigrationService.d.ts +28 -0
  19. package/dist/internal/ProjectMigrationService.js +99 -0
  20. package/dist/internal/Utils.d.ts +66 -0
  21. package/dist/internal/Utils.js +349 -0
  22. package/dist/internal/converter/ConverterConstants.d.ts +3 -0
  23. package/dist/internal/converter/ConverterConstants.js +4 -0
  24. package/dist/internal/converter/DefaultConversionContext.d.ts +29 -0
  25. package/dist/internal/converter/DefaultConversionContext.js +112 -0
  26. package/dist/internal/converter/IConversionContext.d.ts +64 -0
  27. package/dist/internal/converter/IConversionContext.js +11 -0
  28. package/dist/internal/converter/IConverterStrategy.d.ts +35 -0
  29. package/dist/internal/converter/IConverterStrategy.js +1 -0
  30. package/dist/internal/converter/ITypeConverter.d.ts +28 -0
  31. package/dist/internal/converter/ITypeConverter.js +1 -0
  32. package/dist/internal/converter/SpecificTypesConverter.d.ts +12 -0
  33. package/dist/internal/converter/SpecificTypesConverter.js +24 -0
  34. package/dist/internal/converter/codegen/ArrayC3TypeToStatementMapper.d.ts +9 -0
  35. package/dist/internal/converter/codegen/ArrayC3TypeToStatementMapper.js +46 -0
  36. package/dist/internal/converter/codegen/ObjectC3TypeToStatementMapper.d.ts +13 -0
  37. package/dist/internal/converter/codegen/ObjectC3TypeToStatementMapper.js +67 -0
  38. package/dist/internal/converter/codegen/PrimitiveC3TypeToStatementMapper.d.ts +9 -0
  39. package/dist/internal/converter/codegen/PrimitiveC3TypeToStatementMapper.js +24 -0
  40. package/dist/internal/converter/codegen/StatementMapper.d.ts +40 -0
  41. package/dist/internal/converter/codegen/StatementMapper.js +132 -0
  42. package/dist/internal/converter/codegen/StatementMapperConversionState.d.ts +9 -0
  43. package/dist/internal/converter/codegen/StatementMapperConversionState.js +17 -0
  44. package/dist/internal/converter/codegen/StatementMapperConverterStrategy.d.ts +16 -0
  45. package/dist/internal/converter/codegen/StatementMapperConverterStrategy.js +30 -0
  46. package/dist/internal/converter/codegen/UnionC3TypeToStatementMapper.d.ts +9 -0
  47. package/dist/internal/converter/codegen/UnionC3TypeToStatementMapper.js +46 -0
  48. package/dist/internal/converter/common/BaseConversionState.d.ts +9 -0
  49. package/dist/internal/converter/common/BaseConversionState.js +13 -0
  50. package/dist/internal/converter/typescript/ArrayToC3Type.d.ts +9 -0
  51. package/dist/internal/converter/typescript/ArrayToC3Type.js +17 -0
  52. package/dist/internal/converter/typescript/ConverterUtils.d.ts +4 -0
  53. package/dist/internal/converter/typescript/ConverterUtils.js +261 -0
  54. package/dist/internal/converter/typescript/EnumToC3Type.d.ts +12 -0
  55. package/dist/internal/converter/typescript/EnumToC3Type.js +26 -0
  56. package/dist/internal/converter/typescript/ObjectLikeToC3Type.d.ts +15 -0
  57. package/dist/internal/converter/typescript/ObjectLikeToC3Type.js +111 -0
  58. package/dist/internal/converter/typescript/PrimitiveToC3Type.d.ts +10 -0
  59. package/dist/internal/converter/typescript/PrimitiveToC3Type.js +33 -0
  60. package/dist/internal/converter/typescript/QueryOptionsToC3Type.d.ts +9 -0
  61. package/dist/internal/converter/typescript/QueryOptionsToC3Type.js +9 -0
  62. package/dist/internal/converter/typescript/TenantSelectionToC3Type.d.ts +9 -0
  63. package/dist/internal/converter/typescript/TenantSelectionToC3Type.js +9 -0
  64. package/dist/internal/converter/typescript/TypescriptConversionState.d.ts +24 -0
  65. package/dist/internal/converter/typescript/TypescriptConversionState.js +26 -0
  66. package/dist/internal/converter/typescript/TypescriptConverterStrategy.d.ts +16 -0
  67. package/dist/internal/converter/typescript/TypescriptConverterStrategy.js +44 -0
  68. package/dist/internal/converter/typescript/UnionToC3Type.d.ts +15 -0
  69. package/dist/internal/converter/typescript/UnionToC3Type.js +184 -0
  70. package/dist/internal/state/Environment.d.ts +13 -0
  71. package/dist/internal/state/Environment.js +65 -0
  72. package/dist/internal/state/IStateManager.d.ts +19 -0
  73. package/dist/internal/state/IStateManager.js +41 -0
  74. package/dist/internal/state/KinoticProjectConfigUtil.d.ts +9 -0
  75. package/dist/internal/state/KinoticProjectConfigUtil.js +153 -0
  76. package/dist/templates/AdminEntityService.liquid +14 -0
  77. package/dist/templates/BaseAdminEntityService.liquid +19 -0
  78. package/dist/templates/BaseEntityService.liquid +48 -0
  79. package/dist/templates/EntityService.liquid +14 -0
  80. package/dist/templates/KinoticProjectConfig.ts.liquid +10 -0
  81. package/oclif.manifest.json +161 -0
  82. package/package.json +97 -0
@@ -0,0 +1,46 @@
1
+ import { UnionC3Type } from '@kinotic-ai/idl';
2
+ import { ConverterConstants } from '../ConverterConstants.js';
3
+ import { MultiStatementMapper, LiteralStatementMapper } from './StatementMapper.js';
4
+ import { camel } from 'radash';
5
+ export class UnionC3TypeToStatementMapper {
6
+ convert(value, conversionContext) {
7
+ const unionC3Type = value;
8
+ const ret = new MultiStatementMapper(conversionContext.state());
9
+ const state = conversionContext.state();
10
+ const originalJsonPath = conversionContext.currentJsonPath;
11
+ const originalPropertyStack = conversionContext.propertyStack;
12
+ const originalTargetName = state.targetName;
13
+ const originalSourceName = state.sourceName;
14
+ const targetJsonPath = originalTargetName + (originalJsonPath.length > 0 ? '.' + originalJsonPath : '');
15
+ const sourceJsonPath = originalSourceName + (originalJsonPath.length > 0 ? '.' + originalJsonPath : '');
16
+ conversionContext.currentJsonPath = '';
17
+ conversionContext.propertyStack = [];
18
+ // to map the union type we merge all the properties into a single object
19
+ let counter = 1;
20
+ for (let objectC3Type of unionC3Type.types) {
21
+ const targetVariableName = camel(targetJsonPath.replaceAll('.', ' ') + `O${counter}`);
22
+ const sourceVariableName = camel(sourceJsonPath.replaceAll('.', ' ') + ` I${counter}`);
23
+ const castStatement = new LiteralStatementMapper(`let ${sourceVariableName} = ${sourceJsonPath} as ${objectC3Type.name}`);
24
+ if (objectC3Type.metadata) {
25
+ const sourcePath = objectC3Type.metadata[ConverterConstants.SOURCE_FILE_PATH];
26
+ castStatement.neededImports.push({ sourcePath: sourcePath, importName: objectC3Type.name });
27
+ }
28
+ ret.add(castStatement);
29
+ ret.add(new LiteralStatementMapper(`let ${targetVariableName} = ${targetJsonPath}`));
30
+ state.targetName = targetVariableName;
31
+ state.sourceName = sourceVariableName;
32
+ ret.add(conversionContext.convert(objectC3Type));
33
+ // assign back in case convert had side effects that were lost
34
+ ret.add(new LiteralStatementMapper(`${targetJsonPath} = ${targetVariableName}`));
35
+ counter++;
36
+ }
37
+ conversionContext.currentJsonPath = originalJsonPath;
38
+ conversionContext.propertyStack = originalPropertyStack;
39
+ state.targetName = originalTargetName;
40
+ state.sourceName = originalSourceName;
41
+ return ret;
42
+ }
43
+ supports(value, conversionState) {
44
+ return value instanceof UnionC3Type || value.type === 'union';
45
+ }
46
+ }
@@ -0,0 +1,9 @@
1
+ export declare class BaseConversionState {
2
+ private readonly _application;
3
+ /**
4
+ * Create a new instance of the BaseConversionState
5
+ * @param application the application that entities will belong to
6
+ */
7
+ constructor(application: string);
8
+ get application(): string;
9
+ }
@@ -0,0 +1,13 @@
1
+ export class BaseConversionState {
2
+ _application;
3
+ /**
4
+ * Create a new instance of the BaseConversionState
5
+ * @param application the application that entities will belong to
6
+ */
7
+ constructor(application) {
8
+ this._application = application;
9
+ }
10
+ get application() {
11
+ return this._application;
12
+ }
13
+ }
@@ -0,0 +1,9 @@
1
+ import { C3Type } from '@kinotic-ai/idl';
2
+ import { Type } from 'ts-morph';
3
+ import { TypescriptConversionState } from './TypescriptConversionState.js';
4
+ import { IConversionContext } from '../IConversionContext.js';
5
+ import { ITypeConverter } from '../ITypeConverter.js';
6
+ export declare class ArrayToC3Type implements ITypeConverter<Type, C3Type, TypescriptConversionState> {
7
+ convert(value: Type, conversionContext: IConversionContext<Type, C3Type, TypescriptConversionState>): C3Type;
8
+ supports(value: Type, conversionState: TypescriptConversionState): boolean;
9
+ }
@@ -0,0 +1,17 @@
1
+ import { ArrayC3Type } from '@kinotic-ai/idl';
2
+ export class ArrayToC3Type {
3
+ convert(value, conversionContext) {
4
+ let ret;
5
+ const arrayElementType = value?.getArrayElementType();
6
+ if (arrayElementType) {
7
+ ret = new ArrayC3Type(conversionContext.convert(arrayElementType));
8
+ }
9
+ else {
10
+ throw new Error("Type could not be found for array type " + value.getText());
11
+ }
12
+ return ret;
13
+ }
14
+ supports(value, conversionState) {
15
+ return value.isArray();
16
+ }
17
+ }
@@ -0,0 +1,4 @@
1
+ import { C3Decorator, C3Type } from '@kinotic-ai/idl';
2
+ import { Decorator } from 'ts-morph';
3
+ export declare function tsDecoratorToC3Decorator(decorator: Decorator): C3Decorator | null;
4
+ export declare function convertPrecisionToC3Type(decorator: Decorator): C3Type;
@@ -0,0 +1,261 @@
1
+ import { DoubleC3Type, FloatC3Type, IntC3Type, LongC3Type, NotNullDecorator, ShortC3Type } from '@kinotic-ai/idl';
2
+ import { AutoGeneratedIdDecorator, DiscriminatorDecorator, EntityDecorator, FlattenedDecorator, IdDecorator, NestedDecorator, NotIndexedDecorator, QueryDecorator, TenantIdDecorator, TextDecorator, TimeReferenceDecorator, VersionDecorator } from '@kinotic-ai/os-api';
3
+ import { EntityType, MultiTenancyType } from '@kinotic-ai/persistence';
4
+ import { SyntaxKind } from 'ts-morph';
5
+ export function tsDecoratorToC3Decorator(decorator) {
6
+ let ret = null;
7
+ if (decorator.getName() === 'AutoGeneratedId') {
8
+ ret = new AutoGeneratedIdDecorator();
9
+ }
10
+ else if (decorator.getName() === 'Discriminator') {
11
+ const discriminatorDecorator = new DiscriminatorDecorator();
12
+ if (decorator.getArguments().length == 1) {
13
+ const argument = decorator.getArguments()[0];
14
+ if (argument?.getType()?.getLiteralValue()) {
15
+ discriminatorDecorator.propertyName = argument.getType().getLiteralValue();
16
+ }
17
+ else {
18
+ throw new Error('propertyName must be a string literal');
19
+ }
20
+ }
21
+ else {
22
+ throw new Error('propertyName must be set on Discriminator Decorator');
23
+ }
24
+ ret = discriminatorDecorator;
25
+ }
26
+ else if (decorator.getName() === 'Entity') {
27
+ const entityDecorator = new EntityDecorator();
28
+ if (decorator.getArguments().length > 0) {
29
+ const argument = decorator.getArguments()[0];
30
+ if (argument?.getText() == 'MultiTenancyType.SHARED') {
31
+ entityDecorator.multiTenancyType = MultiTenancyType.SHARED;
32
+ }
33
+ else if (argument?.getText() == 'MultiTenancyType.NONE') {
34
+ entityDecorator.multiTenancyType = MultiTenancyType.NONE;
35
+ }
36
+ else {
37
+ throw new Error(`Unsupported MultiTenancyType ${argument?.getText()}`);
38
+ }
39
+ if (decorator.getArguments().length == 2) {
40
+ const entityTypeArg = decorator.getArguments()[1];
41
+ if (entityTypeArg?.getText() == 'EntityType.TABLE') {
42
+ entityDecorator.entityType = EntityType.TABLE;
43
+ }
44
+ else if (entityTypeArg?.getText() == 'EntityType.STREAM') {
45
+ entityDecorator.entityType = EntityType.STREAM;
46
+ }
47
+ else {
48
+ throw new Error(`Unsupported EntityType ${entityTypeArg?.getText()}`);
49
+ }
50
+ }
51
+ }
52
+ ret = entityDecorator;
53
+ }
54
+ else if (decorator.getName() === 'EntityServiceDecorators') {
55
+ const argument = decorator.getArguments()[0];
56
+ if (argument?.getKind() === SyntaxKind.ObjectLiteralExpression) {
57
+ const obj = convertToObjectLiteral(argument);
58
+ ret = {
59
+ type: 'EntityServiceDecorators',
60
+ config: obj,
61
+ };
62
+ }
63
+ else {
64
+ throw new Error('EntityServiceDecorators must have an object literal argument');
65
+ }
66
+ }
67
+ else if (decorator.getName() === 'EsIndexConfiguration') {
68
+ const argument = decorator.getArguments()[0];
69
+ if (argument?.getKind() === SyntaxKind.ObjectLiteralExpression) {
70
+ const obj = convertToObjectLiteral(argument);
71
+ ret = {
72
+ type: 'EsIndexConfigurationDecorator',
73
+ value: obj,
74
+ };
75
+ }
76
+ else {
77
+ throw new Error('EsIndexConfiguration must have an object literal argument');
78
+ }
79
+ }
80
+ else if (decorator.getName() === 'Flattened') {
81
+ ret = new FlattenedDecorator();
82
+ }
83
+ else if (decorator.getName() === 'Id') {
84
+ ret = new IdDecorator();
85
+ }
86
+ else if (decorator.getName() === 'Nested') {
87
+ ret = new NestedDecorator();
88
+ }
89
+ else if (decorator.getName() === 'NotIndexed') {
90
+ ret = new NotIndexedDecorator();
91
+ }
92
+ else if (decorator.getName() === 'NotNull') {
93
+ ret = new NotNullDecorator();
94
+ }
95
+ else if (decorator.getName() === 'Policy') {
96
+ const argument = decorator.getArguments()[0];
97
+ if (argument?.getKind() === SyntaxKind.ArrayLiteralExpression) {
98
+ const obj = parseExpressionToJs(argument);
99
+ ret = {
100
+ type: 'PolicyDecorator',
101
+ policies: obj,
102
+ };
103
+ }
104
+ else {
105
+ throw new Error('Policy must have an array literal argument');
106
+ }
107
+ }
108
+ else if (decorator.getName() === 'Query') {
109
+ if (decorator.getArguments().length == 1) {
110
+ const argument = decorator.getArguments()[0];
111
+ if (argument?.getType()?.getLiteralValue()) {
112
+ ret = new QueryDecorator(argument.getType().getLiteralValue());
113
+ }
114
+ else {
115
+ throw new Error('statement must be set on Query Decorator');
116
+ }
117
+ }
118
+ }
119
+ else if (decorator.getName() === 'Role') {
120
+ const argument = decorator.getArguments()[0];
121
+ if (argument?.getKind() === SyntaxKind.ArrayLiteralExpression) {
122
+ const obj = parseExpressionToJs(argument);
123
+ ret = {
124
+ type: 'RoleDecorator',
125
+ roles: obj,
126
+ };
127
+ }
128
+ else {
129
+ throw new Error('Role must have an array literal argument');
130
+ }
131
+ }
132
+ else if (decorator.getName() === 'TenantId') {
133
+ ret = new TenantIdDecorator();
134
+ }
135
+ else if (decorator.getName() === 'Text') {
136
+ ret = new TextDecorator();
137
+ }
138
+ else if (decorator.getName() === 'TimeReference') {
139
+ ret = new TimeReferenceDecorator();
140
+ }
141
+ else if (decorator.getName() === 'Version') {
142
+ ret = new VersionDecorator();
143
+ }
144
+ return ret;
145
+ }
146
+ export function convertPrecisionToC3Type(decorator) {
147
+ let ret;
148
+ if (decorator.getName() === 'Precision') {
149
+ if (decorator.getArguments().length == 1) {
150
+ const argument = decorator.getArguments()[0];
151
+ if (argument?.getText() == 'PrecisionType.DOUBLE') {
152
+ ret = new DoubleC3Type();
153
+ }
154
+ else if (argument?.getText() == 'PrecisionType.FLOAT') {
155
+ ret = new FloatC3Type();
156
+ }
157
+ else if (argument?.getText() == 'PrecisionType.INT') {
158
+ ret = new IntC3Type();
159
+ }
160
+ else if (argument?.getText() == 'PrecisionType.LONG') {
161
+ ret = new LongC3Type();
162
+ }
163
+ else if (argument?.getText() == 'PrecisionType.SHORT') {
164
+ ret = new ShortC3Type();
165
+ }
166
+ else {
167
+ throw new Error(`Unsupported PrecisionType ${argument?.getText()}`);
168
+ }
169
+ }
170
+ else {
171
+ ret = new IntC3Type();
172
+ }
173
+ return ret;
174
+ }
175
+ else {
176
+ throw new Error('Decorator is not Precision decorator');
177
+ }
178
+ }
179
+ function parseExpressionToJs(expression) {
180
+ switch (expression.getKind()) {
181
+ case SyntaxKind.AsExpression:
182
+ // Directly handle the expression part of the AsExpression
183
+ const asExpr = expression.asKindOrThrow(SyntaxKind.AsExpression);
184
+ return parseExpressionToJs(asExpr.getExpression());
185
+ case SyntaxKind.ObjectLiteralExpression:
186
+ return convertToObjectLiteral(expression);
187
+ case SyntaxKind.ArrayLiteralExpression:
188
+ return expression.asKindOrThrow(SyntaxKind.ArrayLiteralExpression)
189
+ .getElements()
190
+ .map((el) => parseExpressionToJs(el));
191
+ case SyntaxKind.StringLiteral:
192
+ return expression.asKindOrThrow(SyntaxKind.StringLiteral).getLiteralValue();
193
+ case SyntaxKind.NumericLiteral:
194
+ return parseFloat(expression.asKindOrThrow(SyntaxKind.NumericLiteral).getLiteralText());
195
+ case SyntaxKind.TrueKeyword:
196
+ return true;
197
+ case SyntaxKind.FalseKeyword:
198
+ return false;
199
+ case SyntaxKind.CallExpression:
200
+ const callExpr = expression.asKindOrThrow(SyntaxKind.CallExpression);
201
+ if (callExpr.getText().startsWith('$')) { // Check if it is a supported internal function
202
+ return convertCallExpressionToJs(callExpr);
203
+ }
204
+ else {
205
+ throw new Error(`Unsupported call expression: ${callExpr.getText()}`);
206
+ }
207
+ default:
208
+ throw new Error(`Unsupported expression kind: ${expression.getKindName()} text: ${expression.getText()}`);
209
+ }
210
+ }
211
+ function convertCallExpressionToJs(expression) {
212
+ const text = expression.getText();
213
+ if (text.startsWith('$Policy')) {
214
+ if (expression.getArguments().length === 1) {
215
+ const argument = expression.getArguments()[0];
216
+ const obj = parseExpressionToJs(argument);
217
+ // Validate the parsed object structure
218
+ if (!Array.isArray(obj) || !obj.every(arr => Array.isArray(arr) && arr.every(item => typeof item === 'string'))) {
219
+ throw new Error('Policy must contain an array of string arrays (string[][])');
220
+ }
221
+ return {
222
+ type: 'PolicyDecorator',
223
+ policies: obj, // Fixed type assertion
224
+ };
225
+ }
226
+ else {
227
+ throw new Error('Policy must have an array literal argument');
228
+ }
229
+ }
230
+ else if (text.startsWith('$Role')) {
231
+ if (expression.getArguments().length == 1) {
232
+ const argument = expression.getArguments()[0];
233
+ const obj = parseExpressionToJs(argument);
234
+ return {
235
+ type: 'RoleDecorator',
236
+ roles: obj,
237
+ };
238
+ }
239
+ else {
240
+ throw new Error('Role must have an array literal argument');
241
+ }
242
+ }
243
+ else {
244
+ throw new Error(`Unsupported call expression: ${text}`);
245
+ }
246
+ }
247
+ // Convert ObjectLiteralExpression to a JavaScript object
248
+ function convertToObjectLiteral(expression) {
249
+ const result = {};
250
+ for (const prop of expression.getProperties()) {
251
+ if (prop.getKind() === SyntaxKind.PropertyAssignment) {
252
+ const assignment = prop.asKindOrThrow(SyntaxKind.PropertyAssignment);
253
+ const key = assignment.getName();
254
+ const initializer = assignment.getInitializer();
255
+ if (initializer) {
256
+ result[key] = parseExpressionToJs(initializer);
257
+ }
258
+ }
259
+ }
260
+ return result;
261
+ }
@@ -0,0 +1,12 @@
1
+ import { Type } from 'ts-morph';
2
+ import { C3Type } from '@kinotic-ai/idl';
3
+ import { TypescriptConversionState } from './TypescriptConversionState.js';
4
+ import { IConversionContext } from '../IConversionContext.js';
5
+ import { ITypeConverter } from '../ITypeConverter.js';
6
+ /**
7
+ * Converts a typescript enum to a C3 Enum
8
+ */
9
+ export declare class EnumToC3Type implements ITypeConverter<Type, C3Type, TypescriptConversionState> {
10
+ convert(value: Type, conversionContext: IConversionContext<Type, C3Type, TypescriptConversionState>): C3Type;
11
+ supports(value: Type, conversionState: TypescriptConversionState): boolean;
12
+ }
@@ -0,0 +1,26 @@
1
+ import { EnumC3Type } from '@kinotic-ai/idl';
2
+ /**
3
+ * Converts a typescript enum to a C3 Enum
4
+ */
5
+ export class EnumToC3Type {
6
+ convert(value, conversionContext) {
7
+ let ret;
8
+ const name = value.getSymbolOrThrow("No Symbol could be found for object: " + value.getText()).getName();
9
+ const namespace = conversionContext.state().application;
10
+ ret = new EnumC3Type(name, namespace);
11
+ // this is a little strange, but it is the easiest way to get the name of the enum
12
+ value.getUnionTypes().forEach((unionType) => {
13
+ const name = unionType?.getSymbol()?.getName();
14
+ if (name) {
15
+ ret.addValue(name);
16
+ }
17
+ else {
18
+ throw new Error("Could not find name for enum: " + value.getText());
19
+ }
20
+ });
21
+ return ret;
22
+ }
23
+ supports(value, conversionState) {
24
+ return value.isEnum();
25
+ }
26
+ }
@@ -0,0 +1,15 @@
1
+ import { Type } from 'ts-morph';
2
+ import { C3Type } from '@kinotic-ai/idl';
3
+ import { TypescriptConversionState } from './TypescriptConversionState.js';
4
+ import { IConversionContext } from '../IConversionContext.js';
5
+ import { ITypeConverter } from '../ITypeConverter.js';
6
+ /**
7
+ * Converts a typescript Class, Interface, or Type to a C3Type
8
+ */
9
+ export declare class ObjectLikeToC3Type implements ITypeConverter<Type, C3Type, TypescriptConversionState> {
10
+ convert(value: Type, conversionContext: IConversionContext<Type, C3Type, TypescriptConversionState>): C3Type;
11
+ supports(value: Type): boolean;
12
+ private convertDecorators;
13
+ private convertProperties;
14
+ private convertProperty;
15
+ }
@@ -0,0 +1,111 @@
1
+ import { ObjectC3Type, PropertyDefinition } from '@kinotic-ai/idl';
2
+ import { ConverterConstants } from '../ConverterConstants.js';
3
+ import { tsDecoratorToC3Decorator, convertPrecisionToC3Type } from './ConverterUtils.js';
4
+ import { TenantIdDecorator } from '@kinotic-ai/os-api';
5
+ /**
6
+ * Converts a typescript Class, Interface, or Type to a C3Type
7
+ */
8
+ export class ObjectLikeToC3Type {
9
+ convert(value, conversionContext) {
10
+ let ret;
11
+ const name = value.getSymbolOrThrow("No Symbol could be found for object: " + value.getText()).getName();
12
+ const namespace = conversionContext.state().application;
13
+ ret = new ObjectC3Type(name, namespace);
14
+ // Object stack name is used to help name properties that are not defined such as with union literals
15
+ conversionContext.state().objectNameStack.push(name);
16
+ // We store the original source path so, it can be used later
17
+ const declarations = value.getSymbol()?.getDeclarations();
18
+ if (conversionContext.state().shouldAddSourcePathToMetadata
19
+ && declarations
20
+ && declarations.length > 0) {
21
+ if (!ret.metadata) {
22
+ ret.metadata = {};
23
+ }
24
+ ret.metadata[ConverterConstants.SOURCE_FILE_PATH] = declarations[0].getSourceFile().getFilePath();
25
+ }
26
+ // Get value declaration so we can get the decorators
27
+ this.convertDecorators(value, ret);
28
+ // Translate all the typescript properties
29
+ this.convertProperties(value, conversionContext, ret);
30
+ conversionContext.state().objectNameStack.pop();
31
+ return ret;
32
+ }
33
+ supports(value) {
34
+ return value.isObject() && !value.isArray();
35
+ }
36
+ convertDecorators(value, ret) {
37
+ const errText = "No value declaration could be found for object " + value.getText();
38
+ const valueDeclaration = value.getSymbolOrThrow(errText)
39
+ .getValueDeclarationOrThrow(errText);
40
+ // Typescript cannot detect that this can be a DecoratableNode, so we have to cast it twice
41
+ const decoratableNode = valueDeclaration;
42
+ // Now Add any class level decorators
43
+ const decorators = decoratableNode.getDecorators();
44
+ if (decorators) {
45
+ for (const decorator of decorators) {
46
+ const c3Decorator = tsDecoratorToC3Decorator(decorator);
47
+ if (c3Decorator) {
48
+ ret.addDecorator(c3Decorator);
49
+ }
50
+ }
51
+ }
52
+ }
53
+ convertProperties(value, conversionContext, ret) {
54
+ const properties = value.getProperties();
55
+ for (const property of properties) {
56
+ const propertyName = property.getName();
57
+ conversionContext.beginProcessingProperty(propertyName);
58
+ let propertyDefinition = this.convertProperty(property, propertyName, conversionContext);
59
+ ret.addPropertyDefinition(propertyDefinition);
60
+ conversionContext.endProcessingProperty();
61
+ }
62
+ }
63
+ convertProperty(property, propertyName, conversionContext) {
64
+ const valueDeclaration = property.getValueDeclarationOrThrow("No value declaration could be found for property " + propertyName);
65
+ let propertyDefinition;
66
+ if (valueDeclaration.getType().isUnion()) {
67
+ conversionContext.state().unionPropertyNameStack.push(propertyName);
68
+ }
69
+ // Typescript cannot detect that this can be a DecoratableNode, so we have to cast it twice
70
+ const decoratableNode = valueDeclaration;
71
+ if (decoratableNode && decoratableNode.getDecorators) { // decoratableNode.getDecorators checks for existence of function, which will only be present if it is a DecoratableNode
72
+ const precisionDecorator = decoratableNode?.getDecorator('Precision');
73
+ if (precisionDecorator) {
74
+ // TODO: Verify this is a number type. This could also be a union type that has a number in the case of something like
75
+ // public myNumber: number | null
76
+ // or public myNumber?: number
77
+ // Additionally, this should be moved to the standard decorator pattern
78
+ const converted = convertPrecisionToC3Type(precisionDecorator);
79
+ propertyDefinition = new PropertyDefinition(propertyName, converted);
80
+ }
81
+ else {
82
+ const converted = conversionContext.convert(valueDeclaration.getType());
83
+ propertyDefinition = new PropertyDefinition(propertyName, converted);
84
+ }
85
+ if (decoratableNode?.getDecorators()) {
86
+ for (const decorator of decoratableNode.getDecorators()) {
87
+ // We have already handled Precision above
88
+ if (decorator.getName() !== 'Precision') {
89
+ const c3Decorator = tsDecoratorToC3Decorator(decorator);
90
+ if (c3Decorator) {
91
+ if (c3Decorator instanceof TenantIdDecorator) {
92
+ conversionContext.state().multiTenantSelectionEnabled = true;
93
+ }
94
+ if (!propertyDefinition.containsDecorator(c3Decorator)) {
95
+ propertyDefinition.addDecorator(c3Decorator);
96
+ }
97
+ }
98
+ }
99
+ }
100
+ }
101
+ }
102
+ else {
103
+ const converted = conversionContext.convert(valueDeclaration.getType());
104
+ propertyDefinition = new PropertyDefinition(propertyName, converted);
105
+ }
106
+ if (valueDeclaration.getType().isUnion()) {
107
+ conversionContext.state().unionPropertyNameStack.pop();
108
+ }
109
+ return propertyDefinition;
110
+ }
111
+ }
@@ -0,0 +1,10 @@
1
+ import { SpecificTypesConverter } from '../SpecificTypesConverter.js';
2
+ import { Type } from 'ts-morph';
3
+ import { TypescriptConversionState } from './TypescriptConversionState.js';
4
+ import { C3Type } from '@kinotic-ai/idl';
5
+ /**
6
+ * Converts typescript primitive types to C3Types
7
+ */
8
+ export declare class PrimitiveToC3Type extends SpecificTypesConverter<Type, C3Type, TypescriptConversionState, string> {
9
+ constructor();
10
+ }
@@ -0,0 +1,33 @@
1
+ import { SpecificTypesConverter } from '../SpecificTypesConverter.js';
2
+ import { BooleanC3Type, StringC3Type, IntC3Type, DateC3Type, VoidC3Type } from '@kinotic-ai/idl';
3
+ /**
4
+ * Converts typescript primitive types to C3Types
5
+ */
6
+ export class PrimitiveToC3Type extends SpecificTypesConverter {
7
+ constructor() {
8
+ const map = new Map();
9
+ map.set('string', () => {
10
+ return new StringC3Type();
11
+ });
12
+ map.set('boolean', () => {
13
+ return new BooleanC3Type();
14
+ });
15
+ map.set('number', () => {
16
+ return new IntC3Type();
17
+ });
18
+ map.set('date', () => {
19
+ return new DateC3Type();
20
+ });
21
+ map.set('void', () => {
22
+ return new VoidC3Type();
23
+ });
24
+ super((arg) => {
25
+ if (arg.isLiteral()) {
26
+ return arg.getApparentType().getText().toLowerCase();
27
+ }
28
+ else {
29
+ return arg.getText().toLowerCase();
30
+ }
31
+ }, map);
32
+ }
33
+ }
@@ -0,0 +1,9 @@
1
+ import { C3Type } from '@kinotic-ai/idl';
2
+ import { ts, Type } from 'ts-morph';
3
+ import { ITypeConverter } from '../ITypeConverter.js';
4
+ import { TypescriptConversionState } from './TypescriptConversionState.js';
5
+ import { IConversionContext } from '../IConversionContext.js';
6
+ export declare class QueryOptionsToC3Type implements ITypeConverter<Type, C3Type, TypescriptConversionState> {
7
+ convert(value: Type<ts.Type>, conversionContext: IConversionContext<Type, C3Type, TypescriptConversionState>): C3Type;
8
+ supports(value: Type<ts.Type>, conversionState: TypescriptConversionState): boolean;
9
+ }
@@ -0,0 +1,9 @@
1
+ import { QueryOptionsC3Type } from '@kinotic-ai/os-api';
2
+ export class QueryOptionsToC3Type {
3
+ convert(value, conversionContext) {
4
+ return new QueryOptionsC3Type();
5
+ }
6
+ supports(value, conversionState) {
7
+ return value.getAliasSymbol()?.getName() === 'QueryOptions';
8
+ }
9
+ }
@@ -0,0 +1,9 @@
1
+ import { C3Type } from '@kinotic-ai/idl';
2
+ import { ts, Type } from 'ts-morph';
3
+ import { ITypeConverter } from '../ITypeConverter.js';
4
+ import { TypescriptConversionState } from './TypescriptConversionState.js';
5
+ import { IConversionContext } from '../IConversionContext.js';
6
+ export declare class TenantSelectionToC3Type implements ITypeConverter<Type, C3Type, TypescriptConversionState> {
7
+ convert(value: Type<ts.Type>, conversionContext: IConversionContext<Type, C3Type, TypescriptConversionState>): C3Type;
8
+ supports(value: Type<ts.Type>, conversionState: TypescriptConversionState): boolean;
9
+ }
@@ -0,0 +1,9 @@
1
+ import { TenantSelectionC3Type } from '@kinotic-ai/os-api';
2
+ export class TenantSelectionToC3Type {
3
+ convert(value, conversionContext) {
4
+ return new TenantSelectionC3Type();
5
+ }
6
+ supports(value, conversionState) {
7
+ return value.getAliasSymbol()?.getName() === 'TenantSelection';
8
+ }
9
+ }
@@ -0,0 +1,24 @@
1
+ import { BaseConversionState } from '../common/BaseConversionState.js';
2
+ /**
3
+ * The state of the Typescript to C3Type conversion process.
4
+ */
5
+ export declare class TypescriptConversionState extends BaseConversionState {
6
+ /**
7
+ * Contains a stack of object names for objects being processed.
8
+ */
9
+ objectNameStack: string[];
10
+ /**
11
+ * Contains a stack of property names for any properties processed that are a union type.
12
+ */
13
+ unionPropertyNameStack: string[];
14
+ /**
15
+ * Boolean to indicate if the source path should be added to the metadata for the {@link C3Type}s created.
16
+ */
17
+ shouldAddSourcePathToMetadata: boolean;
18
+ /**
19
+ * Boolean to indicate if multi-tenant selection is enabled.
20
+ * This is done by adding a {@link TenantId} decorator to the entity.
21
+ */
22
+ multiTenantSelectionEnabled: boolean;
23
+ constructor(application: string);
24
+ }