@dagger.io/dagger 0.10.0 → 0.10.2

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 (54) hide show
  1. package/dist/api/client.gen.d.ts +35 -5
  2. package/dist/api/client.gen.d.ts.map +1 -1
  3. package/dist/api/client.gen.js +12 -4
  4. package/dist/api/utils.d.ts.map +1 -1
  5. package/dist/api/utils.js +6 -2
  6. package/dist/common/errors/ExecError.d.ts.map +1 -1
  7. package/dist/entrypoint/context.d.ts +8 -0
  8. package/dist/entrypoint/context.d.ts.map +1 -0
  9. package/dist/entrypoint/invoke.d.ts +3 -9
  10. package/dist/entrypoint/invoke.d.ts.map +1 -1
  11. package/dist/entrypoint/invoke.js +17 -28
  12. package/dist/entrypoint/load.d.ts +29 -69
  13. package/dist/entrypoint/load.d.ts.map +1 -1
  14. package/dist/entrypoint/load.js +90 -173
  15. package/dist/entrypoint/register.d.ts +2 -2
  16. package/dist/entrypoint/register.d.ts.map +1 -1
  17. package/dist/entrypoint/register.js +12 -12
  18. package/dist/introspector/scanner/abtractions/argument.d.ts +75 -0
  19. package/dist/introspector/scanner/abtractions/argument.d.ts.map +1 -0
  20. package/dist/introspector/scanner/abtractions/argument.js +137 -0
  21. package/dist/introspector/scanner/abtractions/constructor.d.ts +16 -0
  22. package/dist/introspector/scanner/abtractions/constructor.d.ts.map +1 -0
  23. package/dist/introspector/scanner/abtractions/constructor.js +42 -0
  24. package/dist/introspector/scanner/abtractions/method.d.ts +51 -0
  25. package/dist/introspector/scanner/abtractions/method.d.ts.map +1 -0
  26. package/dist/introspector/scanner/abtractions/method.js +105 -0
  27. package/dist/introspector/scanner/abtractions/module.d.ts +18 -0
  28. package/dist/introspector/scanner/abtractions/module.d.ts.map +1 -0
  29. package/dist/introspector/scanner/abtractions/module.js +59 -0
  30. package/dist/introspector/scanner/abtractions/object.d.ts +37 -0
  31. package/dist/introspector/scanner/abtractions/object.d.ts.map +1 -0
  32. package/dist/introspector/scanner/abtractions/object.js +94 -0
  33. package/dist/introspector/scanner/abtractions/property.d.ts +46 -0
  34. package/dist/introspector/scanner/abtractions/property.d.ts.map +1 -0
  35. package/dist/introspector/scanner/abtractions/property.js +93 -0
  36. package/dist/introspector/scanner/scan.d.ts +2 -1
  37. package/dist/introspector/scanner/scan.d.ts.map +1 -1
  38. package/dist/introspector/scanner/scan.js +2 -181
  39. package/dist/introspector/scanner/serialize.d.ts +0 -24
  40. package/dist/introspector/scanner/serialize.d.ts.map +1 -1
  41. package/dist/introspector/scanner/serialize.js +0 -53
  42. package/dist/introspector/scanner/typeDefs.d.ts +3 -3
  43. package/dist/introspector/scanner/typeDefs.d.ts.map +1 -1
  44. package/dist/introspector/scanner/utils.d.ts +1 -57
  45. package/dist/introspector/scanner/utils.d.ts.map +1 -1
  46. package/dist/introspector/scanner/utils.js +16 -139
  47. package/dist/provisioning/bin.d.ts.map +1 -1
  48. package/dist/provisioning/bin.js +9 -3
  49. package/dist/provisioning/default.d.ts +1 -1
  50. package/dist/provisioning/default.js +1 -1
  51. package/package.json +6 -5
  52. package/dist/introspector/scanner/metadata.d.ts +0 -24
  53. package/dist/introspector/scanner/metadata.d.ts.map +0 -1
  54. /package/dist/{introspector/scanner/metadata.js → entrypoint/context.js} +0 -0
@@ -10,198 +10,85 @@ export async function load(files) {
10
10
  await Promise.all(files.map(async (f) => await import(f)));
11
11
  }
