@platformatic/generators 2.0.0-alpha.8 → 2.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.
@@ -1,397 +0,0 @@
1
- 'use strict'
2
-
3
- const { kebabCase } = require('change-case-all')
4
-
5
- function getJsStackableIndexTestFile (stackableName) {
6
- const configType = kebabCase(stackableName + '-app')
7
-
8
- return `\
9
- 'use strict'
10
-
11
- const test = require('node:test')
12
- const assert = require('node:assert')
13
- const stackable = require('../index')
14
- const { schema } = require('../lib/schema')
15
- const { Generator } = require('../lib/generator')
16
-
17
- test('should export stackable interface', async () => {
18
- assert.strictEqual(typeof stackable, 'function')
19
- assert.strictEqual(stackable.configType, '${configType}')
20
- assert.deepStrictEqual(stackable.schema, schema)
21
- assert.deepStrictEqual(stackable.Generator, Generator)
22
- assert.ok(stackable.configManagerConfig)
23
- assert.ok(typeof stackable.transformConfig, 'function')
24
- })
25
- `
26
- }
27
-
28
- function getTsStackableIndexTestFile (stackableName) {
29
- const configType = kebabCase(stackableName + '-app')
30
-
31
- return `\
32
- import test from 'node:test'
33
- import assert from 'node:assert'
34
- import stackable from '../index'
35
- import { schema } from '../lib/schema'
36
- import { Generator } from '../lib/generator'
37
-
38
- test('should export stackable interface', async () => {
39
- assert.strictEqual(typeof stackable, 'function')
40
- assert.strictEqual(stackable.configType, '${configType}')
41
- assert.deepStrictEqual(stackable.schema, schema)
42
- assert.deepStrictEqual(stackable.Generator, Generator)
43
- assert.ok(stackable.configManagerConfig)
44
- assert.ok(typeof stackable.transformConfig, 'function')
45
- })
46
- `
47
- }
48
-
49
- function getJsStackableSchemaTestFile (stackableName) {
50
- const schemaId = kebabCase(stackableName)
51
-
52
- return `\
53
- 'use strict'
54
-
55
- const test = require('node:test')
56
- const assert = require('node:assert')
57
- const { schema } = require('../index')
58
-
59
- test('should export stackable schema', async () => {
60
- assert.strictEqual(schema.$id, '${schemaId}')
61
- assert.strictEqual(typeof schema.version, 'string')
62
-
63
- assert.deepStrictEqual(schema.properties.greeting, {
64
- type: 'object',
65
- properties: {
66
- text: {
67
- type: 'string'
68
- }
69
- },
70
- required: ['text'],
71
- additionalProperties: false
72
- })
73
- })
74
- `
75
- }
76
-
77
- function getTsStackableSchemaTestFile (stackableName) {
78
- const schemaId = kebabCase(stackableName)
79
-
80
- return `\
81
- import test from 'node:test'
82
- import assert from 'node:assert'
83
- import { schema } from '../index'
84
-
85
- test('should export stackable schema', async () => {
86
- assert.strictEqual(schema.$id, '${schemaId}')
87
- assert.strictEqual(typeof schema.version, 'string')
88
-
89
- assert.deepStrictEqual(schema.properties.greeting, {
90
- type: 'object',
91
- properties: {
92
- text: {
93
- type: 'string'
94
- }
95
- },
96
- required: ['text'],
97
- additionalProperties: false
98
- })
99
- })
100
- `
101
- }
102
-
103
- function getJsStackableGeneratorTestFile () {
104
- return `\
105
- 'use strict'
106
-
107
- const test = require('node:test')
108
- const assert = require('node:assert')
109
- const { tmpdir } = require('node:os')
110
- const { join } = require('node:path')
111
- const { readFile, readdir, mkdtemp } = require('node:fs/promises')
112
- const { safeRemove } = require('@platformatic/utils')
113
- const { Generator } = require('../index')
114
- const stackablePackageJson = require('../package.json')
115
-
116
- test('should return a default Generator config', async () => {
117
- const generator = new Generator()
118
- const defaultConfig = generator.getDefaultConfig()
119
-
120
- assert.strictEqual(defaultConfig.hostname, '0.0.0.0')
121
- assert.strictEqual(defaultConfig.port, 3042)
122
- assert.strictEqual(defaultConfig.greeting, 'Hello world!')
123
- assert.deepStrictEqual(defaultConfig.env, {})
124
- assert.deepStrictEqual(defaultConfig.dependencies, {})
125
- assert.deepStrictEqual(defaultConfig.devDependencies, {})
126
- })
127
-
128
- test('should return Generator config fields definitions', async () => {
129
- const generator = new Generator()
130
- const configFieldsDefs = generator.getConfigFieldsDefinitions()
131
-
132
- const hostnameField = configFieldsDefs.find(
133
- field => field.var === 'PLT_SERVER_HOSTNAME'
134
- )
135
- assert.deepStrictEqual(hostnameField, {
136
- var: 'PLT_SERVER_HOSTNAME',
137
- label: 'What is the hostname?',
138
- default: '0.0.0.0',
139
- type: 'string',
140
- configValue: 'hostname'
141
- })
142
-
143
- const portField = configFieldsDefs.find(
144
- field => field.var === 'PORT'
145
- )
146
- assert.deepStrictEqual(portField, {
147
- var: 'PORT',
148
- label: 'Which port do you want to use?',
149
- default: 3042,
150
- type: 'number',
151
- configValue: 'port'
152
- })
153
-
154
- const greetingField = configFieldsDefs.find(
155
- field => field.var === 'PLT_GREETING_TEXT'
156
- )
157
- assert.deepStrictEqual(greetingField, {
158
- var: 'PLT_GREETING_TEXT',
159
- label: 'What should the stackable greeting say?',
160
- default: 'Hello world!',
161
- type: 'string'
162
- })
163
- })
164
-
165
- test('should generate a stackable app', async (t) => {
166
- const testDir = await mkdtemp(join(tmpdir(), 'stackable-'))
167
- t.after(() => safeRemove(testDir))
168
-
169
- const generator = new Generator()
170
-
171
- generator.setConfig({
172
- serviceName: 'stackable-app',
173
- targetDirectory: testDir
174
- })
175
-
176
- await generator.prepare()
177
- await generator.writeFiles()
178
-
179
- const files = await readdir(testDir)
180
- assert.deepStrictEqual(files.sort(), [
181
- '.env',
182
- '.env.sample',
183
- '.gitignore',
184
- 'global.d.ts',
185
- 'package.json',
186
- 'platformatic.json',
187
- 'stackable.schema.json'
188
- ])
189
-
190
- const packageJson = require(join(testDir, 'package.json'))
191
- assert.strictEqual(packageJson.name, 'stackable-app')
192
-
193
- const envFile = await readFile(join(testDir, '.env'), 'utf8')
194
- const envVars = envFile.split('\\n').filter(Boolean)
195
- assert.deepStrictEqual(envVars.sort(), [
196
- 'PLT_GREETING_TEXT=Hello world!',
197
- 'PLT_SERVER_HOSTNAME=0.0.0.0',
198
- 'PLT_SERVER_LOGGER_LEVEL=info',
199
- 'PLT_TYPESCRIPT=false',
200
- 'PORT=3042'
201
- ])
202
-
203
- const stackableConfig = require(join(testDir, 'platformatic.json'))
204
- const stackableName = stackablePackageJson.name
205
- const stackableVersion = stackablePackageJson.version
206
-
207
- assert.deepStrictEqual(stackableConfig, {
208
- $schema: './stackable.schema.json',
209
- module: \`\${stackableName}@\${stackableVersion}\`,
210
- server: {
211
- hostname: '{PLT_SERVER_HOSTNAME}',
212
- port: '{PORT}',
213
- logger: {
214
- level: '{PLT_SERVER_LOGGER_LEVEL}'
215
- }
216
- },
217
- service: {
218
- openapi: true
219
- },
220
- greeting: {
221
- text: '{PLT_GREETING_TEXT}'
222
- },
223
- watch: true
224
- })
225
- })
226
- `
227
- }
228
-
229
- function getTsStackableGeneratorTestFile () {
230
- return `\
231
- import test from 'node:test'
232
- import assert from 'node:assert'
233
- import { tmpdir } from 'node:os'
234
- import { join } from 'node:path'
235
- import { readFile, readdir, mkdtemp } from 'node:fs/promises'
236
- import { readFileSync } from 'node:fs'
237
- import { Generator } from '../index'
238
- import { safeRemove } from '@platformatic/utils'
239
-
240
- const stackablePackageJsonPath = require.resolve('../../package.json')
241
- const stackablePackageJson = JSON.parse(readFileSync(stackablePackageJsonPath, 'utf8'))
242
-
243
- test('should return a default Generator config', async () => {
244
- const generator = new Generator()
245
- const defaultConfig = generator.getDefaultConfig()
246
-
247
- assert.strictEqual(defaultConfig.hostname, '0.0.0.0')
248
- assert.strictEqual(defaultConfig.port, 3042)
249
- assert.strictEqual(defaultConfig.greeting, 'Hello world!')
250
- assert.deepStrictEqual(defaultConfig.env, {})
251
- assert.deepStrictEqual(defaultConfig.dependencies, {})
252
- assert.deepStrictEqual(defaultConfig.devDependencies, {})
253
- })
254
-
255
- test('should return Generator config fields definitions', async () => {
256
- const generator = new Generator()
257
- const configFieldsDefs = generator.getConfigFieldsDefinitions()
258
-
259
- const hostnameField = configFieldsDefs.find(
260
- field => field.var === 'PLT_SERVER_HOSTNAME'
261
- )
262
- assert.deepStrictEqual(hostnameField, {
263
- var: 'PLT_SERVER_HOSTNAME',
264
- label: 'What is the hostname?',
265
- default: '0.0.0.0',
266
- type: 'string',
267
- configValue: 'hostname'
268
- })
269
-
270
- const portField = configFieldsDefs.find(
271
- field => field.var === 'PORT'
272
- )
273
- assert.deepStrictEqual(portField, {
274
- var: 'PORT',
275
- label: 'Which port do you want to use?',
276
- default: 3042,
277
- type: 'number',
278
- configValue: 'port'
279
- })
280
-
281
- const greetingField = configFieldsDefs.find(
282
- field => field.var === 'PLT_GREETING_TEXT'
283
- )
284
- assert.deepStrictEqual(greetingField, {
285
- var: 'PLT_GREETING_TEXT',
286
- label: 'What should the stackable greeting say?',
287
- default: 'Hello world!',
288
- type: 'string'
289
- })
290
- })
291
-
292
- test('should generate a stackable app', async (t) => {
293
- const testDir = await mkdtemp(join(tmpdir(), 'stackable-'))
294
- t.after(() => safeRemove(testDir))
295
-
296
- const generator = new Generator()
297
-
298
- generator.setConfig({
299
- serviceName: 'stackable-app',
300
- targetDirectory: testDir
301
- })
302
-
303
- await generator.prepare()
304
- await generator.writeFiles()
305
-
306
- const files = await readdir(testDir)
307
- assert.deepStrictEqual(files.sort(), [
308
- '.env',
309
- '.env.sample',
310
- '.gitignore',
311
- 'global.d.ts',
312
- 'package.json',
313
- 'platformatic.json',
314
- 'stackable.schema.json'
315
- ])
316
-
317
- const packageJson = require(join(testDir, 'package.json'))
318
- assert.strictEqual(packageJson.name, 'stackable-app')
319
-
320
- const envFile = await readFile(join(testDir, '.env'), 'utf8')
321
- const envVars = envFile.split('\\n').filter(Boolean)
322
- assert.deepStrictEqual(envVars.sort(), [
323
- 'PLT_GREETING_TEXT=Hello world!',
324
- 'PLT_SERVER_HOSTNAME=0.0.0.0',
325
- 'PLT_SERVER_LOGGER_LEVEL=info',
326
- 'PLT_TYPESCRIPT=false',
327
- 'PORT=3042'
328
- ])
329
-
330
- const stackableConfig = require(join(testDir, 'platformatic.json'))
331
- const stackableName = stackablePackageJson.name
332
- const stackableVersion = stackablePackageJson.version
333
-
334
- assert.deepStrictEqual(stackableConfig, {
335
- $schema: './stackable.schema.json',
336
- module: \`\${stackableName}@\${stackableVersion}\`,
337
- server: {
338
- hostname: '{PLT_SERVER_HOSTNAME}',
339
- port: '{PORT}',
340
- logger: {
341
- level: '{PLT_SERVER_LOGGER_LEVEL}'
342
- }
343
- },
344
- service: {
345
- openapi: true
346
- },
347
- greeting: {
348
- text: '{PLT_GREETING_TEXT}'
349
- },
350
- watch: true
351
- })
352
- })
353
- `
354
- }
355
-
356
- function generateStackableTests (typescript, stackableName) {
357
- if (typescript) {
358
- return [
359
- {
360
- path: 'test',
361
- file: 'index.test.ts',
362
- contents: getTsStackableIndexTestFile(stackableName),
363
- },
364
- {
365
- path: 'test',
366
- file: 'schema.test.ts',
367
- contents: getTsStackableSchemaTestFile(stackableName),
368
- },
369
- {
370
- path: 'test',
371
- file: 'generator.test.ts',
372
- contents: getTsStackableGeneratorTestFile(),
373
- },
374
- ]
375
- }
376
- return [
377
- {
378
- path: 'test',
379
- file: 'index.test.js',
380
- contents: getJsStackableIndexTestFile(stackableName),
381
- },
382
- {
383
- path: 'test',
384
- file: 'schema.test.js',
385
- contents: getJsStackableSchemaTestFile(stackableName),
386
- },
387
- {
388
- path: 'test',
389
- file: 'generator.test.js',
390
- contents: getJsStackableGeneratorTestFile(),
391
- },
392
- ]
393
- }
394
-
395
- module.exports = {
396
- generateStackableTests,
397
- }
@@ -1,317 +0,0 @@
1
- 'use strict'
2
-
3
- const { join } = require('node:path')
4
- const { readFile } = require('node:fs/promises')
5
- const { kebabCase } = require('change-case-all')
6
- const { stripVersion, getLatestNpmVersion } = require('./utils')
7
- const { FileGenerator } = require('./file-generator')
8
- const { PrepareError } = require('./errors')
9
- const { generateGitignore } = require('./create-gitignore')
10
- const { generateStackableCli } = require('./create-stackable-cli')
11
- const { generateStackableFiles } = require('./create-stackable-files')
12
- const { generateStackablePlugins } = require('./create-stackable-plugin')
13
- const { generateStackableTests } = require('./create-stackable-tests')
14
-
15
- /* c8 ignore start */
16
- const fakeLogger = {
17
- info: () => {},
18
- warn: () => {},
19
- debug: () => {},
20
- trace: () => {},
21
- error: () => {},
22
- }
23
- /* c8 ignore start */
24
-
25
- class StackableGenerator extends FileGenerator {
26
- constructor (opts = {}) {
27
- super(opts)
28
- this.files = []
29
- this.logger = opts.logger || fakeLogger
30
- this.questions = []
31
- this.pkgData = null
32
- this.inquirer = opts.inquirer || null
33
- this.targetDirectory = opts.targetDirectory || null
34
- this.config = this.getDefaultConfig()
35
- this.packages = []
36
- }
37
-
38
- getDefaultConfig () {
39
- return {
40
- stackableName: 'my-stackable',
41
- typescript: false,
42
- initGitRepository: false,
43
- dependencies: {},
44
- devDependencies: {},
45
- }
46
- }
47
-
48
- setConfigFields (fields) {
49
- for (const field of fields) {
50
- this.config[field.configValue] = field.value
51
- }
52
- }
53
-
54
- setConfig (config) {
55
- if (!config) {
56
- this.config = this.getDefaultConfig()
57
- }
58
- const oldConfig = this.config
59
- this.config = {
60
- ...this.getDefaultConfig(),
61
- ...oldConfig,
62
- ...config,
63
- }
64
-
65
- if (this.config.targetDirectory) {
66
- this.targetDirectory = this.config.targetDirectory
67
- }
68
- }
69
-
70
- /* c8 ignore start */
71
- async ask () {
72
- if (this.inquirer) {
73
- await this.prepareQuestions()
74
- const newConfig = await this.inquirer.prompt(this.questions)
75
- this.setConfig({
76
- ...this.config,
77
- ...newConfig,
78
- })
79
- }
80
- }
81
-
82
- async prepare () {
83
- try {
84
- this.reset()
85
- await this.getFastifyVersion()
86
- await this.getPlatformaticVersion()
87
-
88
- await this._beforePrepare()
89
-
90
- // generate package.json
91
- const template = await this.generatePackageJson()
92
- this.addFile({
93
- path: '',
94
- file: 'package.json',
95
- contents: JSON.stringify(template, null, 2),
96
- })
97
-
98
- if (this.config.typescript) {
99
- // create tsconfig.json
100
- this.addFile({
101
- path: '',
102
- file: 'tsconfig.json',
103
- contents: JSON.stringify(this.getTsConfig(), null, 2),
104
- })
105
- }
106
-
107
- const typescript = this.config.typescript
108
- const stackableName = this.config.stackableName
109
-
110
- this.files.push(...generateStackableFiles(typescript, stackableName))
111
- this.files.push(...generateStackableCli(typescript, stackableName))
112
- this.files.push(...generateStackablePlugins(typescript))
113
- this.files.push(...generateStackableTests(typescript, stackableName))
114
- this.files.push(generateGitignore())
115
-
116
- await this._afterPrepare()
117
-
118
- return {
119
- targetDirectory: this.targetDirectory,
120
- }
121
- } catch (err) {
122
- if (err.code?.startsWith('PLT_GEN')) {
123
- // throw the same error
124
- throw err
125
- }
126
- const _err = new PrepareError(err.message)
127
- _err.cause = err
128
- throw _err
129
- }
130
- }
131
-
132
- getTsConfig () {
133
- return {
134
- compilerOptions: {
135
- module: 'commonjs',
136
- esModuleInterop: true,
137
- target: 'es2020',
138
- sourceMap: true,
139
- pretty: true,
140
- noEmitOnError: true,
141
- incremental: true,
142
- strict: true,
143
- outDir: 'dist',
144
- },
145
- watchOptions: {
146
- watchFile: 'fixedPollingInterval',
147
- watchDirectory: 'fixedPollingInterval',
148
- fallbackPolling: 'dynamicPriority',
149
- synchronousWatchDirectory: true,
150
- excludeDirectories: ['**/node_modules', 'dist'],
151
- },
152
- }
153
- }
154
-
155
- async prepareQuestions () {
156
- if (!this.config.targetDirectory) {
157
- // directory
158
- this.questions.push({
159
- type: 'input',
160
- name: 'targetDirectory',
161
- message: 'Where would you like to create your project?',
162
- default: 'platformatic',
163
- })
164
- }
165
-
166
- this.questions.push({
167
- type: 'input',
168
- name: 'stackableName',
169
- message: 'What is the name of the stackable?',
170
- default: 'my-stackable',
171
- })
172
-
173
- // typescript
174
- this.questions.push({
175
- type: 'list',
176
- name: 'typescript',
177
- message: 'Do you want to use TypeScript?',
178
- default: false,
179
- choices: [{ name: 'yes', value: true }, { name: 'no', value: false }],
180
- })
181
- }
182
-
183
- /**
184
- * Reads the content of package.json and returns it as an object
185
- * @returns Object
186
- */
187
- async readPackageJsonFile () {
188
- if (this.pkgData) {
189
- return this.pkgData
190
- }
191
- const currentPackageJsonPath = join(__dirname, '..', 'package.json')
192
- this.pkgData = JSON.parse(await readFile(currentPackageJsonPath, 'utf8'))
193
- return this.pkgData
194
- }
195
-
196
- async getFastifyVersion () {
197
- const pkgData = await this.readPackageJsonFile()
198
- this.fastifyVersion = stripVersion(pkgData.dependencies.fastify)
199
- }
200
-
201
- async getPlatformaticVersion () {
202
- const pkgData = await this.readPackageJsonFile()
203
- this.platformaticVersion = stripVersion(pkgData.version)
204
- }
205
-
206
- async generatePackageJson () {
207
- const dependencies = {
208
- '@platformatic/config': `^${this.platformaticVersion}`,
209
- '@platformatic/service': `^${this.platformaticVersion}`,
210
- 'json-schema-to-typescript': '^13.0.0',
211
- }
212
-
213
- const devDependencies = {
214
- borp: '^0.10.0',
215
- fastify: `^${this.fastifyVersion}`,
216
- }
217
-
218
- const npmPackageName = kebabCase(this.config.stackableName)
219
- const createStackableCommand = kebabCase('create-' + this.config.stackableName)
220
- const startStackableCommand = kebabCase('start-' + this.config.stackableName)
221
-
222
- if (this.config.typescript) {
223
- const packageJsonFile = await readFile(join(__dirname, '..', 'package.json'), 'utf-8')
224
- const typescriptVersion = JSON.parse(packageJsonFile).devDependencies.typescript
225
-
226
- return {
227
- name: npmPackageName,
228
- version: '0.0.1',
229
- main: 'dist/index.js',
230
- bin: {
231
- [createStackableCommand]: './dist/cli/create.js',
232
- [startStackableCommand]: './dist/cli/start.js',
233
- },
234
- scripts: {
235
- build: 'tsc --build',
236
- 'gen-schema': 'node lib/schema.js > schema.json',
237
- 'gen-types': 'json2ts > config.d.ts < schema.json',
238
- 'build:config': 'pnpm run gen-schema && pnpm run gen-types',
239
- clean: 'rm -fr ./dist',
240
- test: 'borp',
241
- },
242
- engines: {
243
- node: '^18.8.0 || >=20.6.0',
244
- },
245
- devDependencies: {
246
- ...devDependencies,
247
- typescript: typescriptVersion,
248
- ...this.config.devDependencies,
249
- },
250
- dependencies: {
251
- ...dependencies,
252
- '@platformatic/generators': `^${this.platformaticVersion}`,
253
- ...this.config.dependencies,
254
- },
255
- }
256
- }
257
-
258
- return {
259
- name: npmPackageName,
260
- version: '0.0.1',
261
- main: 'index.js',
262
- bin: {
263
- [createStackableCommand]: './cli/create.js',
264
- [startStackableCommand]: './cli/start.js',
265
- },
266
- scripts: {
267
- 'gen-schema': 'node lib/schema.js > schema.json',
268
- 'gen-types': 'json2ts > config.d.ts < schema.json',
269
- 'build:config': 'pnpm run gen-schema && pnpm run gen-types',
270
- prepublishOnly: 'pnpm run build:config',
271
- lint: 'standard',
272
- test: 'borp',
273
- },
274
- engines: {
275
- node: '^18.8.0 || >=20.6.0',
276
- },
277
- devDependencies: {
278
- ...devDependencies,
279
- standard: '^17.0.0',
280
- ...this.config.devDependencies,
281
- },
282
- dependencies: {
283
- ...dependencies,
284
- ...this.config.dependencies,
285
- },
286
- }
287
- }
288
-
289
- async run () {
290
- const metadata = await this.prepare()
291
- await this.writeFiles()
292
- return metadata
293
- }
294
-
295
- async addPackage (pkg) {
296
- this.config.dependencies[pkg.name] = 'latest'
297
- try {
298
- const version = await getLatestNpmVersion(pkg.name)
299
- if (version) {
300
- this.config.dependencies[pkg.name] = version
301
- }
302
- } catch (err) {
303
- this.logger.warn(`Could not get latest version for ${pkg.name}, setting it to latest`)
304
- }
305
- this.packages.push(pkg)
306
- }
307
-
308
- // implement in the subclass
309
- /* c8 ignore next 1 */
310
- async postInstallActions () {}
311
- async _beforePrepare () {}
312
- async _afterPrepare () {}
313
- async _getConfigFileContents () { return {} }
314
- }
315
-
316
- module.exports = StackableGenerator
317
- module.exports.StackableGenerator = StackableGenerator