@newlogic-digital/cli 0.0.1 → 0.0.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 +3 -2
- package/src/commands/cms/index.js +38 -0
- package/src/commands/cms/prepare.js +121 -0
- package/src/commands/init/cms.js +53 -0
- package/src/commands/init/index.js +58 -0
- package/src/commands/init/ui.js +5 -0
- package/src/utils.js +31 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@newlogic-digital/cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
@@ -20,7 +20,8 @@
|
|
|
20
20
|
"eslint-config-standard": "^17.0.0"
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
|
-
"index.js"
|
|
23
|
+
"index.js",
|
|
24
|
+
"src"
|
|
24
25
|
],
|
|
25
26
|
"engines": {
|
|
26
27
|
"node": ">=16.0.0",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import prepare from './prepare.js'
|
|
2
|
+
import pc from 'picocolors'
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import { join, resolve } from 'path'
|
|
5
|
+
|
|
6
|
+
export const options = {
|
|
7
|
+
path: {
|
|
8
|
+
src: {
|
|
9
|
+
templates: resolve(process.cwd(), 'playground/templates'),
|
|
10
|
+
sections: resolve(process.cwd(), 'playground/templates/Sections')
|
|
11
|
+
},
|
|
12
|
+
app: {
|
|
13
|
+
templates: resolve(process.cwd(), 'app/Templates'),
|
|
14
|
+
sections: resolve(process.cwd(), 'app/Sections'),
|
|
15
|
+
sectionsFactory: resolve(process.cwd(), 'app/Sections/Factory')
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default async function cms(action, name) {
|
|
21
|
+
if (action === 'prepare') {
|
|
22
|
+
await prepare(options).copy(name)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (action === 'new-section') {
|
|
26
|
+
const nameFormatted = name.replaceAll('/', '')
|
|
27
|
+
|
|
28
|
+
if (fs.existsSync(join(options.path.app.sections, `${nameFormatted}.php`))) {
|
|
29
|
+
console.log(`${pc.red('✖')} section ${nameFormatted} already exists`)
|
|
30
|
+
process.exit(1)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
prepare(options).writeSection(name)
|
|
34
|
+
prepare(options).writeSectionFactory(nameFormatted)
|
|
35
|
+
|
|
36
|
+
console.log(`${pc.green('✔')} section ${nameFormatted} created`)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import FastGlob from 'fast-glob'
|
|
2
|
+
import { join, relative, extname } from 'path'
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import fse from 'fs-extra'
|
|
5
|
+
import { stripIndent } from '../../utils.js'
|
|
6
|
+
import pc from 'picocolors'
|
|
7
|
+
|
|
8
|
+
let sectionsCount = 0
|
|
9
|
+
let sectionsFactoryCount = 0
|
|
10
|
+
let templatesCount = 0
|
|
11
|
+
|
|
12
|
+
export default function prepare(options) {
|
|
13
|
+
return {
|
|
14
|
+
async copy(name) {
|
|
15
|
+
if (!name || name === 'sections') {
|
|
16
|
+
if (!fs.existsSync(options.path.src.sections)) {
|
|
17
|
+
console.log(`${pc.red('✖')} path ${options.path.src.sections} doesn't exists`)
|
|
18
|
+
process.exit(1)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (!fs.existsSync(options.path.app.sections)) {
|
|
22
|
+
console.log(`${pc.red('✖')} path ${options.path.app.sections} doesn't exists`)
|
|
23
|
+
process.exit(1)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!fs.existsSync(options.path.app.sectionsFactory)) {
|
|
27
|
+
fs.mkdirSync(options.path.app.sectionsFactory)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
await this.copySections(name === 'sections')
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if (!name || name === 'templates') {
|
|
34
|
+
if (!fs.existsSync(options.path.src.templates)) {
|
|
35
|
+
console.log(`${pc.red('✖')} path ${options.path.src.templates} doesn't exists`)
|
|
36
|
+
process.exit(1)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (!fs.existsSync(options.path.app.sections)) {
|
|
40
|
+
fs.mkdirSync(options.path.app.sections)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
await this.copyTemplates(name === 'templates')
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
writeSection(name, path, force) {
|
|
47
|
+
if (!path) {
|
|
48
|
+
path = join(relative(options.path.src.templates, options.path.src.sections), name) + '.latte'
|
|
49
|
+
name = name.replaceAll('/', '')
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
if (!name.match(/(Ui)/)) {
|
|
53
|
+
if (!fs.existsSync(join(options.path.app.sections, `${name}.php`)) || force) {
|
|
54
|
+
fs.writeFileSync(join(options.path.app.sections, `${name}.php`),
|
|
55
|
+
stripIndent(`
|
|
56
|
+
<?php
|
|
57
|
+
|
|
58
|
+
namespace App\\Sections;
|
|
59
|
+
|
|
60
|
+
class ${name} extends BaseSection
|
|
61
|
+
{
|
|
62
|
+
public function render()
|
|
63
|
+
{
|
|
64
|
+
$this->getTemplate()->render(TEMPLATES_DIR . '/${path}');
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
`).replace(/^\s*\n/g, '')
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
sectionsCount += 1
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
writeSectionFactory(name, force) {
|
|
75
|
+
if (!name.match(/(Ui)/)) {
|
|
76
|
+
if (!fs.existsSync(join(options.path.app.sectionsFactory, `${name}Factory.php`)) || force) {
|
|
77
|
+
fs.writeFileSync(join(options.path.app.sectionsFactory, `${name}Factory.php`),
|
|
78
|
+
stripIndent(`
|
|
79
|
+
<?php
|
|
80
|
+
|
|
81
|
+
namespace App\\Sections\\Factory;
|
|
82
|
+
|
|
83
|
+
use App\\Sections\\${name};
|
|
84
|
+
|
|
85
|
+
interface ${name}Factory
|
|
86
|
+
{
|
|
87
|
+
public function create(): ${name};
|
|
88
|
+
}
|
|
89
|
+
`).replace(/^\s*\n/g, '')
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
sectionsFactoryCount += 1
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
async copySections(force = false) {
|
|
97
|
+
const sections = FastGlob.sync(join(options.path.src.sections, '/**'))
|
|
98
|
+
|
|
99
|
+
sections.forEach(path => {
|
|
100
|
+
const name = relative(options.path.src.sections, path).replace(extname(relative(options.path.src.sections, path)), '').replaceAll('/', '')
|
|
101
|
+
|
|
102
|
+
this.writeSection(name, relative(options.path.src.templates, path), force)
|
|
103
|
+
this.writeSectionFactory(name, force)
|
|
104
|
+
})
|
|
105
|
+
|
|
106
|
+
console.log(`${pc.green('✔')} ${sectionsCount} sections and ${sectionsFactoryCount} factory files copied to app`)
|
|
107
|
+
},
|
|
108
|
+
async copyTemplates(force = false) {
|
|
109
|
+
const templates = FastGlob.sync(join(options.path.src.templates, '/**')).filter(entry => {
|
|
110
|
+
return !fs.existsSync(join(options.path.app.templates, relative(options.path.src.templates, entry))) || force
|
|
111
|
+
})
|
|
112
|
+
|
|
113
|
+
for (const path of templates) {
|
|
114
|
+
await fse.copy(path, join(options.path.app.templates, relative(options.path.src.templates, path)))
|
|
115
|
+
templatesCount += 1
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
console.log(`${pc.green('✔')} ${templatesCount} template files copied to app`)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { execSync } from '../../utils.js'
|
|
2
|
+
import { join, resolve } from 'path'
|
|
3
|
+
import fs from 'fs'
|
|
4
|
+
import os from 'os'
|
|
5
|
+
import pc from 'picocolors'
|
|
6
|
+
import fse from 'fs-extra'
|
|
7
|
+
|
|
8
|
+
const tempDir = join(os.tmpdir(), 'newlogic-cms-web')
|
|
9
|
+
|
|
10
|
+
async function move(path) {
|
|
11
|
+
await fse.move(join(tempDir, path), resolve(process.cwd(), path)).catch(err => console.log(pc.red(err)))
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function clone(path, { variant, branch }) {
|
|
15
|
+
if (variant === 'cms-web') {
|
|
16
|
+
variant = 'newlogic-cms-next-web'
|
|
17
|
+
} else if (variant === 'cms-eshop') {
|
|
18
|
+
variant = 'newlogic-cms-next-eshop'
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
execSync(`git clone -b ${branch} --single-branch --depth 1 git@git.newlogic.cz:newlogic-dev/${variant}.git ${path}`)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export default async function cms(name, { variant, branch }) {
|
|
25
|
+
if (name) {
|
|
26
|
+
clone(name, { variant, branch })
|
|
27
|
+
return
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (fs.existsSync(tempDir)) {
|
|
31
|
+
fse.removeSync(tempDir)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
clone(tempDir, { variant, branch })
|
|
35
|
+
|
|
36
|
+
await move('.docker')
|
|
37
|
+
await move('app')
|
|
38
|
+
await move('config')
|
|
39
|
+
await move('log')
|
|
40
|
+
await move('public/.htaccess')
|
|
41
|
+
await move('public/index.php')
|
|
42
|
+
await move('temp')
|
|
43
|
+
await move('.gitignore')
|
|
44
|
+
await move('.htaccess')
|
|
45
|
+
await move('Makefile')
|
|
46
|
+
await move('composer.json')
|
|
47
|
+
await move('composer.lock')
|
|
48
|
+
await move('docker-compose.yml')
|
|
49
|
+
await move('phpstan.neon')
|
|
50
|
+
await move('pint.json')
|
|
51
|
+
|
|
52
|
+
fse.removeSync(tempDir)
|
|
53
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import prompts from 'prompts'
|
|
2
|
+
import ui from './ui.js'
|
|
3
|
+
import cms from './cms.js'
|
|
4
|
+
|
|
5
|
+
async function init(project, name) {
|
|
6
|
+
const nameAsProject = (project && !project.match(/^(ui|cms)$/))
|
|
7
|
+
|
|
8
|
+
if (!project || nameAsProject) {
|
|
9
|
+
const response = await prompts([
|
|
10
|
+
{
|
|
11
|
+
type: 'select',
|
|
12
|
+
name: 'project',
|
|
13
|
+
message: 'Select a project to init',
|
|
14
|
+
choices: [
|
|
15
|
+
{ title: 'ui', value: 'ui' },
|
|
16
|
+
{ title: 'cms', value: 'cms' }
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
])
|
|
20
|
+
|
|
21
|
+
name = nameAsProject ? project : name
|
|
22
|
+
project = response.project
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const { branch } = await prompts([
|
|
26
|
+
{
|
|
27
|
+
type: 'select',
|
|
28
|
+
name: 'branch',
|
|
29
|
+
message: 'Select a git branch',
|
|
30
|
+
choices: [
|
|
31
|
+
{ title: 'main', value: 'main' },
|
|
32
|
+
{ title: 'dev', value: 'dev' }
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
])
|
|
36
|
+
|
|
37
|
+
if (project === 'ui') {
|
|
38
|
+
ui(name, { branch })
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (project === 'cms') {
|
|
42
|
+
const { variant } = await prompts([
|
|
43
|
+
{
|
|
44
|
+
type: 'select',
|
|
45
|
+
name: 'variant',
|
|
46
|
+
message: 'Select a variant to install',
|
|
47
|
+
choices: [
|
|
48
|
+
{ title: 'cms-web', value: 'cms-web' },
|
|
49
|
+
{ title: 'cms-eshop', value: 'cms-eshop' }
|
|
50
|
+
]
|
|
51
|
+
}
|
|
52
|
+
])
|
|
53
|
+
|
|
54
|
+
await cms(name, { branch, variant })
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export default init
|
package/src/utils.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import childProcess from 'child_process'
|
|
2
|
+
|
|
3
|
+
const execSync = (cmd) => {
|
|
4
|
+
try {
|
|
5
|
+
childProcess.execSync(cmd, { stdio: [0, 1, 2] })
|
|
6
|
+
} catch {
|
|
7
|
+
process.exit(1)
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const stripIndent = (string) => {
|
|
12
|
+
const indent = () => {
|
|
13
|
+
const match = string.match(/^[ \t]*(?=\S)/gm)
|
|
14
|
+
|
|
15
|
+
if (!match) {
|
|
16
|
+
return 0
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return match.reduce((r, a) => Math.min(r, a.length), Infinity)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
if (indent() === 0) {
|
|
23
|
+
return string
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const regex = new RegExp(`^[ \\t]{${indent()}}`, 'gm')
|
|
27
|
+
|
|
28
|
+
return string.replace(regex, '')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { execSync, stripIndent }
|