create-platformatic 2.0.0-alpha.2 → 2.0.0-alpha.21
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/create-platformatic.mjs +2 -2
- package/eslint.config.js +3 -0
- package/package.json +19 -19
- package/src/index.mjs +70 -94
- package/src/utils.mjs +14 -22
- package/test/cli/.gitkeep +0 -0
- package/test/cli/README.md +0 -8
- package/test/cli/composer.test.mjs +0 -80
- package/test/cli/db.test.mjs +0 -86
- package/test/cli/helper.mjs +0 -159
- package/test/cli/runtime.test.mjs +0 -104
- package/test/cli/service.test.mjs +0 -200
- package/test/cli/stackable.test.mjs +0 -101
- package/test/cli/timeout.mjs +0 -3
- package/test/unit/create-git-repository.test.mjs +0 -61
- package/test/unit/fetch-stackables.mjs +0 -71
- package/test/unit/utils.test.mjs +0 -291
package/test/cli/helper.mjs
DELETED
|
@@ -1,159 +0,0 @@
|
|
|
1
|
-
import os from 'node:os'
|
|
2
|
-
import { execa } from 'execa'
|
|
3
|
-
import { join } from 'desm'
|
|
4
|
-
import stripAnsi from 'strip-ansi'
|
|
5
|
-
import { promisify } from 'node:util'
|
|
6
|
-
import { promises as fs } from 'node:fs'
|
|
7
|
-
import path from 'node:path'
|
|
8
|
-
import fastify from 'fastify'
|
|
9
|
-
|
|
10
|
-
const sleep = promisify(setTimeout)
|
|
11
|
-
|
|
12
|
-
export const keys = {
|
|
13
|
-
DOWN: '\x1B\x5B\x42',
|
|
14
|
-
UP: '\x1B\x5B\x41',
|
|
15
|
-
ENTER: '\x0D',
|
|
16
|
-
SPACE: '\x20'
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export const createPath = join(import.meta.url, '..', '..', 'create-platformatic.mjs')
|
|
20
|
-
|
|
21
|
-
const match = (str, match) => {
|
|
22
|
-
if (Array.isArray(match)) {
|
|
23
|
-
return match.some((m) => str.includes(m))
|
|
24
|
-
}
|
|
25
|
-
return str.includes(match)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
export const walk = async (dir) => {
|
|
29
|
-
let files = await fs.readdir(dir)
|
|
30
|
-
files = await Promise.all(files.map(async file => {
|
|
31
|
-
const filePath = path.join(dir, file)
|
|
32
|
-
const stats = await fs.stat(filePath)
|
|
33
|
-
if (stats.isDirectory()) return walk(filePath)
|
|
34
|
-
else if (stats.isFile()) return filePath
|
|
35
|
-
}))
|
|
36
|
-
return files.reduce((all, folderContents) => all.concat(folderContents), [])
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
export const getServices = async (dir) => {
|
|
40
|
-
const files = await fs.readdir(dir)
|
|
41
|
-
const services = []
|
|
42
|
-
for (const file of files) {
|
|
43
|
-
services.push(file)
|
|
44
|
-
}
|
|
45
|
-
return services
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// Actions are in the form:
|
|
49
|
-
// {
|
|
50
|
-
// match: 'Server listening at',
|
|
51
|
-
// do: [keys.DOWN, keys.ENTER]
|
|
52
|
-
// }
|
|
53
|
-
export async function executeCreatePlatformatic (dir, actions = [], options = {}) {
|
|
54
|
-
const done = options.done || 'You are all set!'
|
|
55
|
-
const pkgMgrInstall = options.pkgMgrInstall || false
|
|
56
|
-
const pkgManager = options.pkgManager || 'npm'
|
|
57
|
-
const marketplaceHost = options.marketplaceHost
|
|
58
|
-
|
|
59
|
-
const runCreatePlatformatic = async () => {
|
|
60
|
-
const questions = [...actions]
|
|
61
|
-
try {
|
|
62
|
-
const execaOptions = {
|
|
63
|
-
cwd: dir
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (pkgManager === 'pnpm') {
|
|
67
|
-
execaOptions.env = {
|
|
68
|
-
npm_config_user_agent: 'pnpm/6.14.1 npm/? node/v16.4.2 darwin x64'
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const child = execa('node', [
|
|
73
|
-
createPath,
|
|
74
|
-
`--install=${pkgMgrInstall.toString()}`,
|
|
75
|
-
`--marketplace-host=${marketplaceHost}`
|
|
76
|
-
], execaOptions)
|
|
77
|
-
|
|
78
|
-
// We just need the "lastPrompt" printed before the process stopped to wait for an answer
|
|
79
|
-
// If we don't have any outptu from process for more than 500ms, we assume it's waiting for an answer
|
|
80
|
-
let lastPrompt = ''
|
|
81
|
-
|
|
82
|
-
child.stdout.on('data', (chunk) => {
|
|
83
|
-
const str = stripAnsi(chunk.toString()).trim()
|
|
84
|
-
if (str) {
|
|
85
|
-
lastPrompt = str
|
|
86
|
-
}
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
let expectedQuestion = questions.shift()
|
|
90
|
-
|
|
91
|
-
// We need this because the prompt prints an introduction before asking anything.
|
|
92
|
-
// If we don't like this, we could use a flag to recognize when the introduction is done
|
|
93
|
-
await sleep(5000)
|
|
94
|
-
|
|
95
|
-
while (true) {
|
|
96
|
-
if (!expectedQuestion) {
|
|
97
|
-
await sleep(500)
|
|
98
|
-
// We processed all expected questions, so now we wait for the process to be done.
|
|
99
|
-
// If the "done" string is not printed, the test will timeout
|
|
100
|
-
if (lastPrompt && lastPrompt.includes(done)) {
|
|
101
|
-
safeKill(child)
|
|
102
|
-
return
|
|
103
|
-
}
|
|
104
|
-
} else if (match(lastPrompt, expectedQuestion.match)) {
|
|
105
|
-
console.log('==> MATCH', expectedQuestion.match)
|
|
106
|
-
lastPrompt = ''
|
|
107
|
-
|
|
108
|
-
for (const key of expectedQuestion.do) {
|
|
109
|
-
child.stdin?.write(key)
|
|
110
|
-
const waitAfter = expectedQuestion.waitAfter || 500
|
|
111
|
-
await sleep(waitAfter)
|
|
112
|
-
}
|
|
113
|
-
expectedQuestion = questions.shift()
|
|
114
|
-
} else {
|
|
115
|
-
throw new Error(`Expected ${expectedQuestion.match}, got ${lastPrompt}`)
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
} catch (err) {
|
|
119
|
-
console.error(err)
|
|
120
|
-
throw err
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
await runCreatePlatformatic()
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
export async function safeKill (child) {
|
|
127
|
-
child.kill('SIGINT')
|
|
128
|
-
if (os.platform() === 'win32') {
|
|
129
|
-
try {
|
|
130
|
-
await execa('taskkill', ['/pid', child.pid, '/f', '/t'])
|
|
131
|
-
} catch (err) {
|
|
132
|
-
if (err.stderr.indexOf('not found') === 0) {
|
|
133
|
-
console.error(`Failed to kill process ${child.pid}`)
|
|
134
|
-
console.error(err)
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
export async function startMarketplace (t, opts = {}) {
|
|
141
|
-
const marketplace = fastify()
|
|
142
|
-
|
|
143
|
-
marketplace.get('/templates', async (request, reply) => {
|
|
144
|
-
if (opts.templatesCallback) {
|
|
145
|
-
return opts.templatesCallback(request, reply)
|
|
146
|
-
}
|
|
147
|
-
return [
|
|
148
|
-
{ name: '@platformatic/composer' },
|
|
149
|
-
{ name: '@platformatic/db' },
|
|
150
|
-
{ name: '@platformatic/service' }
|
|
151
|
-
]
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
await marketplace.listen({ port: 0 })
|
|
155
|
-
t.after(() => marketplace.close())
|
|
156
|
-
|
|
157
|
-
const address = marketplace.server.address()
|
|
158
|
-
return `http://127.0.0.1:${address.port}`
|
|
159
|
-
}
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
import { test } from 'node:test'
|
|
2
|
-
import { equal } from 'node:assert'
|
|
3
|
-
import { join } from 'node:path'
|
|
4
|
-
import { tmpdir } from 'node:os'
|
|
5
|
-
import { mkdtemp, rm } from 'node:fs/promises'
|
|
6
|
-
import { timeout } from './timeout.mjs'
|
|
7
|
-
import { isFileAccessible } from '../../src/utils.mjs'
|
|
8
|
-
import {
|
|
9
|
-
executeCreatePlatformatic,
|
|
10
|
-
startMarketplace,
|
|
11
|
-
keys,
|
|
12
|
-
walk,
|
|
13
|
-
getServices
|
|
14
|
-
} from './helper.mjs'
|
|
15
|
-
|
|
16
|
-
let tmpDir
|
|
17
|
-
test.beforeEach(async () => {
|
|
18
|
-
tmpDir = await mkdtemp(join(tmpdir(), 'test-create-platformatic-'))
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
test.afterEach(async () => {
|
|
22
|
-
try {
|
|
23
|
-
await rm(tmpDir, { recursive: true, force: true })
|
|
24
|
-
} catch (e) {
|
|
25
|
-
// on purpose, in win the resource might be still "busy"
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
test('Creates a Platformatic Runtime with two Services', { timeout }, async (t) => {
|
|
30
|
-
const marketplaceHost = await startMarketplace(t)
|
|
31
|
-
// The actions must match IN ORDER
|
|
32
|
-
const actions = [{
|
|
33
|
-
match: 'What kind of project do you want to create?',
|
|
34
|
-
do: [keys.ENTER] // Application
|
|
35
|
-
}, {
|
|
36
|
-
match: 'Where would you like to create your project?',
|
|
37
|
-
do: [keys.ENTER],
|
|
38
|
-
waitAfter: 8000
|
|
39
|
-
}, {
|
|
40
|
-
match: 'Which kind of project do you want to create?',
|
|
41
|
-
do: [keys.ENTER] // Service
|
|
42
|
-
}, {
|
|
43
|
-
match: 'What is the name of the service?',
|
|
44
|
-
do: [keys.ENTER]
|
|
45
|
-
}, {
|
|
46
|
-
match: 'Do you want to create another service?',
|
|
47
|
-
do: [keys.ENTER] // yes
|
|
48
|
-
}, {
|
|
49
|
-
match: 'Which kind of project do you want to create?',
|
|
50
|
-
do: [keys.ENTER] // Service
|
|
51
|
-
}, {
|
|
52
|
-
match: 'What is the name of the service?',
|
|
53
|
-
do: [keys.ENTER]
|
|
54
|
-
}, {
|
|
55
|
-
match: 'Do you want to create another service?',
|
|
56
|
-
do: [keys.DOWN, keys.ENTER] // no
|
|
57
|
-
}, {
|
|
58
|
-
match: 'Which service should be exposed?',
|
|
59
|
-
do: [keys.ENTER]
|
|
60
|
-
}, {
|
|
61
|
-
match: 'Do you want to use TypeScript',
|
|
62
|
-
do: [keys.DOWN, keys.ENTER] // yes
|
|
63
|
-
}, {
|
|
64
|
-
match: 'What port do you want to use?',
|
|
65
|
-
do: [keys.ENTER]
|
|
66
|
-
}, {
|
|
67
|
-
match: 'Do you want to init the git repository',
|
|
68
|
-
do: [keys.DOWN, keys.ENTER] // yes
|
|
69
|
-
}]
|
|
70
|
-
await executeCreatePlatformatic(tmpDir, actions, {
|
|
71
|
-
marketplaceHost,
|
|
72
|
-
pkgManager: 'pnpm'
|
|
73
|
-
})
|
|
74
|
-
|
|
75
|
-
const baseProjectDir = join(tmpDir, 'platformatic')
|
|
76
|
-
const files = await walk(baseProjectDir)
|
|
77
|
-
console.log('==> created files', files)
|
|
78
|
-
equal(await isFileAccessible(join(baseProjectDir, '.gitignore')), true)
|
|
79
|
-
equal(await isFileAccessible(join(baseProjectDir, '.env')), true)
|
|
80
|
-
equal(await isFileAccessible(join(baseProjectDir, '.env.sample')), true)
|
|
81
|
-
equal(await isFileAccessible(join(baseProjectDir, 'platformatic.json')), true)
|
|
82
|
-
equal(await isFileAccessible(join(baseProjectDir, 'README.md')), true)
|
|
83
|
-
equal(await isFileAccessible(join(baseProjectDir, '.git', 'config')), true)
|
|
84
|
-
|
|
85
|
-
// using pnpm will create workspace file
|
|
86
|
-
equal(await isFileAccessible(join(baseProjectDir, 'pnpm-workspace.yaml')), true)
|
|
87
|
-
|
|
88
|
-
// Here check the generated services
|
|
89
|
-
const services = await getServices(join(baseProjectDir, 'services'))
|
|
90
|
-
equal(services.length, 2)
|
|
91
|
-
const baseService0Dir = join(baseProjectDir, 'services', services[0])
|
|
92
|
-
equal(await isFileAccessible(join(baseService0Dir, 'platformatic.json')), true)
|
|
93
|
-
equal(await isFileAccessible(join(baseService0Dir, 'README.md')), true)
|
|
94
|
-
equal(await isFileAccessible(join(baseService0Dir, 'routes', 'root.ts')), true)
|
|
95
|
-
equal(await isFileAccessible(join(baseService0Dir, 'plugins', 'example.ts')), true)
|
|
96
|
-
equal(await isFileAccessible(join(baseService0Dir, 'global.d.ts')), true)
|
|
97
|
-
|
|
98
|
-
const baseService1Dir = join(baseProjectDir, 'services', services[1])
|
|
99
|
-
equal(await isFileAccessible(join(baseService1Dir, 'platformatic.json')), true)
|
|
100
|
-
equal(await isFileAccessible(join(baseService1Dir, 'README.md')), true)
|
|
101
|
-
equal(await isFileAccessible(join(baseService1Dir, 'routes', 'root.ts')), true)
|
|
102
|
-
equal(await isFileAccessible(join(baseService1Dir, 'plugins', 'example.ts')), true)
|
|
103
|
-
equal(await isFileAccessible(join(baseService1Dir, 'global.d.ts')), true)
|
|
104
|
-
})
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import { test } from 'node:test'
|
|
2
|
-
import { equal, notEqual } from 'node:assert'
|
|
3
|
-
import { timeout } from './timeout.mjs'
|
|
4
|
-
import { isFileAccessible, safeMkdir } from '../../src/utils.mjs'
|
|
5
|
-
import { join } from 'node:path'
|
|
6
|
-
import { tmpdir } from 'os'
|
|
7
|
-
import { readFile, mkdtemp, rm, writeFile } from 'node:fs/promises'
|
|
8
|
-
import {
|
|
9
|
-
executeCreatePlatformatic,
|
|
10
|
-
startMarketplace,
|
|
11
|
-
keys,
|
|
12
|
-
walk,
|
|
13
|
-
getServices
|
|
14
|
-
} from './helper.mjs'
|
|
15
|
-
|
|
16
|
-
let tmpDir
|
|
17
|
-
test.beforeEach(async () => {
|
|
18
|
-
tmpDir = await mkdtemp(join(tmpdir(), 'test-create-platformatic-'))
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
test.afterEach(async () => {
|
|
22
|
-
try {
|
|
23
|
-
await rm(tmpDir, { recursive: true, force: true })
|
|
24
|
-
} catch (e) {
|
|
25
|
-
// on purpose, in win the resource might be still "busy"
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
|
|
29
|
-
test('Creates a Platformatic Service with no typescript', { timeout }, async (t) => {
|
|
30
|
-
const marketplaceHost = await startMarketplace(t)
|
|
31
|
-
// The actions must match IN ORDER
|
|
32
|
-
const actions = [{
|
|
33
|
-
match: 'What kind of project do you want to create?',
|
|
34
|
-
do: [keys.ENTER] // Application
|
|
35
|
-
}, {
|
|
36
|
-
match: 'Where would you like to create your project?',
|
|
37
|
-
do: [keys.ENTER],
|
|
38
|
-
waitAfter: 8000
|
|
39
|
-
}, {
|
|
40
|
-
match: 'Which kind of project do you want to create?',
|
|
41
|
-
do: [keys.ENTER] // Service
|
|
42
|
-
}, {
|
|
43
|
-
match: 'What is the name of the service?',
|
|
44
|
-
do: [keys.ENTER]
|
|
45
|
-
}, {
|
|
46
|
-
match: 'Do you want to create another service?',
|
|
47
|
-
do: [keys.DOWN, keys.ENTER] // no
|
|
48
|
-
}, {
|
|
49
|
-
// NOTE THAT HERE THE DEFAULT OPTION FOR SERVICE IS "YES"
|
|
50
|
-
match: 'Do you want to use TypeScript',
|
|
51
|
-
do: [keys.ENTER] // no
|
|
52
|
-
}, {
|
|
53
|
-
match: 'What port do you want to use?',
|
|
54
|
-
do: [keys.ENTER]
|
|
55
|
-
}, {
|
|
56
|
-
match: 'Do you want to init the git repository',
|
|
57
|
-
do: [keys.DOWN, keys.ENTER] // yes
|
|
58
|
-
}]
|
|
59
|
-
await executeCreatePlatformatic(tmpDir, actions, { marketplaceHost })
|
|
60
|
-
|
|
61
|
-
const baseProjectDir = join(tmpDir, 'platformatic')
|
|
62
|
-
const files = await walk(baseProjectDir)
|
|
63
|
-
console.log('==> created files', files)
|
|
64
|
-
equal(await isFileAccessible(join(baseProjectDir, '.gitignore')), true)
|
|
65
|
-
equal(await isFileAccessible(join(baseProjectDir, '.env')), true)
|
|
66
|
-
equal(await isFileAccessible(join(baseProjectDir, '.env.sample')), true)
|
|
67
|
-
equal(await isFileAccessible(join(baseProjectDir, 'platformatic.json')), true)
|
|
68
|
-
equal(await isFileAccessible(join(baseProjectDir, 'README.md')), true)
|
|
69
|
-
|
|
70
|
-
// Here check the generated service
|
|
71
|
-
const services = await getServices(join(baseProjectDir, 'services'))
|
|
72
|
-
equal(services.length, 1)
|
|
73
|
-
const baseServiceDir = join(baseProjectDir, 'services', services[0])
|
|
74
|
-
console.log(baseServiceDir)
|
|
75
|
-
equal(await isFileAccessible(join(baseServiceDir, 'platformatic.json')), true)
|
|
76
|
-
equal(await isFileAccessible(join(baseServiceDir, 'README.md')), true)
|
|
77
|
-
equal(await isFileAccessible(join(baseServiceDir, 'routes', 'root.js')), true)
|
|
78
|
-
equal(await isFileAccessible(join(baseServiceDir, 'plugins', 'example.js')), true)
|
|
79
|
-
})
|
|
80
|
-
|
|
81
|
-
test('Creates a Platformatic Service with typescript', { timeout }, async (t) => {
|
|
82
|
-
const marketplaceHost = await startMarketplace(t)
|
|
83
|
-
// The actions must match IN ORDER
|
|
84
|
-
const actions = [{
|
|
85
|
-
match: 'What kind of project do you want to create?',
|
|
86
|
-
do: [keys.ENTER] // Application
|
|
87
|
-
}, {
|
|
88
|
-
match: 'Where would you like to create your project?',
|
|
89
|
-
do: [keys.ENTER],
|
|
90
|
-
waitAfter: 8000
|
|
91
|
-
}, {
|
|
92
|
-
match: 'Which kind of project do you want to create?',
|
|
93
|
-
do: [keys.ENTER] // Service
|
|
94
|
-
}, {
|
|
95
|
-
match: 'What is the name of the service?',
|
|
96
|
-
do: [keys.ENTER]
|
|
97
|
-
}, {
|
|
98
|
-
match: 'Do you want to create another service?',
|
|
99
|
-
do: [keys.DOWN, keys.ENTER] // no
|
|
100
|
-
}, {
|
|
101
|
-
// NOTE THAT HERE THE DEFAULT OPTION FOR SERVICE IS "YES"
|
|
102
|
-
match: 'Do you want to use TypeScript',
|
|
103
|
-
do: [keys.DOWN, keys.ENTER] // no
|
|
104
|
-
}, {
|
|
105
|
-
match: 'What port do you want to use?',
|
|
106
|
-
do: [keys.ENTER]
|
|
107
|
-
}, {
|
|
108
|
-
match: 'Do you want to init the git repository',
|
|
109
|
-
do: [keys.DOWN, keys.ENTER] // yes
|
|
110
|
-
}]
|
|
111
|
-
await executeCreatePlatformatic(tmpDir, actions, { marketplaceHost })
|
|
112
|
-
|
|
113
|
-
const baseProjectDir = join(tmpDir, 'platformatic')
|
|
114
|
-
const files = await walk(baseProjectDir)
|
|
115
|
-
console.log('==> created files', files)
|
|
116
|
-
equal(await isFileAccessible(join(baseProjectDir, '.gitignore')), true)
|
|
117
|
-
equal(await isFileAccessible(join(baseProjectDir, '.env')), true)
|
|
118
|
-
equal(await isFileAccessible(join(baseProjectDir, '.env.sample')), true)
|
|
119
|
-
equal(await isFileAccessible(join(baseProjectDir, 'platformatic.json')), true)
|
|
120
|
-
equal(await isFileAccessible(join(baseProjectDir, 'README.md')), true)
|
|
121
|
-
|
|
122
|
-
// Here check the generated service
|
|
123
|
-
const services = await getServices(join(baseProjectDir, 'services'))
|
|
124
|
-
equal(services.length, 1)
|
|
125
|
-
const baseServiceDir = join(baseProjectDir, 'services', services[0])
|
|
126
|
-
console.log(baseServiceDir)
|
|
127
|
-
equal(await isFileAccessible(join(baseServiceDir, 'platformatic.json')), true)
|
|
128
|
-
equal(await isFileAccessible(join(baseServiceDir, 'README.md')), true)
|
|
129
|
-
equal(await isFileAccessible(join(baseServiceDir, 'routes', 'root.ts')), true)
|
|
130
|
-
equal(await isFileAccessible(join(baseServiceDir, 'plugins', 'example.ts')), true)
|
|
131
|
-
})
|
|
132
|
-
|
|
133
|
-
test('Creates a Platformatic Service in a non empty directory', { timeout, skip: true }, async (t) => {
|
|
134
|
-
const marketplaceHost = await startMarketplace(t)
|
|
135
|
-
const targetDirectory = join(tmpdir(), 'platformatic-service-test')
|
|
136
|
-
// const targetDirectory = '/tmp/tst'
|
|
137
|
-
async function generateServiceFileStructure (dir) {
|
|
138
|
-
const servicesDir = join(dir, 'services')
|
|
139
|
-
await safeMkdir(servicesDir)
|
|
140
|
-
|
|
141
|
-
const serviceDir = join(servicesDir, 'foo')
|
|
142
|
-
await safeMkdir(join(serviceDir, 'plugins'))
|
|
143
|
-
await safeMkdir(join(serviceDir, 'routes'))
|
|
144
|
-
|
|
145
|
-
await writeFile(join(dir, '.env'), 'SAMPLE_ENV=foobar\n')
|
|
146
|
-
|
|
147
|
-
// creates 2 files. root.js will be overwritten
|
|
148
|
-
await writeFile(join(serviceDir, 'routes', 'root.js'), 'console.log(\'hello world\')')
|
|
149
|
-
await writeFile(join(serviceDir, 'routes', 'sample.js'), 'console.log(\'hello world\')')
|
|
150
|
-
}
|
|
151
|
-
// generate a sample file structure
|
|
152
|
-
await generateServiceFileStructure(targetDirectory)
|
|
153
|
-
|
|
154
|
-
test.after(async () => {
|
|
155
|
-
await rm(targetDirectory, { recursive: true })
|
|
156
|
-
})
|
|
157
|
-
// The actions must match IN ORDER
|
|
158
|
-
const actions = [{
|
|
159
|
-
match: 'What kind of project do you want to create?',
|
|
160
|
-
do: [keys.ENTER] // Application
|
|
161
|
-
}, {
|
|
162
|
-
match: 'Where would you like to create your project?',
|
|
163
|
-
do: [targetDirectory, keys.ENTER],
|
|
164
|
-
waitAfter: 8000
|
|
165
|
-
}, {
|
|
166
|
-
match: 'Confirm you want to use',
|
|
167
|
-
do: [keys.ENTER] // confirm use existing directory
|
|
168
|
-
}, {
|
|
169
|
-
// NOTE THAT HERE THE DEFAULT OPTION FOR SERVICE IS "YES"
|
|
170
|
-
match: 'Do you want to use TypeScript',
|
|
171
|
-
do: [keys.DOWN, keys.ENTER] // no
|
|
172
|
-
}, {
|
|
173
|
-
match: 'What port do you want to use?',
|
|
174
|
-
do: [keys.ENTER]
|
|
175
|
-
}, {
|
|
176
|
-
match: 'Do you want to create the github action to deploy',
|
|
177
|
-
do: [keys.DOWN, keys.ENTER]
|
|
178
|
-
}, {
|
|
179
|
-
match: 'Do you want to enable PR Previews in your application',
|
|
180
|
-
do: [keys.DOWN, keys.ENTER]
|
|
181
|
-
}, {
|
|
182
|
-
match: 'Do you want to init the git repository',
|
|
183
|
-
do: [keys.DOWN, keys.ENTER] // yes
|
|
184
|
-
}]
|
|
185
|
-
await executeCreatePlatformatic(tmpDir, actions, { marketplaceHost })
|
|
186
|
-
|
|
187
|
-
equal(await isFileAccessible(join(targetDirectory, '.gitignore')), true)
|
|
188
|
-
equal(await isFileAccessible(join(targetDirectory, '.env')), true)
|
|
189
|
-
equal(await isFileAccessible(join(targetDirectory, '.env.sample')), true)
|
|
190
|
-
equal(await isFileAccessible(join(targetDirectory, 'platformatic.service.json')), true)
|
|
191
|
-
equal(await isFileAccessible(join(targetDirectory, 'README.md')), true)
|
|
192
|
-
equal(await isFileAccessible(join(targetDirectory, 'routes', 'root.js')), true)
|
|
193
|
-
equal(await isFileAccessible(join(targetDirectory, 'routes', 'sample.js')), true)
|
|
194
|
-
equal(await isFileAccessible(join(targetDirectory, 'plugins', 'example.js')), true)
|
|
195
|
-
equal(await isFileAccessible(join(targetDirectory, '.git', 'config')), true)
|
|
196
|
-
|
|
197
|
-
// check file contents
|
|
198
|
-
notEqual(await readFile(join(targetDirectory, 'routes', 'root.js'), 'utf8'), 'console.log(\'hello world\')')
|
|
199
|
-
equal(await readFile(join(targetDirectory, 'routes', 'sample.js'), 'utf8'), 'console.log(\'hello world\')')
|
|
200
|
-
})
|
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
import { test } from 'node:test'
|
|
2
|
-
import { equal } from 'node:assert'
|
|
3
|
-
import { executeCreatePlatformatic, keys, walk } from './helper.mjs'
|
|
4
|
-
import { timeout } from './timeout.mjs'
|
|
5
|
-
import { isFileAccessible } from '../../src/utils.mjs'
|
|
6
|
-
import { join } from 'node:path'
|
|
7
|
-
import { tmpdir } from 'os'
|
|
8
|
-
import { mkdtemp, rm } from 'node:fs/promises'
|
|
9
|
-
|
|
10
|
-
let tmpDir
|
|
11
|
-
test.beforeEach(async () => {
|
|
12
|
-
tmpDir = await mkdtemp(join(tmpdir(), 'test-create-platformatic-'))
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
test.afterEach(async () => {
|
|
16
|
-
try {
|
|
17
|
-
await rm(tmpDir, { recursive: true, force: true })
|
|
18
|
-
} catch (e) {
|
|
19
|
-
// on purpose, in win the resource might be still "busy"
|
|
20
|
-
}
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
test('Creates a Platformatic Stackable without typescript', { timeout }, async () => {
|
|
24
|
-
// The actions must match IN ORDER
|
|
25
|
-
const actions = [{
|
|
26
|
-
match: 'What kind of project do you want to create?',
|
|
27
|
-
do: [keys.DOWN, keys.ENTER] // Stackable
|
|
28
|
-
}, {
|
|
29
|
-
match: 'Where would you like to create your project?',
|
|
30
|
-
do: [keys.ENTER]
|
|
31
|
-
}, {
|
|
32
|
-
match: 'What is the name of the stackable?',
|
|
33
|
-
do: [keys.ENTER] // my-stackable
|
|
34
|
-
}, {
|
|
35
|
-
match: 'Do you want to use TypeScript',
|
|
36
|
-
do: [keys.ENTER] // no
|
|
37
|
-
}, {
|
|
38
|
-
match: 'Do you want to init the git repository',
|
|
39
|
-
do: [keys.DOWN, keys.ENTER] // yes
|
|
40
|
-
}]
|
|
41
|
-
await executeCreatePlatformatic(tmpDir, actions, {
|
|
42
|
-
done: 'Stackable created successfully!'
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
const baseProjectDir = join(tmpDir, 'platformatic')
|
|
46
|
-
const files = await walk(baseProjectDir)
|
|
47
|
-
console.log('==> created files', files)
|
|
48
|
-
equal(await isFileAccessible(join(baseProjectDir, '.gitignore')), true)
|
|
49
|
-
equal(await isFileAccessible(join(baseProjectDir, 'index.js')), true)
|
|
50
|
-
equal(await isFileAccessible(join(baseProjectDir, 'index.d.ts')), true)
|
|
51
|
-
equal(await isFileAccessible(join(baseProjectDir, 'config.d.ts')), true)
|
|
52
|
-
equal(await isFileAccessible(join(baseProjectDir, 'package.json')), true)
|
|
53
|
-
equal(await isFileAccessible(join(baseProjectDir, 'plugins', 'example.js')), true)
|
|
54
|
-
equal(await isFileAccessible(join(baseProjectDir, 'lib', 'schema.js')), true)
|
|
55
|
-
equal(await isFileAccessible(join(baseProjectDir, 'lib', 'generator.js')), true)
|
|
56
|
-
equal(await isFileAccessible(join(baseProjectDir, 'cli', 'create.js')), true)
|
|
57
|
-
equal(await isFileAccessible(join(baseProjectDir, 'cli', 'start.js')), true)
|
|
58
|
-
equal(await isFileAccessible(join(baseProjectDir, 'test', 'index.test.js')), true)
|
|
59
|
-
equal(await isFileAccessible(join(baseProjectDir, 'test', 'schema.test.js')), true)
|
|
60
|
-
equal(await isFileAccessible(join(baseProjectDir, 'test', 'generator.test.js')), true)
|
|
61
|
-
})
|
|
62
|
-
|
|
63
|
-
test('Creates a Platformatic Stackable with typescript', { timeout }, async () => {
|
|
64
|
-
// The actions must match IN ORDER
|
|
65
|
-
const actions = [{
|
|
66
|
-
match: 'What kind of project do you want to create?',
|
|
67
|
-
do: [keys.DOWN, keys.ENTER] // Stackable
|
|
68
|
-
}, {
|
|
69
|
-
match: 'Where would you like to create your project?',
|
|
70
|
-
do: [keys.ENTER]
|
|
71
|
-
}, {
|
|
72
|
-
match: 'What is the name of the stackable?',
|
|
73
|
-
do: [keys.ENTER] // my-stackable
|
|
74
|
-
}, {
|
|
75
|
-
match: 'Do you want to use TypeScript',
|
|
76
|
-
do: [keys.DOWN, keys.ENTER] // yes
|
|
77
|
-
}, {
|
|
78
|
-
match: 'Do you want to init the git repository',
|
|
79
|
-
do: [keys.ENTER] // no
|
|
80
|
-
}]
|
|
81
|
-
await executeCreatePlatformatic(tmpDir, actions, {
|
|
82
|
-
done: 'Stackable created successfully!'
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
const baseProjectDir = join(tmpDir, 'platformatic')
|
|
86
|
-
const files = await walk(baseProjectDir)
|
|
87
|
-
console.log('==> created files', files)
|
|
88
|
-
equal(await isFileAccessible(join(baseProjectDir, '.gitignore')), true)
|
|
89
|
-
equal(await isFileAccessible(join(baseProjectDir, 'index.ts')), true)
|
|
90
|
-
equal(await isFileAccessible(join(baseProjectDir, 'index.d.ts')), true)
|
|
91
|
-
equal(await isFileAccessible(join(baseProjectDir, 'config.d.ts')), true)
|
|
92
|
-
equal(await isFileAccessible(join(baseProjectDir, 'package.json')), true)
|
|
93
|
-
equal(await isFileAccessible(join(baseProjectDir, 'plugins', 'example.ts')), true)
|
|
94
|
-
equal(await isFileAccessible(join(baseProjectDir, 'lib', 'schema.ts')), true)
|
|
95
|
-
equal(await isFileAccessible(join(baseProjectDir, 'lib', 'generator.ts')), true)
|
|
96
|
-
equal(await isFileAccessible(join(baseProjectDir, 'cli', 'create.ts')), true)
|
|
97
|
-
equal(await isFileAccessible(join(baseProjectDir, 'cli', 'start.ts')), true)
|
|
98
|
-
equal(await isFileAccessible(join(baseProjectDir, 'test', 'index.test.ts')), true)
|
|
99
|
-
equal(await isFileAccessible(join(baseProjectDir, 'test', 'schema.test.ts')), true)
|
|
100
|
-
equal(await isFileAccessible(join(baseProjectDir, 'test', 'generator.test.ts')), true)
|
|
101
|
-
})
|
package/test/cli/timeout.mjs
DELETED
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { tmpdir } from 'os'
|
|
2
|
-
import { join } from 'path'
|
|
3
|
-
import { execa } from 'execa'
|
|
4
|
-
import { test } from 'node:test'
|
|
5
|
-
import { equal, match } from 'node:assert'
|
|
6
|
-
|
|
7
|
-
import { isFileAccessible } from '../../src/utils.mjs'
|
|
8
|
-
import { createGitRepository, GIT_FIRST_COMMIT_MESSAGE, GIT_MAIN_BRANCH } from '../../src/create-git-repository.mjs'
|
|
9
|
-
import { mkdir, rm, writeFile } from 'fs/promises'
|
|
10
|
-
|
|
11
|
-
const loggerSpy = {
|
|
12
|
-
_debug: [],
|
|
13
|
-
_info: [],
|
|
14
|
-
_error: [],
|
|
15
|
-
|
|
16
|
-
debug: function (...args) { this._debug.push(args) },
|
|
17
|
-
info: function (...args) { this._info.push(args) },
|
|
18
|
-
error: function (...args) { this._error.push(args) },
|
|
19
|
-
|
|
20
|
-
reset: function () {
|
|
21
|
-
this._debug = []
|
|
22
|
-
this._info = []
|
|
23
|
-
this._error = []
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const tmpDir = join(tmpdir(), 'test-create-platformatic-git-repo')
|
|
28
|
-
test.beforeEach(async () => {
|
|
29
|
-
loggerSpy.reset()
|
|
30
|
-
await rm(tmpDir, { recursive: true, force: true })
|
|
31
|
-
await mkdir(tmpDir, { recursive: true })
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
test('should create the git repo', async () => {
|
|
35
|
-
await writeFile(join(tmpDir, 'README.md'), '')
|
|
36
|
-
|
|
37
|
-
await createGitRepository(loggerSpy, tmpDir)
|
|
38
|
-
|
|
39
|
-
equal(loggerSpy._debug[0][0], 'Git repository initialized.')
|
|
40
|
-
equal(loggerSpy._debug[1][0], 'Git commit done.')
|
|
41
|
-
equal(loggerSpy._info[0][0], 'Git repository initialized.')
|
|
42
|
-
equal(loggerSpy._error.length, 0)
|
|
43
|
-
|
|
44
|
-
equal(await isFileAccessible(join(tmpDir, '.git/config')), true)
|
|
45
|
-
|
|
46
|
-
const lastCommit = await execa('git', ['show', '-1'], { cwd: tmpDir })
|
|
47
|
-
match(lastCommit.stdout, new RegExp(GIT_FIRST_COMMIT_MESSAGE))
|
|
48
|
-
|
|
49
|
-
const branch = await execa('git', ['branch'], { cwd: tmpDir })
|
|
50
|
-
match(branch.stdout, new RegExp(GIT_MAIN_BRANCH))
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
test('should not create the git repository if already exists', async () => {
|
|
54
|
-
await execa('git', ['init'], { cwd: tmpDir })
|
|
55
|
-
|
|
56
|
-
await createGitRepository(loggerSpy, tmpDir)
|
|
57
|
-
|
|
58
|
-
equal(loggerSpy._debug.length, 0)
|
|
59
|
-
equal(loggerSpy._info[0][0], 'Git repository already exists.')
|
|
60
|
-
equal(loggerSpy._error.length, 0)
|
|
61
|
-
})
|