12
12
  /**
13
- * Load the order of arguments for a given function from the scan result.
13
+ * Return the object invoked from the module.
14
14
  *
15
- * @param scanResult The result of the scan.
16
- * @param parentName The name of the class.
17
- * @param fnName The name of the function.
18
- *
19
- * @returns An array of strings representing the order of arguments.
20
- */
21
- export function loadArgOrder(scanResult, parentName, fnName) {
22
- const classTypeDef = scanResult.classes[parentName];
23
- if (!classTypeDef) {
24
- throw new Error(`could not find class ${parentName}`);
25
- }
26
- // Call for the constructor
27
- if (fnName === "") {
28
- return Object.keys(classTypeDef.constructor?.args ?? {});
29
- }
30
- const methodTypeDef = classTypeDef.methods[fnName];
31
- if (!methodTypeDef) {
32
- throw new Error(`could not find method ${fnName}`);
33
- }
34
- return Object.keys(methodTypeDef.args);
35
- }
36
- /**
37
- * Load the argument for the given function and check if it's variadic.
38
- *
39
- * @param scanResult The result of the scan.
40
- * @param parentName The name of the class.
41
- * @param fnName The name of the function.
42
- * @param argName The name of the argument.
43
- *
44
- * @returns True if the argument is variadic, false otherwise.
45
- */
46
- export function isArgVariadic(scanResult, parentName, fnName, argName) {
47
- const classTypeDef = scanResult.classes[parentName];
48
- if (!classTypeDef) {
49
- throw new Error(`could not find class ${parentName}`);
50
- }
51
- // It's not possible to have variadic arguments in the constructor.
52
- if (fnName === "") {
53
- return false;
54
- }
55
- const methodTypeDef = classTypeDef.methods[fnName];
56
- if (!methodTypeDef) {
57
- throw new Error(`could not find method ${fnName}`);
58
- }
59
- return methodTypeDef.args[argName].isVariadic;
60
- }
61
- /**
62
- * Load the argument type from the scan result.
63
- *
64
- * @param scanResult Result of the scan
65
- * @param parentName Class called
66
- * @param fnName Function called
67
- * @param argName Argument name
68
- * @returns The type of the argument
15
+ * @param module The module to load the object from.
16
+ * @param parentName The name of the parent object.
69
17
  */
