@corva/create-app 0.0.0-2576df8 → 0.0.0-5fb771a
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/README.md +8 -6
- package/common/python/Makefile +8 -5
- package/common/python/pyproject.toml +25 -0
- package/common/python/uv.lock +381 -0
- package/common/ui/config/vite/corva-vite-config.mjs +352 -0
- package/common/ui/devApp.js +1 -0
- package/common/ui/index.html +17 -0
- package/common/ui/isolatedApp.js +1 -0
- package/common/ui/public/DevCenterIsolatedAppPage.html +26 -0
- package/common/ui/public/favicon.ico +0 -0
- package/common/ui/vite.config.mjs +3 -0
- package/common/ui/vitest.global-setup.js +4 -0
- package/common/ui/vitest.setup.js +24 -0
- package/lib/commands/create.js +11 -3
- package/lib/commands/release.js +17 -2
- package/lib/constants/cli.js +5 -8
- package/lib/constants/manifest.js +3 -3
- package/lib/constants/package.js +75 -65
- package/lib/flow.js +6 -0
- package/lib/flows/lib/manifest.js +1 -1
- package/lib/flows/release.js +4 -0
- package/lib/flows/steps/release/resolve-prebuilt-zip.js +35 -0
- package/lib/flows/steps/zip-file-list-resolve.js +3 -2
- package/lib/flows/zip-simple.js +2 -0
- package/lib/helpers/cli-version.js +14 -1
- package/lib/helpers/resolve-app-runtime.js +25 -14
- package/lib/helpers/utils.js +7 -3
- package/lib/main.js +2 -3
- package/lib/options/zip-file-name.js +18 -0
- package/package.json +1 -1
- package/templates/ui/javascript/.eslintrc +1 -2
- package/templates/ui/javascript/AGENTS.md +13 -11
- package/templates/ui/javascript/src/{App.completion.js → App.completion.jsx} +3 -3
- package/templates/ui/javascript/src/{App.drilling.js → App.drilling.jsx} +3 -3
- package/templates/ui/javascript/src/{AppSettings.js → AppSettings.jsx} +1 -1
- package/templates/ui/javascript/src/__tests__/{AppSettings.test.js → AppSettings.test.jsx} +1 -1
- package/templates/ui/typescript/AGENTS.md +10 -8
- package/templates/ui/typescript/src/App.completion.tsx +1 -1
- package/templates/ui/typescript/src/App.drilling.tsx +1 -1
- package/templates/ui/typescript/src/__tests__/AppSettings.test.tsx +1 -1
- package/templates/ui/typescript/tsconfig.json +17 -4
- package/common/python/requirements.txt +0 -2
- package/templates/ui/javascript/config/jest/babelTransform.js +0 -16
- package/templates/ui/javascript/config/jest/cssTransform.js +0 -16
- package/templates/ui/javascript/config/jest/fileTransform.js +0 -48
- package/templates/ui/javascript/config/jest/globalSetup.js +0 -5
- package/templates/ui/javascript/config/jest/setupTests.js +0 -30
- package/templates/ui/javascript/config-overrides.js +0 -10
- package/templates/ui/typescript/config/jest/babelTransform.js +0 -16
- package/templates/ui/typescript/config/jest/cssTransform.js +0 -16
- package/templates/ui/typescript/config/jest/fileTransform.js +0 -48
- package/templates/ui/typescript/config/jest/globalSetup.js +0 -5
- package/templates/ui/typescript/config/jest/setupTests.js +0 -30
- package/templates/ui/typescript/config-overrides.js +0 -10
- /package/templates/ui/javascript/src/{App.scss → App.module.scss} +0 -0
- /package/templates/ui/javascript/src/__tests__/{App.test.js → App.test.jsx} +0 -0
- /package/templates/ui/javascript/src/__tests__/{TestsExample.test.js → TestsExample.test.jsx} +0 -0
- /package/templates/ui/typescript/src/{App.scss → App.module.scss} +0 -0
package/lib/constants/package.js
CHANGED
|
@@ -12,47 +12,47 @@ const uiDependencies = {
|
|
|
12
12
|
'corva-convert-units': '1.10.33',
|
|
13
13
|
'highcharts': '10.3.3',
|
|
14
14
|
'highcharts-react-official': '2.2.2',
|
|
15
|
-
'lodash': '^4.
|
|
16
|
-
'mapbox
|
|
15
|
+
'lodash': '^4.18.1',
|
|
16
|
+
'mapbox-gl': '3.16.0',
|
|
17
17
|
'moment': '2.29.4',
|
|
18
18
|
'moment-timezone': '0.5.43',
|
|
19
|
-
'react': '
|
|
20
|
-
'react-dom': '
|
|
19
|
+
'react': '18.3.1',
|
|
20
|
+
'react-dom': '18.3.1',
|
|
21
21
|
};
|
|
22
22
|
|
|
23
23
|
const jsUiDevDependencies = {
|
|
24
24
|
'@corva/dc-platform-shared': 'latest',
|
|
25
25
|
'@corva/eslint-config-browser': '0.2.2',
|
|
26
|
-
'@testing-library/jest-dom': '
|
|
27
|
-
'@testing-library/react': '
|
|
28
|
-
'@testing-library/
|
|
29
|
-
'@
|
|
30
|
-
'
|
|
31
|
-
'
|
|
26
|
+
'@testing-library/jest-dom': '7.0.1',
|
|
27
|
+
'@testing-library/react': '16.3.2',
|
|
28
|
+
'@testing-library/user-event': '14.6.6',
|
|
29
|
+
'@vitejs/plugin-react': '6.1.1',
|
|
30
|
+
'@vitest/coverage-v8': '4.1.11',
|
|
31
|
+
'dotenv': '16.4.7',
|
|
32
|
+
'dotenv-expand': '11.0.7',
|
|
32
33
|
'eslint': '7.32.0',
|
|
33
|
-
'
|
|
34
|
-
'
|
|
35
|
-
'
|
|
36
|
-
'
|
|
37
|
-
'
|
|
38
|
-
'
|
|
34
|
+
'jsdom': '22.1.0',
|
|
35
|
+
'postcss-preset-env': '11.3.0',
|
|
36
|
+
'rollup-plugin-license': '3.6.0',
|
|
37
|
+
'sass-embedded': '1.100.0',
|
|
38
|
+
'terser': '5.47.1',
|
|
39
|
+
'vite': '8.3.0',
|
|
40
|
+
'vite-plugin-static-copy': '4.1.0',
|
|
41
|
+
'vitest': '4.1.11',
|
|
39
42
|
};
|
|
40
43
|
|
|
41
44
|
const tsUiDevDependencies = {
|
|
42
45
|
...jsUiDevDependencies,
|
|
43
|
-
'@
|
|
44
|
-
'@types/lodash': '4.17.5',
|
|
46
|
+
'@types/lodash': '^4.17.25',
|
|
45
47
|
'@types/material-ui': '0.21.9',
|
|
46
48
|
'@types/minimatch': '3.0.5',
|
|
47
49
|
'@types/mime': '3.0.1',
|
|
48
|
-
'@types/node': '
|
|
49
|
-
'@types/react': '
|
|
50
|
-
'@types/react-dom': '^
|
|
51
|
-
'@types/jest': '^27.0.1',
|
|
50
|
+
'@types/node': '24.12.2',
|
|
51
|
+
'@types/react': '18.2.42',
|
|
52
|
+
'@types/react-dom': '^18.2',
|
|
52
53
|
'@typescript-eslint/eslint-plugin': '^4.31.2',
|
|
53
54
|
'@typescript-eslint/parser': '^4.31.2',
|
|
54
|
-
'
|
|
55
|
-
'typescript': '4.6.3',
|
|
55
|
+
'typescript': '^5.9.3',
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
const corvaUiExtension = {
|
|
@@ -90,13 +90,13 @@ function applyUiExtension(packageJson, extensionNames) {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
const uiScripts = {
|
|
93
|
-
build: '
|
|
94
|
-
start: '
|
|
93
|
+
build: 'vite build',
|
|
94
|
+
start: 'vite --open',
|
|
95
95
|
zip: 'create-corva-app zip .',
|
|
96
96
|
lint: 'eslint --cache ./src/',
|
|
97
97
|
release: 'create-corva-app release .',
|
|
98
|
-
test: '
|
|
99
|
-
coverage: '
|
|
98
|
+
test: 'vitest run',
|
|
99
|
+
coverage: 'vitest run --coverage',
|
|
100
100
|
};
|
|
101
101
|
|
|
102
102
|
const uiPackage = {
|
|
@@ -105,49 +105,18 @@ const uiPackage = {
|
|
|
105
105
|
'scripts': uiScripts,
|
|
106
106
|
'dependencies': uiDependencies,
|
|
107
107
|
'devDependencies': jsUiDevDependencies,
|
|
108
|
-
'jest': {
|
|
109
|
-
roots: ['<rootDir>/src'],
|
|
110
|
-
collectCoverageFrom: ['src/**/*.{js,jsx,ts,tsx}', '!src/**/*.d.ts'],
|
|
111
|
-
coverageThreshold: {
|
|
112
|
-
global: {
|
|
113
|
-
branches: 60,
|
|
114
|
-
functions: 60,
|
|
115
|
-
lines: 60,
|
|
116
|
-
statements: 60,
|
|
117
|
-
},
|
|
118
|
-
},
|
|
119
|
-
setupFilesAfterEnv: ['<rootDir>/config/jest/setupTests.js'],
|
|
120
|
-
globalSetup: '<rootDir>/config/jest/globalSetup.js',
|
|
121
|
-
testMatch: ['<rootDir>/src/**/__tests__/**/*.{js,jsx,ts,tsx}', '<rootDir>/src/**/*.{spec,test}.{js,jsx,ts,tsx}'],
|
|
122
|
-
testEnvironment: 'jsdom',
|
|
123
|
-
transform: {
|
|
124
|
-
'^.+\\.(js|jsx|mjs|cjs|ts|tsx)$': '<rootDir>/config/jest/babelTransform.js',
|
|
125
|
-
'^.+\\.css$': '<rootDir>/config/jest/cssTransform.js',
|
|
126
|
-
'^(?!.*\\.(js|jsx|mjs|cjs|ts|tsx|css|json)$)': '<rootDir>/config/jest/fileTransform.js',
|
|
127
|
-
},
|
|
128
|
-
transformIgnorePatterns: [
|
|
129
|
-
'/node_modules/(?!.*@babel/runtime|@icon-park/react/es).+\\.(js|jsx|mjs|cjs|ts|tsx)$',
|
|
130
|
-
'^.+\\.(css|sass|scss)$',
|
|
131
|
-
],
|
|
132
|
-
modulePaths: [],
|
|
133
|
-
moduleNameMapper: {
|
|
134
|
-
'~(.*)': '<rootDir>/src/$1',
|
|
135
|
-
'^.+\\.(css|sass|scss)$': 'identity-obj-proxy',
|
|
136
|
-
'@corva/ui(.*)': '@corva/ui/cjs-bundle/$1',
|
|
137
|
-
},
|
|
138
|
-
watchPlugins: ['jest-watch-typeahead/filename', 'jest-watch-typeahead/testname'],
|
|
139
|
-
resetMocks: true,
|
|
140
|
-
},
|
|
141
108
|
'lint-staged': {
|
|
142
109
|
'src/**/*.{js,jsx,ts,tsx}': 'eslint --fix',
|
|
143
110
|
},
|
|
144
111
|
'resolutions': {
|
|
145
112
|
'@noble/hashes': '1.8.0',
|
|
113
|
+
'lodash': '4.18.1',
|
|
146
114
|
},
|
|
147
115
|
};
|
|
148
116
|
|
|
149
117
|
const tsUiPackage = {
|
|
150
118
|
...uiPackage,
|
|
119
|
+
scripts: { ...uiScripts, typecheck: 'tsc --noEmit' },
|
|
151
120
|
devDependencies: tsUiDevDependencies,
|
|
152
121
|
// todo: temporary solution, ref https://github.com/oppia/oppia/issues/22283#issuecomment-2756641371
|
|
153
122
|
resolutions: {
|
|
@@ -165,16 +134,19 @@ const nodeNpmScripts = {
|
|
|
165
134
|
};
|
|
166
135
|
|
|
167
136
|
const nodeDependencies = {
|
|
168
|
-
'@corva/node-sdk': '^8.
|
|
137
|
+
'@corva/node-sdk': '^8.5.0',
|
|
169
138
|
};
|
|
170
139
|
|
|
171
140
|
const nodeDevDependencies = {
|
|
172
|
-
'@corva/eslint-config-node': '^
|
|
141
|
+
'@corva/eslint-config-node': '^6.0.0',
|
|
142
|
+
'@typescript-eslint/eslint-plugin': '^8.58.1',
|
|
143
|
+
'@typescript-eslint/parser': '^8.58.1',
|
|
173
144
|
'jest': '^29.7.0',
|
|
174
145
|
'dotenv': '^16.0.3',
|
|
175
146
|
'eslint': '^8.2.0',
|
|
147
|
+
'eslint-plugin-jest': '^27.1.5',
|
|
176
148
|
'prettier': '^2.0.0',
|
|
177
|
-
'typescript': '^5.
|
|
149
|
+
'typescript': '^5.9.3',
|
|
178
150
|
};
|
|
179
151
|
|
|
180
152
|
const nodeTsDevDependencies = {
|
|
@@ -219,12 +191,47 @@ const nodeNpmPackage = {
|
|
|
219
191
|
eslintConfig: {
|
|
220
192
|
root: true,
|
|
221
193
|
extends: '@corva/eslint-config-node',
|
|
194
|
+
overrides: [
|
|
195
|
+
{
|
|
196
|
+
files: ['**/*.ts'],
|
|
197
|
+
parser: '@typescript-eslint/parser',
|
|
198
|
+
parserOptions: {
|
|
199
|
+
project: 'tsconfig.json',
|
|
200
|
+
sourceType: 'module',
|
|
201
|
+
},
|
|
202
|
+
plugins: ['@typescript-eslint/eslint-plugin'],
|
|
203
|
+
rules: {
|
|
204
|
+
'@typescript-eslint/padding-line-between-statements': 'off',
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
files: [
|
|
209
|
+
'**/*.spec.js',
|
|
210
|
+
'**/*.spec.ts',
|
|
211
|
+
'**/*.spec.mjs',
|
|
212
|
+
'**/*.spec.cjs',
|
|
213
|
+
'**/__mocks__/**/*.js',
|
|
214
|
+
'**/__mocks__/**/*.ts',
|
|
215
|
+
'**/__mocks__/**/*.cjs',
|
|
216
|
+
'**/__mocks__/**/*.mjs',
|
|
217
|
+
],
|
|
218
|
+
plugins: ['jest'],
|
|
219
|
+
env: {
|
|
220
|
+
jest: true,
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
],
|
|
224
|
+
},
|
|
225
|
+
overrides: {
|
|
226
|
+
lodash: '4.18.1',
|
|
222
227
|
},
|
|
223
228
|
};
|
|
224
229
|
|
|
225
230
|
const nodeYarnPackage = {
|
|
226
231
|
...nodeNpmPackage,
|
|
227
232
|
scripts: nodeYarnScripts,
|
|
233
|
+
overrides: undefined,
|
|
234
|
+
resolutions: nodeNpmPackage.overrides,
|
|
228
235
|
};
|
|
229
236
|
|
|
230
237
|
const nodeTsNpmPackage = {
|
|
@@ -241,11 +248,14 @@ const nodeTsNpmPackage = {
|
|
|
241
248
|
const nodeTsYarnPackage = {
|
|
242
249
|
...nodeTsNpmPackage,
|
|
243
250
|
scripts: nodeTsYarnScripts,
|
|
251
|
+
overrides: undefined,
|
|
252
|
+
resolutions: nodeNpmPackage.overrides,
|
|
244
253
|
};
|
|
245
254
|
|
|
246
255
|
const extendWithTsConfig = (packageJson, version) => {
|
|
247
256
|
packageJson.devDependencies = {
|
|
248
|
-
|
|
257
|
+
// New @tsconfig/nodeX package versioning: it starts with X major version
|
|
258
|
+
[`@tsconfig/node${version}`]: `^${version}`,
|
|
249
259
|
...packageJson.devDependencies,
|
|
250
260
|
};
|
|
251
261
|
|
package/lib/flow.js
CHANGED
|
@@ -29,6 +29,12 @@ export const runFlow = async (flow, context, indent = '') => {
|
|
|
29
29
|
|
|
30
30
|
const runSteps = async (steps = [], context = {}, indent = '') => {
|
|
31
31
|
for (const step of steps) {
|
|
32
|
+
if (typeof step.skip === 'function' && step.skip(context)) {
|
|
33
|
+
debug('Skipping %s', step.name || step.message);
|
|
34
|
+
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
|
|
32
38
|
if (step.name) {
|
|
33
39
|
const result = await runFlow(step, context, indent);
|
|
34
40
|
|
|
@@ -11,7 +11,7 @@ const SCHEDULER_MAPPING = [SCHEDULER_TYPE_DATA_TIME, SCHEDULER_TYPE_DEPTH, SCHED
|
|
|
11
11
|
{},
|
|
12
12
|
);
|
|
13
13
|
|
|
14
|
-
const NODE_RUNTIMES = [APP_RUNTIMES.
|
|
14
|
+
const NODE_RUNTIMES = [APP_RUNTIMES.NODE24];
|
|
15
15
|
|
|
16
16
|
export class Manifest {
|
|
17
17
|
constructor(manifest) {
|
package/lib/flows/release.js
CHANGED
|
@@ -8,6 +8,7 @@ import { ADD_LABEL_STEP } from './steps/release/add-label.js';
|
|
|
8
8
|
import { ADD_NOTES_STEP } from './steps/release/add-notes.js';
|
|
9
9
|
import { PUBLISH_PACKAGE_STEP } from './steps/release/publish.js';
|
|
10
10
|
import { RELEASE_PREPARE_DATA_STEP } from './steps/release/prepare-data.js';
|
|
11
|
+
import { RESOLVE_PREBUILT_ZIP_STEP } from './steps/release/resolve-prebuilt-zip.js';
|
|
11
12
|
|
|
12
13
|
export const RELEASE_FLOW = {
|
|
13
14
|
name: 'release',
|
|
@@ -15,6 +16,9 @@ export const RELEASE_FLOW = {
|
|
|
15
16
|
PREPARE_FLOW,
|
|
16
17
|
SETUP_API_CLIENT_STEP,
|
|
17
18
|
RELEASE_PREPARE_DATA_STEP,
|
|
19
|
+
// With --zip-file-name the archive already exists, so the zip flow is skipped entirely. That
|
|
20
|
+
// also lets runtimes the zip flow has no file list for (e.g. `provided.*`) be released.
|
|
21
|
+
RESOLVE_PREBUILT_ZIP_STEP,
|
|
18
22
|
ZIP_SIMPLE_FLOW,
|
|
19
23
|
UPLOAD_ZIP_TO_CORVA_STEP,
|
|
20
24
|
WAIT_FOR_BUILD_FINISH_STEP,
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { promises as fs } from 'node:fs';
|
|
2
|
+
import { resolve } from 'node:path';
|
|
3
|
+
|
|
4
|
+
import { StepError } from '../../lib/step-error.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Handles `--zip-file-name`: the caller has already built the package archive, so this records it
|
|
8
|
+
* as the archive to upload and marks the zip flow as a no-op.
|
|
9
|
+
*/
|
|
10
|
+
export const RESOLVE_PREBUILT_ZIP_STEP = {
|
|
11
|
+
message: 'Resolving prebuilt archive...',
|
|
12
|
+
fn: async ({ dirName, options }) => {
|
|
13
|
+
const { zipFileName } = options;
|
|
14
|
+
|
|
15
|
+
if (!zipFileName) {
|
|
16
|
+
return {};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const zipPath = resolve(dirName, zipFileName);
|
|
20
|
+
|
|
21
|
+
try {
|
|
22
|
+
await fs.access(zipPath);
|
|
23
|
+
} catch {
|
|
24
|
+
throw new StepError(`Prebuilt archive ${zipFileName} not found in ${dirName}`);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
zipFileName,
|
|
29
|
+
skipZip: true,
|
|
30
|
+
// The archive belongs to the caller. Neither flag reaches the context today; this is defensive.
|
|
31
|
+
removeOnSuccess: false,
|
|
32
|
+
removeOnFail: false,
|
|
33
|
+
};
|
|
34
|
+
},
|
|
35
|
+
};
|
|
@@ -110,7 +110,8 @@ const resolveDataToZipUiApp = async (itemsToZip = [], { options, pkg, dirName, m
|
|
|
110
110
|
|
|
111
111
|
itemsToZip.push(
|
|
112
112
|
'manifest.json',
|
|
113
|
-
'config
|
|
113
|
+
'vite.config.mjs',
|
|
114
|
+
'index.html',
|
|
114
115
|
'eslint.config.js',
|
|
115
116
|
'eslint.config.mjs',
|
|
116
117
|
'tsconfig.json',
|
|
@@ -255,7 +256,7 @@ const resolveDataForZipPythonApp = async (itemsToZip = [], { manifest, dirName,
|
|
|
255
256
|
);
|
|
256
257
|
}
|
|
257
258
|
|
|
258
|
-
itemsToZip.push('manifest.json', 'requirements.txt');
|
|
259
|
+
itemsToZip.push('manifest.json', 'pyproject.toml', 'uv.lock', 'requirements.txt');
|
|
259
260
|
|
|
260
261
|
return {
|
|
261
262
|
zipFileName,
|
package/lib/flows/zip-simple.js
CHANGED
|
@@ -75,7 +75,20 @@ export async function warnIfOutdated() {
|
|
|
75
75
|
logger.write('Checking for updates...\n');
|
|
76
76
|
|
|
77
77
|
const currentVersion = await getCurrentVersion();
|
|
78
|
-
|
|
78
|
+
|
|
79
|
+
let latestVersion;
|
|
80
|
+
|
|
81
|
+
try {
|
|
82
|
+
latestVersion = await getLatestVersion();
|
|
83
|
+
} catch (caughtError) {
|
|
84
|
+
if (!(caughtError instanceof StepError)) {
|
|
85
|
+
throw caughtError;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
logger.write(' ⚠️ Skipping version check (could not reach npm registry).\n');
|
|
89
|
+
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
79
92
|
|
|
80
93
|
// Skip version check if current version is a prerelease (dev or next)
|
|
81
94
|
if (!isRegularVersion(currentVersion)) {
|
|
@@ -6,6 +6,8 @@ import os from 'os';
|
|
|
6
6
|
import semver from 'semver';
|
|
7
7
|
|
|
8
8
|
const debug = debugFn('cca:resolve-app-runtime');
|
|
9
|
+
const DEFAULT_UI_NODE_VERSION = '24';
|
|
10
|
+
const DEFAULT_UI_NODE_RANGE = '>=24 <25';
|
|
9
11
|
|
|
10
12
|
/**
|
|
11
13
|
*
|
|
@@ -37,11 +39,14 @@ const checkCliVersion = async (command, version) =>
|
|
|
37
39
|
|
|
38
40
|
debug(`%s version output: %s`, command, data.toString());
|
|
39
41
|
|
|
40
|
-
|
|
42
|
+
const currentVersion = semver.coerce(data.toString('utf-8'));
|
|
43
|
+
const requiredVersion = semver.coerce(semverVersionsMapping.node[version] || version);
|
|
44
|
+
|
|
45
|
+
resolve(semver.gte(currentVersion, requiredVersion));
|
|
41
46
|
});
|
|
42
47
|
});
|
|
43
48
|
|
|
44
|
-
const checkNodeVersion = (
|
|
49
|
+
const checkNodeVersion = (range) => async () => {
|
|
45
50
|
try {
|
|
46
51
|
await fs.access(`${os.homedir()}/.nvm/nvm.sh`);
|
|
47
52
|
|
|
@@ -52,7 +57,7 @@ const checkNodeVersion = (version) => async () => {
|
|
|
52
57
|
debug(e);
|
|
53
58
|
debug('nvm is not installed, checking node version');
|
|
54
59
|
|
|
55
|
-
return checkCliVersion('node',
|
|
60
|
+
return checkCliVersion('node', range);
|
|
56
61
|
}
|
|
57
62
|
};
|
|
58
63
|
|
|
@@ -60,19 +65,22 @@ export const IS_WINDOWS = process.platform === 'win32';
|
|
|
60
65
|
|
|
61
66
|
const semverVersionsMapping = {
|
|
62
67
|
node: {
|
|
63
|
-
18: '18.
|
|
64
|
-
20: '20.
|
|
65
|
-
24: '24.
|
|
68
|
+
18: '18.20.8',
|
|
69
|
+
20: '20.20.1',
|
|
70
|
+
24: '24.15.0',
|
|
66
71
|
},
|
|
67
72
|
python: {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
'3.10': '3.10.9',
|
|
71
|
-
'3.11': '3.11.1',
|
|
72
|
-
'3.13': '3.13.7',
|
|
73
|
+
3.13: '3.13.13',
|
|
74
|
+
3.14: '3.14.4',
|
|
73
75
|
},
|
|
74
76
|
};
|
|
75
77
|
|
|
78
|
+
const nodeVersionRanges = {
|
|
79
|
+
18: '>=18 <19',
|
|
80
|
+
20: '>=20 <21',
|
|
81
|
+
24: '>=24 <25',
|
|
82
|
+
};
|
|
83
|
+
|
|
76
84
|
/**
|
|
77
85
|
* @typedef {Object} Runtime
|
|
78
86
|
* @property {string} language
|
|
@@ -80,18 +88,20 @@ const semverVersionsMapping = {
|
|
|
80
88
|
* @property {string} packageManager
|
|
81
89
|
* @property {string} version
|
|
82
90
|
* @property {string} semver
|
|
91
|
+
* @property {string} [enginesNode]
|
|
83
92
|
*/
|
|
84
93
|
export const resolveAppRuntime = (opts) => {
|
|
85
94
|
if (opts.appType === APP_TYPES.UI) {
|
|
86
|
-
const version =
|
|
95
|
+
const version = DEFAULT_UI_NODE_VERSION;
|
|
87
96
|
|
|
88
97
|
return {
|
|
89
98
|
environment: 'node',
|
|
90
99
|
language: opts.useTypescript ? 'typescript' : 'javascript',
|
|
91
|
-
isRuntimeAvailable: checkNodeVersion(
|
|
100
|
+
isRuntimeAvailable: checkNodeVersion(DEFAULT_UI_NODE_RANGE),
|
|
92
101
|
packageManager: opts.packageManager,
|
|
93
102
|
version,
|
|
94
103
|
semver: semverVersionsMapping.node[version],
|
|
104
|
+
enginesNode: DEFAULT_UI_NODE_RANGE,
|
|
95
105
|
};
|
|
96
106
|
}
|
|
97
107
|
|
|
@@ -101,10 +111,11 @@ export const resolveAppRuntime = (opts) => {
|
|
|
101
111
|
return {
|
|
102
112
|
environment: 'node',
|
|
103
113
|
language: opts.useTypescript ? 'typescript' : 'javascript',
|
|
104
|
-
isRuntimeAvailable: checkNodeVersion(version),
|
|
114
|
+
isRuntimeAvailable: checkNodeVersion(nodeVersionRanges[version]),
|
|
105
115
|
packageManager: opts.packageManager,
|
|
106
116
|
version,
|
|
107
117
|
semver: semverVersionsMapping.node[version],
|
|
118
|
+
enginesNode: `^${version}`,
|
|
108
119
|
};
|
|
109
120
|
}
|
|
110
121
|
|
package/lib/helpers/utils.js
CHANGED
|
@@ -7,7 +7,7 @@ export const addUiAppFile = (templateFolder, root, runtime, manifest, opts) => {
|
|
|
7
7
|
try {
|
|
8
8
|
logger.log(chalk.green('adding app file'));
|
|
9
9
|
|
|
10
|
-
const fileExtension = runtime.language === 'typescript' ? 'tsx' : '
|
|
10
|
+
const fileExtension = runtime.language === 'typescript' ? 'tsx' : 'jsx';
|
|
11
11
|
|
|
12
12
|
const segment =
|
|
13
13
|
{
|
|
@@ -26,9 +26,13 @@ export const addUiAppFile = (templateFolder, root, runtime, manifest, opts) => {
|
|
|
26
26
|
};
|
|
27
27
|
|
|
28
28
|
export const getExcludedFiles = (manifest) => {
|
|
29
|
-
|
|
29
|
+
const excludedFiles = ['.ruff_cache', '.venv', '.pytest_cache', '__pycache__'];
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
if (manifest.isUi()) {
|
|
32
|
+
return [...excludedFiles, 'App.drilling.jsx', 'App.completion.jsx', 'App.drilling.tsx', 'App.completion.tsx'];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return excludedFiles;
|
|
32
36
|
};
|
|
33
37
|
|
|
34
38
|
export function copyFileSync(source, target) {
|
package/lib/main.js
CHANGED
|
@@ -17,17 +17,16 @@ import { StepError } from './flows/lib/step-error.js';
|
|
|
17
17
|
function checkNodeVersion() {
|
|
18
18
|
logger.write('Checking node version...');
|
|
19
19
|
|
|
20
|
-
const unsupportedNodeVersion = !semver.satisfies(process.version, '>=
|
|
20
|
+
const unsupportedNodeVersion = !semver.satisfies(process.version, '>=24 <25');
|
|
21
21
|
|
|
22
22
|
if (unsupportedNodeVersion) {
|
|
23
23
|
logger.log(
|
|
24
24
|
chalk.red(
|
|
25
25
|
`\nYou are using Node ${process.version}.\n\n` +
|
|
26
|
-
`Please update to Node
|
|
26
|
+
`Please update to Node 24.x for a better, fully supported experience.\n`,
|
|
27
27
|
),
|
|
28
28
|
);
|
|
29
29
|
|
|
30
|
-
// Fall back to latest supported react-scripts on Node 4
|
|
31
30
|
return process.exit(1);
|
|
32
31
|
}
|
|
33
32
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { InvalidArgumentError, Option } from 'commander';
|
|
2
|
+
|
|
3
|
+
const flags = '--zip-file-name <string>';
|
|
4
|
+
const description =
|
|
5
|
+
'Upload an already-built .zip from the project directory instead of zipping it here. ' +
|
|
6
|
+
'The archive belongs to the caller and is never deleted after upload.';
|
|
7
|
+
|
|
8
|
+
// An unset CI variable arrives as `--zip-file-name=`, and commander 9 takes the next token as the
|
|
9
|
+
// value even when it is another flag — neither should pass for an archive name.
|
|
10
|
+
function argParser(value) {
|
|
11
|
+
if (typeof value !== 'string' || !value.trim() || value.startsWith('-')) {
|
|
12
|
+
throw new InvalidArgumentError('Expected a file name, e.g. --zip-file-name=package.zip.');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const zipFileNameOption = new Option(flags, description).argParser(argParser);
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@corva/create-app","version":"0.0.0-
|
|
1
|
+
{"name":"@corva/create-app","version":"0.0.0-5fb771a","private":false,"description":"Create an app to use it in CORVA.AI","keywords":["react"],"bugs":{"url":"https://github.com/facebook/create-react-app/issues"},"repository":{"type":"git","url":"https://github.com/corva-ai/create-corva-app"},"license":"MIT","type":"module","bin":{"create-corva-app":"./bin/create-corva-app.cjs"},"files":["bin/**/*.cjs","bin/**/*.js","lib/**/*.js","templates","template_extensions","common"],"scripts":{"build":"echo \"build is not configured for package \\\"×\\\", skipping.\"","get-changelog":"conventional-changelog -r 2 -p angular","lint":"eslint . --resolve-plugins-relative-to $(pwd) --max-warnings 0","lint:fix":"eslint . --fix","release":"git add -A && standard-version -a","release-rc":"npm run release -- --prerelease","run:local-ui-ts-completion":"node ./bin/create-corva-app.cjs ../test-app-ui-ts-completions --appName 'TestAppUiTsCompletions' --segments 'completion' --category 'analytics' --appKey 'corva.testappuitscompletions.ui' --appType 'ui' --runtime 'ui' -t --extensions corva","run:local-ui-ts-drilling":"node ./bin/create-corva-app.cjs ../test-app-ui-ts-drilling --appName 'TestAppUiTsDrilling' --segments 'drilling' --category 'analytics' --appKey 'corva.testappuitsdrilling.ui' --appType 'ui' --runtime 'ui' -t --extensions corva","run:local-ui-ts-intervention":"node ./bin/create-corva-app.cjs ../test-app-ui-ts-intervention --appName 'TestAppUiTsIntervention' --segments 'intervention' --category 'analytics' --appKey 'corva.testappuitsintervention.ui' --appType 'ui' --runtime 'ui' -t --extensions corva","test":"NODE_OPTIONS='--experimental-vm-modules --no-warnings' jest"},"lint-staged":{"*.js":"npm run lint:fix"},"resolutions":{"lodash":"4.18.1"},"dependencies":{"archiver":"^5.3.0","chalk":"^4.1.0","commander":"^9.1.0","cross-spawn":"^7.0.3","debug":"^4.3.4","dotenv":"^16.0.0","figlet":"^1.5.0","form-data":"^4.0.0","fs-extra":"^9.0.1","glob":"^8.0.1","got":"^12.5.1","inquirer":"^8.2.3","is-glob":"^4.0.3","lodash":"^4.18.1","npm-api":"^1.0.0","semver":"^7.3.2","terminal-link":"^3.0.0"},"devDependencies":{"@babel/core":"^7.11.0","@babel/eslint-parser":"^7.19.1","@babel/plugin-proposal-class-properties":"^7.18.6","@babel/plugin-syntax-import-assertions":"^7.20.0","@babel/preset-react":"^7.18.6","@commitlint/cli":"^17.3.0","@commitlint/config-conventional":"^17.3.0","@corva/eslint-config-browser":"^0.1.7","@corva/eslint-config-node":"^6.0.0","@corva/node-sdk":"^8.5.0","@types/cross-spawn":"^6.0.2","@types/jest":"^29.5.4","@typescript-eslint/eslint-plugin":"^8.58.1","@typescript-eslint/parser":"^8.58.1","conventional-changelog-cli":"^2.1.0","eslint":"^8.2.0","eslint-config-google":"^0.14.0","eslint-config-prettier":"^8.5.0","eslint-plugin-import":"^2.26.0","eslint-plugin-jest":"^27.1.5","eslint-plugin-jsx-a11y":"^6.7.1","eslint-plugin-prettier":"^4.2.1","eslint-plugin-react":"^7.32.0","eslint-plugin-react-hooks":"^4.6.0","eslint-plugin-require-sort":"^1.3.0","husky":"^8.0.2","jest":"^29.6.4","prettier":"^2.0.0","prettier-plugin-packagejson":"^2.3.0","standard-version":"^9.0.0","typescript":"^5.9.3","zx":"^7.2.3"},"packageManager":"yarn@1.22.19+sha512.ff4579ab459bb25aa7c0ff75b62acebe576f6084b36aa842971cf250a5d8c6cd3bc9420b22ce63c7f93a0857bc6ef29291db39c3e7a23aab5adfd5a4dd6c5d71","standard-version":{"skip":{"tag":true}}}
|
|
@@ -10,22 +10,24 @@ These constraints are enforced by the platform. Violating them breaks the build
|
|
|
10
10
|
1. **Root export** — `src/index.js` MUST default-export `{ component: App, settings: AppSettings }`. The component may also be a `ParentApp` wrapper (e.g., `{ component: ParentApp, settings: AppSettings }`) that wraps `App` with Context.Providers and prop initialization. This is the platform loader contract.
|
|
11
11
|
2. **UI components** — Use only `@corva/ui` components. Import from `@corva/ui/componentsV2`; fall back to `@corva/ui/components` only when a V2 version doesn't exist yet. `@material-ui/core` v4 is available as the underlying library.
|
|
12
12
|
3. **HTTP clients** — Use `corvaDataAPI` / `corvaAPI` from `@corva/ui/clients` for all network requests.
|
|
13
|
-
4. **Do not rename or delete** `App.
|
|
13
|
+
4. **Do not rename or delete** `App.jsx`, `AppSettings.jsx`, or `index.js` — they are platform entry points.
|
|
14
14
|
|
|
15
15
|
## Project Structure
|
|
16
16
|
|
|
17
17
|
```
|
|
18
18
|
src/
|
|
19
|
-
App.
|
|
20
|
-
AppSettings.
|
|
19
|
+
App.jsx — Main app component (default export required)
|
|
20
|
+
AppSettings.jsx — Settings panel component (default export required)
|
|
21
21
|
index.js — Root export: { component, settings }
|
|
22
22
|
constants.js — Default settings values
|
|
23
|
-
App.scss — Component styles
|
|
24
|
-
__tests__/ —
|
|
23
|
+
App.module.scss — Component styles
|
|
24
|
+
__tests__/ — Vitest test files
|
|
25
25
|
__mocks__/ — Mock data (mockAppProps.js, mockAppSettingsProps.js)
|
|
26
26
|
assets/ — Static assets (SVGs, images)
|
|
27
|
-
config/
|
|
28
|
-
config
|
|
27
|
+
config/vite/ — Shared Corva Vite config
|
|
28
|
+
vite.config.mjs — Vite entry config
|
|
29
|
+
vitest.setup.js — Test environment setup
|
|
30
|
+
index.html — Dev server host page
|
|
29
31
|
manifest.json — Corva platform app metadata (generated at scaffold time)
|
|
30
32
|
```
|
|
31
33
|
|
|
@@ -98,7 +100,7 @@ transition: transition(color, background-color);
|
|
|
98
100
|
**Import in component:**
|
|
99
101
|
|
|
100
102
|
```javascript
|
|
101
|
-
import styles from './App.scss';
|
|
103
|
+
import styles from './App.module.scss';
|
|
102
104
|
// Use: <div className={styles.container}>
|
|
103
105
|
```
|
|
104
106
|
|
|
@@ -265,11 +267,11 @@ General rules:
|
|
|
265
267
|
|
|
266
268
|
## Testing
|
|
267
269
|
|
|
268
|
-
- **Framework:**
|
|
270
|
+
- **Framework:** Vitest + React Testing Library
|
|
269
271
|
- **Wrapper:** Use `AppTestWrapper` from `@corva/ui/testing` to wrap components
|
|
270
|
-
- **Mocking:** Mock network requests (
|
|
272
|
+
- **Mocking:** Mock network requests (`vi.mock`/`vi.fn` or msw), never call real APIs
|
|
271
273
|
- **Timezone:** UTC is enforced (`process.env.TZ = 'UTC'`)
|
|
272
|
-
- **Mocked globals:** `ResizeObserver`, `MutationObserver` (in `
|
|
274
|
+
- **Mocked globals:** `ResizeObserver`, `MutationObserver` (in `vitest.setup.js`)
|
|
273
275
|
|
|
274
276
|
## Commands
|
|
275
277
|
|
|
@@ -4,7 +4,7 @@ import { useAppCommons } from '@corva/ui/effects';
|
|
|
4
4
|
import { DEFAULT_SETTINGS } from './constants';
|
|
5
5
|
import logo from './assets/logo.svg';
|
|
6
6
|
|
|
7
|
-
import styles from './App.scss';
|
|
7
|
+
import styles from './App.module.scss';
|
|
8
8
|
|
|
9
9
|
const App = () => {
|
|
10
10
|
const { appKey, fracFleet, well, wells, appSettings } = useAppCommons();
|
|
@@ -19,7 +19,7 @@ const App = () => {
|
|
|
19
19
|
<div className={styles.container}>
|
|
20
20
|
<img src={logo} alt="logo" className={styles.logo} />
|
|
21
21
|
<p>
|
|
22
|
-
Edit <code>src/App.
|
|
22
|
+
Edit <code>src/App.jsx</code> and save to reload.
|
|
23
23
|
<br />
|
|
24
24
|
<br />
|
|
25
25
|
</p>
|
|
@@ -47,6 +47,6 @@ const App = () => {
|
|
|
47
47
|
);
|
|
48
48
|
};
|
|
49
49
|
|
|
50
|
-
// Important: Do not change root component default export (App.
|
|
50
|
+
// Important: Do not change root component default export (App.jsx). Use it as container
|
|
51
51
|
// for your App. It's required to make build and zip scripts work as expected;
|
|
52
52
|
export default App;
|