@platformatic/generators 1.13.0 → 1.13.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.
@@ -1,9 +1,9 @@
1
1
  import { BaseLogger } from 'pino'
2
2
  import { FileGenerator } from './file-generator'
3
-
3
+ import { PackageConfiguration } from './utils'
4
4
  export namespace BaseGenerator {
5
5
  export type BaseGeneratorOptions = FileGenerator.FileGeneratorOptions & {
6
- type?: 'service' | 'db' | 'composer'
6
+ module: string
7
7
  inquirer?: object
8
8
  }
9
9
 
@@ -24,6 +24,11 @@ export namespace BaseGenerator {
24
24
  type Dependency = {
25
25
  [key: string]: string
26
26
  }
27
+
28
+ type PackageDefinition = {
29
+ name: string,
30
+ options: PackageConfiguration
31
+ }
27
32
  type BaseGeneratorConfig = Record<string, any> & {
28
33
  port?: number
29
34
  hostname?: string
@@ -37,7 +42,7 @@ export namespace BaseGenerator {
37
42
  env?: KeyValue,
38
43
  isRuntimeContext?: boolean,
39
44
  serviceName?: string,
40
- envPrefix?: string
45
+ envPrefix?: string
41
46
  }
42
47
 
43
48
  type WhereClause = {
@@ -71,6 +76,7 @@ export namespace BaseGenerator {
71
76
  config: BaseGeneratorConfig
72
77
  questions: Array<object>
73
78
 
79
+ packages: PackageConfiguration[]
74
80
  constructor(opts?: BaseGeneratorOptions)
75
81
 
76
82
  setConfig(config?: BaseGeneratorConfig): void
@@ -82,6 +88,8 @@ export namespace BaseGenerator {
82
88
  getFastifyVersion(): Promise<string>
83
89
  getPlatformaticVersion(): Promise<string>
84
90
 
91
+ addPackage(pkg: PackageDefinition): void
92
+
85
93
  prepare(): Promise<GeneratorMetadata>
86
94
  run(): Promise<GeneratorMetadata>
87
95
  addQuestion(question: any, where?: WhereClause): Promise<void>
@@ -101,5 +109,7 @@ export namespace BaseGenerator {
101
109
  _getConfigFileContents(): Promise<JSONValue>
102
110
  _generateEnv(): Promise<void>
103
111
  appendConfigEnv(): Promise<void>
112
+
113
+ postInstallActions(): Promise<void>
104
114
  }
105
- }
115
+ }
@@ -5,8 +5,8 @@ const { stripVersion, convertServiceNameToPrefix, addPrefixToEnv, extractEnvVari
5
5
  const { join } = require('node:path')
6
6
  const { FileGenerator } = require('./file-generator')
7
7
  const { generateTests, generatePlugins } = require('./create-plugin')
8
+ const { PrepareError, MissingEnvVariable, ModuleNeeded } = require('./errors')
8
9
  const { generateGitignore } = require('./create-gitignore')
9
- const { NoQuestionsError, PrepareError, MissingEnvVariable } = require('./errors')
10
10
  const generateName = require('boring-name-generator')
11
11
  /* c8 ignore start */
12
12
  const fakeLogger = {
@@ -21,14 +21,18 @@ const fakeLogger = {
21
21
  class BaseGenerator extends FileGenerator {
22
22
  constructor (opts = {}) {
23
23
  super(opts)
24
- this.type = opts.type
25
24
  this.files = []
26
25
  this.logger = opts.logger || fakeLogger
27
26
  this.questions = []
28
27
  this.pkgData = null
29
- this.inquirer = null
28
+ this.inquirer = opts.inquirer || null
30
29
  this.targetDirectory = opts.targetDirectory || null
31
30
  this.config = this.getDefaultConfig()
31
+ this.packages = []
32
+ this.module = opts.module
33
+ if (!this.module) {
34
+ throw ModuleNeeded()
35
+ }
32
36
  }
33
37
 
34
38
  getDefaultConfig () {
@@ -114,11 +118,13 @@ class BaseGenerator extends FileGenerator {
114
118
 
115
119
  /* c8 ignore start */
116
120
  async ask () {
117
- if (!this.questions.length) {
118
- throw new NoQuestionsError()
119
- }
120
121
  if (this.inquirer) {
121
- this.config = await this.inquirer.prompt(this.questions)
122
+ await this.prepareQuestions()
123
+ const newConfig = await this.inquirer.prompt(this.questions)
124
+ this.setConfig({
125
+ ...this.config,
126
+ ...newConfig
127
+ })
122
128
  }
123
129
  }
124
130
 
@@ -153,8 +159,6 @@ class BaseGenerator extends FileGenerator {
153
159
 
154
160
  await this.generateConfigFile()
155
161
 
156
- await this.prepareQuestions()
157
-
158
162
  await this.generateEnv()
159
163
 
160
164
  if (this.config.typescript) {
@@ -171,12 +175,16 @@ class BaseGenerator extends FileGenerator {
171
175
  this.files.push(...generatePlugins(this.config.typescript))
172
176
  if (this.config.tests) {
173
177
  // create tests
174
- this.files.push(...generateTests(this.config.typescript, this.type))
178
+ this.files.push(...generateTests(this.config.typescript, this.module))
175
179
  }
176
180
  }
181
+
177
182
  this.files.push(generateGitignore())
183
+
178
184
  await this._afterPrepare()
185
+
179
186
  this.checkEnvVariablesInConfigFile()
187
+
180
188
  return {
181
189
  targetDirectory: this.targetDirectory,
182
190
  env: this.config.env
@@ -186,12 +194,14 @@ class BaseGenerator extends FileGenerator {
186
194
  // throw the same error
187
195
  throw err
188
196
  }
189
- throw new PrepareError(err.message)
197
+ const _err = new PrepareError(err.message)
198
+ _err.cause = err
199
+ throw _err
190
200
  }
191
201
  }
192
202
 
193
203
  checkEnvVariablesInConfigFile () {
194
- const configFileName = this.getConfigFileName()
204
+ const configFileName = 'platformatic.json'
195
205
  const fileOjbect = this.getFileObject(configFileName)
196
206
  const envVars = extractEnvVariablesFromText(fileOjbect.contents)
197
207
  const envKeys = Object.keys(this.config.env)
@@ -230,113 +240,36 @@ class BaseGenerator extends FileGenerator {
230
240
  }
231
241
 
232
242
  async prepareQuestions () {
233
- // directory
234
- this.questions.push({
235
- type: 'input',
236
- name: 'targetDirectory',
237
- message: 'Where would you like to create your project?'
238
- })
239
-
240
- // typescript
241
- this.questions.push({
242
- type: 'list',
243
- name: 'typescript',
244
- message: 'Do you want to use TypeScript?',
245
- default: false,
246
- choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
247
- })
248
-
249
- // init git repository
250
- this.questions.push({
251
- type: 'list',
252
- name: 'initGitRepository',
253
- message: 'Do you want to init the git repository?',
254
- default: false,
255
- choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
256
- })
257
-
258
- // port
259
- this.questions.push({
260
- type: 'input',
261
- name: 'port',
262
- message: 'What port do you want to use?'
263
- })
264
-
265
- // github actions
266
- this.questions.push({
267
- type: 'list',
268
- name: 'staticWorkspaceGitHubAction',
269
- message: 'Do you want to create the github action to deploy this application to Platformatic Cloud?',
270
- default: true,
271
- choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
272
- },
273
- {
274
- type: 'list',
275
- name: 'dynamicWorkspaceGitHubAction',
276
- message: 'Do you want to enable PR Previews in your application?',
277
- default: true,
278
- choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
279
- })
280
- }
281
-
282
- async addQuestion (question, where) {
283
- if (where) {
284
- if (where.before) {
285
- const position = this.questions.reduce((acc, element, idx) => {
286
- if (acc === null) {
287
- if (element.name === where.before) {
288
- acc = idx
289
- }
290
- }
291
- return acc
292
- }, null)
293
-
294
- if (position) {
295
- this.questions.splice(position, 0, question)
296
- }
297
- } else if (where.after) {
298
- const position = this.questions.reduce((acc, element, idx) => {
299
- if (acc === null) {
300
- if (element.name === where.after) {
301
- acc = idx + 1
302
- }
303
- }
304
- return acc
305
- }, null)
306
-
307
- if (position) {
308
- this.questions.splice(position, 0, question)
309
- }
243
+ if (!this.config.isRuntimeContext) {
244
+ if (!this.config.targetDirectory) {
245
+ // directory
246
+ this.questions.push({
247
+ type: 'input',
248
+ name: 'targetDirectory',
249
+ message: 'Where would you like to create your project?'
250
+ })
310
251
  }
311
- } else {
312
- this.questions.push(question)
313
- }
314
- }
315
252
 
316
- removeQuestion (variableName) {
317
- const position = this.questions.reduce((acc, element, idx) => {
318
- if (acc === null) {
319
- if (element.name === variableName) {
320
- acc = idx
321
- }
322
- }
323
- return acc
324
- }, null)
325
- if (position) {
326
- this.questions.splice(position, 1)
327
- }
328
- }
253
+ // typescript
254
+ this.questions.push({
255
+ type: 'list',
256
+ name: 'typescript',
257
+ message: 'Do you want to use TypeScript?',
258
+ default: false,
259
+ choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
260
+ })
329
261
 
330
- getConfigFileName () {
331
- if (!this.type) {
332
- return 'platformatic.json'
333
- } else {
334
- return `platformatic.${this.type}.json`
262
+ // port
263
+ this.questions.push({
264
+ type: 'input',
265
+ name: 'port',
266
+ message: 'What port do you want to use?'
267
+ })
335
268
  }
336
269
  }
337
270
 
338
271
  async generateConfigFile () {
339
- const configFileName = this.getConfigFileName()
272
+ const configFileName = 'platformatic.json'
340
273
  const contents = await this._getConfigFileContents()
341
274
  this.addFile({
342
275
  path: '',
@@ -406,6 +339,13 @@ class BaseGenerator extends FileGenerator {
406
339
  })
407
340
  await this._generateEnv()
408
341
  this.appendConfigEnv()
342
+
343
+ const { contents } = this.getFileObject('.env')
344
+ this.addFile({
345
+ path: '',
346
+ file: '.env.sample',
347
+ contents
348
+ })
409
349
  }
410
350
  }
411
351
 
@@ -415,7 +355,13 @@ class BaseGenerator extends FileGenerator {
415
355
  return metadata
416
356
  }
417
357
 
358
+ addPackage (pkg) {
359
+ this.packages.push(pkg)
360
+ }
361
+
418
362
  // implement in the subclass
363
+ /* c8 ignore next 1 */
364
+ async postInstallActions () {}
419
365
  async _beforePrepare () {}
420
366
  async _afterPrepare () {}
421
367
  async _getConfigFileContents () { return {} }
@@ -115,7 +115,7 @@ function testHelperTS (mod, customizations = { pre: '', post: '', config: '', re
115
115
  return `\
116
116
  import { join } from 'node:path'
117
117
  import { readFile } from 'node:fs/promises'
118
- import { buildServer } from '@platformatic/${mod}'
118
+ import { buildServer } from '${mod}'
119
119
  import { test } from 'node:test'
120
120
  ${customizations.requires}
121
121
 
@@ -125,7 +125,7 @@ type TestContext = Parameters<Exclude<testfn, undefined>>[0]
125
125
  export async function getServer (t: TestContext) {
126
126
  ${customizations.pre}
127
127
  // We go up two folder because this files executes in the dist folder
128
- const config = JSON.parse(await readFile(join(__dirname, '..', '..', 'platformatic.${mod}.json'), 'utf8'))
128
+ const config = JSON.parse(await readFile(join(__dirname, '..', '..', 'platformatic'), 'utf8'))
129
129
  // Add your config customizations here. For example you want to set
130
130
  // all things that are set in the config file to read from an env variable
131
131
  config.server.logger.level = 'warn'
@@ -199,13 +199,13 @@ function generateRouteWithTypesSupport (typescript) {
199
199
  }
200
200
  }
201
201
 
202
- function generateTests (typescript, type, customizations) {
202
+ function generateTests (typescript, mod, customizations) {
203
203
  const output = []
204
204
  if (typescript) {
205
205
  output.push({
206
206
  path: 'test',
207
207
  file: 'helper.ts',
208
- contents: testHelperTS(type, customizations)
208
+ contents: testHelperTS(mod, customizations)
209
209
  })
210
210
  output.push({
211
211
  path: join('test', 'plugins'),
@@ -221,7 +221,7 @@ function generateTests (typescript, type, customizations) {
221
221
  output.push({
222
222
  path: 'test',
223
223
  file: 'helper.js',
224
- contents: testHelperJS(type, customizations)
224
+ contents: testHelperJS(mod, customizations)
225
225
  })
226
226
  output.push({
227
227
  path: join('test', 'plugins'),
package/lib/errors.js CHANGED
@@ -5,7 +5,8 @@ const createError = require('@fastify/error')
5
5
  const ERROR_PREFIX = 'PLT_GEN'
6
6
 
7
7
  module.exports = {
8
- NoQuestionsError: createError(`${ERROR_PREFIX}_NO_QUESTIONS_ERROR`, 'No questions added.'),
8
+ ModuleNeeded: createError(`${ERROR_PREFIX}_PREPARE_ERROR`, 'The module which the package will be published to must be specified'),
9
9
  PrepareError: createError(`${ERROR_PREFIX}_PREPARE_ERROR`, 'Error while generating the files: %s.'),
10
- MissingEnvVariable: createError(`${ERROR_PREFIX}_MISSING_ENV_VAR`, 'Env variable %s is defined in config file %s, but not in config.env object.')
10
+ MissingEnvVariable: createError(`${ERROR_PREFIX}_MISSING_ENV_VAR`, 'Env variable %s is defined in config file %s, but not in config.env object.'),
11
+ WrongTypeError: createError(`${ERROR_PREFIX}_WRONG_TYPE`, 'Invalid value type. Accepted values are \'string\', \'number\' and \'boolean\', found \'%s\'.')
11
12
  }
package/lib/utils.d.ts CHANGED
@@ -2,6 +2,12 @@ type Env = {
2
2
  [key: string]: string
3
3
  }
4
4
 
5
+ export type PackageConfiguration = {
6
+ type: 'number' | 'string' | 'boolean'
7
+ path: string
8
+ value: number | string | boolean
9
+ }
10
+
5
11
  export namespace GeneratorUtils {
6
12
  export function safeMkdir(dir: string): Promise<void>
7
13
  export function stripVersion(version: string): string
@@ -9,4 +15,5 @@ export namespace GeneratorUtils {
9
15
  export function addPrefixToEnv(env: Env, prefix: string): Env
10
16
  export function envObjectToString(env: Env): string
11
17
  export function extractEnvVariablesFromText(text: string): string[]
18
+ export function getPackageConfigurationObject(config: PackageConfiguration[]): object
12
19
  }
package/lib/utils.js CHANGED
@@ -1,6 +1,7 @@
1
1
  'use strict'
2
2
 
3
3
  const { mkdir } = require('node:fs/promises')
4
+ const { WrongTypeError } = require('./errors')
4
5
 
5
6
  async function safeMkdir (dir) {
6
7
  try {
@@ -58,10 +59,41 @@ function extractEnvVariablesFromText (text) {
58
59
  }
59
60
  return []
60
61
  }
61
-
62
+ function getPackageConfigurationObject (config) {
63
+ const output = {}
64
+ let current = output
65
+ for (const param of config) {
66
+ const props = param.path.split('.')
67
+ props.forEach((prop, idx) => {
68
+ if (idx === props.length - 1) {
69
+ switch (param.type) {
70
+ case 'string' :
71
+ current[prop] = param.value.toString()
72
+ break
73
+ case 'number':
74
+ current[prop] = parseInt(param.value)
75
+ break
76
+ case 'boolean':
77
+ current[prop] = (param.value === 'true')
78
+ break
79
+ default:
80
+ throw new WrongTypeError(param.type)
81
+ }
82
+ current = output
83
+ } else {
84
+ if (!current[prop]) {
85
+ current[prop] = {}
86
+ }
87
+ current = current[prop]
88
+ }
89
+ })
90
+ }
91
+ return output
92
+ }
62
93
  module.exports = {
63
94
  addPrefixToEnv,
64
95
  convertServiceNameToPrefix,
96
+ getPackageConfigurationObject,
65
97
  envObjectToString,
66
98
  extractEnvVariablesFromText,
67
99
  safeMkdir,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@platformatic/generators",
3
- "version": "1.13.0",
3
+ "version": "1.13.2",
4
4
  "description": "Main classes and utils for generators.",
5
5
  "main": "index.js",
6
6
  "keywords": [],
@@ -20,7 +20,8 @@ afterEach(async () => {
20
20
  test('should write file and dirs', async (t) => {
21
21
  const dir = await getTempDir()
22
22
  const gen = new BaseGenerator({
23
- logger: fakeLogger
23
+ logger: fakeLogger,
24
+ module: '@platformatic/service'
24
25
  })
25
26
 
26
27
  gen.setConfig({
@@ -43,6 +44,13 @@ test('should write file and dirs', async (t) => {
43
44
 
44
45
  test('extended class should generate config', async (t) => {
45
46
  class ServiceClass extends BaseGenerator {
47
+ constructor (opts) {
48
+ super({
49
+ ...opts,
50
+ module: '@platformatic/service'
51
+ })
52
+ }
53
+
46
54
  async _getConfigFileContents () {
47
55
  // Implement when extending this class
48
56
  return {
@@ -52,7 +60,6 @@ test('extended class should generate config', async (t) => {
52
60
  }
53
61
 
54
62
  const svc = new ServiceClass({
55
- type: 'service',
56
63
  logger: fakeLogger
57
64
  })
58
65
 
@@ -61,14 +68,14 @@ test('extended class should generate config', async (t) => {
61
68
  const configFile = svc.files[1]
62
69
  assert.deepEqual(configFile, {
63
70
  path: '',
64
- file: 'platformatic.service.json',
71
+ file: 'platformatic.json',
65
72
  contents: JSON.stringify({ foo: 'bar' }, null, 2)
66
73
  })
67
74
  })
68
75
 
69
76
  test('setConfig', async (t) => {
70
77
  const bg = new BaseGenerator({
71
- type: 'service'
78
+ module: '@platformatic/service'
72
79
  })
73
80
 
74
81
  // should init the default config
@@ -140,7 +147,7 @@ test('setConfig', async (t) => {
140
147
 
141
148
  test('should append env values', async (t) => {
142
149
  const bg = new BaseGenerator({
143
- type: 'service'
150
+ module: '@platformatic/service'
144
151
  })
145
152
  // partial config with defaults
146
153
  bg.setConfig({
@@ -152,11 +159,85 @@ test('should append env values', async (t) => {
152
159
  await bg.prepare()
153
160
  const dotEnvFile = bg.getFileObject('.env')
154
161
  assert.equal(dotEnvFile.contents, 'FOO=bar\n')
162
+
163
+ const dotEnvSampleFile = bg.getFileObject('.env.sample')
164
+ assert.equal(dotEnvSampleFile.contents, 'FOO=bar\n')
165
+ })
166
+
167
+ test('should prepare the questions', async (t) => {
168
+ const bg = new BaseGenerator({
169
+ module: '@platformatic/service'
170
+ })
171
+ // partial config with defaults
172
+ bg.setConfig({
173
+ env: {
174
+ FOO: 'bar'
175
+ }
176
+ })
177
+
178
+ await bg.prepareQuestions()
179
+ assert.deepStrictEqual(bg.questions, [{
180
+ type: 'input',
181
+ name: 'targetDirectory',
182
+ message: 'Where would you like to create your project?'
183
+ }, {
184
+ type: 'list',
185
+ name: 'typescript',
186
+ message: 'Do you want to use TypeScript?',
187
+ default: false,
188
+ choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
189
+ }, {
190
+ type: 'input',
191
+ name: 'port',
192
+ message: 'What port do you want to use?'
193
+ }])
194
+ })
195
+
196
+ test('should prepare the questions with a targetDirectory', async (t) => {
197
+ const bg = new BaseGenerator({
198
+ module: '@platformatic/service'
199
+ })
200
+ // partial config with defaults
201
+ bg.setConfig({
202
+ targetDirectory: './foo',
203
+ env: {
204
+ FOO: 'bar'
205
+ }
206
+ })
207
+
208
+ await bg.prepareQuestions()
209
+ assert.deepStrictEqual(bg.questions, [{
210
+ type: 'list',
211
+ name: 'typescript',
212
+ message: 'Do you want to use TypeScript?',
213
+ default: false,
214
+ choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
215
+ }, {
216
+ type: 'input',
217
+ name: 'port',
218
+ message: 'What port do you want to use?'
219
+ }])
220
+ })
221
+
222
+ test('should prepare the questions in runtime context', async (t) => {
223
+ const bg = new BaseGenerator({
224
+ module: '@platformatic/service'
225
+ })
226
+ // partial config with defaults
227
+ bg.setConfig({
228
+ isRuntimeContext: true,
229
+ env: {
230
+ FOO: 'bar'
231
+ }
232
+ })
233
+
234
+ await bg.prepareQuestions()
235
+ assert.deepStrictEqual(bg.questions, [])
155
236
  })
156
237
 
157
238
  test('should return service metadata', async (t) => {
158
239
  const bg = new BaseGenerator({
159
- type: 'service'
240
+ module: '@platformatic/service'
160
241
  })
161
242
  // partial config with defaults
162
243
  bg.setConfig({
@@ -177,7 +258,7 @@ test('should return service metadata', async (t) => {
177
258
 
178
259
  test('should generate javascript plugin, routes and tests', async (t) => {
179
260
  const bg = new BaseGenerator({
180
- type: 'service'
261
+ module: '@platformatic/service'
181
262
  })
182
263
  bg.setConfig({
183
264
  plugin: true,
@@ -193,7 +274,7 @@ test('should generate javascript plugin, routes and tests', async (t) => {
193
274
 
194
275
  test('should generate tsConfig file and typescript files', async (t) => {
195
276
  const bg = new BaseGenerator({
196
- type: 'service'
277
+ module: '@platformatic/service'
197
278
  })
198
279
  bg.setConfig({
199
280
  typescript: true,
@@ -231,98 +312,10 @@ test('should generate tsConfig file and typescript files', async (t) => {
231
312
  assert.ok(bg.getFileObject('example.test.ts', 'test/plugins'))
232
313
  })
233
314
 
234
- test('should generate platformatic.json file if no type is generated', async (t) => {
235
- const bg = new BaseGenerator()
236
- await bg.prepare()
237
- const configFileObject = bg.getFileObject('platformatic.json')
238
- assert.ok(configFileObject)
239
- })
240
-
241
- test('should add questions in the correct position (before)', async (t) => {
242
- const question = {
243
- type: 'input',
244
- name: 'serviceName',
245
- message: 'What is the name of the service?'
246
- }
247
-
248
- const bg = new BaseGenerator({
249
- type: 'service'
250
- })
251
-
252
- await bg.prepare()
253
- const originalQuestionsLength = bg.questions.length
254
- bg.addQuestion(question, { before: 'typescript' }) // should add as second question
255
-
256
- assert.equal(bg.questions.length, originalQuestionsLength + 1)
257
- assert.deepEqual(bg.questions[1], {
258
- type: 'input',
259
- name: 'serviceName',
260
- message: 'What is the name of the service?'
261
- })
262
- })
263
-
264
- test('should add questions in the correct position (after)', async (t) => {
265
- const question = {
266
- type: 'input',
267
- name: 'serviceName',
268
- message: 'What is the name of the service?'
269
- }
270
-
271
- const bg = new BaseGenerator({
272
- type: 'service'
273
- })
274
-
275
- await bg.prepare()
276
- const originalQuestionsLength = bg.questions.length
277
- bg.addQuestion(question, { after: 'typescript' }) // should add as third question
278
-
279
- assert.equal(bg.questions.length, originalQuestionsLength + 1)
280
- assert.deepEqual(bg.questions[2], {
281
- type: 'input',
282
- name: 'serviceName',
283
- message: 'What is the name of the service?'
284
- })
285
- })
286
-
287
- test('should add questions at the end', async (t) => {
288
- const question = {
289
- type: 'input',
290
- name: 'serviceName',
291
- message: 'What is the name of the service?'
292
- }
293
-
315
+ test('should throw if preapare fails', async (t) => {
294
316
  const bg = new BaseGenerator({
295
- type: 'service'
296
- })
297
-
298
- await bg.prepare()
299
- const originalQuestionsLength = bg.questions.length
300
- bg.addQuestion(question)
301
-
302
- assert.equal(bg.questions.length, originalQuestionsLength + 1)
303
- assert.deepEqual(bg.questions[originalQuestionsLength], {
304
- type: 'input',
305
- name: 'serviceName',
306
- message: 'What is the name of the service?'
317
+ module: '@platformatic/service'
307
318
  })
308
- })
309
-
310
- test('should remove question', async (t) => {
311
- const bg = new BaseGenerator()
312
-
313
- await bg.prepare()
314
-
315
- bg.removeQuestion('typescript')
316
-
317
- bg.questions.forEach((question) => {
318
- if (question.name === 'typescript') {
319
- assert.fail()
320
- }
321
- })
322
- })
323
-
324
- test('should throw if preapare fails', async (t) => {
325
- const bg = new BaseGenerator()
326
319
 
327
320
  bg._beforePrepare = async () => {
328
321
  throw new Error('beforePrepare error')
@@ -337,7 +330,9 @@ test('should throw if preapare fails', async (t) => {
337
330
  })
338
331
 
339
332
  test('should throw if there is a missing env variable', async () => {
340
- const bg = new BaseGenerator()
333
+ const bg = new BaseGenerator({
334
+ module: '@platformatic/service'
335
+ })
341
336
 
342
337
  bg._getConfigFileContents = async () => {
343
338
  return {
@@ -361,9 +356,32 @@ test('should throw if there is a missing env variable', async () => {
361
356
  }
362
357
  })
363
358
 
359
+ test('should add package', async () => {
360
+ const bg = new BaseGenerator({
361
+ module: '@platformatic/service'
362
+ })
363
+
364
+ const packageDefinition = {
365
+ name: '@my/package',
366
+ options: [
367
+ {
368
+ path: 'foobar',
369
+ type: 'string',
370
+ value: 'foobar'
371
+ }
372
+ ]
373
+ }
374
+ bg.addPackage(packageDefinition)
375
+
376
+ assert.equal(bg.packages.length, 1)
377
+ assert.deepEqual(bg.packages[0], packageDefinition)
378
+ })
379
+
364
380
  describe('runtime context', () => {
365
381
  test('should set config.envPrefix correctly', async (t) => {
366
- const bg = new BaseGenerator()
382
+ const bg = new BaseGenerator({
383
+ module: '@platformatic/service'
384
+ })
367
385
 
368
386
  bg.setConfig({
369
387
  isRuntimeContext: true,
@@ -390,7 +408,9 @@ describe('runtime context', () => {
390
408
  })
391
409
 
392
410
  test('should generate correct env file from config.env', async (t) => {
393
- const bg = new BaseGenerator()
411
+ const bg = new BaseGenerator({
412
+ module: '@platformatic/service'
413
+ })
394
414
 
395
415
  bg.setConfig({
396
416
  isRuntimeContext: true,
@@ -412,7 +432,7 @@ describe('runtime context', () => {
412
432
 
413
433
  test('should return service metadata', async (t) => {
414
434
  const bg = new BaseGenerator({
415
- type: 'service'
435
+ module: '@platformatic/service'
416
436
  })
417
437
  // partial config with defaults
418
438
  bg.setConfig({
@@ -435,7 +455,7 @@ describe('runtime context', () => {
435
455
 
436
456
  test('should generate service name if not provided', async () => {
437
457
  const bg = new BaseGenerator({
438
- type: 'service'
458
+ module: '@platformatic/service'
439
459
  })
440
460
  bg.setConfig({
441
461
  targetDirectory: '/foo/bar',
@@ -2,8 +2,7 @@
2
2
 
3
3
  const { test, describe } = require('node:test')
4
4
  const assert = require('node:assert')
5
- const { stripVersion, convertServiceNameToPrefix, addPrefixToEnv, envObjectToString } = require('../lib/utils')
6
- const { extractEnvVariablesFromText } = require('../lib/utils')
5
+ const { stripVersion, convertServiceNameToPrefix, addPrefixToEnv, envObjectToString, extractEnvVariablesFromText, getPackageConfigurationObject } = require('../lib/utils')
7
6
 
8
7
  describe('utils', () => {
9
8
  describe('stripVersion', async () => {
@@ -86,4 +85,67 @@ describe('utils', () => {
86
85
  assert.deepEqual(env, [])
87
86
  })
88
87
  })
88
+
89
+ describe('getPackageConfigurationObject', async () => {
90
+ const input = [
91
+ {
92
+ path: 'prefix',
93
+ value: '/foo',
94
+ type: 'string'
95
+ },
96
+ {
97
+ path: 'foo.fooOption1',
98
+ value: 'value1',
99
+ type: 'string'
100
+ },
101
+ {
102
+ path: 'foo.fooOption2',
103
+ value: 'value2',
104
+ type: 'string'
105
+ },
106
+ {
107
+ path: 'foobar',
108
+ value: '123',
109
+ type: 'number'
110
+ },
111
+ {
112
+ path: 'boolean.truthy',
113
+ value: 'true',
114
+ type: 'boolean'
115
+ },
116
+ {
117
+ path: 'boolean.falsey',
118
+ value: 'false',
119
+ type: 'boolean'
120
+ }
121
+ ]
122
+ const config = getPackageConfigurationObject(input)
123
+ assert.deepEqual(config, {
124
+ prefix: '/foo',
125
+ foo: {
126
+ fooOption1: 'value1',
127
+ fooOption2: 'value2'
128
+ },
129
+ foobar: 123,
130
+ boolean: {
131
+ truthy: true,
132
+ falsey: false
133
+ }
134
+ })
135
+
136
+ // should throw
137
+ try {
138
+ getPackageConfigurationObject([
139
+ {
140
+ path: 'wrong',
141
+ type: 'object',
142
+ value: {}
143
+ }
144
+ ])
145
+ assert.fail()
146
+ } catch (err) {
147
+ assert.equal(err.code, 'PLT_GEN_WRONG_TYPE')
148
+ assert.equal(err.message, 'Invalid value type. Accepted values are \'string\', \'number\' and \'boolean\', found \'object\'.')
149
+ }
150
+ })
89
151
  })