70
- export function loadArgType(scanResult, parentName, fnName, argName) {
71
- const classTypeDef = scanResult.classes[parentName];
72
- if (!classTypeDef) {
73
- throw new Error(`could not find class ${parentName}`);
74
- }
75
- // Call for the constructor
76
- if (fnName === "") {
77
- const argTypeDef = classTypeDef.constructor?.args[argName];
78
- if (!argTypeDef) {
79
- throw new Error(`could not find argument ${argName} type in constructor`);
80
- }
81
- return argTypeDef.typeDef;
82
- }
83
- const methodTypeDef = classTypeDef.methods[fnName];
84
- if (!methodTypeDef) {
85
- throw new Error(`could not find method ${fnName}`);
86
- }
87
- const argTypeDef = methodTypeDef.args[argName];
88
- if (!argTypeDef) {
89
- throw new Error(`could not find argument ${argName} type`);
90
- }
91
- return argTypeDef.typeDef;
18
+ export function loadInvokedObject(module, parentName) {
19
+ return module.objects[parentName];
92
20
  }
93
- /**
94
- * Load the property type from the scan result.
95
- *
96
- * @param scanResult Result of the scan
97
- * @param parentName Class called
98
- * @param propertyName property of the class
99
- * @returns the type of the property
100
- */
101
- export function loadPropertyType(scanResult, parentName, propertyName) {
102
- const classTypeDef = scanResult.classes[parentName];
103
- if (!classTypeDef) {
104
- throw new Error(`could not find class ${parentName}`);
105
- }
106
- const propertyTypeDef = classTypeDef.fields[propertyName];
107
- if (!propertyTypeDef) {
108
- throw new Error(`could not find property ${propertyName} type`);
21
+ export function loadInvokedMethod(object, ctx) {
22
+ if (ctx.fnName === "") {
23
+ return object._constructor;
109
24
  }
110
- return propertyTypeDef.typeDef;
25
+ return object.methods[ctx.fnName];
111
26
  }
112
27
  /**
113
- * Load the true name from the scan result
28
+ * Load the values of the arguments from the context.
114
29
  *
115
- * @param scanResult Result of the scan
116
- * @param parentName Class called
117
- * @param alias exposed name
118
- * @param kind location of the alias
30
+ * @param method Method to load the arguments from.
31
+ * @param ctx The context of the invocation.
119
32
  */
120
- export function loadName(scanResult, parentName, alias, kind) {
121
- const classTypeDef = scanResult.classes[parentName];
122
- if (!classTypeDef) {
123
- throw new Error(`could not find class ${parentName}`);
124
- }
125
- switch (kind) {
126
- case "object": {
127
- return classTypeDef.name;
33
+ export async function loadArgs(method, ctx) {
34
+ const args = {};
35
+ // Load arguments
36
+ for (const argName of method.getArgOrder()) {
37
+ const argument = method.arguments[argName];
38
+ if (!argument) {
39
+ throw new Error(`could not find argument ${argName}`);
128
40
  }
129
- case "function": {
130
- // Handle constructor
131
- if (alias === "") {
132
- return "";
133
- }
134
- const methodTypeDef = classTypeDef.methods[alias];
135
- if (!methodTypeDef) {
136
- throw new Error(`could not find method ${alias} type`);
41
+ const loadedArg = await loadValue(ctx.fnArgs[argName], argument.type);
42
+ // If the argument is variadic, we need to load each args independently
43
+ // so it's correctly propagated when it's sent to the function.
44
+ // Note: variadic args are always last in the list of args.
45
+ if (argument.isVariadic) {
46
+ for (const [i, arg] of (loadedArg ?? []).entries()) {
47
+ args[`${argName}${i}`] = arg;
137
48
  }
138
- return methodTypeDef.name;
49
+ continue;
139
50
  }
140
- case "field": {
141
- const propertyTypeDef = classTypeDef.fields[alias];
142
- if (!propertyTypeDef) {
143
- throw new Error(`could not find property ${alias}`);
144
- }
145
- return propertyTypeDef.name;
51
+ // If the argument is nullable and the loaded arg is undefined with no default value, we set it to null.
52
+ if (argument.isNullable &&
53
+ loadedArg === undefined &&
54
+ !argument.defaultValue) {
55
+ args[argName] = null;
56
+ continue;
146
57
  }
58
+ args[argName] = loadedArg;
147
59
  }
60
+ return args;
148
61
  }
149
62
  /**
150
- * Load the alias from the true property name.
151
- * If not found, return the original alias because it's not
152
- * a registered field.
153
- *
154
- * @param scanResult Result of the scan
155
- * @param parentName Class called
156
- * @param alias exposed name
157
- */
158
- export function loadResultAlias(scanResult, parentName, alias) {
159
- const classTypeDef = scanResult.classes[parentName];
160
- if (!classTypeDef) {
161
- return alias;
162
- }
163
- const fieldTypeDef = Object.values(classTypeDef.fields).find((field) => field.name === alias);
164
- if (!fieldTypeDef) {
165
- return alias;
166
- }
167
- return fieldTypeDef.alias ?? fieldTypeDef.name;
168
- }
169
- /**
170
- * Return the eventual parent name of a field if its return type is a
171
- * registered object.
172
- * If not found, return the original parent name.
63
+ * Load the state of the parent object from the context.
173
64
  *
174
- * @param scanResult The result of the scan.
175
- * @param parentName Original parent name
176
- * @param alias The field alias
65
+ * @param object The object to load the parent state from.
66
+ * @param ctx The context of the invocation.
177
67
  */
178
- export function loadAliasParentName(scanResult, parentName, alias) {
179
- const classTypeDef = scanResult.classes[parentName];
180
- if (!classTypeDef) {
181
- return parentName;
182
- }
183
- const fieldTypeDef = Object.values(classTypeDef.fields).find((field) => field.name === alias);
184
- if (!fieldTypeDef) {
185
- return parentName;
186
- }
187
- if (fieldTypeDef.typeDef.kind === TypeDefKind.ObjectKind) {
188
- return fieldTypeDef.typeDef.name;
68
+ export async function loadParentState(object, ctx) {
69
+ const parentState = {};
70
+ for (const [key, value] of Object.entries(ctx.parentArgs)) {
71
+ const property = object.properties[key];
72
+ if (!property) {
73
+ throw new Error(`could not find parent property ${key}`);
74
+ }
75
+ parentState[property.name] = await loadValue(value, property.type);
189
76
  }
190
- return parentName;
77
+ return parentState;
191
78
  }
192
79
  /**
193
- * This function load the argument as a Dagger type.
80
+ * This function load the value as a Dagger type.
194
81
  *
195
82
  * Note: The JSON.parse() is required to remove extra quotes
196
83
  */
197
- export async function loadArg(value, type) {
84
+ export async function loadValue(value, type) {
198
85
  // If value is undefinied, return it directly.
199
86
  if (value === undefined) {
200
87
  return value;
201
88
  }
202
89
  switch (type.kind) {
203
90
  case TypeDefKind.ListKind:
204
- return Promise.all(value.map(async (v) => await loadArg(v, type.typeDef)));
91
+ return Promise.all(value.map(async (v) => await loadValue(v, type.typeDef)));
205
92
  case TypeDefKind.ObjectKind: {
206
93
  const objectType = type.name;
207
94
  // Workaround to call get any object that has an id
@@ -215,7 +102,7 @@ export async function loadArg(value, type) {
215
102
  // TODO(supports subfields serialization)
216
103
  return value;
217
104
  }
218
- // Cannot use , to specify multiple matching case so instead we use fallthrough.
105
+ // Cannot use `,` to specify multiple matching case so instead we use fallthrough.
219
106
  case TypeDefKind.StringKind:
220
107
  case TypeDefKind.IntegerKind:
221
108
  case TypeDefKind.BooleanKind:
@@ -226,30 +113,60 @@ export async function loadArg(value, type) {
226
113
  }
227
114
  }
228
115
  /**
229
- * Load subfields of the result and IDable object.
116
+ * Load the object type from the return type of the method.
117
+ * This covers the case where the return type is an other object of the module.
118
+ * For example: `msg(): Message` where message is an object of the module.
230
119
  *
231
- * @param result The result of the invocation.
232
- * @param scanResult The result of the scan.
233
- * @param parentName The name of the parent object.
234
- * @returns Loaded result.
120
+ * @param module The module to load the object from.
121
+ * @param object The current object to load the return type from.
122
+ * @param method The method to load the return type from.
235
123
  */
236
- export async function loadResult(result, scanResult, parentName) {
124
+ export function loadObjectReturnType(module, object, method) {
125
+ const retType = method.returnType;
126
+ switch (retType.kind) {
127
+ case TypeDefKind.ListKind: {
128
+ // Loop until we find the original object type.
129
+ // This way we handle the list of list (e.g Object[][][]...[])
130
+ let listType = retType;
131
+ while (listType.kind === TypeDefKind.ListKind) {
132
+ listType = listType.typeDef;
133
+ }
134
+ return module.objects[listType.name];
135
+ }
136
+ case TypeDefKind.ObjectKind:
137
+ return module.objects[retType.name];
138
+ default:
139
+ return object;
140
+ }
141
+ }
142
+ export async function loadResult(result, module, object) {
237
143
  // Handle IDable objects
238
144
  if (result && typeof result?.id === "function") {
239
145
  result = await result.id();
240
146
  }
241
147
  // Handle arrays
242
148
  if (Array.isArray(result)) {
243
- result = await Promise.all(result.map(async (r) => await loadResult(r, scanResult, parentName)));
149
+ result = await Promise.all(result.map(async (r) => await loadResult(r, module, object)));
244
150
  return result;
245
151
  }
246
152
  // Handle objects
247
153
  if (typeof result === "object") {
248
154
  const state = {};
249
155
  for (const [key, value] of Object.entries(result)) {
250
- state[loadResultAlias(scanResult, parentName, key)] = await loadResult(value, scanResult, loadAliasParentName(scanResult, parentName, key));
156
+ const property = Object.values(object.properties).find((p) => p.name === key);
157
+ if (!property) {
158
+ throw new Error(`could not find result property ${key}`);
159
+ }
160
+ if (property.type.kind === TypeDefKind.ObjectKind) {
161
+ const referencedObject = module.objects[property.type.name];
162
+ if (referencedObject) {
163
+ object = referencedObject;
164
+ }
165
+ }
166
+ state[property.alias ?? property.name] = await loadResult(value, module, object);
251
167
  }
252
- result = state;
168
+ return state;
253
169
  }
170
+ // Handle primitive types
254
171
  return result;
255
172
  }
@@ -1,7 +1,7 @@
1
1
  import { ModuleID } from "../api/client.gen.js";
2
- import { ScanResult } from "../introspector/scanner/scan.js";
2
+ import { DaggerModule } from "../introspector/scanner/abtractions/module.js";
3
3
  /**
4
4
  * Register the module files and returns its ID
5
5
  */
6
- export declare function register(files: string[], scanResult: ScanResult): Promise<ModuleID>;
6
+ export declare function register(files: string[], module: DaggerModule): Promise<ModuleID>;
7
7
  //# sourceMappingURL=register.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../entrypoint/register.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,QAAQ,EAGT,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAA;AAU5D;;GAEG;AACH,wBAAsB,QAAQ,CAC5B,KAAK,EAAE,MAAM,EAAE,EACf,UAAU,EAAE,UAAU,GACrB,OAAO,CAAC,QAAQ,CAAC,CA8CnB"}
1
+ {"version":3,"file":"register.d.ts","sourceRoot":"","sources":["../../entrypoint/register.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,QAAQ,EAGT,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,+CAA+C,CAAA;AAU5E;;GAEG;AACH,wBAAsB,QAAQ,CAC5B,KAAK,EAAE,MAAM,EAAE,EACf,MAAM,EAAE,YAAY,GACnB,OAAO,CAAC,QAAQ,CAAC,CA8CnB"}
@@ -2,33 +2,33 @@ import { dag, TypeDefKind, } from "../api/client.gen.js";
2
2
  /**
3
3
  * Register the module files and returns its ID
4
4
  */
5
- export async function register(files, scanResult) {
5
+ export async function register(files, module) {
6
6
  // Get a new module that we will fill in with all the types
7
7
  let mod = dag.module_();
8
8
  // Add module description if any.
9
- if (scanResult.module.description) {
10
- mod = mod.withDescription(scanResult.module.description);
9
+ if (module.description) {
10
+ mod = mod.withDescription(module.description);
11
11
  }
12
12
  // For each class scanned, register its type, method and properties in the module.
13
- Object.values(scanResult.classes).forEach((modClass) => {
13
+ Object.values(module.objects).forEach((object) => {
14
14
  // Register the class Typedef object in Dagger
15
- let typeDef = dag.typeDef().withObject(modClass.name, {
16
- description: modClass.description,
15
+ let typeDef = dag.typeDef().withObject(object.name, {
16
+ description: object.description,
17
17
  });
18
18
  // Register all functions (methods) to this object
19
- Object.values(modClass.methods).forEach((method) => {
20
- typeDef = typeDef.withFunction(addFunction(method));
19
+ Object.values(object.methods).forEach((method) => {
20
+ typeDef = typeDef.withFunction(addFunction(method.typeDef));
21
21
  });
22
22
  // Register all fields that belong to this object
23
- Object.values(modClass.fields).forEach((field) => {
23
+ Object.values(object.properties).forEach((field) => {
24
24
  if (field.isExposed) {
25
- typeDef = typeDef.withField(field.alias ?? field.name, addTypeDef(field.typeDef), {
25
+ typeDef = typeDef.withField(field.alias ?? field.name, addTypeDef(field.typeDef.typeDef), {
26
26
  description: field.description,
27
27
  });
28
28
  }
29
29
  });
30
- if (modClass.constructor) {
31
- typeDef = typeDef.withConstructor(addConstructor(modClass.constructor, typeDef));
30
+ if (object._constructor) {
31
+ typeDef = typeDef.withConstructor(addConstructor(object._constructor.typeDef, typeDef));
32
32
  }
33
33
  // Add it to the module object
34
34
  mod = mod.withObject(typeDef);
@@ -0,0 +1,75 @@
1
+ import ts from "typescript";
2
+ import { TypeDefKind } from "../../../api/client.gen.js";
3
+ import { FunctionArgTypeDef, TypeDef } from "../typeDefs.js";
4
+ export type Arguments = {
5
+ [name: string]: Argument;
6
+ };
7
+ /**
8
+ * Argument is an abstraction of a function argument.
9
+ *
10
+ * This aims to simplify and adds clarity to how we analyse the code and using
11
+ * clear accessor.
12
+ */
13
+ export declare class Argument {
14
+ private symbol;
15
+ private checker;
16
+ private param;
17
+ /**
18
+ * Create a new Argument instance.
19
+ *
20
+ * @param checker Checker to use to introspect the type of the argument.
21
+ * @param param The symbol of the argument to introspect.
22
+ *
23
+ * @throws UnknownDaggerError If the symbol doesn't have any declaration.
24
+ * @throws UnknownDaggerError If the declaration of the symbol isn't a parameter.
25
+ */
26
+ constructor(checker: ts.TypeChecker, param: ts.Symbol);
27
+ get name(): string;
28
+ get description(): string;
29
+ /**
30
+ * Return the type of the argument in a Dagger TypeDef format.
31
+ */
32
+ get type(): TypeDef<TypeDefKind>;
33
+ get defaultValue(): string | undefined;
34
+ /**
35
+ * Return true if the parameter is optional.
36
+ *
37
+ * A parameter is considered optional if he fits one of the following:
38
+ * - It has a question token (e.g. `foo?: <type>`).
39
+ * - It's variadic (e.g. `...foo: <type>[]`).
40
+ * - It's nullable (e.g. `foo: <type> | null`).
41
+ */
42
+ get isOptional(): boolean;
43
+ /**
44
+ * Return true if the parameter is nullable.
45
+ *
46
+ * A parameter is considered nullable if itstype is a union type with `null`
47
+ * on the list of types.
48
+ * Example: `foo: string | null`.
49
+ */
50
+ get isNullable(): boolean;
51
+ get isVariadic(): boolean;
52
+ get typeDef(): FunctionArgTypeDef;
53
+ toJSON(): {
54
+ name: string;
55
+ description: string;
56
+ type: TypeDef<TypeDefKind>;
57
+ isVariadic: boolean;
58
+ isNullable: boolean;
59
+ isOptional: boolean;
60
+ defaultValue: string | undefined;
61
+ };
62
+ /**
63
+ * The TypeScript Compiler API returns the raw default value as it is written
64
+ * by the user.
65
+ * However, some notations are not supported by GraphQL so this function
66
+ * formats the default value to be compatible with the GraphQL syntax.
67
+ *
68
+ * Formatting rules:
69
+ * - Single quote strings are converted to double quote strings.
70
+ *
71
+ * @param value The value to format.
72
+ */
73
+ private formatDefaultValue;
74
+ }
75
+ //# sourceMappingURL=argument.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"argument.d.ts","sourceRoot":"","sources":["../../../../introspector/scanner/abtractions/argument.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAA;AAG3B,OAAO,EAAE,WAAW,EAAE,MAAM,4BAA4B,CAAA;AACxD,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAA;AAI5D,MAAM,MAAM,SAAS,GAAG;IAAE,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAA;CAAE,CAAA;AAEpD;;;;;GAKG;AACH,qBAAa,QAAQ;IACnB,OAAO,CAAC,MAAM,CAAW;IAEzB,OAAO,CAAC,OAAO,CAAgB;IAE/B,OAAO,CAAC,KAAK,CAAyB;IAEtC;;;;;;;;OAQG;gBACS,OAAO,EAAE,EAAE,CAAC,WAAW,EAAE,KAAK,EAAE,EAAE,CAAC,MAAM;IAuBrD,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,WAAW,IAAI,MAAM,CAIxB;IAED;;OAEG;IACH,IAAI,IAAI,IAAI,OAAO,CAAC,WAAW,CAAC,CAgB/B;IAED,IAAI,YAAY,IAAI,MAAM,GAAG,SAAS,CAMrC;IAED;;;;;;;OAOG;IACH,IAAI,UAAU,IAAI,OAAO,CAMxB;IAED;;;;;;OAMG;IACH,IAAI,UAAU,IAAI,OAAO,CAcxB;IAED,IAAI,UAAU,IAAI,OAAO,CAExB;IAID,IAAI,OAAO,IAAI,kBAAkB,CAShC;IAED,MAAM;;;;;;;;;IAYN;;;;;;;;;;OAUG;IACH,OAAO,CAAC,kBAAkB;CAU3B"}
@@ -0,0 +1,137 @@
1
+ import ts from "typescript";
2
+ import { UnknownDaggerError } from "../../../common/errors/UnknownDaggerError.js";
3
+ import { serializeType } from "../serialize.js";
4
+ import { typeNameToTypedef } from "../utils.js";
5
+ /**
6
+ * Argument is an abstraction of a function argument.
7
+ *
8
+ * This aims to simplify and adds clarity to how we analyse the code and using
9
+ * clear accessor.
10
+ */
11
+ export class Argument {
12
+ symbol;
13
+ checker;
14
+ param;
15
+ /**
16
+ * Create a new Argument instance.
17
+ *
18
+ * @param checker Checker to use to introspect the type of the argument.
19
+ * @param param The symbol of the argument to introspect.
20
+ *
21
+ * @throws UnknownDaggerError If the symbol doesn't have any declaration.
22
+ * @throws UnknownDaggerError If the declaration of the symbol isn't a parameter.
23
+ */
24
+ constructor(checker, param) {
25
+ this.symbol = param;
26
+ this.checker = checker;
27
+ const declarations = this.symbol.getDeclarations();
28
+ if (!declarations || declarations.length < 0) {
29
+ throw new UnknownDaggerError(`could not find param declarations of symbol ${this.symbol.name}`, {});
30
+ }
31
+ const parameterDeclaration = declarations[0];
32
+ if (!ts.isParameter(parameterDeclaration)) {
33
+ throw new UnknownDaggerError(`the declaration of symbol ${this.symbol.name} isn't a parameter`, {});
34
+ }
35
+ this.param = parameterDeclaration;
36
+ }
37
+ get name() {
38
+ return this.symbol.getName();
39
+ }
40
+ get description() {
41
+ return ts.displayPartsToString(this.symbol.getDocumentationComment(this.checker));
42
+ }
43
+ /**
44
+ * Return the type of the argument in a Dagger TypeDef format.
45
+ */
46
+ get type() {
47
+ if (!this.symbol.valueDeclaration) {
48
+ throw new UnknownDaggerError("could not find symbol value declaration", {});
49
+ }
50
+ const type = this.checker.getTypeOfSymbolAtLocation(this.symbol, this.symbol.valueDeclaration);
51
+ const typeName = serializeType(this.checker, type);
52
+ return typeNameToTypedef(typeName);
53
+ }
54
+ get defaultValue() {
55
+ if (this.param.initializer === undefined) {
56
+ return undefined;
57
+ }
58
+ return this.formatDefaultValue(this.param.initializer.getText());
59
+ }
60
+ /**
61
+ * Return true if the parameter is optional.
62
+ *
63
+ * A parameter is considered optional if he fits one of the following:
64
+ * - It has a question token (e.g. `foo?: <type>`).
65
+ * - It's variadic (e.g. `...foo: <type>[]`).
66
+ * - It's nullable (e.g. `foo: <type> | null`).
67
+ */
68
+ get isOptional() {
69
+ return (this.param.questionToken !== undefined ||
70
+ this.isVariadic ||
71
+ this.isNullable);
72
+ }
73
+ /**
74
+ * Return true if the parameter is nullable.
75
+ *
76
+ * A parameter is considered nullable if itstype is a union type with `null`
77
+ * on the list of types.
78
+ * Example: `foo: string | null`.
79
+ */
80
+ get isNullable() {
81
+ if (!this.param.type) {
82
+ return false;
83
+ }
84
+ if (ts.isUnionTypeNode(this.param.type)) {
85
+ for (const _type of this.param.type.types) {
86
+ if (_type.getText() === "null") {
87
+ return true;
88
+ }
89
+ }
90
+ }
91
+ return false;
92
+ }
93
+ get isVariadic() {
94
+ return this.param.dotDotDotToken !== undefined;
95
+ }
96
+ // TODO(TomChv): replace with `ToJson` method
97
+ // after the refactor is complete.
98
+ get typeDef() {
99
+ return {
100
+ name: this.name,
101
+ description: this.description,
102
+ optional: this.isOptional,
103
+ defaultValue: this.defaultValue,
104
+ isVariadic: this.isVariadic,
105
+ typeDef: this.type,
106
+ };
107
+ }
108
+ toJSON() {
109
+ return {
110
+ name: this.name,
111
+ description: this.description,
112
+ type: this.type,
113
+ isVariadic: this.isVariadic,
114
+ isNullable: this.isNullable,
115
+ isOptional: this.isOptional,
116
+ defaultValue: this.defaultValue,
117
+ };
118
+ }
119
+ /**
120
+ * The TypeScript Compiler API returns the raw default value as it is written
121
+ * by the user.
122
+ * However, some notations are not supported by GraphQL so this function
123
+ * formats the default value to be compatible with the GraphQL syntax.
124
+ *
125
+ * Formatting rules:
126
+ * - Single quote strings are converted to double quote strings.
127
+ *
128
+ * @param value The value to format.
129
+ */
130
+ formatDefaultValue(value) {
131
+ const isSingleQuoteString = () => value.startsWith("'") && value.endsWith("'");
132
+ if (isSingleQuoteString()) {
133
+ return `"${value.slice(1, value.length - 1)}"`;
134
+ }
135
+ return value;
136
+ }
137
+ }
@@ -0,0 +1,16 @@
1
+ import ts from "typescript";
2
+ import { Arguments } from "./argument.js";
3
+ import { ConstructorTypeDef } from "../typeDefs.js";
4
+ export declare class Constructor {
5
+ private checker;
6
+ private declaration;
7
+ constructor(checker: ts.TypeChecker, declaration: ts.ConstructorDeclaration);
8
+ get name(): string;
9
+ get arguments(): Arguments;
10
+ get typeDef(): ConstructorTypeDef;
11
+ toJSON(): {
12
+ args: Arguments;
13
+ };
14
+ getArgOrder(): string[];
15
+ }
16
+ //# sourceMappingURL=constructor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constructor.d.ts","sourceRoot":"","sources":["../../../../introspector/scanner/abtractions/constructor.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAA;AAE3B,OAAO,EAAY,SAAS,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,EAAE,kBAAkB,EAAsB,MAAM,gBAAgB,CAAA;AAEvE,qBAAa,WAAW;IACtB,OAAO,CAAC,OAAO,CAAgB;IAE/B,OAAO,CAAC,WAAW,CAA2B;gBAElC,OAAO,EAAE,EAAE,CAAC,WAAW,EAAE,WAAW,EAAE,EAAE,CAAC,sBAAsB;IAK3E,IAAI,IAAI,IAAI,MAAM,CAEjB;IAED,IAAI,SAAS,IAAI,SAAS,CAgBzB;IAID,IAAI,OAAO,IAAI,kBAAkB,CAWhC;IAED,MAAM;;;IAMN,WAAW,IAAI,MAAM,EAAE;CAGxB"}
@@ -0,0 +1,42 @@
1
+ import { UnknownDaggerError } from "../../../common/errors/UnknownDaggerError.js";
2
+ import { Argument } from "./argument.js";
3
+ export class Constructor {
4
+ checker;
5
+ declaration;
6
+ constructor(checker, declaration) {
7
+ this.checker = checker;
8
+ this.declaration = declaration;
9
+ }
10
+ get name() {
11
+ return "";
12
+ }
13
+ get arguments() {
14
+ return this.declaration.parameters.reduce((acc, param) => {
15
+ const symbol = this.checker.getSymbolAtLocation(param.name);
16
+ if (!symbol) {
17
+ throw new UnknownDaggerError(`could not get constructor param: ${param.name.getText()}`, {});
18
+ }
19
+ const argument = new Argument(this.checker, symbol);
20
+ acc[argument.name] = argument;
21
+ return acc;
22
+ }, {});
23
+ }
24
+ // TODO(TomChv): replace with `ToJson` method
25
+ // after the refactor is complete.
26
+ get typeDef() {
27
+ return {
28
+ args: Object.entries(this.arguments).reduce((acc, [name, arg]) => {
29
+ acc[name] = arg.typeDef;
30
+ return acc;
31
+ }, {}),
32
+ };
33
+ }
34
+ toJSON() {
35
+ return {
36
+ args: this.arguments,
37
+ };
38
+ }
39
+ getArgOrder() {
40
+ return Object.keys(this.arguments);
41
+ }
42
+ }