@platformatic/generators 1.19.0 → 1.20.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.
- package/index.js +2 -0
- package/lib/create-plugin.js +1 -1
- package/lib/create-stackable-cli.js +167 -0
- package/lib/create-stackable-files.js +344 -0
- package/lib/create-stackable-plugin.js +48 -0
- package/lib/file-generator.js +3 -3
- package/lib/stackable-generator.js +309 -0
- package/package.json +9 -7
- package/test/base-generator.test.js +2 -1
- package/test/stackable-generator.test.js +96 -0
package/index.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
3
|
const { BaseGenerator } = require('./lib/base-generator')
|
|
4
|
+
const { StackableGenerator } = require('./lib/stackable-generator')
|
|
4
5
|
const { generateTests } = require('./lib/create-plugin')
|
|
5
6
|
const { addPrefixToEnv } = require('./lib/utils')
|
|
6
7
|
module.exports = {
|
|
7
8
|
addPrefixToEnv,
|
|
8
9
|
BaseGenerator,
|
|
10
|
+
StackableGenerator,
|
|
9
11
|
generateTests
|
|
10
12
|
}
|
package/lib/create-plugin.js
CHANGED
|
@@ -54,7 +54,7 @@ function testHelperJS (mod, customization = { pre: '', post: '', config: '' }) {
|
|
|
54
54
|
|
|
55
55
|
const { join } = require('node:path')
|
|
56
56
|
const { readFile } = require('node:fs/promises')
|
|
57
|
-
const { buildServer } = require('
|
|
57
|
+
const { buildServer } = require('${mod}')
|
|
58
58
|
${customization.requires || ''}
|
|
59
59
|
|
|
60
60
|
async function getServer (t) {
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { kebabCase } = require('change-case-all')
|
|
4
|
+
|
|
5
|
+
function getJsStackableStartCli () {
|
|
6
|
+
return `\
|
|
7
|
+
#!/usr/bin/env node
|
|
8
|
+
'use strict'
|
|
9
|
+
|
|
10
|
+
const stackable = require('../index')
|
|
11
|
+
const { start } = require('@platformatic/service')
|
|
12
|
+
const { printAndExitLoadConfigError } = require('@platformatic/config')
|
|
13
|
+
|
|
14
|
+
start(stackable, process.argv.splice(2)).catch(printAndExitLoadConfigError)
|
|
15
|
+
`
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function getTsStackableStartCli () {
|
|
19
|
+
return `\
|
|
20
|
+
#!/usr/bin/env node
|
|
21
|
+
import stackable from '../index'
|
|
22
|
+
import { start } from '@platformatic/service'
|
|
23
|
+
import { printAndExitLoadConfigError } from '@platformatic/config'
|
|
24
|
+
|
|
25
|
+
start(stackable, process.argv.splice(2)).catch(printAndExitLoadConfigError)
|
|
26
|
+
`
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function getJsStackableCreateCli (stackableName) {
|
|
30
|
+
return `\
|
|
31
|
+
#!/usr/bin/env node
|
|
32
|
+
'use strict'
|
|
33
|
+
|
|
34
|
+
const { join } = require('node:path')
|
|
35
|
+
const pino = require('pino')
|
|
36
|
+
const pretty = require('pino-pretty')
|
|
37
|
+
const minimist = require('minimist')
|
|
38
|
+
const { Generator } = require('../lib/generator')
|
|
39
|
+
|
|
40
|
+
async function execute () {
|
|
41
|
+
const logger = pino(pretty({
|
|
42
|
+
translateTime: 'SYS:HH:MM:ss',
|
|
43
|
+
ignore: 'hostname,pid'
|
|
44
|
+
}))
|
|
45
|
+
|
|
46
|
+
const args = minimist(process.argv.slice(2), {
|
|
47
|
+
string: ['dir', 'port', 'hostname'],
|
|
48
|
+
boolean: ['typescript', 'install', 'plugin', 'git'],
|
|
49
|
+
default: {
|
|
50
|
+
dir: join(process.cwd(), '${kebabCase(stackableName + '-app')}'),
|
|
51
|
+
port: 3042,
|
|
52
|
+
hostname: '0.0.0.0',
|
|
53
|
+
plugin: true,
|
|
54
|
+
typescript: false,
|
|
55
|
+
git: false,
|
|
56
|
+
install: true
|
|
57
|
+
}
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
const generator = new Generator({ logger })
|
|
61
|
+
|
|
62
|
+
generator.setConfig({
|
|
63
|
+
port: args.port,
|
|
64
|
+
hostname: args.hostname,
|
|
65
|
+
plugin: args.plugin,
|
|
66
|
+
tests: args.plugin,
|
|
67
|
+
typescript: args.typescript,
|
|
68
|
+
initGitRepository: args.git,
|
|
69
|
+
targetDirectory: args.dir
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
await generator.run()
|
|
73
|
+
|
|
74
|
+
logger.info('Application created successfully! Run \`npm run start\` to start an application.')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
execute()
|
|
78
|
+
`
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function getTsStackableCreateCli (stackableName) {
|
|
82
|
+
return `\
|
|
83
|
+
#!/usr/bin/env node
|
|
84
|
+
import { join } from 'node:path'
|
|
85
|
+
import pino from 'pino'
|
|
86
|
+
import pretty from 'pino-pretty'
|
|
87
|
+
import minimist from 'minimist'
|
|
88
|
+
import { Generator } from '../lib/generator'
|
|
89
|
+
|
|
90
|
+
async function execute () {
|
|
91
|
+
const logger = pino(pretty({
|
|
92
|
+
translateTime: 'SYS:HH:MM:ss',
|
|
93
|
+
ignore: 'hostname,pid'
|
|
94
|
+
}))
|
|
95
|
+
|
|
96
|
+
const args = minimist(process.argv.slice(2), {
|
|
97
|
+
string: ['dir', 'port', 'hostname'],
|
|
98
|
+
boolean: ['typescript', 'install', 'plugin', 'git'],
|
|
99
|
+
default: {
|
|
100
|
+
dir: join(process.cwd(), '${kebabCase(stackableName + '-app')}'),
|
|
101
|
+
port: 3042,
|
|
102
|
+
hostname: '0.0.0.0',
|
|
103
|
+
plugin: true,
|
|
104
|
+
typescript: false,
|
|
105
|
+
git: false,
|
|
106
|
+
install: true
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
const generator = new Generator({ logger })
|
|
111
|
+
|
|
112
|
+
generator.setConfig({
|
|
113
|
+
port: args.port,
|
|
114
|
+
hostname: args.hostname,
|
|
115
|
+
plugin: args.plugin,
|
|
116
|
+
tests: args.plugin,
|
|
117
|
+
typescript: args.typescript,
|
|
118
|
+
initGitRepository: args.git,
|
|
119
|
+
targetDirectory: args.dir
|
|
120
|
+
})
|
|
121
|
+
|
|
122
|
+
await generator.run()
|
|
123
|
+
|
|
124
|
+
logger.info('Application created successfully! Run \`npm run start\` to start an application.')
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
execute()
|
|
128
|
+
`
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function generateStackableCli (typescript, stackableName) {
|
|
132
|
+
if (typescript) {
|
|
133
|
+
return [
|
|
134
|
+
{
|
|
135
|
+
path: 'cli',
|
|
136
|
+
file: 'start.ts',
|
|
137
|
+
contents: getTsStackableStartCli(),
|
|
138
|
+
options: { mode: 0o755 }
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
path: 'cli',
|
|
142
|
+
file: 'create.ts',
|
|
143
|
+
contents: getTsStackableCreateCli(stackableName),
|
|
144
|
+
options: { mode: 0o755 }
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return [
|
|
150
|
+
{
|
|
151
|
+
path: 'cli',
|
|
152
|
+
file: 'start.js',
|
|
153
|
+
contents: getJsStackableStartCli(),
|
|
154
|
+
options: { mode: 0o755 }
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
path: 'cli',
|
|
158
|
+
file: 'create.js',
|
|
159
|
+
contents: getJsStackableCreateCli(stackableName),
|
|
160
|
+
options: { mode: 0o755 }
|
|
161
|
+
}
|
|
162
|
+
]
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
module.exports = {
|
|
166
|
+
generateStackableCli
|
|
167
|
+
}
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { pascalCase, camelCase, capitalCase, kebabCase } = require('change-case-all')
|
|
4
|
+
|
|
5
|
+
function getJsStackableIndexFile (stackableName) {
|
|
6
|
+
return `\
|
|
7
|
+
'use strict'
|
|
8
|
+
|
|
9
|
+
const { platformaticService } = require('@platformatic/service')
|
|
10
|
+
const { schema } = require('./lib/schema')
|
|
11
|
+
const { Generator } = require('./lib/generator')
|
|
12
|
+
|
|
13
|
+
async function stackable (fastify, opts) {
|
|
14
|
+
await fastify.register(platformaticService, opts)
|
|
15
|
+
await fastify.register(require('./plugins/example'), opts)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
stackable.configType = '${kebabCase(stackableName + '-app')}'
|
|
19
|
+
stackable.schema = schema
|
|
20
|
+
stackable.Generator = Generator
|
|
21
|
+
stackable.configManagerConfig = {
|
|
22
|
+
schema,
|
|
23
|
+
envWhitelist: ['PORT', 'HOSTNAME'],
|
|
24
|
+
allowToWatch: ['.env'],
|
|
25
|
+
schemaOptions: {
|
|
26
|
+
useDefaults: true,
|
|
27
|
+
coerceTypes: true,
|
|
28
|
+
allErrors: true,
|
|
29
|
+
strict: false
|
|
30
|
+
},
|
|
31
|
+
transformConfig: async () => {}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// break Fastify encapsulation
|
|
35
|
+
stackable[Symbol.for('skip-override')] = true
|
|
36
|
+
|
|
37
|
+
module.exports = stackable
|
|
38
|
+
`
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getTsStackableIndexFile (stackableName) {
|
|
42
|
+
const stackableConfigType = pascalCase(stackableName + 'Config')
|
|
43
|
+
|
|
44
|
+
return `\
|
|
45
|
+
import { platformaticService, Stackable } from '@platformatic/service'
|
|
46
|
+
import { schema } from './lib/schema'
|
|
47
|
+
import { Generator } from './lib/generator'
|
|
48
|
+
import { ${stackableConfigType} } from './config'
|
|
49
|
+
|
|
50
|
+
const stackable: Stackable<${stackableConfigType}> = async function (fastify, opts) {
|
|
51
|
+
await fastify.register(platformaticService, opts)
|
|
52
|
+
await fastify.register(require('./plugins/example'), opts)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
stackable.configType = '${kebabCase(stackableName + '-app')}'
|
|
56
|
+
stackable.schema = schema
|
|
57
|
+
stackable.Generator = Generator
|
|
58
|
+
stackable.configManagerConfig = {
|
|
59
|
+
schema,
|
|
60
|
+
envWhitelist: ['PORT', 'HOSTNAME'],
|
|
61
|
+
allowToWatch: ['.env'],
|
|
62
|
+
schemaOptions: {
|
|
63
|
+
useDefaults: true,
|
|
64
|
+
coerceTypes: true,
|
|
65
|
+
allErrors: true,
|
|
66
|
+
strict: false
|
|
67
|
+
},
|
|
68
|
+
transformConfig: async () => {}
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// break Fastify encapsulation
|
|
72
|
+
// @ts-ignore
|
|
73
|
+
stackable[Symbol.for('skip-override')] = true
|
|
74
|
+
|
|
75
|
+
export default stackable
|
|
76
|
+
`
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function getStackableIndexTypesFile (stackableName) {
|
|
80
|
+
const stackableConfigType = pascalCase(stackableName + 'Config')
|
|
81
|
+
|
|
82
|
+
return `\
|
|
83
|
+
import { FastifyInstance } from 'fastify'
|
|
84
|
+
import { PlatformaticApp } from '@platformatic/service'
|
|
85
|
+
import { ${stackableConfigType} } from './config'
|
|
86
|
+
|
|
87
|
+
declare module 'fastify' {
|
|
88
|
+
interface FastifyInstance {
|
|
89
|
+
platformatic: PlatformaticApp<${stackableConfigType}>
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
`
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function getJsStackableGeneratorFile (stackableName) {
|
|
96
|
+
const stackableGeneratorType = pascalCase(stackableName + 'Generator')
|
|
97
|
+
|
|
98
|
+
return `\
|
|
99
|
+
'use strict'
|
|
100
|
+
|
|
101
|
+
const { Generator: ServiceGenerator } = require('@platformatic/service')
|
|
102
|
+
const { schema } = require('./schema')
|
|
103
|
+
|
|
104
|
+
class ${stackableGeneratorType} extends ServiceGenerator {
|
|
105
|
+
getDefaultConfig () {
|
|
106
|
+
const defaultBaseConfig = super.getDefaultConfig()
|
|
107
|
+
const defaultConfig = {
|
|
108
|
+
greeting: 'Hello world!'
|
|
109
|
+
}
|
|
110
|
+
return Object.assign({}, defaultBaseConfig, defaultConfig)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
async _getConfigFileContents () {
|
|
114
|
+
const baseConfig = await super._getConfigFileContents()
|
|
115
|
+
const config = {
|
|
116
|
+
$schema: './stackable.schema.json',
|
|
117
|
+
greeting: {
|
|
118
|
+
text: '{PLT_GREETING_TEXT}'
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return Object.assign({}, baseConfig, config)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async _beforePrepare () {
|
|
125
|
+
super._beforePrepare()
|
|
126
|
+
|
|
127
|
+
this.config.env = {
|
|
128
|
+
PLT_GREETING_TEXT: this.config.greeting ?? 'Hello world!',
|
|
129
|
+
...this.config.env
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
async _afterPrepare () {
|
|
134
|
+
this.addFile({
|
|
135
|
+
path: '',
|
|
136
|
+
file: 'stackable.schema.json',
|
|
137
|
+
contents: JSON.stringify(schema, null, 2)
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
module.exports = ${stackableGeneratorType}
|
|
143
|
+
module.exports.Generator = ${stackableGeneratorType}
|
|
144
|
+
`
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function getTsStackableGeneratorFile (stackableName) {
|
|
148
|
+
const stackableGeneratorType = pascalCase(stackableName + 'Generator')
|
|
149
|
+
|
|
150
|
+
return `\
|
|
151
|
+
import { Generator as ServiceGenerator } from '@platformatic/service'
|
|
152
|
+
import { BaseGenerator } from '@platformatic/generators'
|
|
153
|
+
import { schema } from './schema'
|
|
154
|
+
|
|
155
|
+
class ${stackableGeneratorType} extends ServiceGenerator {
|
|
156
|
+
getDefaultConfig (): BaseGenerator.JSONValue {
|
|
157
|
+
const defaultBaseConfig = super.getDefaultConfig()
|
|
158
|
+
const defaultConfig = {
|
|
159
|
+
greeting: 'Hello world!'
|
|
160
|
+
}
|
|
161
|
+
return Object.assign({}, defaultBaseConfig, defaultConfig)
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
async _getConfigFileContents (): Promise<BaseGenerator.JSONValue> {
|
|
165
|
+
const baseConfig = await super._getConfigFileContents()
|
|
166
|
+
const config = {
|
|
167
|
+
$schema: './stackable.schema.json',
|
|
168
|
+
greeting: {
|
|
169
|
+
text: '{PLT_GREETING_TEXT}'
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return Object.assign({}, baseConfig, config)
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async _beforePrepare () {
|
|
176
|
+
super._beforePrepare()
|
|
177
|
+
|
|
178
|
+
this.config.env = {
|
|
179
|
+
PLT_GREETING_TEXT: this.config.greeting ?? 'Hello world!',
|
|
180
|
+
...this.config.env
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
async _afterPrepare () {
|
|
185
|
+
this.addFile({
|
|
186
|
+
path: '',
|
|
187
|
+
file: 'stackable.schema.json',
|
|
188
|
+
contents: JSON.stringify(schema, null, 2)
|
|
189
|
+
})
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
export default ${stackableGeneratorType}
|
|
194
|
+
export { ${stackableGeneratorType} as Generator }
|
|
195
|
+
`
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
function getJsStackableSchemaFile (stackableName) {
|
|
199
|
+
const schemaId = kebabCase(stackableName)
|
|
200
|
+
const schemaTitle = capitalCase(stackableName + 'Config')
|
|
201
|
+
const schemaVarName = camelCase(stackableName + 'Schema')
|
|
202
|
+
|
|
203
|
+
return `\
|
|
204
|
+
'use strict'
|
|
205
|
+
|
|
206
|
+
const { schema } = require('@platformatic/service')
|
|
207
|
+
|
|
208
|
+
const ${schemaVarName} = {
|
|
209
|
+
...schema.schema,
|
|
210
|
+
$id: '${schemaId}',
|
|
211
|
+
title: '${schemaTitle}',
|
|
212
|
+
properties: {
|
|
213
|
+
...schema.schema.properties,
|
|
214
|
+
greeting: {
|
|
215
|
+
type: 'object',
|
|
216
|
+
properties: {
|
|
217
|
+
text: {
|
|
218
|
+
type: 'string'
|
|
219
|
+
}
|
|
220
|
+
},
|
|
221
|
+
required: ['text'],
|
|
222
|
+
additionalProperties: false
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
module.exports.schema = ${schemaVarName}
|
|
228
|
+
|
|
229
|
+
if (require.main === module) {
|
|
230
|
+
console.log(JSON.stringify(${schemaVarName}, null, 2))
|
|
231
|
+
}
|
|
232
|
+
`
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function getTsStackableSchemaFile (stackableName) {
|
|
236
|
+
const schemaId = kebabCase(stackableName)
|
|
237
|
+
const schemaTitle = capitalCase(stackableName + 'Config')
|
|
238
|
+
const schemaVarName = camelCase(stackableName + 'Schema')
|
|
239
|
+
|
|
240
|
+
return `\
|
|
241
|
+
import { schema } from '@platformatic/service'
|
|
242
|
+
|
|
243
|
+
const ${schemaVarName} = {
|
|
244
|
+
...schema.schema,
|
|
245
|
+
$id: '${schemaId}',
|
|
246
|
+
title: '${schemaTitle}',
|
|
247
|
+
properties: {
|
|
248
|
+
...schema.schema.properties,
|
|
249
|
+
greeting: {
|
|
250
|
+
type: 'object',
|
|
251
|
+
properties: {
|
|
252
|
+
text: {
|
|
253
|
+
type: 'string'
|
|
254
|
+
}
|
|
255
|
+
},
|
|
256
|
+
required: ['text'],
|
|
257
|
+
additionalProperties: false
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export { ${schemaVarName} as schema }
|
|
263
|
+
|
|
264
|
+
if (require.main === module) {
|
|
265
|
+
console.log(JSON.stringify(${schemaVarName}, null, 2))
|
|
266
|
+
}
|
|
267
|
+
`
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
function getStackableConfigTypesFile (stackableName) {
|
|
271
|
+
const stackableConfigType = pascalCase(stackableName + 'Config')
|
|
272
|
+
|
|
273
|
+
return `\
|
|
274
|
+
// Use npm run build:config to generate this file from the Stackable schema
|
|
275
|
+
export interface ${stackableConfigType} {
|
|
276
|
+
greeting?: {
|
|
277
|
+
text: string;
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
`
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function generateStackableFiles (typescript, stackableName) {
|
|
284
|
+
if (typescript) {
|
|
285
|
+
return [
|
|
286
|
+
{
|
|
287
|
+
path: '',
|
|
288
|
+
file: 'index.ts',
|
|
289
|
+
contents: getTsStackableIndexFile(stackableName)
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
path: '',
|
|
293
|
+
file: 'index.d.ts',
|
|
294
|
+
contents: getStackableIndexTypesFile(stackableName)
|
|
295
|
+
},
|
|
296
|
+
{
|
|
297
|
+
path: '',
|
|
298
|
+
file: 'config.d.ts',
|
|
299
|
+
contents: getStackableConfigTypesFile(stackableName)
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
path: 'lib',
|
|
303
|
+
file: 'generator.ts',
|
|
304
|
+
contents: getTsStackableGeneratorFile(stackableName)
|
|
305
|
+
},
|
|
306
|
+
{
|
|
307
|
+
path: 'lib',
|
|
308
|
+
file: 'schema.ts',
|
|
309
|
+
contents: getTsStackableSchemaFile(stackableName)
|
|
310
|
+
}
|
|
311
|
+
]
|
|
312
|
+
}
|
|
313
|
+
return [
|
|
314
|
+
{
|
|
315
|
+
path: '',
|
|
316
|
+
file: 'index.js',
|
|
317
|
+
contents: getJsStackableIndexFile(stackableName)
|
|
318
|
+
},
|
|
319
|
+
{
|
|
320
|
+
path: '',
|
|
321
|
+
file: 'index.d.ts',
|
|
322
|
+
contents: getStackableIndexTypesFile(stackableName)
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
path: '',
|
|
326
|
+
file: 'config.d.ts',
|
|
327
|
+
contents: getStackableConfigTypesFile(stackableName)
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
path: 'lib',
|
|
331
|
+
file: 'generator.js',
|
|
332
|
+
contents: getJsStackableGeneratorFile(stackableName)
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
path: 'lib',
|
|
336
|
+
file: 'schema.js',
|
|
337
|
+
contents: getJsStackableSchemaFile(stackableName)
|
|
338
|
+
}
|
|
339
|
+
]
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
module.exports = {
|
|
343
|
+
generateStackableFiles
|
|
344
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
function getJsStackablePluginFile () {
|
|
4
|
+
return `\
|
|
5
|
+
/// <reference path="../index.d.ts" />
|
|
6
|
+
'use strict'
|
|
7
|
+
/** @param {import('fastify').FastifyInstance} fastify */
|
|
8
|
+
module.exports = async function (fastify, opts) {
|
|
9
|
+
const config = fastify.platformatic.config
|
|
10
|
+
const greeting = config.greeting
|
|
11
|
+
fastify.log.info({ greeting }, 'Loading stackable greeting plugin.')
|
|
12
|
+
fastify.decorate('greeting', greeting)
|
|
13
|
+
}
|
|
14
|
+
`
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function getTsStackablePluginFile () {
|
|
18
|
+
return `\
|
|
19
|
+
/// <reference path="../index.d.ts" />
|
|
20
|
+
import { FastifyInstance, FastifyPluginOptions } from 'fastify'
|
|
21
|
+
|
|
22
|
+
export default async function (fastify: FastifyInstance, opts: FastifyPluginOptions) {
|
|
23
|
+
const config = fastify.platformatic.config
|
|
24
|
+
const greeting = config.greeting
|
|
25
|
+
fastify.log.info({ greeting }, 'Loading stackable greeting plugin.')
|
|
26
|
+
fastify.decorate('greeting', greeting)
|
|
27
|
+
}
|
|
28
|
+
`
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function generateStackablePlugins (typescript) {
|
|
32
|
+
if (typescript) {
|
|
33
|
+
return [{
|
|
34
|
+
path: 'plugins',
|
|
35
|
+
file: 'example.ts',
|
|
36
|
+
contents: getTsStackablePluginFile()
|
|
37
|
+
}]
|
|
38
|
+
}
|
|
39
|
+
return [{
|
|
40
|
+
path: 'plugins',
|
|
41
|
+
file: 'example.js',
|
|
42
|
+
contents: getJsStackablePluginFile()
|
|
43
|
+
}]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = {
|
|
47
|
+
generateStackablePlugins
|
|
48
|
+
}
|
package/lib/file-generator.js
CHANGED
|
@@ -24,7 +24,7 @@ class FileGenerator {
|
|
|
24
24
|
this.targetDirectory = dir
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
addFile ({ path, file, contents }) {
|
|
27
|
+
addFile ({ path, file, contents, options = {} }) {
|
|
28
28
|
const fileObject = this.getFileObject(file, path)
|
|
29
29
|
if (path.startsWith('/')) {
|
|
30
30
|
path = path.substring(1)
|
|
@@ -32,7 +32,7 @@ class FileGenerator {
|
|
|
32
32
|
if (fileObject) {
|
|
33
33
|
fileObject.contents = contents
|
|
34
34
|
} else {
|
|
35
|
-
this.files.push({ path, file, contents })
|
|
35
|
+
this.files.push({ path, file, contents, options })
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
|
|
@@ -62,7 +62,7 @@ class FileGenerator {
|
|
|
62
62
|
await safeMkdir(baseDir)
|
|
63
63
|
}
|
|
64
64
|
const fullFilePath = join(baseDir, fileToWrite.file)
|
|
65
|
-
await writeFile(fullFilePath, fileToWrite.contents)
|
|
65
|
+
await writeFile(fullFilePath, fileToWrite.contents, fileToWrite.options)
|
|
66
66
|
this.logger.info(`${fullFilePath} written!`)
|
|
67
67
|
}
|
|
68
68
|
}
|
|
@@ -0,0 +1,309 @@
|
|
|
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
|
+
|
|
14
|
+
/* c8 ignore start */
|
|
15
|
+
const fakeLogger = {
|
|
16
|
+
info: () => {},
|
|
17
|
+
warn: () => {},
|
|
18
|
+
debug: () => {},
|
|
19
|
+
trace: () => {},
|
|
20
|
+
error: () => {}
|
|
21
|
+
}
|
|
22
|
+
/* c8 ignore start */
|
|
23
|
+
|
|
24
|
+
class StackableGenerator extends FileGenerator {
|
|
25
|
+
constructor (opts = {}) {
|
|
26
|
+
super(opts)
|
|
27
|
+
this.files = []
|
|
28
|
+
this.logger = opts.logger || fakeLogger
|
|
29
|
+
this.questions = []
|
|
30
|
+
this.pkgData = null
|
|
31
|
+
this.inquirer = opts.inquirer || null
|
|
32
|
+
this.targetDirectory = opts.targetDirectory || null
|
|
33
|
+
this.config = this.getDefaultConfig()
|
|
34
|
+
this.packages = []
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
getDefaultConfig () {
|
|
38
|
+
return {
|
|
39
|
+
stackableName: 'my-stackable',
|
|
40
|
+
typescript: false,
|
|
41
|
+
initGitRepository: false,
|
|
42
|
+
dependencies: {},
|
|
43
|
+
devDependencies: {}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
setConfigFields (fields) {
|
|
48
|
+
for (const field of fields) {
|
|
49
|
+
this.config[field.configValue] = field.value
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
setConfig (config) {
|
|
54
|
+
if (!config) {
|
|
55
|
+
this.config = this.getDefaultConfig()
|
|
56
|
+
}
|
|
57
|
+
const oldConfig = this.config
|
|
58
|
+
this.config = {
|
|
59
|
+
...this.getDefaultConfig(),
|
|
60
|
+
...oldConfig,
|
|
61
|
+
...config
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (this.config.targetDirectory) {
|
|
65
|
+
this.targetDirectory = this.config.targetDirectory
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/* c8 ignore start */
|
|
70
|
+
async ask () {
|
|
71
|
+
if (this.inquirer) {
|
|
72
|
+
await this.prepareQuestions()
|
|
73
|
+
const newConfig = await this.inquirer.prompt(this.questions)
|
|
74
|
+
this.setConfig({
|
|
75
|
+
...this.config,
|
|
76
|
+
...newConfig
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async prepare () {
|
|
82
|
+
try {
|
|
83
|
+
this.reset()
|
|
84
|
+
await this.getFastifyVersion()
|
|
85
|
+
await this.getPlatformaticVersion()
|
|
86
|
+
|
|
87
|
+
await this._beforePrepare()
|
|
88
|
+
|
|
89
|
+
// generate package.json
|
|
90
|
+
const template = await this.generatePackageJson()
|
|
91
|
+
this.addFile({
|
|
92
|
+
path: '',
|
|
93
|
+
file: 'package.json',
|
|
94
|
+
contents: JSON.stringify(template, null, 2)
|
|
95
|
+
})
|
|
96
|
+
|
|
97
|
+
if (this.config.typescript) {
|
|
98
|
+
// create tsconfig.json
|
|
99
|
+
this.addFile({
|
|
100
|
+
path: '',
|
|
101
|
+
file: 'tsconfig.json',
|
|
102
|
+
contents: JSON.stringify(this.getTsConfig(), null, 2)
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const typescript = this.config.typescript
|
|
107
|
+
const stackableName = this.config.stackableName
|
|
108
|
+
|
|
109
|
+
this.files.push(...generateStackableFiles(typescript, stackableName))
|
|
110
|
+
this.files.push(...generateStackableCli(typescript, stackableName))
|
|
111
|
+
this.files.push(...generateStackablePlugins(typescript))
|
|
112
|
+
this.files.push(generateGitignore())
|
|
113
|
+
|
|
114
|
+
await this._afterPrepare()
|
|
115
|
+
|
|
116
|
+
return {
|
|
117
|
+
targetDirectory: this.targetDirectory
|
|
118
|
+
}
|
|
119
|
+
} catch (err) {
|
|
120
|
+
if (err.code?.startsWith('PLT_GEN')) {
|
|
121
|
+
// throw the same error
|
|
122
|
+
throw err
|
|
123
|
+
}
|
|
124
|
+
const _err = new PrepareError(err.message)
|
|
125
|
+
_err.cause = err
|
|
126
|
+
throw _err
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
getTsConfig () {
|
|
131
|
+
return {
|
|
132
|
+
compilerOptions: {
|
|
133
|
+
module: 'commonjs',
|
|
134
|
+
esModuleInterop: true,
|
|
135
|
+
target: 'es2020',
|
|
136
|
+
sourceMap: true,
|
|
137
|
+
pretty: true,
|
|
138
|
+
noEmitOnError: true,
|
|
139
|
+
incremental: true,
|
|
140
|
+
strict: true,
|
|
141
|
+
outDir: 'dist'
|
|
142
|
+
},
|
|
143
|
+
watchOptions: {
|
|
144
|
+
watchFile: 'fixedPollingInterval',
|
|
145
|
+
watchDirectory: 'fixedPollingInterval',
|
|
146
|
+
fallbackPolling: 'dynamicPriority',
|
|
147
|
+
synchronousWatchDirectory: true,
|
|
148
|
+
excludeDirectories: ['**/node_modules', 'dist']
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
async prepareQuestions () {
|
|
154
|
+
if (!this.config.targetDirectory) {
|
|
155
|
+
// directory
|
|
156
|
+
this.questions.push({
|
|
157
|
+
type: 'input',
|
|
158
|
+
name: 'targetDirectory',
|
|
159
|
+
message: 'Where would you like to create your project?',
|
|
160
|
+
default: 'platformatic'
|
|
161
|
+
})
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
this.questions.push({
|
|
165
|
+
type: 'input',
|
|
166
|
+
name: 'stackableName',
|
|
167
|
+
message: 'What is the name of the stackable?',
|
|
168
|
+
default: 'my-stackable'
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
// typescript
|
|
172
|
+
this.questions.push({
|
|
173
|
+
type: 'list',
|
|
174
|
+
name: 'typescript',
|
|
175
|
+
message: 'Do you want to use TypeScript?',
|
|
176
|
+
default: false,
|
|
177
|
+
choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
|
|
178
|
+
})
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Reads the content of package.json and returns it as an object
|
|
183
|
+
* @returns Object
|
|
184
|
+
*/
|
|
185
|
+
async readPackageJsonFile () {
|
|
186
|
+
if (this.pkgData) {
|
|
187
|
+
return this.pkgData
|
|
188
|
+
}
|
|
189
|
+
const currentPackageJsonPath = join(__dirname, '..', 'package.json')
|
|
190
|
+
this.pkgData = JSON.parse(await readFile(currentPackageJsonPath, 'utf8'))
|
|
191
|
+
return this.pkgData
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async getFastifyVersion () {
|
|
195
|
+
const pkgData = await this.readPackageJsonFile()
|
|
196
|
+
this.fastifyVersion = stripVersion(pkgData.dependencies.fastify)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
async getPlatformaticVersion () {
|
|
200
|
+
const pkgData = await this.readPackageJsonFile()
|
|
201
|
+
this.platformaticVersion = stripVersion(pkgData.version)
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
async generatePackageJson () {
|
|
205
|
+
const dependencies = {
|
|
206
|
+
'@platformatic/config': `^${this.platformaticVersion}`,
|
|
207
|
+
'@platformatic/service': `^${this.platformaticVersion}`,
|
|
208
|
+
'json-schema-to-typescript': '^13.0.0',
|
|
209
|
+
pino: '^8.0.0',
|
|
210
|
+
'pino-pretty': '^10.0.0',
|
|
211
|
+
minimist: '^1.2.0',
|
|
212
|
+
platformatic: `^${this.platformaticVersion}`
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
const devDependencies = {
|
|
216
|
+
fastify: `^${this.fastifyVersion}`
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const npmPackageName = kebabCase(this.config.stackableName)
|
|
220
|
+
const createStackableCommand = kebabCase('create-' + this.config.stackableName)
|
|
221
|
+
const startStackableCommand = kebabCase('start-' + this.config.stackableName)
|
|
222
|
+
|
|
223
|
+
if (this.config.typescript) {
|
|
224
|
+
const packageJsonFile = await readFile(join(__dirname, '..', 'package.json'), 'utf-8')
|
|
225
|
+
const typescriptVersion = JSON.parse(packageJsonFile).devDependencies.typescript
|
|
226
|
+
|
|
227
|
+
return {
|
|
228
|
+
name: npmPackageName,
|
|
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
|
+
'build:config': 'node ./dist/lib/schema.js | json2ts > config.d.ts',
|
|
237
|
+
clean: 'rm -fr ./dist'
|
|
238
|
+
},
|
|
239
|
+
devDependencies: {
|
|
240
|
+
...devDependencies,
|
|
241
|
+
'@types/minimist': '^1.2.5',
|
|
242
|
+
typescript: typescriptVersion,
|
|
243
|
+
...this.config.devDependencies
|
|
244
|
+
},
|
|
245
|
+
dependencies: {
|
|
246
|
+
...dependencies,
|
|
247
|
+
'@platformatic/generators': `^${this.platformaticVersion}`,
|
|
248
|
+
...this.config.dependencies
|
|
249
|
+
},
|
|
250
|
+
engines: {
|
|
251
|
+
node: '^18.8.0 || >=20.6.0'
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return {
|
|
257
|
+
name: npmPackageName,
|
|
258
|
+
main: 'index.js',
|
|
259
|
+
bin: {
|
|
260
|
+
[createStackableCommand]: './cli/create.js',
|
|
261
|
+
[startStackableCommand]: './cli/start.js'
|
|
262
|
+
},
|
|
263
|
+
scripts: {
|
|
264
|
+
'build:config': 'node lib/schema.js | json2ts > config.d.ts'
|
|
265
|
+
},
|
|
266
|
+
devDependencies: {
|
|
267
|
+
...devDependencies,
|
|
268
|
+
...this.config.devDependencies
|
|
269
|
+
},
|
|
270
|
+
dependencies: {
|
|
271
|
+
...dependencies,
|
|
272
|
+
...this.config.dependencies
|
|
273
|
+
},
|
|
274
|
+
engines: {
|
|
275
|
+
node: '^18.8.0 || >=20.6.0'
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
async run () {
|
|
281
|
+
const metadata = await this.prepare()
|
|
282
|
+
await this.writeFiles()
|
|
283
|
+
return metadata
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
async addPackage (pkg) {
|
|
287
|
+
this.config.dependencies[pkg.name] = 'latest'
|
|
288
|
+
try {
|
|
289
|
+
const version = await getLatestNpmVersion(pkg.name)
|
|
290
|
+
if (version) {
|
|
291
|
+
this.config.dependencies[pkg.name] = version
|
|
292
|
+
}
|
|
293
|
+
} catch (err) {
|
|
294
|
+
this.logger.warn(`Could not get latest version for ${pkg.name}, setting it to latest`)
|
|
295
|
+
}
|
|
296
|
+
this.packages.push(pkg)
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
// implement in the subclass
|
|
300
|
+
/* c8 ignore next 1 */
|
|
301
|
+
async postInstallActions () {}
|
|
302
|
+
async _beforePrepare () {}
|
|
303
|
+
async _afterPrepare () {}
|
|
304
|
+
async _getConfigFileContents () { return {} }
|
|
305
|
+
async _generateEnv () {}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
module.exports = StackableGenerator
|
|
309
|
+
module.exports.StackableGenerator = StackableGenerator
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platformatic/generators",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.20.0",
|
|
4
4
|
"description": "Main classes and utils for generators.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"keywords": [],
|
|
@@ -9,20 +9,22 @@
|
|
|
9
9
|
"dependencies": {
|
|
10
10
|
"@fastify/error": "^3.4.1",
|
|
11
11
|
"boring-name-generator": "^1.0.3",
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
12
|
+
"change-case-all": "^2.1.0",
|
|
13
|
+
"fastify": "^4.26.0",
|
|
14
|
+
"pino": "^8.17.2",
|
|
15
|
+
"undici": "^6.6.0"
|
|
15
16
|
},
|
|
16
17
|
"devDependencies": {
|
|
17
18
|
"@types/inquirer": "^9.0.7",
|
|
18
|
-
"
|
|
19
|
+
"borp": "^0.9.0",
|
|
20
|
+
"c8": "^9.1.0",
|
|
19
21
|
"glob": "^10.3.10",
|
|
20
22
|
"snazzy": "^9.0.0",
|
|
21
23
|
"standard": "^17.1.0",
|
|
22
|
-
"typescript": "^5.
|
|
24
|
+
"typescript": "^5.3.3"
|
|
23
25
|
},
|
|
24
26
|
"scripts": {
|
|
25
27
|
"lint": "standard | snazzy",
|
|
26
|
-
"test": "pnpm run lint &&
|
|
28
|
+
"test": "pnpm run lint && borp -C -X fixtures -X test --concurrency=1"
|
|
27
29
|
}
|
|
28
30
|
}
|
|
@@ -74,7 +74,8 @@ test('extended class should generate config', async (t) => {
|
|
|
74
74
|
assert.deepEqual(configFile, {
|
|
75
75
|
path: '',
|
|
76
76
|
file: 'platformatic.json',
|
|
77
|
-
contents: JSON.stringify({ foo: 'bar' }, null, 2)
|
|
77
|
+
contents: JSON.stringify({ foo: 'bar' }, null, 2),
|
|
78
|
+
options: {}
|
|
78
79
|
})
|
|
79
80
|
})
|
|
80
81
|
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
const { readFile, rm } = require('node:fs/promises')
|
|
4
|
+
const { test, afterEach } = require('node:test')
|
|
5
|
+
const assert = require('node:assert')
|
|
6
|
+
const { join } = require('node:path')
|
|
7
|
+
|
|
8
|
+
const { fakeLogger, getTempDir } = require('./helpers')
|
|
9
|
+
const { StackableGenerator } = require('../lib/stackable-generator')
|
|
10
|
+
|
|
11
|
+
afterEach(async () => {
|
|
12
|
+
try {
|
|
13
|
+
await rm(join(__dirname, 'tmp'), { recursive: true })
|
|
14
|
+
} catch (err) {
|
|
15
|
+
// do nothing
|
|
16
|
+
}
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
test('should create a stackable project without typescript', async (t) => {
|
|
20
|
+
const dir = await getTempDir()
|
|
21
|
+
const gen = new StackableGenerator({
|
|
22
|
+
logger: fakeLogger
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
gen.setConfig({
|
|
26
|
+
targetDirectory: dir
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
await gen.run()
|
|
30
|
+
// check files are created
|
|
31
|
+
const packageJson = JSON.parse(await readFile(join(dir, 'package.json'), 'utf8'))
|
|
32
|
+
assert.ok(packageJson.scripts)
|
|
33
|
+
assert.ok(packageJson.dependencies)
|
|
34
|
+
assert.ok(packageJson.engines)
|
|
35
|
+
|
|
36
|
+
const indexFile = await readFile(join(dir, 'index.js'), 'utf8')
|
|
37
|
+
assert.ok(indexFile.length > 0)
|
|
38
|
+
|
|
39
|
+
const indexTypesFile = await readFile(join(dir, 'index.d.ts'), 'utf8')
|
|
40
|
+
assert.ok(indexTypesFile.length > 0)
|
|
41
|
+
|
|
42
|
+
const schemaFile = await readFile(join(dir, 'lib', 'schema.js'), 'utf8')
|
|
43
|
+
assert.ok(schemaFile.length > 0)
|
|
44
|
+
|
|
45
|
+
const generatorFile = await readFile(join(dir, 'lib', 'generator.js'), 'utf8')
|
|
46
|
+
assert.ok(generatorFile.length > 0)
|
|
47
|
+
|
|
48
|
+
const startCommandFile = await readFile(join(dir, 'cli', 'start.js'), 'utf8')
|
|
49
|
+
assert.ok(startCommandFile.length > 0)
|
|
50
|
+
|
|
51
|
+
const createCommandFile = await readFile(join(dir, 'cli', 'create.js'), 'utf8')
|
|
52
|
+
assert.ok(createCommandFile.length > 0)
|
|
53
|
+
|
|
54
|
+
const gitignore = await readFile(join(dir, '.gitignore'), 'utf8')
|
|
55
|
+
assert.ok(gitignore.length > 0)
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
test('should create a stackable project with typescript', async (t) => {
|
|
59
|
+
const dir = await getTempDir()
|
|
60
|
+
const gen = new StackableGenerator({
|
|
61
|
+
logger: fakeLogger
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
gen.setConfig({
|
|
65
|
+
targetDirectory: dir,
|
|
66
|
+
typescript: true
|
|
67
|
+
})
|
|
68
|
+
|
|
69
|
+
await gen.run()
|
|
70
|
+
// check files are created
|
|
71
|
+
const packageJson = JSON.parse(await readFile(join(dir, 'package.json'), 'utf8'))
|
|
72
|
+
assert.ok(packageJson.scripts)
|
|
73
|
+
assert.ok(packageJson.dependencies)
|
|
74
|
+
assert.ok(packageJson.engines)
|
|
75
|
+
|
|
76
|
+
const indexFile = await readFile(join(dir, 'index.ts'), 'utf8')
|
|
77
|
+
assert.ok(indexFile.length > 0)
|
|
78
|
+
|
|
79
|
+
const indexTypesFile = await readFile(join(dir, 'index.d.ts'), 'utf8')
|
|
80
|
+
assert.ok(indexTypesFile.length > 0)
|
|
81
|
+
|
|
82
|
+
const schemaFile = await readFile(join(dir, 'lib', 'schema.ts'), 'utf8')
|
|
83
|
+
assert.ok(schemaFile.length > 0)
|
|
84
|
+
|
|
85
|
+
const generatorFile = await readFile(join(dir, 'lib', 'generator.ts'), 'utf8')
|
|
86
|
+
assert.ok(generatorFile.length > 0)
|
|
87
|
+
|
|
88
|
+
const startCommandFile = await readFile(join(dir, 'cli', 'start.ts'), 'utf8')
|
|
89
|
+
assert.ok(startCommandFile.length > 0)
|
|
90
|
+
|
|
91
|
+
const createCommandFile = await readFile(join(dir, 'cli', 'create.ts'), 'utf8')
|
|
92
|
+
assert.ok(createCommandFile.length > 0)
|
|
93
|
+
|
|
94
|
+
const gitignore = await readFile(join(dir, '.gitignore'), 'utf8')
|
|
95
|
+
assert.ok(gitignore.length > 0)
|
|
96
|
+
})
|