@create-mastery/cli 0.1.0 → 0.1.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/cli.ts +35 -9
- package/commands/add/component.ts +4 -6
- package/commands/add/language.ts +10 -7
- package/commands/generate-schema.ts +16 -15
- package/commands/scripts.ts +3 -3
- package/commands/version.ts +11 -11
- package/package.json +4 -3
- package/utils/find-project-root.ts +15 -0
- package/utils/require-project-root.ts +17 -0
package/cli.ts
CHANGED
|
@@ -1,21 +1,32 @@
|
|
|
1
1
|
#!/usr/bin/env tsx
|
|
2
2
|
|
|
3
|
+
import { execSync } from 'node:child_process'
|
|
4
|
+
import { readFileSync } from 'node:fs'
|
|
5
|
+
import path from 'node:path'
|
|
6
|
+
import chalk from 'chalk'
|
|
3
7
|
import { program } from 'commander'
|
|
4
8
|
import gradient from 'gradient-string'
|
|
9
|
+
import type { PackageJson } from 'type-fest'
|
|
5
10
|
import addComponent from './commands/add/component'
|
|
6
11
|
import addLanguage from './commands/add/language'
|
|
7
12
|
import { genSchema } from './commands/generate-schema'
|
|
8
13
|
import printScripts from './commands/scripts'
|
|
9
14
|
import printVersion from './commands/version'
|
|
10
|
-
import cliInfo from './package.json'
|
|
11
15
|
import { createMasteryASCIIArtBig } from './utils/arts'
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
16
|
+
import { requireProjectRoot } from './utils/require-project-root'
|
|
17
|
+
import { fileURLToPath } from 'node:url'
|
|
18
|
+
|
|
19
|
+
const __filename = fileURLToPath(import.meta.url)
|
|
20
|
+
const __dirname = path.dirname(__filename)
|
|
14
21
|
|
|
15
22
|
const add = program.command('add').description('add a language or component')
|
|
16
23
|
const gen = program.command('gen').description('generate the dictionary schema')
|
|
17
24
|
|
|
18
|
-
|
|
25
|
+
const cliPackagePath = path.resolve(__dirname, './package.json')
|
|
26
|
+
|
|
27
|
+
const cliInfo: PackageJson = JSON.parse(readFileSync(cliPackagePath, 'utf-8'))
|
|
28
|
+
|
|
29
|
+
program.version(cliInfo.version ?? '')
|
|
19
30
|
program.name('cm')
|
|
20
31
|
|
|
21
32
|
program.addHelpText(
|
|
@@ -29,7 +40,7 @@ program.addHelpText(
|
|
|
29
40
|
// I know this may look silly, but it's for creating space between the prompt and the help message
|
|
30
41
|
program.addHelpText('afterAll', ' ')
|
|
31
42
|
|
|
32
|
-
program.description(cliInfo.description)
|
|
43
|
+
program.description(cliInfo.description ?? '')
|
|
33
44
|
|
|
34
45
|
program
|
|
35
46
|
.command('version')
|
|
@@ -37,12 +48,21 @@ program
|
|
|
37
48
|
'display the version of the Create Mastery website and some other useful information'
|
|
38
49
|
)
|
|
39
50
|
.option('-v, --verbose', 'verbose output of version command', false)
|
|
40
|
-
.action((options) =>
|
|
51
|
+
.action((options) => {
|
|
52
|
+
const projectRoot = requireProjectRoot()
|
|
53
|
+
printVersion(options.verbose, cliInfo, projectRoot)
|
|
54
|
+
})
|
|
41
55
|
|
|
42
56
|
program
|
|
43
57
|
.command('scripts')
|
|
44
58
|
.description('display all the available scripts in package.json')
|
|
45
|
-
.action(() =>
|
|
59
|
+
.action(() => {
|
|
60
|
+
const projectRoot = requireProjectRoot()
|
|
61
|
+
const siteInfo: PackageJson = JSON.parse(
|
|
62
|
+
readFileSync(path.join(projectRoot, 'package.json'), 'utf-8')
|
|
63
|
+
)
|
|
64
|
+
printScripts(siteInfo)
|
|
65
|
+
})
|
|
46
66
|
|
|
47
67
|
program
|
|
48
68
|
.command('clone')
|
|
@@ -66,7 +86,10 @@ program
|
|
|
66
86
|
gen
|
|
67
87
|
.command('schema')
|
|
68
88
|
.description('generates the schema for the dictionaries')
|
|
69
|
-
.action(() =>
|
|
89
|
+
.action(() => {
|
|
90
|
+
const projectRoot = requireProjectRoot()
|
|
91
|
+
genSchema(projectRoot)
|
|
92
|
+
})
|
|
70
93
|
|
|
71
94
|
add
|
|
72
95
|
.command('component')
|
|
@@ -74,7 +97,10 @@ add
|
|
|
74
97
|
.argument('<name>', 'component to add')
|
|
75
98
|
.option('-p, --props', 'the component is generated with props', false)
|
|
76
99
|
.option('-c, --client', 'the component is a client component', false)
|
|
77
|
-
.action((name, options) =>
|
|
100
|
+
.action((name, options) => {
|
|
101
|
+
const projectRoot = requireProjectRoot()
|
|
102
|
+
addComponent(name, options.props, options.client, projectRoot)
|
|
103
|
+
})
|
|
78
104
|
|
|
79
105
|
add
|
|
80
106
|
.command('language')
|
|
@@ -1,17 +1,15 @@
|
|
|
1
1
|
import fs from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
|
-
import { fileURLToPath } from 'node:url'
|
|
4
3
|
import chalk from 'chalk'
|
|
5
4
|
|
|
6
|
-
const __filename = fileURLToPath(import.meta.url)
|
|
7
|
-
const __dirname = path.dirname(__filename)
|
|
8
|
-
const componentsDir = path.resolve(__dirname, '../../../src/components/')
|
|
9
|
-
|
|
10
5
|
export default function addComponent(
|
|
11
6
|
componentName: string,
|
|
12
7
|
props: boolean,
|
|
13
|
-
client: boolean
|
|
8
|
+
client: boolean,
|
|
9
|
+
projectRoot: string
|
|
14
10
|
) {
|
|
11
|
+
const componentsDir = path.resolve(projectRoot, 'src/components/')
|
|
12
|
+
|
|
15
13
|
const filePath = path.resolve(componentsDir, `${componentName}.tsx`)
|
|
16
14
|
const dirPath = path.dirname(filePath)
|
|
17
15
|
|
package/commands/add/language.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import fs from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
|
-
import { fileURLToPath } from 'node:url'
|
|
4
3
|
import chalk from 'chalk'
|
|
4
|
+
import { findProjectRoot } from '../../utils/find-project-root'
|
|
5
5
|
|
|
6
|
-
const
|
|
7
|
-
const __dirname = path.dirname(__filename)
|
|
8
|
-
const dictionarieDir = path.resolve(__dirname, '../../../src/i18n/dictionaries')
|
|
6
|
+
const projectRoot = findProjectRoot()
|
|
9
7
|
|
|
10
8
|
type Json =
|
|
11
9
|
| string
|
|
@@ -37,7 +35,7 @@ function genLocales(files: string[]) {
|
|
|
37
35
|
const content = `export type locales = ${locales}\n`
|
|
38
36
|
|
|
39
37
|
fs.writeFileSync(
|
|
40
|
-
path.resolve(
|
|
38
|
+
path.resolve(projectRoot ?? '', '../../../src/i18n/types/locales.ts'),
|
|
41
39
|
content
|
|
42
40
|
)
|
|
43
41
|
}
|
|
@@ -54,7 +52,7 @@ function genI18n(files: string[]) {
|
|
|
54
52
|
}`
|
|
55
53
|
|
|
56
54
|
fs.writeFileSync(
|
|
57
|
-
path.resolve(
|
|
55
|
+
path.resolve(projectRoot ?? '', '../../../src/i18n/i18n.ts'),
|
|
58
56
|
content
|
|
59
57
|
)
|
|
60
58
|
}
|
|
@@ -72,7 +70,7 @@ function genDictionaryLoaders(files: string[]) {
|
|
|
72
70
|
|
|
73
71
|
fs.writeFileSync(
|
|
74
72
|
path.resolve(
|
|
75
|
-
|
|
73
|
+
projectRoot ?? '',
|
|
76
74
|
'../../../src/i18n/dictionaries/dictionaries-loaders.ts'
|
|
77
75
|
),
|
|
78
76
|
dictionariesLoaders
|
|
@@ -80,6 +78,11 @@ function genDictionaryLoaders(files: string[]) {
|
|
|
80
78
|
}
|
|
81
79
|
|
|
82
80
|
export default function addLanguage(language: string) {
|
|
81
|
+
const dictionarieDir = path.resolve(
|
|
82
|
+
projectRoot ?? '',
|
|
83
|
+
'../../../src/i18n/dictionaries'
|
|
84
|
+
)
|
|
85
|
+
|
|
83
86
|
const input = JSON.parse(fs.readFileSync(`${dictionarieDir}/en.json`, 'utf8'))
|
|
84
87
|
const output = stripValues(input)
|
|
85
88
|
|
|
@@ -1,20 +1,7 @@
|
|
|
1
|
-
import * as GenerateSchema from 'generate-schema'
|
|
2
|
-
|
|
3
1
|
import fs from 'node:fs'
|
|
4
2
|
import path from 'node:path'
|
|
5
|
-
import { fileURLToPath } from 'node:url'
|
|
6
3
|
import chalk from 'chalk'
|
|
7
|
-
|
|
8
|
-
const __filename = fileURLToPath(import.meta.url)
|
|
9
|
-
const __dirname = path.dirname(__filename)
|
|
10
|
-
const dictionarieDir = path.resolve(__dirname, '../../src/i18n/dictionaries/')
|
|
11
|
-
const dictionary = JSON.parse(
|
|
12
|
-
fs.readFileSync(`${dictionarieDir}/en.json`, 'utf8')
|
|
13
|
-
)
|
|
14
|
-
const schemaPath = path.resolve(
|
|
15
|
-
__dirname,
|
|
16
|
-
`${dictionarieDir}/schema.schema.json`
|
|
17
|
-
)
|
|
4
|
+
import * as GenerateSchema from 'generate-schema'
|
|
18
5
|
|
|
19
6
|
interface JsonSchema {
|
|
20
7
|
type: string
|
|
@@ -45,7 +32,21 @@ function addRequiredRecursively(
|
|
|
45
32
|
}
|
|
46
33
|
}
|
|
47
34
|
|
|
48
|
-
export function genSchema() {
|
|
35
|
+
export function genSchema(projectRoot: string) {
|
|
36
|
+
const dictionarieDir = path.resolve(
|
|
37
|
+
projectRoot ?? '',
|
|
38
|
+
'src/i18n/dictionaries/'
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
const dictionary = JSON.parse(
|
|
42
|
+
fs.readFileSync(`${dictionarieDir}/en.json`, 'utf8')
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
const schemaPath = path.resolve(
|
|
46
|
+
projectRoot ?? '',
|
|
47
|
+
`${dictionarieDir}/schema.schema.json`
|
|
48
|
+
)
|
|
49
|
+
|
|
49
50
|
const schema = GenerateSchema.json('dictionary schema', dictionary)
|
|
50
51
|
|
|
51
52
|
addRequiredRecursively(schema, dictionary)
|
package/commands/scripts.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import chalk from 'chalk'
|
|
2
|
-
import
|
|
2
|
+
import type { PackageJson } from 'type-fest'
|
|
3
3
|
import { createMasteryASCIIArtSmall } from '../utils/arts'
|
|
4
4
|
|
|
5
|
-
export default function printScripts() {
|
|
5
|
+
export default function printScripts(siteInfo: PackageJson) {
|
|
6
6
|
console.log(chalk.blue(createMasteryASCIIArtSmall))
|
|
7
7
|
console.log(chalk.blue('Available scripts:'))
|
|
8
8
|
console.log(chalk.blue('──────────────────────────────────────────'))
|
|
9
|
-
Object.entries(siteInfo.scripts).forEach(([key, value]) => {
|
|
9
|
+
Object.entries(siteInfo.scripts ?? '').forEach(([key, value]) => {
|
|
10
10
|
console.log(
|
|
11
11
|
`${chalk.blue(key.padEnd(10))} ${chalk.blue('─')} ${chalk.reset(value)}`
|
|
12
12
|
)
|
package/commands/version.ts
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
1
|
import fs from 'node:fs'
|
|
2
2
|
import path from 'node:path'
|
|
3
|
-
import { fileURLToPath } from 'node:url'
|
|
4
3
|
import chalk from 'chalk'
|
|
5
4
|
import { globSync } from 'glob'
|
|
6
|
-
import
|
|
5
|
+
import type { PackageJson } from 'type-fest'
|
|
7
6
|
import { createMasteryASCIIArtSmall } from '../utils/arts'
|
|
8
7
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
8
|
+
export default function printVersion(
|
|
9
|
+
verbose: boolean,
|
|
10
|
+
cliInfo: PackageJson,
|
|
11
|
+
projectRoot: string
|
|
12
|
+
) {
|
|
13
|
+
const dictionarieDir = path.resolve(projectRoot, 'src/i18n/dictionaries')
|
|
14
|
+
const guideDirectory = path.resolve(projectRoot, 'src/app/**/guide')
|
|
15
15
|
|
|
16
16
|
// since schema.schema.json is also counted we decrement the value by 1 to get the actual number of languages
|
|
17
17
|
const getLanguages = () =>
|
|
18
18
|
fs.readdirSync(dictionarieDir).filter((f) => f.endsWith('.json')).length - 1
|
|
19
19
|
|
|
20
|
-
const deps = Object.keys(
|
|
21
|
-
const devDeps = Object.keys(
|
|
20
|
+
const deps = Object.keys(cliInfo.dependencies ?? '').length
|
|
21
|
+
const devDeps = Object.keys(cliInfo.devDependencies ?? '').length
|
|
22
22
|
|
|
23
23
|
const languages: number = getLanguages()
|
|
24
24
|
const guides: number = globSync(`${guideDirectory}/**/*.tsx`).length
|
|
25
25
|
|
|
26
26
|
console.log(chalk.blue(createMasteryASCIIArtSmall))
|
|
27
|
-
console.log(chalk.blue('VERSION ─'), chalk.reset(
|
|
27
|
+
console.log(chalk.blue('VERSION ─'), chalk.reset(cliInfo.version))
|
|
28
28
|
console.log(chalk.blue('GUIDES ─'), chalk.reset(guides))
|
|
29
29
|
console.log(chalk.blue('LANGUAGES ─'), chalk.reset(languages))
|
|
30
30
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@create-mastery/cli",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "The official Create Website CLI, created to enhance the DX",
|
|
5
5
|
"homepage": "https://github.com/Create-Mastery/website/tree/main/cli#readme",
|
|
6
6
|
"repository": {
|
|
@@ -15,12 +15,13 @@
|
|
|
15
15
|
"cm": "cli.ts"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"gradient-string": "^3.0.0",
|
|
19
18
|
"chalk": "^5.6.2",
|
|
20
19
|
"commander": "^14.0.2",
|
|
21
20
|
"generate-schema": "^2.6.0",
|
|
22
21
|
"glob": "^13.0.0",
|
|
23
|
-
"
|
|
22
|
+
"gradient-string": "^3.0.0",
|
|
23
|
+
"tsx": "^4.21.0",
|
|
24
|
+
"type-fest": "^5.4.3"
|
|
24
25
|
},
|
|
25
26
|
"devDependencies": {
|
|
26
27
|
"@biomejs/biome": "^2.3.11"
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import fs from 'node:fs'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
|
|
4
|
+
export function findProjectRoot(startDir = process.cwd()): string | null {
|
|
5
|
+
let dir = startDir
|
|
6
|
+
|
|
7
|
+
while (dir !== path.parse(dir).root) {
|
|
8
|
+
if (fs.existsSync(path.join(dir, '.create-mastery-root'))) {
|
|
9
|
+
return dir
|
|
10
|
+
}
|
|
11
|
+
dir = path.dirname(dir)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
return null
|
|
15
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import chalk from 'chalk'
|
|
2
|
+
import { findProjectRoot } from './find-project-root'
|
|
3
|
+
|
|
4
|
+
export function requireProjectRoot(): string {
|
|
5
|
+
const root = findProjectRoot()
|
|
6
|
+
|
|
7
|
+
if (!root) {
|
|
8
|
+
console.error(
|
|
9
|
+
chalk.red(
|
|
10
|
+
'Not inside a Create Mastery project. Run this command inside a project.'
|
|
11
|
+
)
|
|
12
|
+
)
|
|
13
|
+
process.exit(1)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return root
|
|
17
|
+
}
|