@digigov/cli-lab 1.0.1 → 1.2.1
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/.rush/temp/package-deps_build.json +12 -6
- package/.rush/temp/package-deps_lint.json +15 -0
- package/.rush/temp/shrinkwrap-deps.json +11 -11
- package/CHANGELOG.json +53 -0
- package/CHANGELOG.md +33 -1
- package/lib/extra/index.mjs +49 -20
- package/misc/html-types.js +121 -0
- package/misc/react-core-components.js +1424 -0
- package/package.json +3 -2
- package/scripts/add-package-to-subtree-branch.mjs +76 -0
- package/scripts/generate-react-core.mjs +174 -0
- package/scripts/merge-subtree.mjs +22 -0
- package/scripts/publish.mjs +18 -4
- package/scripts/verify-and-update-local-package-versions.mjs +29 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@digigov/cli-lab",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.1",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"directories": {
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"zx": "~1.15.2",
|
|
16
16
|
"zx-extra": "~0.0.4",
|
|
17
17
|
"inquirer": "~8.1.2",
|
|
18
|
-
"glob": "7.1.6"
|
|
18
|
+
"glob": "7.1.6",
|
|
19
|
+
"fs-extra": "~10.0.0"
|
|
19
20
|
}
|
|
20
21
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#!/usr/bin/env zx
|
|
2
|
+
import "zx-extra";
|
|
3
|
+
import "../lib/extra/index.mjs";
|
|
4
|
+
|
|
5
|
+
const dryRun = argv['dry']
|
|
6
|
+
console.log(argv)
|
|
7
|
+
const CI = process.env['CI']
|
|
8
|
+
console.log('CI', CI)
|
|
9
|
+
const configName = 'subtree.config.json'
|
|
10
|
+
const subtreeConfigFileExists = await find(configName)
|
|
11
|
+
console.log(subtreeConfigFileExists)
|
|
12
|
+
|
|
13
|
+
if (!subtreeConfigFileExists.length) {
|
|
14
|
+
console.log('Creating subtree.config file')
|
|
15
|
+
await writeJSON(configName, {})
|
|
16
|
+
}
|
|
17
|
+
const subtreeConfigFile = process.cwd() + '/' + configName
|
|
18
|
+
const subtreeConfig = await readJSON(subtreeConfigFile) || {}
|
|
19
|
+
const tempFolder = 'common/temp/repo'
|
|
20
|
+
await rm(tempFolder)
|
|
21
|
+
await mkdir(tempFolder)
|
|
22
|
+
cd(tempFolder)
|
|
23
|
+
await cli.git.clone('../../.. .')
|
|
24
|
+
await cli.git.checkout(`main`)
|
|
25
|
+
const rushLib = require('@microsoft/rush-lib');
|
|
26
|
+
const rushConfiguration = rushLib.RushConfiguration.loadFromDefaultLocation({
|
|
27
|
+
startingFolder: process.cwd()
|
|
28
|
+
});
|
|
29
|
+
const answers = subtreeConfig
|
|
30
|
+
const cwd = process.cwd()
|
|
31
|
+
const allPackages = rushConfiguration.projects.map(p => p.packageName)
|
|
32
|
+
if (!CI) {
|
|
33
|
+
answers.remote = await question(`Enter the repository url you want to push`,
|
|
34
|
+
subtreeConfig.remote)
|
|
35
|
+
answers.packages = await checkbox(
|
|
36
|
+
`Select package to be published to Github`,
|
|
37
|
+
allPackages, subtreeConfig.packages)
|
|
38
|
+
}
|
|
39
|
+
const branchName = answers.remote.replace('https://', '')
|
|
40
|
+
|
|
41
|
+
const notPublishedPackages = allPackages.filter((p) => !answers.packages.includes(p))
|
|
42
|
+
answers.lastCommitID = await cli.git.log(`-1 --pretty=format:"%h"`, {stdout: true})
|
|
43
|
+
await writeJSON(subtreeConfigFile, answers)
|
|
44
|
+
// delete old git history before X months, based on Date
|
|
45
|
+
|
|
46
|
+
const oneMonthSeconds = 1000 * 60 * 60 * 24 * 30;
|
|
47
|
+
const d = Date.now();
|
|
48
|
+
const beforeDateDate = new Date(d - oneMonthSeconds * 3);
|
|
49
|
+
const afterDateDate = new Date(d - oneMonthSeconds * 4);
|
|
50
|
+
const beforeDate = `${beforeDateDate.getFullYear()}-${beforeDateDate.getMonth()}-${beforeDateDate.getDay()}`;
|
|
51
|
+
const afterDate = `${afterDateDate.getFullYear()}-${afterDateDate.getMonth()}-${afterDateDate.getDay()}`;
|
|
52
|
+
const commitId = await cli.git.log(`-1 --before={${beforeDate}} --after={${afterDate}} --pretty=format:"%h"`, { stdout: true })
|
|
53
|
+
await cli.git.checkout(`--orphan ${branchName} ${commitId}`)
|
|
54
|
+
await cli.git.commit(`-m "chore: remove old commits from git history before ${afterDate}"`)
|
|
55
|
+
await cli.git.rebase(`--onto ${branchName} ${commitId} main`)
|
|
56
|
+
await cli.git.branch(`-D ${branchName}`)
|
|
57
|
+
await cli.git.checkout(`-b ${branchName}`)
|
|
58
|
+
const notPublishedProjects = notPublishedPackages.map(packageName =>
|
|
59
|
+
rushConfiguration
|
|
60
|
+
.findProjectByShorthandName(packageName)
|
|
61
|
+
.projectFolder
|
|
62
|
+
.replace(`${cwd}/`, '')
|
|
63
|
+
).join(' ')
|
|
64
|
+
process.env['FILTER_BRANCH_SQUELCH_WARNING'] = 1
|
|
65
|
+
await cli.git['filter-branch'](`--force --index-filter \
|
|
66
|
+
"git rm -r --cached --ignore-unmatch ${notPublishedProjects}" \
|
|
67
|
+
--prune-empty --tag-name-filter cat -- --all`)
|
|
68
|
+
const rushJSON = await readJSON(rushConfiguration.rushJsonFile)
|
|
69
|
+
rushJSON.projects = rushJSON.projects.filter(project => !notPublishedPackages.includes(project.packageName))
|
|
70
|
+
await writeJSON('rush.json', rushJSON)
|
|
71
|
+
await cli.rush.update('--full --purge')
|
|
72
|
+
await cli.git.commit('-am "chore: remove unpublished projects from rush json"')
|
|
73
|
+
await cli.git.branch('-M main')
|
|
74
|
+
await cli.git.remote('add partial ' + answers.remote)
|
|
75
|
+
await cli.git.push('-f -u partial main')
|
|
76
|
+
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#!/usr/bin/env zx
|
|
2
|
+
|
|
3
|
+
import '../lib/extra/index.mjs';
|
|
4
|
+
|
|
5
|
+
const components = require('../misc/react-core-components')
|
|
6
|
+
const htmlTypes = require('../misc/html-types')
|
|
7
|
+
// uppercase the first letter of a word
|
|
8
|
+
const ucFirst = (str) => str.charAt(0).toUpperCase() + str.slice(1);
|
|
9
|
+
function findRefInChildren(children){
|
|
10
|
+
for(const child of children){
|
|
11
|
+
if(child.props && child.props.ref){
|
|
12
|
+
return child.element
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
for(const componentName in components){
|
|
17
|
+
const component = components[componentName]
|
|
18
|
+
if(component.element){
|
|
19
|
+
let mainElement = component.element
|
|
20
|
+
if(component.children){
|
|
21
|
+
mainElement = findRefInChildren(component.children) || mainElement
|
|
22
|
+
}
|
|
23
|
+
const componentPath = `libs-ui/react-core/src/${componentName}/index.tsx`
|
|
24
|
+
const componentTestPath = `libs-ui/react-core/src/${componentName}/index.test.tsx`
|
|
25
|
+
const componentCode = `
|
|
26
|
+
import React from 'react';
|
|
27
|
+
import clsx from 'clsx';
|
|
28
|
+
|
|
29
|
+
type ${ucFirst(mainElement)}ElementAttributes = JSX.IntrinsicElements['${mainElement}']
|
|
30
|
+
export interface ${componentName}Props extends ${ucFirst(mainElement)}ElementAttributes {
|
|
31
|
+
${
|
|
32
|
+
component.props && Object.keys(component.props).map(propName => {
|
|
33
|
+
const prop = component.props[propName]
|
|
34
|
+
return `
|
|
35
|
+
/**
|
|
36
|
+
* ${propName} is optional.
|
|
37
|
+
*/
|
|
38
|
+
${propName}?: ${prop.type ? prop.type:
|
|
39
|
+
prop.values? Object.keys(prop.values).map(value=>`'${value}'`).join('|'): 'string'}`
|
|
40
|
+
}).join(';\n')
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Details for the ${componentName}.
|
|
45
|
+
*/
|
|
46
|
+
export const ${componentName} = React.forwardRef<${htmlTypes[mainElement]}, ${componentName}Props>(
|
|
47
|
+
function ${componentName}({
|
|
48
|
+
${
|
|
49
|
+
component.props && Object.keys(component.props).map(propName => {
|
|
50
|
+
const prop = component.props[propName]
|
|
51
|
+
return `${propName}${prop.default && (prop.type === 'boolean' || prop.type === 'number')? `=${prop.default},`:
|
|
52
|
+
prop.default? `='${prop.default}',`: ','}`
|
|
53
|
+
}).join('\n')
|
|
54
|
+
}
|
|
55
|
+
className,
|
|
56
|
+
children,
|
|
57
|
+
...props
|
|
58
|
+
}, ref) {
|
|
59
|
+
return (
|
|
60
|
+
${renderJsonToJsx(component, mainElement)}
|
|
61
|
+
);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
export default ${componentName};
|
|
65
|
+
`
|
|
66
|
+
const componentTestCode = `
|
|
67
|
+
import React from 'react';
|
|
68
|
+
import { mount } from 'enzyme';
|
|
69
|
+
|
|
70
|
+
import ${componentName} from '@digigov/react-core/${componentName}';
|
|
71
|
+
|
|
72
|
+
it('renders the ${componentName} with no props', () => {
|
|
73
|
+
expect(mount(<${componentName}${component.nochildren?`/>`:`>hello</${componentName}>`})).toMatchSnapshot();
|
|
74
|
+
});
|
|
75
|
+
${component.props && Object.keys(component.props).map(propName => {
|
|
76
|
+
const prop = component.props[propName]
|
|
77
|
+
if(prop.values && prop.type !== 'boolean'){
|
|
78
|
+
return Object.keys(prop.values).map(value=>{
|
|
79
|
+
return `
|
|
80
|
+
it('renders the ${componentName} with ${propName}=${value}', () => {
|
|
81
|
+
expect(mount(<${componentName} ${propName}={${prop.type === 'number'? value: `'${value}'`}}${component.nochildren?`/>`:`>hello</${componentName}>`})).toMatchSnapshot();
|
|
82
|
+
})`
|
|
83
|
+
}).join('\n')
|
|
84
|
+
}
|
|
85
|
+
if(prop.type === 'boolean'){
|
|
86
|
+
return `
|
|
87
|
+
it('renders the ${componentName} with ${propName}=true', () => {
|
|
88
|
+
expect(mount(<${componentName} ${propName}={true}${component.nochildren?`/>`:`>hello</${componentName}>`})).toMatchSnapshot();
|
|
89
|
+
})
|
|
90
|
+
|
|
91
|
+
it('renders the ${componentName} with ${propName}=false', () => {
|
|
92
|
+
expect(mount(<${componentName} ${propName}={false}${component.nochildren?`/>`:`>hello</${componentName}>`})).toMatchSnapshot();
|
|
93
|
+
})
|
|
94
|
+
|
|
95
|
+
`
|
|
96
|
+
}
|
|
97
|
+
return ''
|
|
98
|
+
}).join('\n')}
|
|
99
|
+
|
|
100
|
+
`
|
|
101
|
+
writeFile(componentPath, componentCode)
|
|
102
|
+
writeFile(componentTestPath, componentTestCode)
|
|
103
|
+
console.log(componentCode)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
// render json to jsx
|
|
110
|
+
function renderJsonToJsx (json, mainElement) {
|
|
111
|
+
let topLevel = false
|
|
112
|
+
if(!Array.isArray(json)){
|
|
113
|
+
if(!json.children){
|
|
114
|
+
json.children = [{element: 'children'}]
|
|
115
|
+
}
|
|
116
|
+
json = [json]
|
|
117
|
+
topLevel = true
|
|
118
|
+
|
|
119
|
+
}
|
|
120
|
+
return json.map(component => {
|
|
121
|
+
if(mainElement === component.element){
|
|
122
|
+
component.props.ref = {
|
|
123
|
+
pass: true
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if(component.element && component.element !== 'children'){
|
|
127
|
+
const elementCode = `<${component.element}
|
|
128
|
+
${component.props ? Object.keys(component.props).map(propName => {
|
|
129
|
+
const prop = component.props[propName]
|
|
130
|
+
if(prop.pass){
|
|
131
|
+
return `${propName}={${propName}}`
|
|
132
|
+
}
|
|
133
|
+
return ''
|
|
134
|
+
}).filter(p=>p).join('\n'): ''}
|
|
135
|
+
className={clsx(${topLevel?'className,':''} {
|
|
136
|
+
${component.classes ? component.classes.map(cl=>`'${cl}': true,`).filter(cl=>cl).join('\n'):''}
|
|
137
|
+
${component.props ? Object.keys(component.props).map(propName => {
|
|
138
|
+
const prop = component.props[propName]
|
|
139
|
+
let classes = ''
|
|
140
|
+
if(prop.values && prop.type !== 'boolean' && prop.type!=='number'){
|
|
141
|
+
return Object.keys(prop.values).map(value=>{
|
|
142
|
+
const className = prop.values[value]
|
|
143
|
+
return `'${className}': ${propName} === '${value}',`
|
|
144
|
+
}).filter(t=>t).join('\n')
|
|
145
|
+
}
|
|
146
|
+
if(prop.values && prop.type === 'boolean'){
|
|
147
|
+
return Object.keys(prop.values).map(value=>{
|
|
148
|
+
const className = prop.values[value]
|
|
149
|
+
return `'${className}': ${propName} === ${value},`
|
|
150
|
+
}).filter(t=>t).join('\n')
|
|
151
|
+
}
|
|
152
|
+
if(prop.values && prop.type === 'number'){
|
|
153
|
+
return Object.keys(prop.values).map(value=>{
|
|
154
|
+
const className = prop.values[value]
|
|
155
|
+
return `'${className}': ${propName} === ${value},`
|
|
156
|
+
}).filter(t=>t).join('\n')
|
|
157
|
+
}
|
|
158
|
+
return ''
|
|
159
|
+
}).filter(t=>t).join(''): ''}
|
|
160
|
+
})}
|
|
161
|
+
${mainElement === component.element? `{...props}`: ''}
|
|
162
|
+
>${
|
|
163
|
+
component.children? renderJsonToJsx(component.children, mainElement): ''
|
|
164
|
+
}</${component.element}>`
|
|
165
|
+
return elementCode
|
|
166
|
+
}else if(component.element === 'children'){
|
|
167
|
+
return `{children}`
|
|
168
|
+
}else if(component.text){
|
|
169
|
+
return `${component.text}`
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
}).join('').replace(
|
|
173
|
+
/className=\{clsx\( \{\s*\}\)\}/g,'')
|
|
174
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env zx
|
|
2
|
+
import "zx-extra";
|
|
3
|
+
import "../lib/extra/index.mjs";
|
|
4
|
+
|
|
5
|
+
// await cd('./common/temp/repo')
|
|
6
|
+
const subtree = await readJSON('./subtree.config.json');
|
|
7
|
+
const branchName = await question('Enter branch name: ')
|
|
8
|
+
await cli.git.remote(`rm partial`)
|
|
9
|
+
await cli.git.remote(`add partial ${subtree.remote}`)
|
|
10
|
+
await cli.git.pull('partial')
|
|
11
|
+
const commitIDs = (
|
|
12
|
+
await cli.git.log(
|
|
13
|
+
` partial/main..partial/${branchName} --pretty=format:"%h"`,
|
|
14
|
+
{stdout: true})
|
|
15
|
+
)
|
|
16
|
+
.split('\n')
|
|
17
|
+
await cli.git.branch(`-D github/${branchName}`)
|
|
18
|
+
await cli.git.checkout(`-b github/${branchName} ${subtree.lastCommitID}`)
|
|
19
|
+
commitIDs.reverse()
|
|
20
|
+
for(const commitID of commitIDs) {
|
|
21
|
+
await cli.git['cherry-pick'](`${commitID}`)
|
|
22
|
+
}
|
package/scripts/publish.mjs
CHANGED
|
@@ -2,18 +2,33 @@
|
|
|
2
2
|
import "zx-extra";
|
|
3
3
|
import "../lib/extra/index.mjs";
|
|
4
4
|
|
|
5
|
+
const rushJSON = await readJSON(await findUp('rush.json'));
|
|
6
|
+
const defaultBranch = rushJSON.repository.defaultBranch;
|
|
7
|
+
const currentBranch = await cli.git.branch('--show-current', { stdout: true });
|
|
8
|
+
|
|
5
9
|
const shouldPublishAll = await confirm('Do you want to publish all packages?');
|
|
6
10
|
|
|
7
11
|
const featureVersion = await confirm('Is it a feature version?');
|
|
8
12
|
const featureVersionName = featureVersion && await question('What is the feature name? ');
|
|
13
|
+
let targetBranch = await select('Which target branch do you want to use?', [
|
|
14
|
+
defaultBranch,
|
|
15
|
+
currentBranch.trim(),
|
|
16
|
+
'other (specify)'
|
|
17
|
+
]);
|
|
18
|
+
|
|
19
|
+
if(targetBranch.indexOf('other (specify)') > -1) {
|
|
20
|
+
let branches = await cli.git.branch(`--format='%(refname:short)'`, {stdout: true});
|
|
21
|
+
branches = branches.split('\n').filter(i => i);
|
|
22
|
+
targetBranch = await select("Select the target branch where the changelogs will be commited", branches);
|
|
23
|
+
}
|
|
9
24
|
|
|
10
25
|
await requireEnv('NPM_AUTH_TOKEN', true);
|
|
11
26
|
|
|
12
27
|
if(shouldPublishAll && !featureVersion) {
|
|
13
28
|
await cli.rush.change();
|
|
14
|
-
await cli.rush.
|
|
29
|
+
await cli.rush.publish('-a');
|
|
15
30
|
await cli.rush.build();
|
|
16
|
-
await cli.rush.publish(
|
|
31
|
+
await cli.rush.publish(`-p --include-all --target-branch ${targetBranch} --set-access-level public`);
|
|
17
32
|
} else if(shouldPublishAll && featureVersion) {
|
|
18
33
|
await cli.rush.publish(`--prerelease-name ${featureVersionName} -a`);
|
|
19
34
|
await cli.rush.build();
|
|
@@ -21,7 +36,7 @@ if(shouldPublishAll && !featureVersion) {
|
|
|
21
36
|
} else if(!shouldPublishAll && !featureVersion) {
|
|
22
37
|
console.log('Not supported')
|
|
23
38
|
process.exit()
|
|
24
|
-
const {projects} =
|
|
39
|
+
const {projects} = rushJSON;
|
|
25
40
|
const publishablePackages = projects.filter(project => project.shouldPublish);
|
|
26
41
|
const publishPackages = await checkbox(
|
|
27
42
|
'Select packages',
|
|
@@ -29,7 +44,6 @@ if(shouldPublishAll && !featureVersion) {
|
|
|
29
44
|
);
|
|
30
45
|
for(const packageName of publishPackages) {
|
|
31
46
|
// cd(projects.find(({packageName}) => packageName===packageName).projectFolder))
|
|
32
|
-
|
|
33
47
|
}
|
|
34
48
|
console.log(publishPackages)
|
|
35
49
|
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env zx
|
|
2
|
+
import "zx-extra";
|
|
3
|
+
import "../lib/extra/index.mjs";
|
|
4
|
+
|
|
5
|
+
const rushLib = require('@microsoft/rush-lib');
|
|
6
|
+
const rushConfiguration = rushLib.RushConfiguration.loadFromDefaultLocation({
|
|
7
|
+
startingFolder: process.cwd()
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
const localPackageVersions = rushConfiguration.projects.reduce((versions, project) => {
|
|
11
|
+
return { ...versions, [project.packageJson.name]: project.packageJson.version };
|
|
12
|
+
}, {});
|
|
13
|
+
|
|
14
|
+
console.log(localPackageVersions);
|
|
15
|
+
rushConfiguration.projects.forEach(project => {
|
|
16
|
+
for (const dependencyType of ['dependencies', 'devDependencies', 'peerDependencies']) {
|
|
17
|
+
const dependencies = project.packageJson[dependencyType];
|
|
18
|
+
if (dependencies) {
|
|
19
|
+
for (const dependencyName in dependencies) {
|
|
20
|
+
const dependencyVersion = dependencies[dependencyName];
|
|
21
|
+
if (localPackageVersions[dependencyName] && localPackageVersions[dependencyName] !== dependencyVersion) {
|
|
22
|
+
console.log(`${project.packageJson.name} ${dependencyType} ${dependencyName} ${dependencyVersion}`);
|
|
23
|
+
project.packageJsonEditor.addOrUpdateDependency(dependencyName, localPackageVersions[dependencyName], dependencyType);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
project.packageJsonEditor.saveIfModified();
|
|
29
|
+
});
|