@spark-ui/cli-utils 1.3.1 → 1.4.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/CHANGELOG.md +10 -0
- package/bin/core/Logger.mjs +19 -0
- package/bin/core/System.mjs +45 -0
- package/bin/core/index.mjs +2 -0
- package/bin/generators/Generator.mjs +5 -0
- package/bin/generators/TemplateGenerator.mjs +83 -0
- package/bin/generators/index.mjs +2 -0
- package/bin/spark-generate.mjs +35 -120
- package/bin/spark-setup-theme.mjs +6 -4
- package/bin/validators/DescriptionValidator.mjs +19 -0
- package/bin/validators/NameValidator.mjs +25 -0
- package/bin/validators/Validator.mjs +5 -0
- package/bin/validators/index.mjs +2 -0
- package/package.json +3 -2
- package/src/index.stories.mdx +51 -0
- package/templates/{[.npmignore].js → component/[.npmignore].js} +0 -0
- package/templates/{[package.json].js → component/[package.json].js} +2 -2
- package/templates/{[tsconfig.json].js → component/[tsconfig.json].js} +0 -0
- package/templates/{[vite.config.ts].js → component/[vite.config.ts].js} +0 -0
- package/templates/{src → component/src}/[Component.stories.mdx].js +4 -4
- package/templates/{src → component/src}/[Component.stories.tsx].js +2 -2
- package/templates/{src → component/src}/[Component.test.tsx].js +2 -2
- package/templates/{src → component/src}/[Component.tsx].js +2 -2
- package/templates/component/src/[Component.variants.tsx].js +8 -0
- package/templates/{src → component/src}/[index.ts].js +2 -2
- package/templates/hook/[.npmignore].js +3 -0
- package/templates/hook/[package.json].js +15 -0
- package/templates/hook/[tsconfig.json].js +4 -0
- package/templates/hook/[vite.config.ts].js +7 -0
- package/templates/hook/src/[index.ts].js +8 -0
- package/templates/hook/src/[name.stories.mdx].js +42 -0
- package/templates/hook/src/[name.test.tsx].js +17 -0
- package/templates/hook/src/[name.tsx].js +10 -0
- package/templates/util/[.npmignore].js +1 -0
- package/templates/util/[package.json].js +15 -0
- package/templates/util/[tsconfig.json].js +5 -0
- package/templates/util/[vite.config.ts].js +23 -0
- package/templates/util/src/[index.ts].js +1 -0
- package/templates/src/[Component.variants.tsx].js +0 -8
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,16 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# [1.4.0](https://github.com/adevinta/spark/compare/@spark-ui/cli-utils@1.3.2...@spark-ui/cli-utils@1.4.0) (2023-02-22)
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
- **cli-utils:** add hook and utils template ([e22d672](https://github.com/adevinta/spark/commit/e22d672e349909cc4bc8673312846d10d77e7ea5))
|
|
11
|
+
|
|
12
|
+
## [1.3.2](https://github.com/adevinta/spark/compare/@spark-ui/cli-utils@1.3.1...@spark-ui/cli-utils@1.3.2) (2023-02-22)
|
|
13
|
+
|
|
14
|
+
**Note:** Version bump only for package @spark-ui/cli-utils
|
|
15
|
+
|
|
6
16
|
## [1.3.1](https://github.com/adevinta/spark/compare/@spark-ui/cli-utils@1.3.0...@spark-ui/cli-utils@1.3.1) (2023-02-21)
|
|
7
17
|
|
|
8
18
|
**Note:** Version bump only for package @spark-ui/cli-utils
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import chalk from 'chalk'
|
|
2
|
+
|
|
3
|
+
export class Logger {
|
|
4
|
+
success(message) {
|
|
5
|
+
console.log(chalk.green(message))
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
error(message) {
|
|
9
|
+
console.log(chalk.red(message))
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
info(message) {
|
|
13
|
+
console.log(chalk.yellow(message))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
warning(message) {
|
|
17
|
+
console.log(chalk.green(message))
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import fse from 'fs-extra'
|
|
2
|
+
import glob from 'glob'
|
|
3
|
+
|
|
4
|
+
export class System {
|
|
5
|
+
logger
|
|
6
|
+
|
|
7
|
+
constructor({ logger }) {
|
|
8
|
+
this.logger = logger
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
exit(message) {
|
|
12
|
+
this.logger.error(`✖ Error: ${message}\n`)
|
|
13
|
+
process.exit(1)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
getBasePath() {
|
|
17
|
+
return process.cwd()
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
getPackageJSON() {
|
|
21
|
+
const basePath = this.getBasePath()
|
|
22
|
+
|
|
23
|
+
const raw = fse.readFileSync(`${basePath}/package.json`).toString()
|
|
24
|
+
|
|
25
|
+
return JSON.parse(raw)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
isPackageCreated(name) {
|
|
29
|
+
const base = this.getBasePath()
|
|
30
|
+
const packageJSON = this.getPackageJSON()
|
|
31
|
+
|
|
32
|
+
return packageJSON.workspaces.some(workspace => {
|
|
33
|
+
const packages = glob.sync(`${base}/${workspace}/`)
|
|
34
|
+
|
|
35
|
+
return packages.some(path => path.endsWith(`/${name}/`))
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
writeFile({ path, content }) {
|
|
40
|
+
return fse
|
|
41
|
+
.outputFile(path, content)
|
|
42
|
+
.then(() => this.logger.info(`Created ${path}`))
|
|
43
|
+
.catch(error => this.exit(`Failed creating ${path}`))
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { join } from 'node:path'
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import glob from 'glob'
|
|
4
|
+
import { pascalCase } from 'pascal-case'
|
|
5
|
+
import { camelCase } from 'camel-case'
|
|
6
|
+
|
|
7
|
+
import { System } from '../core/index.mjs'
|
|
8
|
+
import { Generator } from './Generator.mjs'
|
|
9
|
+
|
|
10
|
+
export class TemplateGenerator extends Generator {
|
|
11
|
+
static TYPES = {
|
|
12
|
+
COMPONENT: 'component',
|
|
13
|
+
HOOK: 'hook',
|
|
14
|
+
UTIL: 'util',
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static CONTEXTS = {
|
|
18
|
+
[TemplateGenerator.TYPES.COMPONENT]: 'components',
|
|
19
|
+
[TemplateGenerator.TYPES.HOOK]: 'components',
|
|
20
|
+
[TemplateGenerator.TYPES.UTIL]: 'utils',
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
constructor({ system }) {
|
|
24
|
+
super()
|
|
25
|
+
this.system = system
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
getDest({ type, name }) {
|
|
29
|
+
const basePath = this.system.getBasePath()
|
|
30
|
+
const context = TemplateGenerator.CONTEXTS[type]
|
|
31
|
+
|
|
32
|
+
return `${basePath}/packages/${context}/${name}`
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
getTemplatePaths({ type }) {
|
|
36
|
+
const pattern = fileURLToPath(new URL(`../../templates/${type}/**/*.js`, import.meta.url))
|
|
37
|
+
|
|
38
|
+
return new Promise((resolve, reject) => {
|
|
39
|
+
glob(pattern, async (error, paths) => {
|
|
40
|
+
if (error) {
|
|
41
|
+
return reject(error)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
resolve(paths)
|
|
45
|
+
})
|
|
46
|
+
})
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
getTemplatePath({ path, name, type, dest }) {
|
|
50
|
+
const parsed = path
|
|
51
|
+
.replace(/(.*)\/templates\/([a-z-]+)\//, `${dest}/`)
|
|
52
|
+
.replaceAll(/\[|\]|\.js$/g, '')
|
|
53
|
+
|
|
54
|
+
if (type === TemplateGenerator.TYPES.COMPONENT) {
|
|
55
|
+
return parsed.replace('Component', pascalCase(name))
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (type === TemplateGenerator.TYPES.HOOK) {
|
|
59
|
+
return parsed.replace('name', camelCase(name))
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
return parsed
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async execute({ type, name, description }) {
|
|
66
|
+
const dest = this.getDest({ type, name })
|
|
67
|
+
const paths = await this.getTemplatePaths({ type })
|
|
68
|
+
|
|
69
|
+
const promises = paths.map(path =>
|
|
70
|
+
import(path).then(module => ({
|
|
71
|
+
path: this.getTemplatePath({ path, name, type, dest }),
|
|
72
|
+
content: module.default({
|
|
73
|
+
name,
|
|
74
|
+
description,
|
|
75
|
+
}),
|
|
76
|
+
}))
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
const files = await Promise.all(promises)
|
|
80
|
+
|
|
81
|
+
return Promise.all(files.map(file => this.system.writeFile(file)))
|
|
82
|
+
}
|
|
83
|
+
}
|
package/bin/spark-generate.mjs
CHANGED
|
@@ -1,156 +1,71 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import chalk from 'chalk'
|
|
4
|
-
import fse from 'fs-extra'
|
|
5
3
|
import * as prompt from '@clack/prompts'
|
|
6
|
-
import { fileURLToPath } from 'node:url'
|
|
7
|
-
import glob from 'glob'
|
|
8
|
-
import { pascalCase } from 'pascal-case'
|
|
9
|
-
import { log, showError, writeFile } from '../utils.js'
|
|
10
4
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
5
|
+
import { TemplateGenerator } from './generators/index.mjs'
|
|
6
|
+
import { Logger, System } from './core/index.mjs'
|
|
7
|
+
import { DescriptionValidator, NameValidator } from './validators/index.mjs'
|
|
14
8
|
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
const WORKSPACES = {
|
|
21
|
-
[TEMPLATE_TYPE.COMPONENT]: '/packages/components',
|
|
22
|
-
[TEMPLATE_TYPE.HOOK]: '/packages/hooks',
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const ERRORS = {
|
|
26
|
-
ABORT: 'Aborted package generation',
|
|
27
|
-
NO_PKG_NAME: 'Package name must me defined',
|
|
28
|
-
INVALID_PKG_NAME: 'Name name must contain letters and dash symbols only (ex: "my-package")',
|
|
29
|
-
INVALID_DESCRIPTION: 'Description is too short (minimum is 10 chars)',
|
|
30
|
-
PKG_ALREADY_EXISTS:
|
|
31
|
-
'A package with that name already exists. Either delete it manually or use another name.',
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
const packageUtils = {
|
|
35
|
-
/** Validate the format of the package name (kebab case format) */
|
|
36
|
-
hasValidName: name => /^[a-z-]*$/.test(name),
|
|
37
|
-
/** Check that a package of the same name does not exists across all workspaces */
|
|
38
|
-
alreadyExists: name => {
|
|
39
|
-
return rootPackageJSON.workspaces.some(workspace => {
|
|
40
|
-
const existingPackages = glob.sync(`${BASE_DIR}/${workspace}/`)
|
|
41
|
-
return existingPackages.some(path => path.endsWith(`/${name}/`))
|
|
42
|
-
})
|
|
43
|
-
},
|
|
44
|
-
/** Retrieves the target folder of the generated package */
|
|
45
|
-
getDirectory: (name, template) => `${WORKSPACES[template]}/${name}/`,
|
|
46
|
-
/** Retrieves the full path to the folder of the generated package */
|
|
47
|
-
getFullPath: (name, template) => `${BASE_DIR}${packageUtils.getDirectory(name, template)}`,
|
|
48
|
-
}
|
|
9
|
+
const logger = new Logger()
|
|
10
|
+
const system = new System({ logger })
|
|
11
|
+
const generator = new TemplateGenerator({ system })
|
|
49
12
|
|
|
50
|
-
async
|
|
13
|
+
export const run = async () => {
|
|
51
14
|
const name = await prompt.text({
|
|
52
15
|
message: 'Package name (must contain letters and dash symbols only):',
|
|
53
16
|
initialValue: '',
|
|
54
17
|
validate(value) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
18
|
+
const validator = new NameValidator({ system })
|
|
19
|
+
|
|
20
|
+
return validator.validate(value)
|
|
58
21
|
},
|
|
59
22
|
})
|
|
60
23
|
|
|
61
|
-
if (prompt.isCancel(name))
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
24
|
+
if (prompt.isCancel(name)) {
|
|
25
|
+
system.exit('Aborted package generation')
|
|
26
|
+
}
|
|
65
27
|
|
|
66
|
-
|
|
67
|
-
const template = await prompt.select({
|
|
28
|
+
const type = await prompt.select({
|
|
68
29
|
message: 'Chose a template:',
|
|
69
|
-
initialValue:
|
|
30
|
+
initialValue: 'component',
|
|
70
31
|
options: [
|
|
71
32
|
{
|
|
72
|
-
value:
|
|
33
|
+
value: TemplateGenerator.TYPES.COMPONENT,
|
|
73
34
|
label: 'Component',
|
|
74
|
-
hint: '
|
|
35
|
+
hint: 'TypeScript component package',
|
|
75
36
|
},
|
|
76
37
|
{
|
|
77
|
-
value:
|
|
38
|
+
value: TemplateGenerator.TYPES.HOOK,
|
|
78
39
|
label: 'Hook',
|
|
79
|
-
hint: '
|
|
40
|
+
hint: 'TypeScript hook package',
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
value: TemplateGenerator.TYPES.UTIL,
|
|
44
|
+
label: 'Utility',
|
|
45
|
+
hint: 'TypeScript utility package',
|
|
80
46
|
},
|
|
81
47
|
],
|
|
82
48
|
})
|
|
83
49
|
|
|
84
|
-
if (prompt.isCancel(
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
50
|
+
if (prompt.isCancel(type)) {
|
|
51
|
+
system.exit('Aborted package generation')
|
|
52
|
+
}
|
|
88
53
|
|
|
89
|
-
async function promptPackageDescription() {
|
|
90
54
|
const description = await prompt.text({
|
|
91
55
|
message: 'Describe your package (short description):',
|
|
92
56
|
initialValue: '',
|
|
93
57
|
validate(value) {
|
|
94
|
-
|
|
95
|
-
|
|
58
|
+
const validator = new DescriptionValidator()
|
|
59
|
+
|
|
60
|
+
return validator.validate(value)
|
|
96
61
|
},
|
|
97
62
|
})
|
|
98
63
|
|
|
99
|
-
if (prompt.isCancel(description))
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
/**
|
|
105
|
-
* Program starts here
|
|
106
|
-
*/
|
|
107
|
-
prompt.intro(`Generate Spark package`)
|
|
108
|
-
|
|
109
|
-
const name = await promptPackageName()
|
|
110
|
-
const template = await promptPackageTemplate()
|
|
111
|
-
const description = await promptPackageDescription()
|
|
112
|
-
|
|
113
|
-
const packagePath = packageUtils.getFullPath(name, template)
|
|
114
|
-
|
|
115
|
-
switch (template) {
|
|
116
|
-
case TEMPLATE_TYPE.COMPONENT:
|
|
117
|
-
generateComponentPackage(name, description)
|
|
118
|
-
break
|
|
119
|
-
case TEMPLATE_TYPE.HOOK:
|
|
120
|
-
generateHookPackage(name, description)
|
|
121
|
-
break
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
prompt.outro(`Generating package...`)
|
|
125
|
-
|
|
126
|
-
function generateComponentPackage(name, description) {
|
|
127
|
-
const templatesPattern = fileURLToPath(new URL('../templates/**/*.js', import.meta.url))
|
|
128
|
-
|
|
129
|
-
glob(templatesPattern, async (err, res) => {
|
|
130
|
-
if (err) showError(err)
|
|
131
|
-
if (res) {
|
|
132
|
-
const templateContents = res.map(templatePath =>
|
|
133
|
-
import(templatePath).then(module => ({
|
|
134
|
-
path: templatePath
|
|
135
|
-
.replace(/(.*)\/templates\//, packagePath)
|
|
136
|
-
.replace('Component', pascalCase(name))
|
|
137
|
-
.replaceAll(/\[|\]|\.js$/g, ''),
|
|
138
|
-
content: module.default({
|
|
139
|
-
component: name,
|
|
140
|
-
description: description,
|
|
141
|
-
}),
|
|
142
|
-
}))
|
|
143
|
-
)
|
|
64
|
+
if (prompt.isCancel(description)) {
|
|
65
|
+
system.exit('Aborted package generation')
|
|
66
|
+
}
|
|
144
67
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
Promise.all(filesToWrite.map(writeFile)).then(() => {
|
|
148
|
-
log.success('All package files has been properly written!')
|
|
149
|
-
})
|
|
150
|
-
}
|
|
151
|
-
})
|
|
68
|
+
generator.execute({ name, type, description })
|
|
152
69
|
}
|
|
153
70
|
|
|
154
|
-
|
|
155
|
-
showError('Todo: template for hook packages is not ready yet.')
|
|
156
|
-
}
|
|
71
|
+
run()
|
|
@@ -5,7 +5,8 @@ import { join, extname, parse, sep } from 'path'
|
|
|
5
5
|
import { readFileSync, readdirSync, writeFileSync, unlinkSync } from 'fs'
|
|
6
6
|
import { transformSync } from 'esbuild'
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
const logger = new Logger()
|
|
9
|
+
const system = new System({ logger })
|
|
9
10
|
|
|
10
11
|
const jsFileExtension = '.js'
|
|
11
12
|
|
|
@@ -14,7 +15,7 @@ const configFile = readdirSync(process.cwd()).find(fileName =>
|
|
|
14
15
|
)
|
|
15
16
|
|
|
16
17
|
if (!configFile) {
|
|
17
|
-
|
|
18
|
+
system.exit(
|
|
18
19
|
"We couldn't find a `spark.theme.config` file in this folder. Please make sure that the file is located in the root folder of your project"
|
|
19
20
|
)
|
|
20
21
|
}
|
|
@@ -24,8 +25,9 @@ const filePath = join(process.cwd(), configFile)
|
|
|
24
25
|
|
|
25
26
|
const allowedExtensions = ['.ts', '.mts', '.cts', '.js', '.cjs', '.mjs']
|
|
26
27
|
const fileExtension = extname(filePath)
|
|
28
|
+
|
|
27
29
|
if (!allowedExtensions.includes(fileExtension)) {
|
|
28
|
-
|
|
30
|
+
system.exit(`Your spark.theme.config file extension (${fileExtension}) is not supported.`)
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
const tsCode = readFileSync(filePath, 'utf-8')
|
|
@@ -42,6 +44,6 @@ const child = spawn(process.execPath, [jsFilePath], {
|
|
|
42
44
|
|
|
43
45
|
child.on('exit', code => {
|
|
44
46
|
if (!configFileIsInJS) unlinkSync(jsFilePath)
|
|
45
|
-
|
|
47
|
+
logger.success('✨ Your Spark theme config files have been successfully created!')
|
|
46
48
|
process.exit(code)
|
|
47
49
|
})
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Validator } from './Validator.mjs'
|
|
2
|
+
|
|
3
|
+
export class DescriptionValidator extends Validator {
|
|
4
|
+
constructor() {
|
|
5
|
+
super()
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
validate(description) {
|
|
9
|
+
if (!description) {
|
|
10
|
+
return 'You package must have a description'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (description.length < 10) {
|
|
14
|
+
return 'Description is too short (minimum is 10 chars)'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return undefined
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { System } from '../core/index.mjs'
|
|
2
|
+
import { Validator } from './Validator.mjs'
|
|
3
|
+
|
|
4
|
+
export class NameValidator extends Validator {
|
|
5
|
+
system
|
|
6
|
+
|
|
7
|
+
constructor({ system }) {
|
|
8
|
+
super()
|
|
9
|
+
this.system = system
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
validate(name) {
|
|
13
|
+
if (!name) {
|
|
14
|
+
return 'Package name must me defined'
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (!/^[a-z-]*$/.test(name)) {
|
|
18
|
+
return 'Name name must contain letters and dash symbols only (ex: "my-package")'
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (this.system.isPackageCreated(name)) {
|
|
22
|
+
return 'A package with that name already exists. Either delete it manually or use another name.'
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@spark-ui/cli-utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Spark CLI utils",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
"type": "module",
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@clack/prompts": "0.2.2",
|
|
16
|
+
"camel-case": "4.1.2",
|
|
16
17
|
"chalk": "5.2.0",
|
|
17
18
|
"commander": "10.0.0",
|
|
18
19
|
"esbuild": "0.17.8",
|
|
@@ -25,5 +26,5 @@
|
|
|
25
26
|
"url": "git@github.com:adevinta/spark.git",
|
|
26
27
|
"directory": "packages/utils/cli"
|
|
27
28
|
},
|
|
28
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "61d037acf7909f745ced1d1a0196fe6d2838850e"
|
|
29
30
|
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Meta } from '@storybook/blocks'
|
|
2
|
+
import { StoryHeading } from '@docs/helpers/StoryHeading'
|
|
3
|
+
|
|
4
|
+
<Meta title="utils/CLI" />
|
|
5
|
+
|
|
6
|
+
# CLI utils
|
|
7
|
+
|
|
8
|
+
This package provides some CLI commands to improve the development experience when building the Spark design system. Right now there are some different commands available:
|
|
9
|
+
|
|
10
|
+
- A command for generating new components: `$ spark generate`.
|
|
11
|
+
- A command for doing the initial setup for a new theme: `$ spark setup-theme`.
|
|
12
|
+
|
|
13
|
+
## Contents
|
|
14
|
+
|
|
15
|
+
- [Installation](#installation)
|
|
16
|
+
- [Generating a new package](#generating-a-new-package)
|
|
17
|
+
- [Setting up a theme](#setting-up-a-theme)
|
|
18
|
+
|
|
19
|
+
<StoryHeading label="Installation" as="h2" />
|
|
20
|
+
|
|
21
|
+
CLI utils can be used by installing the package `@spark-ui/cli-utils` in your project:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
$ npm install --save-dev @spark-ui/cli-utils
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
or just by running the following command:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
$ npx spark COMMAND_NAME
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
<StoryHeading label="Generating a new package" as="h2" />
|
|
34
|
+
|
|
35
|
+
In order to generate a new package, the following command has to be executed:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
$ spark generate
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Then, a command prompt will guide you through the process by asking you for:
|
|
42
|
+
|
|
43
|
+
- the package name (required),
|
|
44
|
+
- the template used (required, only `Component` template available right now)
|
|
45
|
+
- and the package description (optional).
|
|
46
|
+
|
|
47
|
+
<StoryHeading label="Setting up a theme" as="h2" />
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
$ spark setup-theme
|
|
51
|
+
```
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { pascalCase } from 'pascal-case'
|
|
2
2
|
|
|
3
|
-
export default ({
|
|
4
|
-
const componentName = pascalCase(
|
|
3
|
+
export default ({ name, description }) => {
|
|
4
|
+
const componentName = pascalCase(name)
|
|
5
5
|
|
|
6
6
|
return `import { ArgsTable, Meta, Story } from '@storybook/addon-docs'
|
|
7
7
|
import { ReactLiveBlock } from '@docs/helpers/ReactLiveBlock'
|
|
@@ -20,13 +20,13 @@ ${description}
|
|
|
20
20
|
<StoryHeading label="Install" />
|
|
21
21
|
|
|
22
22
|
\`\`\`
|
|
23
|
-
npm install @spark-ui/${
|
|
23
|
+
npm install @spark-ui/${name}
|
|
24
24
|
\`\`\`
|
|
25
25
|
|
|
26
26
|
<StoryHeading label="Import" />
|
|
27
27
|
|
|
28
28
|
\`\`\`
|
|
29
|
-
import { ${componentName} } from "@spark-ui/${
|
|
29
|
+
import { ${componentName} } from "@spark-ui/${name}"
|
|
30
30
|
\`\`\`
|
|
31
31
|
|
|
32
32
|
<StoryHeading label="Props" />
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { pascalCase } from 'pascal-case'
|
|
2
2
|
|
|
3
|
-
export default ({
|
|
4
|
-
const componentName = pascalCase(
|
|
3
|
+
export default ({ name, description }) => {
|
|
4
|
+
const componentName = pascalCase(name)
|
|
5
5
|
|
|
6
6
|
return `import { ReactLiveBlock } from '@docs/helpers/ReactLiveBlock'
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { pascalCase } from 'pascal-case'
|
|
2
2
|
|
|
3
|
-
export default ({
|
|
4
|
-
const componentName = pascalCase(
|
|
3
|
+
export default ({ name }) => {
|
|
4
|
+
const componentName = pascalCase(name)
|
|
5
5
|
|
|
6
6
|
return `import { render, screen } from '@testing-library/react'
|
|
7
7
|
import userEvent from '@testing-library/user-event'
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { pascalCase } from 'pascal-case'
|
|
2
2
|
|
|
3
|
-
export default ({
|
|
4
|
-
const componentName = pascalCase(
|
|
3
|
+
export default ({ name }) => {
|
|
4
|
+
const componentName = pascalCase(name)
|
|
5
5
|
|
|
6
6
|
return `import { ComponentPropsWithoutRef, PropsWithChildren } from 'react'
|
|
7
7
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { pascalCase } from 'pascal-case'
|
|
2
2
|
|
|
3
|
-
export default ({
|
|
4
|
-
const componentName = pascalCase(
|
|
3
|
+
export default ({ name }) => {
|
|
4
|
+
const componentName = pascalCase(name)
|
|
5
5
|
|
|
6
6
|
return `export { ${componentName} } from './${componentName}'
|
|
7
7
|
`
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export default ({ name, description }) => `{
|
|
2
|
+
"name": "@spark-ui/${name}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "${description}",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"module": "./dist/index.mjs",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "vite build"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
`
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { camelCase } from 'camel-case'
|
|
2
|
+
|
|
3
|
+
export default ({ name, description }) => {
|
|
4
|
+
const hookName = camelCase(name)
|
|
5
|
+
|
|
6
|
+
return `import { ArgsTable, Meta, Story } from '@storybook/addon-docs'
|
|
7
|
+
import { ReactLiveBlock } from '@docs/helpers/ReactLiveBlock'
|
|
8
|
+
import { StoryHeading } from '@docs/helpers/StoryHeading'
|
|
9
|
+
|
|
10
|
+
import { ${hookName} } from '.'
|
|
11
|
+
|
|
12
|
+
import * as stories from './${hookName}.stories'
|
|
13
|
+
|
|
14
|
+
<Meta title="Hooks/${hookName}" />
|
|
15
|
+
|
|
16
|
+
# ${hookName}
|
|
17
|
+
|
|
18
|
+
${description}
|
|
19
|
+
|
|
20
|
+
<StoryHeading label="Install" />
|
|
21
|
+
|
|
22
|
+
\`\`\`
|
|
23
|
+
npm install @spark-ui/${name}
|
|
24
|
+
\`\`\`
|
|
25
|
+
|
|
26
|
+
<StoryHeading label="Import" />
|
|
27
|
+
|
|
28
|
+
\`\`\`
|
|
29
|
+
import { ${hookName} } from "@spark-ui/${name}"
|
|
30
|
+
\`\`\`
|
|
31
|
+
|
|
32
|
+
<StoryHeading label="Usage" />
|
|
33
|
+
|
|
34
|
+
<ArgsTable of={${hookName}} />
|
|
35
|
+
|
|
36
|
+
\`\`\`jsx
|
|
37
|
+
import { ${hookName} } from "@spark-ui/${name}"
|
|
38
|
+
|
|
39
|
+
const Demo = () => {}
|
|
40
|
+
\`\`\`
|
|
41
|
+
`
|
|
42
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { camelCase } from 'camel-case'
|
|
2
|
+
|
|
3
|
+
export default ({ name }) => {
|
|
4
|
+
const hookName = camelCase(name)
|
|
5
|
+
|
|
6
|
+
return `import { renderHook } from '@testing-library/react'
|
|
7
|
+
import { describe, expect, it } from 'vitest'
|
|
8
|
+
|
|
9
|
+
import { ${hookName} } from './${hookName}'
|
|
10
|
+
|
|
11
|
+
describe('${hookName}', () => {
|
|
12
|
+
it('should be defined', () => {
|
|
13
|
+
expect(${hookName}).toBeDefined()
|
|
14
|
+
})
|
|
15
|
+
})
|
|
16
|
+
`
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default () => 'src'
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export default ({ name, description }) => `{
|
|
2
|
+
"name": "@spark-ui/${name}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "${description}",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"module": "./dist/index.mjs",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "vite build"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
`
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export default () => `import { terser } from 'rollup-plugin-terser'
|
|
2
|
+
import dts from 'vite-plugin-dts'
|
|
3
|
+
|
|
4
|
+
export default {
|
|
5
|
+
build: {
|
|
6
|
+
target: 'es2015',
|
|
7
|
+
lib: {
|
|
8
|
+
entry: 'src/index.ts',
|
|
9
|
+
formats: ['es', 'cjs'],
|
|
10
|
+
fileName: 'index',
|
|
11
|
+
},
|
|
12
|
+
rollupOptions: {
|
|
13
|
+
external: ['node:path', 'node:fs'],
|
|
14
|
+
plugins: [terser()],
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
plugins: [
|
|
18
|
+
dts({
|
|
19
|
+
entryRoot: './src',
|
|
20
|
+
}),
|
|
21
|
+
],
|
|
22
|
+
}
|
|
23
|
+
`
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default () => ''
|