@strapi/typescript-utils 0.0.0-next.f45143c5e2a8a9d85691d0abf79a3f42024a0c71 → 0.0.0-next.f7babb775ed9a7e18d8351cb7f74c63e016323c4

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.
@@ -3,8 +3,8 @@
3
3
  const { factory } = require('typescript');
4
4
  const _ = require('lodash/fp');
5
5
 
6
- const { addImport } = require('./imports');
7
- const { getTypeNode, toTypeLiteral } = require('./utils');
6
+ const { addImport } = require('../imports');
7
+ const { getTypeNode, toTypeLiteral, withAttributeNamespace, NAMESPACES } = require('./utils');
8
8
  const mappers = require('./mappers');
9
9
 
10
10
  /**
@@ -26,7 +26,8 @@ const getAttributeType = (attributeName, attribute, uid) => {
26
26
 
27
27
  const [attributeType, typeParams] = mappers[attribute.type]({ uid, attribute, attributeName });
28
28
 
29
- addImport(attributeType);
29
+ // Make sure the attribute namespace is imported
30
+ addImport(NAMESPACES.attribute);
30
31
 
31
32
  return getTypeNode(attributeType, typeParams);
32
33
  };
@@ -42,38 +43,36 @@ const getAttributeModifiers = (attribute) => {
42
43
 
43
44
  // Required
44
45
  if (attribute.required) {
45
- addImport('RequiredAttribute');
46
-
47
- modifiers.push(factory.createTypeReferenceNode(factory.createIdentifier('RequiredAttribute')));
46
+ modifiers.push(
47
+ factory.createTypeReferenceNode(factory.createIdentifier(withAttributeNamespace('Required')))
48
+ );
48
49
  }
49
50
 
50
51
  // Private
51
52
  if (attribute.private) {
52
- addImport('PrivateAttribute');
53
-
54
- modifiers.push(factory.createTypeReferenceNode(factory.createIdentifier('PrivateAttribute')));
53
+ modifiers.push(
54
+ factory.createTypeReferenceNode(factory.createIdentifier(withAttributeNamespace('Private')))
55
+ );
55
56
  }
56
57
 
57
58
  // Unique
58
59
  if (attribute.unique) {
59
- addImport('UniqueAttribute');
60
-
61
- modifiers.push(factory.createTypeReferenceNode(factory.createIdentifier('UniqueAttribute')));
60
+ modifiers.push(
61
+ factory.createTypeReferenceNode(factory.createIdentifier(withAttributeNamespace('Unique')))
62
+ );
62
63
  }
63
64
 
64
65
  // Configurable
65
66
  if (attribute.configurable) {
66
- addImport('ConfigurableAttribute');
67
-
68
67
  modifiers.push(
69
- factory.createTypeReferenceNode(factory.createIdentifier('ConfigurableAttribute'))
68
+ factory.createTypeReferenceNode(
69
+ factory.createIdentifier(withAttributeNamespace('Configurable'))
70
+ )
70
71
  );
71
72
  }
72
73
 
73
74
  // Custom field
74
75
  if (attribute.customField) {
75
- addImport('CustomField');
76
-
77
76
  const customFieldUid = factory.createStringLiteral(attribute.customField);
78
77
  const typeArguments = [customFieldUid];
79
78
 
@@ -82,17 +81,18 @@ const getAttributeModifiers = (attribute) => {
82
81
  }
83
82
 
84
83
  modifiers.push(
85
- factory.createTypeReferenceNode(factory.createIdentifier('CustomField'), typeArguments)
84
+ factory.createTypeReferenceNode(
85
+ factory.createIdentifier(withAttributeNamespace('CustomField')),
86
+ typeArguments
87
+ )
86
88
  );
87
89
  }
88
90
 
89
91
  // Plugin Options
90
92
  if (!_.isEmpty(attribute.pluginOptions)) {
91
- addImport('SetPluginOptions');
92
-
93
93
  modifiers.push(
94
94
  factory.createTypeReferenceNode(
95
- factory.createIdentifier('SetPluginOptions'),
95
+ factory.createIdentifier(withAttributeNamespace('SetPluginOptions')),
96
96
  // Transform the pluginOptions object into an object literal expression
97
97
  [toTypeLiteral(attribute.pluginOptions)]
98
98
  )
@@ -102,38 +102,37 @@ const getAttributeModifiers = (attribute) => {
102
102
  // Min / Max
103
103
  // TODO: Always provide a second type argument for min/max (ie: resolve the attribute scalar type with a `GetAttributeType<${mappers[attribute][0]}>` (useful for biginter (string values)))
104
104
  if (!_.isNil(attribute.min) || !_.isNil(attribute.max)) {
105
- addImport('SetMinMax');
106
-
107
105
  const minMaxProperties = _.pick(['min', 'max'], attribute);
108
106
 
109
107
  modifiers.push(
110
- factory.createTypeReferenceNode(factory.createIdentifier('SetMinMax'), [
111
- toTypeLiteral(minMaxProperties),
112
- ])
108
+ factory.createTypeReferenceNode(
109
+ factory.createIdentifier(withAttributeNamespace('SetMinMax')),
110
+ [toTypeLiteral(minMaxProperties)]
111
+ )
113
112
  );
114
113
  }
115
114
 
116
115
  // Min length / Max length
117
116
  if (!_.isNil(attribute.minLength) || !_.isNil(attribute.maxLength)) {
118
- addImport('SetMinMaxLength');
119
-
120
117
  const minMaxProperties = _.pick(['minLength', 'maxLength'], attribute);
121
118
 
122
119
  modifiers.push(
123
- factory.createTypeReferenceNode(factory.createIdentifier('SetMinMaxLength'), [
124
- toTypeLiteral(minMaxProperties),
125
- ])
120
+ factory.createTypeReferenceNode(
121
+ factory.createIdentifier(withAttributeNamespace('SetMinMaxLength')),
122
+ [toTypeLiteral(minMaxProperties)]
123
+ )
126
124
  );
127
125
  }
128
126
 
129
127
  // Default
130
128
  if (!_.isNil(attribute.default)) {
131
- addImport('DefaultTo');
132
-
133
129
  const defaultLiteral = toTypeLiteral(attribute.default);
134
130
 
135
131
  modifiers.push(
136
- factory.createTypeReferenceNode(factory.createIdentifier('DefaultTo'), [defaultLiteral])
132
+ factory.createTypeReferenceNode(
133
+ factory.createIdentifier(withAttributeNamespace('DefaultTo')),
134
+ [defaultLiteral]
135
+ )
137
136
  );
138
137
  }
139
138
 
@@ -0,0 +1,15 @@
1
+ 'use strict';
2
+
3
+ const schema = require('./schema');
4
+ const attributes = require('./attributes');
5
+ const mappers = require('./mappers');
6
+ const utils = require('./utils');
7
+ const imports = require('../imports');
8
+
9
+ module.exports = {
10
+ schema,
11
+ attributes,
12
+ mappers,
13
+ utils,
14
+ imports,
15
+ };
@@ -3,56 +3,56 @@
3
3
  const ts = require('typescript');
4
4
  const _ = require('lodash/fp');
5
5
 
6
- const { toTypeLiteral } = require('./utils');
6
+ const { toTypeLiteral, withAttributeNamespace } = require('./utils');
7
7
 
8
8
  const { factory } = ts;
9
9
 
10
10
  module.exports = {
11
11
  string() {
12
- return ['StringAttribute'];
12
+ return [withAttributeNamespace('String')];
13
13
  },
14
14
  text() {
15
- return ['TextAttribute'];
15
+ return [withAttributeNamespace('Text')];
16
16
  },
17
17
  richtext() {
18
- return ['RichTextAttribute'];
18
+ return [withAttributeNamespace('RichText')];
19
19
  },
20
20
  password() {
21
- return ['PasswordAttribute'];
21
+ return [withAttributeNamespace('Password')];
22
22
  },
23
23
  email() {
24
- return ['EmailAttribute'];
24
+ return [withAttributeNamespace('Email')];
25
25
  },
26
26
  date() {
27
- return ['DateAttribute'];
27
+ return [withAttributeNamespace('Date')];
28
28
  },
29
29
  time() {
30
- return ['TimeAttribute'];
30
+ return [withAttributeNamespace('Time')];
31
31
  },
32
32
  datetime() {
33
- return ['DateTimeAttribute'];
33
+ return [withAttributeNamespace('DateTime')];
34
34
  },
35
35
  timestamp() {
36
- return ['TimestampAttribute'];
36
+ return [withAttributeNamespace('Timestamp')];
37
37
  },
38
38
  integer() {
39
- return ['IntegerAttribute'];
39
+ return [withAttributeNamespace('Integer')];
40
40
  },
41
41
  biginteger() {
42
- return ['BigIntegerAttribute'];
42
+ return [withAttributeNamespace('BigInteger')];
43
43
  },
44
44
  float() {
45
- return ['FloatAttribute'];
45
+ return [withAttributeNamespace('Float')];
46
46
  },
47
47
  decimal() {
48
- return ['DecimalAttribute'];
48
+ return [withAttributeNamespace('Decimal')];
49
49
  },
50
50
  uid({ attribute, uid }) {
51
51
  const { targetField, options } = attribute;
52
52
 
53
53
  // If there are no params to compute, then return the attribute type alone
54
54
  if (targetField === undefined && options === undefined) {
55
- return ['UIDAttribute'];
55
+ return [withAttributeNamespace('UID')];
56
56
  }
57
57
 
58
58
  const params = [];
@@ -74,21 +74,21 @@ module.exports = {
74
74
  params.push(toTypeLiteral(options));
75
75
  }
76
76
 
77
- return ['UIDAttribute', params];
77
+ return [withAttributeNamespace('UID'), params];
78
78
  },
79
79
  enumeration({ attribute }) {
80
80
  const { enum: enumValues } = attribute;
81
81
 
82
- return ['EnumerationAttribute', [toTypeLiteral(enumValues)]];
82
+ return [withAttributeNamespace('Enumeration'), [toTypeLiteral(enumValues)]];
83
83
  },
84
84
  boolean() {
85
- return ['BooleanAttribute'];
85
+ return [withAttributeNamespace('Boolean')];
86
86
  },
87
87
  json() {
88
- return ['JSONAttribute'];
88
+ return [withAttributeNamespace('JSON')];
89
89
  },
90
90
  media() {
91
- return ['MediaAttribute'];
91
+ return [withAttributeNamespace('Media')];
92
92
  },
93
93
  relation({ uid, attribute }) {
94
94
  const { relation, target } = attribute;
@@ -97,13 +97,13 @@ module.exports = {
97
97
 
98
98
  if (isMorphRelation) {
99
99
  return [
100
- 'RelationAttribute',
100
+ withAttributeNamespace('Relation'),
101
101
  [factory.createStringLiteral(uid, true), factory.createStringLiteral(relation, true)],
102
102
  ];
103
103
  }
104
104
 
105
105
  return [
106
- 'RelationAttribute',
106
+ withAttributeNamespace('Relation'),
107
107
  [
108
108
  factory.createStringLiteral(uid, true),
109
109
  factory.createStringLiteral(relation, true),
@@ -119,13 +119,13 @@ module.exports = {
119
119
  params.push(factory.createTrue());
120
120
  }
121
121
 
122
- return ['ComponentAttribute', params];
122
+ return [withAttributeNamespace('Component'), params];
123
123
  },
124
124
  dynamiczone({ attribute }) {
125
125
  const componentsParam = factory.createTupleTypeNode(
126
126
  attribute.components.map((component) => factory.createStringLiteral(component))
127
127
  );
128
128
 
129
- return ['DynamicZoneAttribute', [componentsParam]];
129
+ return [withAttributeNamespace('DynamicZone'), [componentsParam]];
130
130
  },
131
131
  };
@@ -4,9 +4,14 @@ const ts = require('typescript');
4
4
  const { factory } = require('typescript');
5
5
  const { isEmpty } = require('lodash/fp');
6
6
 
7
- const { getSchemaExtendsTypeName, getSchemaInterfaceName, toTypeLiteral } = require('./utils');
7
+ const {
8
+ getSchemaExtendsTypeName,
9
+ getSchemaInterfaceName,
10
+ toTypeLiteral,
11
+ NAMESPACES,
12
+ } = require('./utils');
8
13
  const attributeToPropertySignature = require('./attributes');
9
- const { addImport } = require('./imports');
14
+ const { addImport } = require('../imports');
10
15
 
11
16
  /**
12
17
  * Generate a property signature for the schema's `attributes` field
@@ -51,11 +56,11 @@ const generateSchemaDefinition = (schema) => {
51
56
  const interfaceName = getSchemaInterfaceName(uid);
52
57
  const parentType = getSchemaExtendsTypeName(schema);
53
58
 
54
- // Make sure the extended interface are imported
55
- addImport(parentType);
59
+ // Make sure the Schema namespace is imported
60
+ addImport(NAMESPACES.schema);
56
61
 
57
62
  // Properties whose values can be mapped to a literal type expression
58
- const literalPropertiesDefinitions = ['info', 'options', 'pluginOptions']
63
+ const literalPropertiesDefinitions = ['collectionName', 'info', 'options', 'pluginOptions']
59
64
  // Ignore non-existent or empty declarations
60
65
  .filter((key) => !isEmpty(schema[key]))
61
66
  // Generate literal definition for each property
@@ -69,7 +74,6 @@ const generateSchemaDefinition = (schema) => {
69
74
 
70
75
  // Generate the schema's interface declaration
71
76
  const schemaType = factory.createInterfaceDeclaration(
72
- undefined,
73
77
  [factory.createModifier(ts.SyntaxKind.ExportKeyword)],
74
78
  factory.createIdentifier(interfaceName),
75
79
  undefined,
@@ -17,13 +17,10 @@ const {
17
17
  propEq,
18
18
  } = require('lodash/fp');
19
19
 
20
- /**
21
- * Get all components and content-types in a Strapi application
22
- *
23
- * @param {Strapi} strapi
24
- * @returns {object}
25
- */
26
- const getAllStrapiSchemas = (strapi) => ({ ...strapi.contentTypes, ...strapi.components });
20
+ const NAMESPACES = {
21
+ schema: 'Schema',
22
+ attribute: 'Attribute',
23
+ };
27
24
 
