@neuxnet/neux-cli 0.2.3
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 +438 -0
- package/README.zh-CN.md +554 -0
- package/assets/container/assets/index.css +1 -0
- package/assets/container/assets/index.js +137 -0
- package/assets/container/assets/pageFrame.css +1 -0
- package/assets/container/assets/pageFrame.js +56 -0
- package/assets/container/assets/service.js +6 -0
- package/assets/container/assets/vconsole.js +931 -0
- package/assets/container/favicon.ico +0 -0
- package/assets/container/images/icon-arrow.png +0 -0
- package/assets/container/images/mini-action-white.png +0 -0
- package/assets/container/images/mini-action.png +0 -0
- package/assets/container/images/mini-arrow-left-white.png +0 -0
- package/assets/container/images/mini-arrow-left.jpg +0 -0
- package/assets/container/images/mini-arrow-left.png +0 -0
- package/assets/container/images/mini-close-white.png +0 -0
- package/assets/container/images/mini-close.png +0 -0
- package/assets/container/images/more.png +0 -0
- package/assets/container/images/search.jpg +0 -0
- package/assets/container/index.html +1 -0
- package/assets/container/pageFrame.html +1 -0
- package/assets/init/tabbar/home-active.png +0 -0
- package/assets/init/tabbar/home.png +0 -0
- package/assets/init/tabbar/list-active.png +0 -0
- package/assets/init/tabbar/list.png +0 -0
- package/assets/init/types/neux-api.d.ts +1402 -0
- package/package.json +68 -0
- package/scripts/generate-init-types.js +210 -0
- package/scripts/sync-compiler.js +22 -0
- package/scripts/sync-web-container.js +34 -0
- package/src/bin/cli.js +646 -0
- package/src/core/brand.js +11 -0
- package/src/core/compiler.js +305 -0
- package/src/core/defaults.js +12 -0
- package/src/core/dev.js +15 -0
- package/src/core/errors.js +17 -0
- package/src/core/fs.js +66 -0
- package/src/core/i18n.js +37 -0
- package/src/core/init.js +866 -0
- package/src/core/lifecycle.js +32 -0
- package/src/core/manifest.js +72 -0
- package/src/core/pack.js +156 -0
- package/src/core/package-info.js +27 -0
- package/src/core/preview-server.js +123 -0
- package/src/core/project.js +101 -0
- package/src/core/prompts.js +71 -0
- package/src/core/proxy-security.js +141 -0
- package/src/core/proxy.js +156 -0
- package/src/core/qr.js +41 -0
- package/src/core/terminal-qr.js +72 -0
- package/src/core/update.js +278 -0
- package/src/core/watch.js +113 -0
- package/src/core/web.js +649 -0
- package/src/core/zip.js +120 -0
- package/src/index.js +20 -0
- package/src/providers/service-client.js +149 -0
- package/src/providers/service-config.js +264 -0
- package/src/providers/service.js +146 -0
- package/src/providers/upload.js +112 -0
- package/vendor/dimina-compiler/bin/index.cjs +265 -0
- package/vendor/dimina-compiler/bin/index.js +263 -0
- package/vendor/dimina-compiler/compatibility-B-DoZtUX.cjs +395 -0
- package/vendor/dimina-compiler/compatibility-Cl3-DO6V.js +366 -0
- package/vendor/dimina-compiler/core/logic-compiler.cjs +378 -0
- package/vendor/dimina-compiler/core/logic-compiler.js +374 -0
- package/vendor/dimina-compiler/core/style-compiler.cjs +392 -0
- package/vendor/dimina-compiler/core/style-compiler.js +377 -0
- package/vendor/dimina-compiler/core/view-compiler.cjs +1601 -0
- package/vendor/dimina-compiler/core/view-compiler.js +1582 -0
- package/vendor/dimina-compiler/index.cjs +762 -0
- package/vendor/dimina-compiler/index.js +751 -0
- package/vendor/dimina-compiler/sourcemap-BgtIgqkC.cjs +1377 -0
- package/vendor/dimina-compiler/sourcemap-CKjhV9h7.js +1135 -0
package/package.json
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@neuxnet/neux-cli",
|
|
3
|
+
"version": "0.2.3",
|
|
4
|
+
"description": "Standalone CLI and Node API for Neux mini program build, pack, preview, and CI automation.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"neux": "src/bin/cli.js"
|
|
8
|
+
},
|
|
9
|
+
"exports": {
|
|
10
|
+
".": "./src/index.js",
|
|
11
|
+
"./package.json": "./package.json"
|
|
12
|
+
},
|
|
13
|
+
"files": [
|
|
14
|
+
"src",
|
|
15
|
+
"scripts",
|
|
16
|
+
"assets/container",
|
|
17
|
+
"assets/init",
|
|
18
|
+
"vendor/dimina-compiler",
|
|
19
|
+
"README.md",
|
|
20
|
+
"README.zh-CN.md"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"sync:container": "node ./scripts/sync-web-container.js",
|
|
24
|
+
"sync:compiler": "node ./scripts/sync-compiler.js",
|
|
25
|
+
"prepare:publish": "npm run sync:compiler && npm run sync:container",
|
|
26
|
+
"generate:init-types": "node ./scripts/generate-init-types.js",
|
|
27
|
+
"test": "node --test",
|
|
28
|
+
"smoke:help": "node ./src/bin/cli.js --help",
|
|
29
|
+
"pack:dry": "npm pack --dry-run"
|
|
30
|
+
},
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": ">=20"
|
|
33
|
+
},
|
|
34
|
+
"dependencies": {
|
|
35
|
+
"@vue/compiler-sfc": "^3.5.34",
|
|
36
|
+
"autoprefixer": "^10.5.0",
|
|
37
|
+
"cheerio": "^1.2.0",
|
|
38
|
+
"chokidar": "^4.0.3",
|
|
39
|
+
"commander": "^14.0.3",
|
|
40
|
+
"cssnano": "^8.0.1",
|
|
41
|
+
"esbuild": "^0.28.0",
|
|
42
|
+
"htmlparser2": "^12.0.0",
|
|
43
|
+
"less": "^4.6.4",
|
|
44
|
+
"listr2": "^9.0.5",
|
|
45
|
+
"magic-string": "^0.30.21",
|
|
46
|
+
"oxc-parser": "^0.132.0",
|
|
47
|
+
"oxc-walker": "^1.0.0",
|
|
48
|
+
"postcss": "^8.5.14",
|
|
49
|
+
"postcss-selector-parser": "^7.1.1",
|
|
50
|
+
"qrcode": "^1.5.4",
|
|
51
|
+
"sass": "^1.99.0",
|
|
52
|
+
"source-map-js": "^1.2.1"
|
|
53
|
+
},
|
|
54
|
+
"keywords": [
|
|
55
|
+
"miniapp",
|
|
56
|
+
"cli",
|
|
57
|
+
"ci",
|
|
58
|
+
"preview"
|
|
59
|
+
],
|
|
60
|
+
"license": "Apache-2.0",
|
|
61
|
+
"publishConfig": {
|
|
62
|
+
"access": "public"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"jsqr": "^1.4.0",
|
|
66
|
+
"pngjs": "^5.0.0"
|
|
67
|
+
}
|
|
68
|
+
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import fs from 'node:fs/promises'
|
|
2
|
+
import path from 'node:path'
|
|
3
|
+
import { fileURLToPath } from 'node:url'
|
|
4
|
+
|
|
5
|
+
const scriptDir = path.dirname(fileURLToPath(import.meta.url))
|
|
6
|
+
const projectRoot = path.resolve(scriptDir, '../..')
|
|
7
|
+
const sourceRoot = path.join(projectRoot, 'fe/packages/service/src/api')
|
|
8
|
+
const docsRoot = path.resolve(projectRoot, '../neuminiappdoc/content/en/4.api-reference')
|
|
9
|
+
const output = path.join(scriptDir, '../assets/init/types/neux-api.d.ts')
|
|
10
|
+
const names = new Set()
|
|
11
|
+
const internalNames = new Set([
|
|
12
|
+
'env',
|
|
13
|
+
'fileSystemManagerAPINames',
|
|
14
|
+
'invokeAPI',
|
|
15
|
+
'invokePromiseAPI',
|
|
16
|
+
'registerEnumerableApiNames',
|
|
17
|
+
'replaceSyncStorageSnapshot',
|
|
18
|
+
])
|
|
19
|
+
const apiMetadata = {
|
|
20
|
+
request: {
|
|
21
|
+
description: 'Sends an HTTP request and invokes the success, fail, and complete callbacks.',
|
|
22
|
+
params: 'URL, method, headers, data, timeout, and lifecycle callbacks.',
|
|
23
|
+
typeName: 'NeuxRequestOptions',
|
|
24
|
+
},
|
|
25
|
+
showToast: {
|
|
26
|
+
description: 'Displays a short feedback message to the user.',
|
|
27
|
+
params: 'title, icon, image, duration, and mask.',
|
|
28
|
+
typeName: 'NeuxShowToastOptions',
|
|
29
|
+
},
|
|
30
|
+
showModal: {
|
|
31
|
+
description: 'Displays a modal dialog with optional cancel and confirm actions.',
|
|
32
|
+
params: 'title, content, showCancel, cancelText, confirmText, and callbacks.',
|
|
33
|
+
typeName: 'NeuxShowModalOptions',
|
|
34
|
+
},
|
|
35
|
+
showLoading: {
|
|
36
|
+
description: 'Displays a loading indicator until hideLoading is called.',
|
|
37
|
+
params: 'title and mask.',
|
|
38
|
+
typeName: 'NeuxShowLoadingOptions',
|
|
39
|
+
},
|
|
40
|
+
navigateTo: {
|
|
41
|
+
description: 'Opens a new page and keeps the current page in the navigation stack.',
|
|
42
|
+
params: 'url, events, and success, fail, and complete callbacks.',
|
|
43
|
+
typeName: 'NeuxNavigateOptions',
|
|
44
|
+
},
|
|
45
|
+
redirectTo: {
|
|
46
|
+
description: 'Closes the current page and navigates to another page.',
|
|
47
|
+
params: 'url and success, fail, and complete callbacks.',
|
|
48
|
+
typeName: 'NeuxNavigateOptions',
|
|
49
|
+
},
|
|
50
|
+
reLaunch: {
|
|
51
|
+
description: 'Closes all pages and opens the target page.',
|
|
52
|
+
params: 'url and success, fail, and complete callbacks.',
|
|
53
|
+
typeName: 'NeuxNavigateOptions',
|
|
54
|
+
},
|
|
55
|
+
switchTab: {
|
|
56
|
+
description: 'Navigates to a tab bar page and closes other non-tab pages.',
|
|
57
|
+
params: 'url and success, fail, and complete callbacks.',
|
|
58
|
+
typeName: 'NeuxNavigateOptions',
|
|
59
|
+
},
|
|
60
|
+
setStorage: {
|
|
61
|
+
description: 'Stores a value in the mini app storage namespace.',
|
|
62
|
+
params: 'key, data, and success, fail, and complete callbacks.',
|
|
63
|
+
typeName: 'NeuxSetStorageOptions',
|
|
64
|
+
},
|
|
65
|
+
getStorage: {
|
|
66
|
+
description: 'Reads a value from the mini app storage namespace.',
|
|
67
|
+
params: 'key and success, fail, and complete callbacks.',
|
|
68
|
+
typeName: 'NeuxGetStorageOptions',
|
|
69
|
+
},
|
|
70
|
+
setClipboardData: {
|
|
71
|
+
description: 'Writes text to the system clipboard.',
|
|
72
|
+
params: 'data and success, fail, and complete callbacks.',
|
|
73
|
+
typeName: 'NeuxSetClipboardDataOptions',
|
|
74
|
+
},
|
|
75
|
+
getClipboardData: {
|
|
76
|
+
description: 'Reads text from the system clipboard.',
|
|
77
|
+
params: 'success, fail, and complete callbacks.',
|
|
78
|
+
typeName: 'NeuxCallbackOptions',
|
|
79
|
+
},
|
|
80
|
+
chooseImage: {
|
|
81
|
+
description: 'Opens the image picker or camera and returns selected image files.',
|
|
82
|
+
params: 'count, sizeType, sourceType, and lifecycle callbacks.',
|
|
83
|
+
typeName: 'NeuxChooseImageOptions',
|
|
84
|
+
},
|
|
85
|
+
scanCode: {
|
|
86
|
+
description: 'Scans a QR code or barcode using the host camera.',
|
|
87
|
+
params: 'onlyFromCamera, scanType, and lifecycle callbacks.',
|
|
88
|
+
typeName: 'NeuxScanCodeOptions',
|
|
89
|
+
},
|
|
90
|
+
login: {
|
|
91
|
+
description: 'Requests a login code from the host application.',
|
|
92
|
+
params: 'success, fail, and complete callbacks.',
|
|
93
|
+
typeName: 'NeuxCallbackOptions',
|
|
94
|
+
},
|
|
95
|
+
getLocation: {
|
|
96
|
+
description: 'Reads the current device location after authorization.',
|
|
97
|
+
params: 'type, altitude, isHighAccuracy, and lifecycle callbacks.',
|
|
98
|
+
typeName: 'NeuxGetLocationOptions',
|
|
99
|
+
},
|
|
100
|
+
setNavigationBarTitle: {
|
|
101
|
+
description: 'Changes the title displayed in the current page navigation bar.',
|
|
102
|
+
params: 'title and success, fail, and complete callbacks.',
|
|
103
|
+
typeName: 'NeuxSetNavigationBarTitleOptions',
|
|
104
|
+
},
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function visit(directory) {
|
|
108
|
+
for (const entry of await fs.readdir(directory, { withFileTypes: true })) {
|
|
109
|
+
const filePath = path.join(directory, entry.name)
|
|
110
|
+
if (entry.isDirectory()) await visit(filePath)
|
|
111
|
+
if (entry.name !== 'index.js') continue
|
|
112
|
+
const source = await fs.readFile(filePath, 'utf8')
|
|
113
|
+
for (const match of source.matchAll(/export\s+(?:async\s+)?function\s+([A-Za-z_$][\w$]*)|export\s+(?:const|let|var)\s+([A-Za-z_$][\w$]*)|export\s*\{([^}]+)\}/g)) {
|
|
114
|
+
if (match[1] || match[2]) names.add(match[1] || match[2])
|
|
115
|
+
if (match[3]) {
|
|
116
|
+
for (const item of match[3].split(',')) {
|
|
117
|
+
const name = item.trim().split(/\s+as\s+/)[0]
|
|
118
|
+
if (/^[A-Za-z_$][\w$]*$/.test(name)) names.add(name)
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
await visit(sourceRoot)
|
|
126
|
+
const apiNames = [...names]
|
|
127
|
+
.filter(name => !name.startsWith('__') && !name.startsWith('notify') && !internalNames.has(name))
|
|
128
|
+
.sort()
|
|
129
|
+
const docsLinks = new Map()
|
|
130
|
+
|
|
131
|
+
function routePath(relativePath) {
|
|
132
|
+
return relativePath
|
|
133
|
+
.slice(0, -3)
|
|
134
|
+
.split(path.sep)
|
|
135
|
+
.map(segment => segment.replace(/^\d+\./, ''))
|
|
136
|
+
.join('/')
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async function collectDocLinks(directory = docsRoot, relative = '') {
|
|
140
|
+
try {
|
|
141
|
+
for (const entry of await fs.readdir(directory, { withFileTypes: true })) {
|
|
142
|
+
const filePath = path.join(directory, entry.name)
|
|
143
|
+
const fileRelative = path.join(relative, entry.name)
|
|
144
|
+
if (entry.isDirectory()) await collectDocLinks(filePath, fileRelative)
|
|
145
|
+
if (!entry.isFile() || !entry.name.endsWith('.md') || entry.name === 'index.md') continue
|
|
146
|
+
const slug = entry.name.slice(0, -3)
|
|
147
|
+
const apiName = slug.split('-').map((part, index) => index === 0 ? part : `${part[0].toUpperCase()}${part.slice(1)}`).join('')
|
|
148
|
+
docsLinks.set(apiName, `/en/api-reference/${routePath(fileRelative)}`)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
if (error.code !== 'ENOENT') throw error
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
await collectDocLinks()
|
|
157
|
+
const docsBaseUrl = 'https://demo-c.paas.superapp.neuvision.cn/miniappdoc'
|
|
158
|
+
const optionTypes = [
|
|
159
|
+
'type NeuxCallback = (result?: any) => void;',
|
|
160
|
+
'type NeuxCallbackOptions = { success?: NeuxCallback; fail?: NeuxCallback; complete?: NeuxCallback; };',
|
|
161
|
+
'type NeuxRequestOptions = NeuxCallbackOptions & { url: string; method?: string; header?: Record<string, string>; data?: any; timeout?: number; };',
|
|
162
|
+
'type NeuxShowToastOptions = NeuxCallbackOptions & { title: string; icon?: \'success\' | \'error\' | \'loading\' | \'none\'; image?: string; duration?: number; mask?: boolean; };',
|
|
163
|
+
'type NeuxShowModalOptions = NeuxCallbackOptions & { title?: string; content?: string; showCancel?: boolean; cancelText?: string; confirmText?: string; cancelColor?: string; confirmColor?: string; };',
|
|
164
|
+
'type NeuxShowLoadingOptions = NeuxCallbackOptions & { title: string; mask?: boolean; };',
|
|
165
|
+
'type NeuxNavigateOptions = NeuxCallbackOptions & { url: string; events?: Record<string, NeuxCallback>; };',
|
|
166
|
+
'type NeuxSetStorageOptions = NeuxCallbackOptions & { key: string; data: any; };',
|
|
167
|
+
'type NeuxGetStorageOptions = NeuxCallbackOptions & { key: string; };',
|
|
168
|
+
'type NeuxSetClipboardDataOptions = NeuxCallbackOptions & { data: string; };',
|
|
169
|
+
'type NeuxChooseImageOptions = NeuxCallbackOptions & { count?: number; sizeType?: string[]; sourceType?: string[]; };',
|
|
170
|
+
'type NeuxScanCodeOptions = NeuxCallbackOptions & { onlyFromCamera?: boolean; scanType?: string[]; };',
|
|
171
|
+
'type NeuxGetLocationOptions = NeuxCallbackOptions & { type?: string; altitude?: boolean; isHighAccuracy?: boolean; };',
|
|
172
|
+
'type NeuxSetNavigationBarTitleOptions = NeuxCallbackOptions & { title: string; };',
|
|
173
|
+
].join('\n')
|
|
174
|
+
const methods = apiNames.map(name => {
|
|
175
|
+
const metadata = apiMetadata[name] || {
|
|
176
|
+
description: `Provides the ${name} mini app capability.`,
|
|
177
|
+
params: 'API-specific arguments. See the linked API reference for the exact signature.',
|
|
178
|
+
}
|
|
179
|
+
const link = `${docsBaseUrl}${docsLinks.get(name) || '/en/api-reference'}`
|
|
180
|
+
return [
|
|
181
|
+
' /**',
|
|
182
|
+
` * ${metadata.description}`,
|
|
183
|
+
` * @param options ${metadata.params}`,
|
|
184
|
+
` * @see ${link}`,
|
|
185
|
+
' */',
|
|
186
|
+
` ${metadata.typeName ? `${name}(options?: ${metadata.typeName}): any;` : `${name}(...args: any[]): any;`}`,
|
|
187
|
+
].join('\n')
|
|
188
|
+
}).join('\n')
|
|
189
|
+
const content = [
|
|
190
|
+
optionTypes,
|
|
191
|
+
'',
|
|
192
|
+
'declare type NeuxApi = {',
|
|
193
|
+
methods,
|
|
194
|
+
'}',
|
|
195
|
+
'',
|
|
196
|
+
'declare const wx: NeuxApi',
|
|
197
|
+
'declare const nx: NeuxApi',
|
|
198
|
+
'declare const custom: NeuxApi',
|
|
199
|
+
'',
|
|
200
|
+
'declare function App<T extends Record<string, any> = Record<string, any>>(options: T): T',
|
|
201
|
+
'declare function Page<T extends Record<string, any> = Record<string, any>>(options: T): T',
|
|
202
|
+
'declare function Component<T extends Record<string, any> = Record<string, any>>(options: T): T',
|
|
203
|
+
'declare function Behavior<T extends Record<string, any> = Record<string, any>>(options: T): T',
|
|
204
|
+
'declare function getApp<T extends Record<string, any> = Record<string, any>>(): T',
|
|
205
|
+
'declare function getCurrentPages<T extends Record<string, any> = Record<string, any>>(): T[]',
|
|
206
|
+
'',
|
|
207
|
+
].join('\n')
|
|
208
|
+
await fs.mkdir(path.dirname(output), { recursive: true })
|
|
209
|
+
await fs.writeFile(output, content, 'utf8')
|
|
210
|
+
console.log(`Generated ${apiNames.length} API declarations.`)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'node:fs'
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
6
|
+
|
|
7
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
8
|
+
const packageRoot = path.resolve(__dirname, '..')
|
|
9
|
+
const defaultSource = path.resolve(packageRoot, '../fe/packages/compiler/dist')
|
|
10
|
+
const source = path.resolve(process.argv[2] || defaultSource)
|
|
11
|
+
const target = path.join(packageRoot, 'vendor/dimina-compiler')
|
|
12
|
+
|
|
13
|
+
if (!fs.existsSync(path.join(source, 'index.js'))) {
|
|
14
|
+
console.error(`Compiler dist not found: ${source}`)
|
|
15
|
+
console.error('Run `pnpm --dir ../fe --filter @dimina/compiler build` first or pass a compiler dist directory.')
|
|
16
|
+
process.exit(1)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
fs.rmSync(target, { recursive: true, force: true })
|
|
20
|
+
fs.mkdirSync(target, { recursive: true })
|
|
21
|
+
fs.cpSync(source, target, { recursive: true })
|
|
22
|
+
console.log(`Synced compiler: ${source} -> ${target}`)
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import fs from 'node:fs'
|
|
4
|
+
import path from 'node:path'
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
6
|
+
|
|
7
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
8
|
+
const packageRoot = path.resolve(__dirname, '..')
|
|
9
|
+
const defaultSource = path.resolve(packageRoot, '../fe/packages/container/dist')
|
|
10
|
+
const source = path.resolve(process.argv[2] || defaultSource)
|
|
11
|
+
const target = path.join(packageRoot, 'assets/container')
|
|
12
|
+
const entries = [
|
|
13
|
+
'index.html',
|
|
14
|
+
'pageFrame.html',
|
|
15
|
+
'favicon.ico',
|
|
16
|
+
'assets',
|
|
17
|
+
'images',
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
if (!fs.existsSync(path.join(source, 'index.html'))) {
|
|
21
|
+
console.error(`Container dist not found: ${source}`)
|
|
22
|
+
console.error('Run `pnpm --dir ../fe --filter @dimina/container build` first or pass a source directory.')
|
|
23
|
+
process.exit(1)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
fs.rmSync(target, { recursive: true, force: true })
|
|
27
|
+
fs.mkdirSync(target, { recursive: true })
|
|
28
|
+
for (const entry of entries) {
|
|
29
|
+
const from = path.join(source, entry)
|
|
30
|
+
if (fs.existsSync(from)) {
|
|
31
|
+
fs.cpSync(from, path.join(target, entry), { recursive: true })
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
console.log(`Synced web container: ${source} -> ${target}`)
|