create-platformatic 0.45.1 → 0.46.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.
- package/package.json +4 -4
- package/src/composer/create-composer-cli.mjs +1 -1
- package/src/create-plugins.mjs +232 -0
- package/src/db/create-db-cli.mjs +3 -2
- package/src/db/create-db.mjs +246 -36
- package/src/ghaction.mjs +1 -1
- package/src/runtime/create-runtime-cli.mjs +1 -1
- package/src/service/create-service-cli.mjs +6 -3
- package/src/service/create-service.mjs +3 -84
- package/test/cli-options.test.mjs +0 -84
- package/test/composer/create-composer.test.mjs +0 -75
- package/test/create-gitignore.test.mjs +0 -35
- package/test/create-package-json.test.mjs +0 -81
- package/test/db/create-db.test.mjs +0 -295
- package/test/exports.test.mjs +0 -8
- package/test/get-pkg-manager.test.mjs +0 -36
- package/test/ghaction-dynamic.test.mjs +0 -98
- package/test/ghaction-static.test.mjs +0 -97
- package/test/runtime/create-runtime.test.mjs +0 -70
- package/test/service/create-service.test.mjs +0 -147
- package/test/utils.test.mjs +0 -261
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-platformatic",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.46.2",
|
|
4
4
|
"description": "Create platformatic-db interactive tool",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"semver": "^7.5.1",
|
|
35
35
|
"undici": "^5.22.1",
|
|
36
36
|
"which": "^3.0.1",
|
|
37
|
-
"@platformatic/config": "0.
|
|
37
|
+
"@platformatic/config": "0.46.2"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"ajv": "^8.12.0",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"tap": "^16.3.6",
|
|
48
48
|
"typescript": "~5.2.0",
|
|
49
49
|
"yaml": "^2.3.1",
|
|
50
|
-
"@platformatic/db": "0.
|
|
51
|
-
"@platformatic/service": "0.
|
|
50
|
+
"@platformatic/db": "0.46.2",
|
|
51
|
+
"@platformatic/service": "0.46.2"
|
|
52
52
|
},
|
|
53
53
|
"scripts": {
|
|
54
54
|
"test": "standard | snazzy && cross-env NODE_OPTIONS=\"--loader=esmock --no-warnings\" c8 tap --no-coverage test/*test.mjs test/*/*test.mjs",
|
|
@@ -93,8 +93,8 @@ const createPlatformaticComposer = async (_args, opts) => {
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
if (!opts.skipGitHubActions) {
|
|
96
|
-
await askDynamicWorkspaceCreateGHAction(logger, env, 'composer', false, projectDir)
|
|
97
96
|
await askStaticWorkspaceGHAction(logger, env, 'composer', false, projectDir)
|
|
97
|
+
await askDynamicWorkspaceCreateGHAction(logger, env, 'composer', false, projectDir)
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
100
|
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { join } from 'path'
|
|
2
|
+
import { writeFile, mkdir } from 'fs/promises'
|
|
3
|
+
import { isFileAccessible } from './utils.mjs'
|
|
4
|
+
|
|
5
|
+
const JS_PLUGIN_WITH_TYPES_SUPPORT = `\
|
|
6
|
+
/// <reference path="../global.d.ts" />
|
|
7
|
+
'use strict'
|
|
8
|
+
/** @param {import('fastify').FastifyInstance} fastify */
|
|
9
|
+
module.exports = async function (fastify, opts) {
|
|
10
|
+
fastify.decorate('example', 'foobar')
|
|
11
|
+
}
|
|
12
|
+
`
|
|
13
|
+
|
|
14
|
+
const TS_PLUGIN_WITH_TYPES_SUPPORT = `\
|
|
15
|
+
/// <reference path="../global.d.ts" />
|
|
16
|
+
import { FastifyInstance, FastifyPluginOptions } from 'fastify'
|
|
17
|
+
|
|
18
|
+
export default async function (fastify: FastifyInstance, opts: FastifyPluginOptions) {
|
|
19
|
+
fastify.decorate('example', 'foobar')
|
|
20
|
+
}
|
|
21
|
+
`
|
|
22
|
+
|
|
23
|
+
const JS_ROUTES_WITH_TYPES_SUPPORT = `\
|
|
24
|
+
/// <reference path="../global.d.ts" />
|
|
25
|
+
'use strict'
|
|
26
|
+
/** @param {import('fastify').FastifyInstance} fastify */
|
|
27
|
+
module.exports = async function (fastify, opts) {
|
|
28
|
+
fastify.get('/example', async (request, reply) => {
|
|
29
|
+
return { hello: fastify.example }
|
|
30
|
+
})
|
|
31
|
+
}
|
|
32
|
+
`
|
|
33
|
+
|
|
34
|
+
const TS_ROUTES_WITH_TYPES_SUPPORT = `\
|
|
35
|
+
/// <reference path="../global.d.ts" />
|
|
36
|
+
import { FastifyInstance, FastifyPluginOptions } from 'fastify'
|
|
37
|
+
|
|
38
|
+
declare module 'fastify' {
|
|
39
|
+
interface FastifyInstance {
|
|
40
|
+
example: string
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export default async function (fastify: FastifyInstance, opts: FastifyPluginOptions) {
|
|
45
|
+
fastify.get('/example', async (request, reply) => {
|
|
46
|
+
return { hello: fastify.example }
|
|
47
|
+
})
|
|
48
|
+
}
|
|
49
|
+
`
|
|
50
|
+
|
|
51
|
+
function testHelperJS (mod, customization = { pre: '', post: '', config: '' }) {
|
|
52
|
+
return `\
|
|
53
|
+
'use strict'
|
|
54
|
+
|
|
55
|
+
const { join } = require('node:path')
|
|
56
|
+
const { readFile } = require('node:fs/promises')
|
|
57
|
+
const { buildServer } = require('@platformatic/${mod}')
|
|
58
|
+
${customization.requires || ''}
|
|
59
|
+
|
|
60
|
+
async function getServer (t) {
|
|
61
|
+
${customization.pre || ''}
|
|
62
|
+
const config = JSON.parse(await readFile(join(__dirname, '..', 'platformatic.${mod}.json'), 'utf8'))
|
|
63
|
+
// Add your config customizations here. For example you want to set
|
|
64
|
+
// all things that are set in the config file to read from an env variable
|
|
65
|
+
config.server.logger.level = 'warn'
|
|
66
|
+
config.watch = false
|
|
67
|
+
${customization.config || ''}
|
|
68
|
+
// Add your config customizations here
|
|
69
|
+
const server = await buildServer(config)
|
|
70
|
+
t.after(() => server.close())
|
|
71
|
+
${customization.post || ''}
|
|
72
|
+
return server
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
module.exports.getServer = getServer
|
|
76
|
+
`
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const TEST_ROUTES_JS = `\
|
|
80
|
+
'use strict'
|
|
81
|
+
|
|
82
|
+
const test = require('node:test')
|
|
83
|
+
const assert = require('node:assert')
|
|
84
|
+
const { getServer } = require('../helper')
|
|
85
|
+
|
|
86
|
+
test('example', async (t) => {
|
|
87
|
+
const server = await getServer(t)
|
|
88
|
+
const res = await server.inject({
|
|
89
|
+
method: 'GET',
|
|
90
|
+
url: '/example'
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
assert.strictEqual(res.statusCode, 200)
|
|
94
|
+
assert.deepStrictEqual(res.json(), {
|
|
95
|
+
hello: 'foobar'
|
|
96
|
+
})
|
|
97
|
+
})
|
|
98
|
+
`
|
|
99
|
+
|
|
100
|
+
const TEST_PLUGIN_JS = `\
|
|
101
|
+
'use strict'
|
|
102
|
+
|
|
103
|
+
const test = require('node:test')
|
|
104
|
+
const assert = require('node:assert')
|
|
105
|
+
const { getServer } = require('../helper')
|
|
106
|
+
|
|
107
|
+
test('example decorator', async (t) => {
|
|
108
|
+
const server = await getServer(t)
|
|
109
|
+
|
|
110
|
+
assert.strictEqual(server.example, 'foobar')
|
|
111
|
+
})
|
|
112
|
+
`
|
|
113
|
+
|
|
114
|
+
function testHelperTS (mod, customizations = { pre: '', post: '', config: '', requires: '' }) {
|
|
115
|
+
return `\
|
|
116
|
+
import { join } from 'node:path'
|
|
117
|
+
import { readFile } from 'node:fs/promises'
|
|
118
|
+
import { buildServer } from '@platformatic/${mod}'
|
|
119
|
+
${customizations.requires}
|
|
120
|
+
|
|
121
|
+
export async function getServer (t) {
|
|
122
|
+
${customizations.pre}
|
|
123
|
+
// We go up two folder because this files executes in the dist folder
|
|
124
|
+
const config = JSON.parse(await readFile(join(__dirname, '..', '..', 'platformatic.${mod}.json'), 'utf8'))
|
|
125
|
+
// Add your config customizations here. For example you want to set
|
|
126
|
+
// all things that are set in the config file to read from an env variable
|
|
127
|
+
config.server.logger.level = 'warn'
|
|
128
|
+
config.watch = false
|
|
129
|
+
${customizations.config}
|
|
130
|
+
// Add your config customizations here
|
|
131
|
+
const server = await buildServer(config)
|
|
132
|
+
t.after(() => server.close())
|
|
133
|
+
${customizations.post}
|
|
134
|
+
return server
|
|
135
|
+
}
|
|
136
|
+
`
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const TEST_ROUTES_TS = `\
|
|
140
|
+
import test from 'node:test'
|
|
141
|
+
import assert from 'node:assert'
|
|
142
|
+
import { getServer } from '../helper'
|
|
143
|
+
|
|
144
|
+
test('root', async (t) => {
|
|
145
|
+
const server = await getServer(t)
|
|
146
|
+
const res = await server.inject({
|
|
147
|
+
method: 'GET',
|
|
148
|
+
url: '/example'
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
assert.strictEqual(res.statusCode, 200)
|
|
152
|
+
assert.deepStrictEqual(res.json(), {
|
|
153
|
+
hello: 'foobar'
|
|
154
|
+
})
|
|
155
|
+
})
|
|
156
|
+
`
|
|
157
|
+
|
|
158
|
+
const TEST_PLUGIN_TS = `\
|
|
159
|
+
import test from 'node:test'
|
|
160
|
+
import assert from 'node:assert'
|
|
161
|
+
import { getServer } from '../helper'
|
|
162
|
+
|
|
163
|
+
test('example decorator', async (t) => {
|
|
164
|
+
const server = await getServer(t)
|
|
165
|
+
|
|
166
|
+
assert.strictEqual(server.example, 'foobar')
|
|
167
|
+
})
|
|
168
|
+
`
|
|
169
|
+
|
|
170
|
+
export async function generatePluginWithTypesSupport (logger, currentDir, isTypescript) {
|
|
171
|
+
const accessible = await isFileAccessible('plugins', currentDir)
|
|
172
|
+
if (accessible) {
|
|
173
|
+
logger.info('Plugins folder "plugins" found, skipping creation of plugins folder.')
|
|
174
|
+
return
|
|
175
|
+
}
|
|
176
|
+
await mkdir(join(currentDir, 'plugins'))
|
|
177
|
+
const pluginTemplate = isTypescript
|
|
178
|
+
? TS_PLUGIN_WITH_TYPES_SUPPORT
|
|
179
|
+
: JS_PLUGIN_WITH_TYPES_SUPPORT
|
|
180
|
+
const pluginName = isTypescript
|
|
181
|
+
? 'example.ts'
|
|
182
|
+
: 'example.js'
|
|
183
|
+
await writeFile(join(currentDir, 'plugins', pluginName), pluginTemplate)
|
|
184
|
+
logger.info('Plugins folder "plugins" successfully created.')
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export async function generateRouteWithTypesSupport (logger, currentDir, isTypescript) {
|
|
188
|
+
const accessible = await isFileAccessible('routes', currentDir)
|
|
189
|
+
if (accessible) {
|
|
190
|
+
logger.info('Routes folder "routes" found, skipping creation of routes folder.')
|
|
191
|
+
return
|
|
192
|
+
}
|
|
193
|
+
await mkdir(join(currentDir, 'routes'))
|
|
194
|
+
const routesTemplate = isTypescript
|
|
195
|
+
? TS_ROUTES_WITH_TYPES_SUPPORT
|
|
196
|
+
: JS_ROUTES_WITH_TYPES_SUPPORT
|
|
197
|
+
const routesName = isTypescript
|
|
198
|
+
? 'root.ts'
|
|
199
|
+
: 'root.js'
|
|
200
|
+
await writeFile(join(currentDir, 'routes', routesName), routesTemplate)
|
|
201
|
+
logger.info('Routes folder "routes" successfully created.')
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
export async function generateTests (logger, currentDir, isTypescript, mod, customizations) {
|
|
205
|
+
const accessible = await isFileAccessible('tests', currentDir)
|
|
206
|
+
if (accessible) {
|
|
207
|
+
logger.info('Test folder found, skipping creation of tests.')
|
|
208
|
+
return
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
await mkdir(join(currentDir, 'test'))
|
|
212
|
+
await mkdir(join(currentDir, 'test', 'plugins'))
|
|
213
|
+
await mkdir(join(currentDir, 'test', 'routes'))
|
|
214
|
+
|
|
215
|
+
if (isTypescript) {
|
|
216
|
+
await writeFile(join(currentDir, 'test', 'helper.ts'), testHelperTS(mod, customizations))
|
|
217
|
+
await writeFile(join(currentDir, 'test', 'plugins', 'example.test.ts'), TEST_PLUGIN_TS)
|
|
218
|
+
await writeFile(join(currentDir, 'test', 'routes', 'root.test.ts'), TEST_ROUTES_TS)
|
|
219
|
+
} else {
|
|
220
|
+
await writeFile(join(currentDir, 'test', 'helper.js'), testHelperJS(mod, customizations))
|
|
221
|
+
await writeFile(join(currentDir, 'test', 'plugins', 'example.test.js'), TEST_PLUGIN_JS)
|
|
222
|
+
await writeFile(join(currentDir, 'test', 'routes', 'root.test.js'), TEST_ROUTES_JS)
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
logger.info('Test folder "tests" successfully created.')
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
export async function generatePlugins (logger, currentDir, isTypescript, mod, helperCustomization) {
|
|
229
|
+
await generatePluginWithTypesSupport(logger, currentDir, isTypescript)
|
|
230
|
+
await generateRouteWithTypesSupport(logger, currentDir, isTypescript)
|
|
231
|
+
await generateTests(logger, currentDir, isTypescript, mod, helperCustomization)
|
|
232
|
+
}
|
package/src/db/create-db-cli.mjs
CHANGED
|
@@ -166,7 +166,8 @@ const createPlatformaticDB = async (_args, opts) => {
|
|
|
166
166
|
const fastifyVersion = await getDependencyVersion('fastify')
|
|
167
167
|
|
|
168
168
|
const scripts = {
|
|
169
|
-
migrate: 'platformatic db migrations apply'
|
|
169
|
+
migrate: 'platformatic db migrations apply',
|
|
170
|
+
test: useTypescript ? 'tsc && node --test dist/test/*/*.test.js' : 'node --test test/*/*.test.js'
|
|
170
171
|
}
|
|
171
172
|
|
|
172
173
|
const dependencies = {
|
|
@@ -245,8 +246,8 @@ const createPlatformaticDB = async (_args, opts) => {
|
|
|
245
246
|
}
|
|
246
247
|
|
|
247
248
|
if (!opts.skipGitHubActions) {
|
|
248
|
-
await askDynamicWorkspaceCreateGHAction(logger, env, 'db', useTypescript, projectDir)
|
|
249
249
|
await askStaticWorkspaceGHAction(logger, env, 'db', useTypescript, projectDir)
|
|
250
|
+
await askDynamicWorkspaceCreateGHAction(logger, env, 'db', useTypescript, projectDir)
|
|
250
251
|
}
|
|
251
252
|
}
|
|
252
253
|
|
package/src/db/create-db.mjs
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { writeFile, mkdir, appendFile } from 'fs/promises'
|
|
2
|
-
import { join
|
|
2
|
+
import { join } from 'path'
|
|
3
3
|
import { findDBConfigFile, isFileAccessible } from '../utils.mjs'
|
|
4
4
|
import { getTsConfig } from '../get-tsconfig.mjs'
|
|
5
|
+
import { generatePlugins } from '../create-plugins.mjs'
|
|
5
6
|
|
|
6
7
|
const connectionStrings = {
|
|
7
8
|
postgres: 'postgres://postgres:postgres@127.0.0.1:5432/postgres',
|
|
@@ -32,9 +33,222 @@ const moviesMigrationUndo = `
|
|
|
32
33
|
DROP TABLE movies;
|
|
33
34
|
`
|
|
34
35
|
|
|
35
|
-
const getPluginName = (isTypescript) => isTypescript === true ? 'plugin.ts' : 'plugin.js'
|
|
36
36
|
const TS_OUT_DIR = 'dist'
|
|
37
37
|
|
|
38
|
+
const jsHelperSqlite = {
|
|
39
|
+
requires: `
|
|
40
|
+
const os = require('node:os')
|
|
41
|
+
const path = require('node:path')
|
|
42
|
+
const fs = require('node:fs/promises')
|
|
43
|
+
|
|
44
|
+
let counter = 0
|
|
45
|
+
`,
|
|
46
|
+
pre: `
|
|
47
|
+
const dbPath = join(os.tmpdir(), 'db-' + process.pid + '-' + counter++ + '.sqlite')
|
|
48
|
+
const connectionString = 'sqlite://' + dbPath
|
|
49
|
+
`,
|
|
50
|
+
config: `
|
|
51
|
+
config.migrations.autoApply = true
|
|
52
|
+
config.types.autogenerate = false
|
|
53
|
+
config.db.connectionString = connectionString
|
|
54
|
+
`,
|
|
55
|
+
post: `
|
|
56
|
+
t.after(async () => {
|
|
57
|
+
await fs.unlink(dbPath)
|
|
58
|
+
})
|
|
59
|
+
`
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function jsHelperPostgres (connectionString) {
|
|
63
|
+
return {
|
|
64
|
+
// TODO(mcollina): replace sql-mapper
|
|
65
|
+
requires: `
|
|
66
|
+
const { createConnectionPool } = require('@platformatic/sql-mapper')
|
|
67
|
+
const connectionString = '${connectionString}'
|
|
68
|
+
let counter = 0
|
|
69
|
+
`,
|
|
70
|
+
pre: `
|
|
71
|
+
const { db, sql } = await createConnectionPool({
|
|
72
|
+
log: {
|
|
73
|
+
debug: () => {},
|
|
74
|
+
info: () => {},
|
|
75
|
+
trace: () => {}
|
|
76
|
+
},
|
|
77
|
+
connectionString,
|
|
78
|
+
poolSize: 1
|
|
79
|
+
})
|
|
80
|
+
|
|
81
|
+
const newDB = \`t-\${process.pid}-\${counter++}\`
|
|
82
|
+
t.diagnostic('Creating database ' + newDB)
|
|
83
|
+
|
|
84
|
+
await db.query(sql\`
|
|
85
|
+
CREATE DATABASE \${sql.ident(newDB)}
|
|
86
|
+
\`)
|
|
87
|
+
`,
|
|
88
|
+
config: `
|
|
89
|
+
config.migrations.autoApply = true
|
|
90
|
+
config.types.autogenerate = false
|
|
91
|
+
config.db.connectionString = connectionString.replace(/\\/[a-zA-Z0-9\\-_]+$/, '/' + newDB)
|
|
92
|
+
config.db.schemalock = false
|
|
93
|
+
`,
|
|
94
|
+
post: `
|
|
95
|
+
t.after(async () => {
|
|
96
|
+
t.diagnostic('Disposing test database ' + newDB)
|
|
97
|
+
await db.query(sql\`
|
|
98
|
+
DROP DATABASE \${sql.ident(newDB)}
|
|
99
|
+
\`)
|
|
100
|
+
await db.dispose()
|
|
101
|
+
})
|
|
102
|
+
`
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function jsHelperMySQL (connectionString) {
|
|
107
|
+
return {
|
|
108
|
+
// TODO(mcollina): replace sql-mapper
|
|
109
|
+
requires: `
|
|
110
|
+
const { createConnectionPool } = require('@platformatic/sql-mapper')
|
|
111
|
+
const connectionString = '${connectionString}'
|
|
112
|
+
let counter = 0
|
|
113
|
+
`,
|
|
114
|
+
pre: `
|
|
115
|
+
const { db, sql } = await createConnectionPool({
|
|
116
|
+
log: {
|
|
117
|
+
debug: () => {},
|
|
118
|
+
info: () => {},
|
|
119
|
+
trace: () => {}
|
|
120
|
+
},
|
|
121
|
+
connectionString,
|
|
122
|
+
poolSize: 1
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
const newDB = \`t-\${process.pid}-\${counter++}\`
|
|
126
|
+
t.diagnostic('Creating database ' + newDB)
|
|
127
|
+
|
|
128
|
+
await db.query(sql\`
|
|
129
|
+
CREATE DATABASE \${sql.ident(newDB)}
|
|
130
|
+
\`)
|
|
131
|
+
`,
|
|
132
|
+
config: `
|
|
133
|
+
config.migrations.autoApply = true
|
|
134
|
+
config.types.autogenerate = false
|
|
135
|
+
config.db.connectionString = connectionString.replace(/\\/[a-zA-Z0-9\\-_]+$/, '/' + newDB)
|
|
136
|
+
config.db.schemalock = false
|
|
137
|
+
`,
|
|
138
|
+
post: `
|
|
139
|
+
t.after(async () => {
|
|
140
|
+
t.diagnostic('Disposing test database ' + newDB)
|
|
141
|
+
await db.query(sql\`
|
|
142
|
+
DROP DATABASE \${sql.ident(newDB)}
|
|
143
|
+
\`)
|
|
144
|
+
await db.dispose()
|
|
145
|
+
})
|
|
146
|
+
`
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
const moviesTestJS = `\
|
|
151
|
+
'use strict'
|
|
152
|
+
|
|
153
|
+
const test = require('node:test')
|
|
154
|
+
const assert = require('node:assert')
|
|
155
|
+
const { getServer } = require('../helper')
|
|
156
|
+
|
|
157
|
+
test('movies', async (t) => {
|
|
158
|
+
const server = await getServer(t)
|
|
159
|
+
|
|
160
|
+
{
|
|
161
|
+
const res = await server.inject({
|
|
162
|
+
method: 'GET',
|
|
163
|
+
url: '/movies'
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
assert.strictEqual(res.statusCode, 200)
|
|
167
|
+
assert.deepStrictEqual(res.json(), [])
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
let id
|
|
171
|
+
{
|
|
172
|
+
const res = await server.inject({
|
|
173
|
+
method: 'POST',
|
|
174
|
+
url: '/movies',
|
|
175
|
+
body: {
|
|
176
|
+
title: 'The Matrix'
|
|
177
|
+
}
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
assert.strictEqual(res.statusCode, 200)
|
|
181
|
+
const body = res.json()
|
|
182
|
+
assert.strictEqual(body.title, 'The Matrix')
|
|
183
|
+
assert.strictEqual(body.id !== undefined, true)
|
|
184
|
+
id = body.id
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
{
|
|
188
|
+
const res = await server.inject({
|
|
189
|
+
method: 'GET',
|
|
190
|
+
url: '/movies'
|
|
191
|
+
})
|
|
192
|
+
|
|
193
|
+
assert.strictEqual(res.statusCode, 200)
|
|
194
|
+
assert.deepStrictEqual(res.json(), [{
|
|
195
|
+
id,
|
|
196
|
+
title: 'The Matrix'
|
|
197
|
+
}])
|
|
198
|
+
}
|
|
199
|
+
})
|
|
200
|
+
`
|
|
201
|
+
|
|
202
|
+
const moviesTestTS = `\
|
|
203
|
+
import test from 'node:test'
|
|
204
|
+
import assert from 'node:assert'
|
|
205
|
+
import { getServer } from '../helper'
|
|
206
|
+
|
|
207
|
+
test('movies', async (t) => {
|
|
208
|
+
const server = await getServer(t)
|
|
209
|
+
|
|
210
|
+
{
|
|
211
|
+
const res = await server.inject({
|
|
212
|
+
method: 'GET',
|
|
213
|
+
url: '/movies'
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
assert.strictEqual(res.statusCode, 200)
|
|
217
|
+
assert.deepStrictEqual(res.json(), [])
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
let id : Number
|
|
221
|
+
{
|
|
222
|
+
const res = await server.inject({
|
|
223
|
+
method: 'POST',
|
|
224
|
+
url: '/movies',
|
|
225
|
+
body: {
|
|
226
|
+
title: 'The Matrix'
|
|
227
|
+
}
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
assert.strictEqual(res.statusCode, 200)
|
|
231
|
+
const body = res.json()
|
|
232
|
+
assert.strictEqual(body.title, 'The Matrix')
|
|
233
|
+
assert.strictEqual(body.id !== undefined, true)
|
|
234
|
+
id = body.id as Number
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
{
|
|
238
|
+
const res = await server.inject({
|
|
239
|
+
method: 'GET',
|
|
240
|
+
url: '/movies'
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
assert.strictEqual(res.statusCode, 200)
|
|
244
|
+
assert.deepStrictEqual(res.json(), [{
|
|
245
|
+
id,
|
|
246
|
+
title: 'The Matrix'
|
|
247
|
+
}])
|
|
248
|
+
}
|
|
249
|
+
})
|
|
250
|
+
`
|
|
251
|
+
|
|
38
252
|
function generateConfig (migrations, plugin, types, typescript, version) {
|
|
39
253
|
const config = {
|
|
40
254
|
$schema: `https://platformatic.dev/schemas/v${version}/db`,
|
|
@@ -64,7 +278,12 @@ function generateConfig (migrations, plugin, types, typescript, version) {
|
|
|
64
278
|
|
|
65
279
|
if (plugin === true) {
|
|
66
280
|
config.plugins = {
|
|
67
|
-
paths: [
|
|
281
|
+
paths: [{
|
|
282
|
+
path: './plugins',
|
|
283
|
+
encapsulate: false
|
|
284
|
+
}, {
|
|
285
|
+
path: './routes'
|
|
286
|
+
}]
|
|
68
287
|
}
|
|
69
288
|
}
|
|
70
289
|
|
|
@@ -101,38 +320,6 @@ PLT_TYPESCRIPT=true
|
|
|
101
320
|
return env
|
|
102
321
|
}
|
|
103
322
|
|
|
104
|
-
const JS_PLUGIN_WITH_TYPES_SUPPORT = `\
|
|
105
|
-
/// <reference path="./global.d.ts" />
|
|
106
|
-
'use strict'
|
|
107
|
-
|
|
108
|
-
/** @param {import('fastify').FastifyInstance} app */
|
|
109
|
-
module.exports = async function (app) {}
|
|
110
|
-
`
|
|
111
|
-
|
|
112
|
-
const TS_PLUGIN_WITH_TYPES_SUPPORT = `\
|
|
113
|
-
/// <reference path="./global.d.ts" />
|
|
114
|
-
import { FastifyInstance } from 'fastify'
|
|
115
|
-
|
|
116
|
-
export default async function (app: FastifyInstance) {}
|
|
117
|
-
`
|
|
118
|
-
|
|
119
|
-
async function generatePluginWithTypesSupport (logger, currentDir, isTypescript) {
|
|
120
|
-
const pluginPath = resolve(currentDir, getPluginName(isTypescript))
|
|
121
|
-
|
|
122
|
-
const isPluginExists = await isFileAccessible(pluginPath)
|
|
123
|
-
if (isPluginExists) {
|
|
124
|
-
logger.info(`Plugin file ${pluginPath} found, skipping creation of plugin file.`)
|
|
125
|
-
return
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const pluginTemplate = isTypescript
|
|
129
|
-
? TS_PLUGIN_WITH_TYPES_SUPPORT
|
|
130
|
-
: JS_PLUGIN_WITH_TYPES_SUPPORT
|
|
131
|
-
|
|
132
|
-
await writeFile(pluginPath, pluginTemplate)
|
|
133
|
-
logger.info(`Plugin file created at ${relative(currentDir, pluginPath)}`)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
323
|
export function getConnectionString (database) {
|
|
137
324
|
return connectionStrings[database]
|
|
138
325
|
}
|
|
@@ -201,7 +388,30 @@ export async function createDB ({ hostname, database = 'sqlite', port, migration
|
|
|
201
388
|
}
|
|
202
389
|
|
|
203
390
|
if (plugin) {
|
|
204
|
-
|
|
391
|
+
let jsHelper = { pre: '', config: '', post: '' }
|
|
392
|
+
switch (database) {
|
|
393
|
+
case 'sqlite':
|
|
394
|
+
jsHelper = jsHelperSqlite
|
|
395
|
+
break
|
|
396
|
+
case 'mysql':
|
|
397
|
+
jsHelper = jsHelperMySQL(connectionString)
|
|
398
|
+
break
|
|
399
|
+
case 'postgres':
|
|
400
|
+
jsHelper = jsHelperPostgres(connectionString)
|
|
401
|
+
break
|
|
402
|
+
case 'mariadb':
|
|
403
|
+
jsHelper = jsHelperMySQL(connectionString)
|
|
404
|
+
break
|
|
405
|
+
}
|
|
406
|
+
await generatePlugins(logger, currentDir, typescript, 'db', jsHelper)
|
|
407
|
+
|
|
408
|
+
if (createMigrations) {
|
|
409
|
+
if (typescript) {
|
|
410
|
+
await writeFile(join(currentDir, 'test', 'routes', 'movies.test.ts'), moviesTestTS)
|
|
411
|
+
} else {
|
|
412
|
+
await writeFile(join(currentDir, 'test', 'routes', 'movies.test.js'), moviesTestJS)
|
|
413
|
+
}
|
|
414
|
+
}
|
|
205
415
|
}
|
|
206
416
|
|
|
207
417
|
const output = {
|
package/src/ghaction.mjs
CHANGED
|
@@ -176,7 +176,7 @@ export const askStaticWorkspaceGHAction = async (logger, env, type, buildTS, pro
|
|
|
176
176
|
{
|
|
177
177
|
type: 'list',
|
|
178
178
|
name: 'githubAction',
|
|
179
|
-
message: 'Do you want to create the github action to deploy this application to Platformatic Cloud
|
|
179
|
+
message: 'Do you want to create the github action to deploy this application to Platformatic Cloud?',
|
|
180
180
|
default: true,
|
|
181
181
|
choices: [{ name: 'yes', value: true }, { name: 'no', value: false }]
|
|
182
182
|
}
|
|
@@ -114,8 +114,8 @@ export async function createPlatformaticRuntime (_args) {
|
|
|
114
114
|
|
|
115
115
|
const env = await createRuntime(logger, projectDir, version, servicesDir, entrypoint)
|
|
116
116
|
|
|
117
|
-
await askDynamicWorkspaceCreateGHAction(logger, env, 'service', false, projectDir)
|
|
118
117
|
await askStaticWorkspaceGHAction(logger, env, 'service', false, projectDir)
|
|
118
|
+
await askDynamicWorkspaceCreateGHAction(logger, env, 'service', false, projectDir)
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
export async function createRuntimeService ({ servicesDir, names, logger }) {
|
|
@@ -78,8 +78,11 @@ const createPlatformaticService = async (_args, opts = {}) => {
|
|
|
78
78
|
const fastifyVersion = await getDependencyVersion('fastify')
|
|
79
79
|
|
|
80
80
|
if (!opts.skipPackageJson) {
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
const test = useTypescript ? 'tsc && node --test dist/test/*/*.test.js' : 'node --test test/*/*.test.js'
|
|
82
|
+
await createPackageJson(version, fastifyVersion, logger, projectDir, useTypescript, {
|
|
83
|
+
test
|
|
84
|
+
}, {
|
|
85
|
+
'@platformatic/service': `^${version}`
|
|
83
86
|
})
|
|
84
87
|
}
|
|
85
88
|
if (!opts.skipGitignore) {
|
|
@@ -103,8 +106,8 @@ const createPlatformaticService = async (_args, opts = {}) => {
|
|
|
103
106
|
}
|
|
104
107
|
|
|
105
108
|
if (!opts.skipGitHubActions) {
|
|
106
|
-
await askDynamicWorkspaceCreateGHAction(logger, env, 'service', useTypescript, projectDir)
|
|
107
109
|
await askStaticWorkspaceGHAction(logger, env, 'service', useTypescript, projectDir)
|
|
110
|
+
await askDynamicWorkspaceCreateGHAction(logger, env, 'service', useTypescript, projectDir)
|
|
108
111
|
}
|
|
109
112
|
}
|
|
110
113
|
|