28
25
  /**
29
26
  * Extract a valid interface name from a schema uid
@@ -58,7 +55,11 @@ const getSchemaModelType = (schema) => {
58
55
  const getSchemaExtendsTypeName = (schema) => {
59
56
  const base = getSchemaModelType(schema);
60
57
 
61
- return `${upperFirst(base)}Schema`;
58
+ if (base === null) {
59
+ return null;
60
+ }
61
+
62
+ return `${NAMESPACES.schema}.${upperFirst(base)}`;
62
63
  };
63
64
 
64
65
  /**
@@ -120,13 +121,7 @@ const toTypeLiteral = (data) => {
120
121
 
121
122
  return [
122
123
  ...acc,
123
- factory.createPropertyDeclaration(
124
- undefined,
125
- undefined,
126
- identifier,
127
- undefined,
128
- toTypeLiteral(value)
129
- ),
124
+ factory.createPropertyDeclaration(undefined, identifier, undefined, toTypeLiteral(value)),
130
125
  ];
131
126
  }, []);
132
127
 
@@ -149,8 +144,26 @@ const getDefinitionAttributesCount = (definition) => {
149
144
  return attributesNode.type.members.length;
150
145
  };
151
146
 
147
+ /**
148
+ * Add the attribute namespace before the typename
149
+ *
150
+ * @param {string} typeName
151
+ * @returns {string}
152
+ */
153
+ const withAttributeNamespace = (typeName) => `${NAMESPACES.attribute}.${typeName}`;
154
+
155
+ /**
156
+ * Add the schema namespace before the typename
157
+ *
158
+ * @param {string} typeName
159
+ * @returns {string}
160
+ */
161
+ const withSchemaNamespace = (typeName) => `${NAMESPACES.schema}.${typeName}`;
162
+
152
163
  module.exports = {
153
- getAllStrapiSchemas,
164
+ NAMESPACES,
165
+ withAttributeNamespace,
166
+ withSchemaNamespace,
154
167
  getSchemaInterfaceName,
155
168
  getSchemaExtendsTypeName,
156
169
  getSchemaModelType,
@@ -0,0 +1,58 @@
1
+ 'use strict';
2
+
3
+ const { factory } = require('typescript');
4
+
5
+ const { models } = require('../common');
6
+ const { emitDefinitions, format, generateSharedExtensionDefinition } = require('../utils');
7
+
8
+ /**
9
+ * Generate type definitions for Strapi Components
10
+ *
11
+ * @param {object} [options]
12
+ * @param {object} options.strapi
13
+ * @param {object} options.logger
14
+ * @param {string} options.pwd
15
+ */
16
+ const generateComponentsDefinitions = async (options = {}) => {
17
+ const { strapi } = options;
18
+
19
+ const { components } = strapi;
20
+
21
+ const componentsDefinitions = Object.values(components).map((contentType) => ({
22
+ uid: contentType.uid,
23
+ definition: models.schema.generateSchemaDefinition(contentType),
24
+ }));
25
+
26
+ const formattedSchemasDefinitions = componentsDefinitions.reduce((acc, def) => {
27
+ acc.push(
28
+ // Definition
29
+ def.definition,
30
+
31
+ // Add a newline between each interface declaration
32
+ factory.createIdentifier('\n')
33
+ );
34
+
35
+ return acc;
36
+ }, []);
37
+
38
+ const allDefinitions = [
39
+ // Imports
40
+ ...models.imports.generateImportDefinition(),
41
+
42
+ // Add a newline after the import statement
43
+ factory.createIdentifier('\n'),
44
+
45
+ // Schemas
46
+ ...formattedSchemasDefinitions,
47
+
48
+ // Global
49
+ generateSharedExtensionDefinition('Components', componentsDefinitions),
50
+ ];
51
+
52
+ const output = emitDefinitions(allDefinitions);
53
+ const formattedOutput = await format(output);
54
+
55
+ return { output: formattedOutput, stats: {} };
56
+ };
57
+
58
+ module.exports = generateComponentsDefinitions;
@@ -0,0 +1,6 @@
1
+ 'use strict';
2
+
3
+ const TYPES_ROOT_DIR = 'types';
4
+ const GENERATED_OUT_DIR = 'generated';
5
+
6
+ module.exports = { GENERATED_OUT_DIR, TYPES_ROOT_DIR };
@@ -0,0 +1,58 @@
1
+ 'use strict';
2
+
3
+ const { factory } = require('typescript');
4
+
5
+ const { models } = require('../common');
6
+ const { emitDefinitions, format, generateSharedExtensionDefinition } = require('../utils');
7
+
8
+ /**
9
+ * Generate type definitions for Strapi Content-Types
10
+ *
11
+ * @param {object} [options]
12
+ * @param {object} options.strapi
13
+ * @param {object} options.logger
14
+ * @param {string} options.pwd
15
+ */
16
+ const generateContentTypesDefinitions = async (options = {}) => {
17
+ const { strapi } = options;
18
+
19
+ const { contentTypes } = strapi;
20
+
21
+ const contentTypesDefinitions = Object.values(contentTypes).map((contentType) => ({
22
+ uid: contentType.uid,
23
+ definition: models.schema.generateSchemaDefinition(contentType),
24
+ }));
25
+
26
+ const formattedSchemasDefinitions = contentTypesDefinitions.reduce((acc, def) => {
27
+ acc.push(
28
+ // Definition
29
+ def.definition,
30
+
31
+ // Add a newline between each interface declaration
32
+ factory.createIdentifier('\n')
33
+ );
34
+
35
+ return acc;
36
+ }, []);
37
+
38
+ const allDefinitions = [
39
+ // Imports
40
+ ...models.imports.generateImportDefinition(),
41
+
42
+ // Add a newline after the import statement
43
+ factory.createIdentifier('\n'),
44
+
45
+ // Schemas
46
+ ...formattedSchemasDefinitions,
47
+
48
+ // Global
49
+ generateSharedExtensionDefinition('ContentTypes', contentTypesDefinitions),
50
+ ];
51
+
52
+ const output = emitDefinitions(allDefinitions);
53
+ const formattedOutput = await format(output);
54
+
55
+ return { output: formattedOutput, stats: {} };
56
+ };
57
+
58
+ module.exports = generateContentTypesDefinitions;
@@ -1,7 +1,122 @@
1
1
  'use strict';
2
2
 
3
- const generateSchemasDefinitions = require('./schemas');
3
+ const path = require('path');
4
+ const chalk = require('chalk');
4
5
 
5
- module.exports = {
6
- generateSchemasDefinitions,
6
+ const { TYPES_ROOT_DIR, GENERATED_OUT_DIR } = require('./constants');
7
+ const { saveDefinitionToFileSystem, createLogger, timer } = require('./utils');
8
+ const generateContentTypesDefinitions = require('./content-types');
9
+ const generateComponentsDefinitions = require('./components');
10
+
11
+ const GENERATORS = {
12
+ contentTypes: generateContentTypesDefinitions,
13
+ components: generateComponentsDefinitions,
7
14
  };
15
+
16
+ /**
17
+ * @typedef GenerateConfig
18
+ *
19
+ * @property {object} strapi
20
+ * @property {boolean} pwd
21
+ * @property {object} [artifacts]
22
+ * @property {boolean} [artifacts.contentTypes]
23
+ * @property {boolean} [artifacts.components]
24
+ * @property {boolean} [artifacts.services]
25
+ * @property {boolean} [artifacts.controllers]
26
+ * @property {boolean} [artifacts.policies]
27
+ * @property {boolean} [artifacts.middlewares]
28
+ * @property {object} [logger]
29
+ * @property {boolean} [logger.silent]
30
+ * @property {boolean} [logger.debug]
31
+ * @property {boolean} [logger.verbose]
32
+ */
33
+
34
+ /**
35
+ * Generate types definitions based on the given configuration
36
+ *
37
+ * @param {GenerateConfig} [config]
38
+ */
39
+ const generate = async (config = {}) => {
40
+ const { pwd, rootDir = TYPES_ROOT_DIR, strapi, artifacts = {}, logger: loggerConfig } = config;
41
+ const reports = {};
42
+ const logger = createLogger(loggerConfig);
43
+ const psTimer = timer().start();
44
+
45
+ const registryPwd = path.join(pwd, rootDir, GENERATED_OUT_DIR);
46
+ const generatorConfig = { strapi, pwd: registryPwd, logger };
47
+
48
+ const returnWithMessage = () => {
49
+ const nbWarnings = chalk.yellow(`${logger.warnings} warning(s)`);
50
+ const nbErrors = chalk.red(`${logger.errors} error(s)`);
51
+
52
+ const status = logger.errors > 0 ? chalk.red('errored') : chalk.green('completed successfully');
53
+
54
+ psTimer.end();
55
+
56
+ logger.info(`The task ${status} with ${nbWarnings} and ${nbErrors} in ${psTimer.duration}s.`);
57
+
58
+ return reports;
59
+ };
60
+
61
+ const enabledArtifacts = Object.keys(artifacts).filter((p) => artifacts[p] === true);
62
+
63
+ logger.info('Starting the type generation process');
64
+ logger.debug(`Enabled artifacts: ${enabledArtifacts.join(', ')}`);
65
+
66
+ for (const artifact of enabledArtifacts) {
67
+ const boldArtifact = chalk.bold(artifact); // used for log messages
68
+
69
+ logger.info(`Generating types for ${boldArtifact}`);
70
+
71
+ if (artifact in GENERATORS) {
72
+ const generator = GENERATORS[artifact];
73
+
74
+ try {
75
+ const artifactGenTimer = timer().start();
76
+
77
+ reports[artifact] = await generator(generatorConfig);
78
+
79
+ artifactGenTimer.end();
80
+
81
+ logger.debug(`Generated ${boldArtifact} in ${artifactGenTimer.duration}s`);
82
+ } catch (e) {
83
+ logger.error(
84
+ `Failed to generate types for ${boldArtifact}: ${e.message ?? e.toString()}. Exiting`
85
+ );
86
+ return returnWithMessage();
87
+ }
88
+ } else {
89
+ logger.warn(`The types generator for ${boldArtifact} is not implemented, skipping`);
90
+ }
91
+ }
92
+
93
+ for (const artifact of Object.keys(reports)) {
94
+ const boldArtifact = chalk.bold(artifact); // used for log messages
95
+
96
+ const artifactFsTimer = timer().start();
97
+
98
+ const report = reports[artifact];
99
+ const filename = `${artifact}.d.ts`;
100
+
101
+ try {
102
+ const outPath = await saveDefinitionToFileSystem(registryPwd, filename, report.output);
103
+ const relativeOutPath = path.relative(__dirname, outPath);
104
+
105
+ artifactFsTimer.end();
106
+
107
+ logger.info(`Saved ${boldArtifact} types in ${chalk.bold(relativeOutPath)}`);
108
+ logger.debug(`Saved ${boldArtifact} in ${artifactFsTimer.duration}s`);
109
+ } catch (e) {
110
+ logger.error(
111
+ `An error occurred while saving ${boldArtifact} types to the filesystem: ${
112
+ e.message ?? e.toString()
113
+ }. Exiting`
114
+ );
115
+ return returnWithMessage();
116
+ }
117
+ }
118
+
119
+ return returnWithMessage();
120
+ };
121
+
122
+ module.exports = { generate };