@coze/cli 0.0.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/dist/cli.mjs ADDED
@@ -0,0 +1,957 @@
1
+ import * as __WEBPACK_EXTERNAL_MODULE_commander__ from "commander";
2
+ import * as __WEBPACK_EXTERNAL_MODULE_openid_client__ from "openid-client";
3
+ import * as __WEBPACK_EXTERNAL_MODULE_picocolors__ from "picocolors";
4
+ import * as __WEBPACK_EXTERNAL_MODULE__npmcli_config_lib_definitions_index_js__ from "@npmcli/config/lib/definitions/index.js";
5
+ import * as __WEBPACK_EXTERNAL_MODULE__npmcli_config__ from "@npmcli/config";
6
+ import * as __WEBPACK_EXTERNAL_MODULE_node_path__ from "node:path";
7
+ import * as __WEBPACK_EXTERNAL_MODULE_node_fs__ from "node:fs";
8
+ import * as __WEBPACK_EXTERNAL_MODULE_semver__ from "semver";
9
+ import * as __WEBPACK_EXTERNAL_MODULE_lodash__ from "lodash";
10
+ import * as __WEBPACK_EXTERNAL_MODULE_cross_spawn__ from "cross-spawn";
11
+ import * as __WEBPACK_EXTERNAL_MODULE__inquirer_prompts__ from "@inquirer/prompts";
12
+ import * as __WEBPACK_EXTERNAL_MODULE_node_module__ from "node:module";
13
+ import * as __WEBPACK_EXTERNAL_MODULE__rsbuild_core__ from "@rsbuild/core";
14
+ import * as __WEBPACK_EXTERNAL_MODULE__rsbuild_plugin_react__ from "@rsbuild/plugin-react";
15
+ import * as __WEBPACK_EXTERNAL_MODULE__rsbuild_plugin_less__ from "@rsbuild/plugin-less";
16
+ import * as __WEBPACK_EXTERNAL_MODULE_prettier__ from "prettier";
17
+ import * as __WEBPACK_EXTERNAL_MODULE__rslib_core__ from "@rslib/core";
18
+ import * as __WEBPACK_EXTERNAL_MODULE_form_data__ from "form-data";
19
+ import * as __WEBPACK_EXTERNAL_MODULE_axios__ from "axios";
20
+ import * as __WEBPACK_EXTERNAL_MODULE_express__ from "express";
21
+ import * as __WEBPACK_EXTERNAL_MODULE_chokidar__ from "chokidar";
22
+ const logger = {
23
+ info (...messages) {
24
+ console.log(__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].blue('[INFO]'), ...messages);
25
+ },
26
+ success (...messages) {
27
+ console.log(__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].green('[SUCCESS]'), ...messages);
28
+ },
29
+ warning (...messages) {
30
+ console.log(__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].yellow('[WARNING]'), ...messages);
31
+ },
32
+ error (...messages) {
33
+ console.error(__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].red('[ERROR]'), ...messages);
34
+ },
35
+ debug (...messages) {
36
+ if (process.env.DEBUG) console.log(__WEBPACK_EXTERNAL_MODULE_picocolors__["default"].magenta('[DEBUG]'), ...messages);
37
+ }
38
+ };
39
+ var constants_Region = /*#__PURE__*/ function(Region) {
40
+ Region["CN"] = "cn";
41
+ Region["CN_BOE"] = "boe";
42
+ Region["I18N"] = "i18n";
43
+ Region["LOCAL"] = "local";
44
+ return Region;
45
+ }({});
46
+ const REGISTRY_HOST = {
47
+ ["cn"]: 'npm-hub.coze.cn',
48
+ ["i18n"]: 'npm-hub.coze.com',
49
+ ["boe"]: 'npm-hub-boe.bytedance.net',
50
+ ["local"]: 'localhost:3000'
51
+ };
52
+ const CLIENT_ID_MAP = {
53
+ ["cn"]: '13474932957575400683007237571476.app.coze',
54
+ ["boe"]: '70653688608994412341629476687797.app.coze',
55
+ ["local"]: '70653688608994412341629476687797.app.coze'
56
+ };
57
+ const ISSUER_MAP = {
58
+ ["cn"]: 'https://api.coze.cn',
59
+ ["boe"]: 'https://api-bot-boe.bytedance.net',
60
+ ["local"]: 'https://api-bot-boe.bytedance.net'
61
+ };
62
+ /* eslint-disable security/detect-object-injection -- ignore */ class OauthClient {
63
+ constructor(region = constants_Region.CN_BOE){
64
+ const cozeHubIssuer = new __WEBPACK_EXTERNAL_MODULE_openid_client__.Issuer({
65
+ issuer: ISSUER_MAP[region],
66
+ device_authorization_endpoint: `${ISSUER_MAP[region]}/api/permission/oauth2/device/code`,
67
+ token_endpoint: `${ISSUER_MAP[region]}/api/permission/oauth2/token`,
68
+ revocation_endpoint: `${ISSUER_MAP[region]}/api/permission/oauth2/revoke`,
69
+ scope: 'createMessage'
70
+ });
71
+ this.client = new cozeHubIssuer.Client({
72
+ client_id: CLIENT_ID_MAP[region],
73
+ token_endpoint_auth_method: 'none'
74
+ });
75
+ }
76
+ async activate(npmConfig) {
77
+ const { refreshToken } = await npmConfig.loadConfig();
78
+ if (refreshToken) try {
79
+ const tokenSet = await this.client.refresh(refreshToken);
80
+ await npmConfig.storeToken(tokenSet);
81
+ } catch (e) {
82
+ logger.error('refresh failed: ', e);
83
+ await this.auth(npmConfig);
84
+ }
85
+ else await this.auth(npmConfig);
86
+ }
87
+ async deactivate(npmConfig) {
88
+ const { refreshToken } = await npmConfig.loadConfig();
89
+ await this.client.revoke(refreshToken);
90
+ await npmConfig.clearToken();
91
+ }
92
+ async auth(npmConfig) {
93
+ const handle = await this.client.deviceAuthorization({
94
+ duration_seconds: 86399
95
+ });
96
+ const completeUrl = `${handle.verification_uri}?user_code=${handle.user_code}`;
97
+ const open = await import("open").then((mod)=>mod.default);
98
+ await open(completeUrl);
99
+ let tokenSet = null;
100
+ while(!tokenSet)try {
101
+ tokenSet = await handle.poll();
102
+ logger.success('authenticated');
103
+ await npmConfig.storeToken(tokenSet);
104
+ } catch (error) {
105
+ logger.error('poll failed:', error);
106
+ throw error;
107
+ }
108
+ }
109
+ }
110
+ const { shorthands, definitions, flatten } = __WEBPACK_EXTERNAL_MODULE__npmcli_config_lib_definitions_index_js__["default"];
111
+ const CONFIG_TYPE = 'user';
112
+ const REFRESH_TOKEN_KEY = 'refresh_token';
113
+ const DEFAULT_PACKAGE_SCOPE = 'coze';
114
+ const DEFAULT_BUSINESS_SOURCE = 'coze';
115
+ class NpmConfig {
116
+ constructor({ projectDir, scope, region, source } = {}){
117
+ this.config = {
118
+ scope: scope ?? DEFAULT_PACKAGE_SCOPE,
119
+ authToken: '',
120
+ refreshToken: '',
121
+ registryUrl: '',
122
+ region,
123
+ source: source ?? DEFAULT_BUSINESS_SOURCE
124
+ };
125
+ const dir = projectDir ?? process.cwd();
126
+ this.proxy = new __WEBPACK_EXTERNAL_MODULE__npmcli_config__["default"]({
127
+ npmPath: dir,
128
+ definitions,
129
+ shorthands,
130
+ flatten,
131
+ cwd: dir
132
+ });
133
+ }
134
+ get registryScope() {
135
+ return `@${this.config.scope}:registry`;
136
+ }
137
+ get registryUrl() {
138
+ const registryHost = REGISTRY_HOST[this.region];
139
+ return this.region === constants_Region.LOCAL ? `http://${registryHost}/` : `https://${registryHost}/`;
140
+ }
141
+ get registryAuthUrl() {
142
+ const registryHost = REGISTRY_HOST[this.region];
143
+ return `//${registryHost}/:_authToken`;
144
+ }
145
+ get region() {
146
+ // has specified region
147
+ if (this.config.region) return this.config.region;
148
+ const registry = this.proxy.get(this.registryScope);
149
+ if (!registry) return constants_Region.CN_BOE;
150
+ const registryHost = new URL(registry).host;
151
+ for (const [region, host] of Object.entries(REGISTRY_HOST))if (registryHost === host) return region;
152
+ return constants_Region.CN_BOE;
153
+ }
154
+ async loadConfig() {
155
+ if (this.proxy.loaded) return this.config;
156
+ await this.proxy.load();
157
+ const token = this.proxy.get(this.registryAuthUrl, CONFIG_TYPE) ?? '';
158
+ Object.assign(this.config, {
159
+ region: this.region,
160
+ registryUrl: this.proxy.get(this.registryScope) || this.registryUrl,
161
+ authToken: token,
162
+ refreshToken: this.proxy.get(`${this.config.scope}_${REFRESH_TOKEN_KEY}`, CONFIG_TYPE) || ''
163
+ });
164
+ return this.config;
165
+ }
166
+ async storeToken(tokenSet) {
167
+ // clear other region info
168
+ for (const [region] of Object.entries(REGISTRY_HOST))if (region !== this.region) this.proxy.delete(this.registryScope, CONFIG_TYPE);
169
+ this.proxy.set(this.registryScope, this.registryUrl, CONFIG_TYPE);
170
+ this.proxy.set(this.registryAuthUrl, `${this.config.source}:${tokenSet.access_token || ''}`, CONFIG_TYPE);
171
+ this.proxy.set(`${this.config.source}_${REFRESH_TOKEN_KEY}`, tokenSet.refresh_token || '', CONFIG_TYPE);
172
+ await this.proxy.save(CONFIG_TYPE);
173
+ Object.assign(this.config, {
174
+ authToken: tokenSet.access_token,
175
+ refreshToken: tokenSet.refresh_token
176
+ });
177
+ logger.success(`token saved for registry: ${this.registryUrl}`);
178
+ }
179
+ async clearToken() {
180
+ this.proxy.delete(this.registryScope, CONFIG_TYPE);
181
+ this.proxy.delete(this.registryAuthUrl, CONFIG_TYPE);
182
+ this.proxy.delete(`${this.config.scope}_${REFRESH_TOKEN_KEY}`, CONFIG_TYPE);
183
+ await this.proxy.save(CONFIG_TYPE);
184
+ Object.assign(this.config, {
185
+ authToken: '',
186
+ refreshToken: ''
187
+ });
188
+ logger.success(`token cleared for registry: ${this.registryUrl}`);
189
+ }
190
+ getProxy() {
191
+ return this.proxy;
192
+ }
193
+ }
194
+ /* eslint-disable @typescript-eslint/no-explicit-any -- ignore */ /* eslint-disable security/detect-non-literal-fs-filename -- ignore */ function resolvePackageJson(projectDir) {
195
+ const pkgJsonFilePath = __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(projectDir, 'package.json');
196
+ if (!__WEBPACK_EXTERNAL_MODULE_node_fs__["default"].existsSync(pkgJsonFilePath)) throw new Error(`package.json not found in ${projectDir}`);
197
+ const content = __WEBPACK_EXTERNAL_MODULE_node_fs__["default"].readFileSync(pkgJsonFilePath, 'utf-8');
198
+ return JSON.parse(content);
199
+ }
200
+ function resolvePackageDir(dir = '') {
201
+ if (__WEBPACK_EXTERNAL_MODULE_node_path__["default"].isAbsolute(dir)) return dir;
202
+ return __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(process.cwd(), dir);
203
+ }
204
+ /**
205
+ * @coze/a-b -> __coze__a_b
206
+ * @coze-ui/a-b -> __coze_ui__a_b
207
+ * a-b -> a_b
208
+ */ function pkgName2RemoteName(pkgName) {
209
+ const hasScope = pkgName.startsWith('@');
210
+ const parts = pkgName.split('/');
211
+ return `${hasScope ? `__${parts[0].slice(1)}__` : parts[0]}${parts.slice(1).join('_')}`.replace(/-/g, '_');
212
+ }
213
+ // @module-federation/rsbuild-plugin only support cjs
214
+ const config_require = (0, __WEBPACK_EXTERNAL_MODULE_node_module__.createRequire)(import.meta.url);
215
+ const pluginModuleFederation = config_require('@module-federation/rsbuild-plugin').pluginModuleFederation;
216
+ const { isEmpty, merge } = __WEBPACK_EXTERNAL_MODULE_lodash__["default"];
217
+ const CONFIG_FILE_NAME = 'ui.config';
218
+ const CONFIG_FILE_EXTNAME = [
219
+ '.js',
220
+ '.ts',
221
+ '.tsx',
222
+ '.mjs',
223
+ '.mts',
224
+ '.cjs',
225
+ '.cts'
226
+ ];
227
+ const CDN_MAP = {
228
+ boe: '//lf0-fast-deliver-inner.bytedance.net/obj/eden-internal/ibo-lgvj/ljhwZthlaukjlkulzlp/',
229
+ cn: '//lf3-static.bytednsdoc.com/obj/eden-cn/ibo-lgvj/ljhwZthlaukjlkulzlp/'
230
+ };
231
+ async function loadConfig({ cwd = process.cwd(), path }) {
232
+ const configFilePath = resolveConfigPath(cwd, path);
233
+ const { content } = await (0, __WEBPACK_EXTERNAL_MODULE__rsbuild_core__.loadConfig)({
234
+ cwd: (0, __WEBPACK_EXTERNAL_MODULE_node_path__.dirname)(configFilePath),
235
+ path: configFilePath
236
+ });
237
+ content._privateMeta = {
238
+ configFilePath
239
+ };
240
+ return content;
241
+ }
242
+ function getShareRslibConfig(uiConfig, libConfig) {
243
+ const projectDir = (0, __WEBPACK_EXTERNAL_MODULE_node_path__.dirname)(uiConfig._privateMeta.configFilePath);
244
+ const pkgJson = JSON.parse(__WEBPACK_EXTERNAL_MODULE_node_fs__["default"].readFileSync(__WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(projectDir, 'package.json'), 'utf-8'));
245
+ const umdName = pkgName2RemoteName(pkgJson.name);
246
+ const entries = resolveExports(uiConfig);
247
+ const tsconfigPath = resolveTsconfigPath(projectDir);
248
+ const libs = [];
249
+ const formats = [
250
+ 'cjs',
251
+ 'esm',
252
+ 'umd',
253
+ 'mf'
254
+ ];
255
+ Object.entries(entries).forEach(([dist, src])=>{
256
+ for (const format of formats){
257
+ // mf should use exposes instead of multiple entries
258
+ if ('mf' === format && '.' !== dist) continue;
259
+ const config = {
260
+ dts: {
261
+ bundle: false
262
+ },
263
+ format,
264
+ output: {
265
+ distPath: {
266
+ root: __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join('dist', format, dist)
267
+ }
268
+ },
269
+ source: {
270
+ tsconfigPath,
271
+ entry: {
272
+ index: src
273
+ }
274
+ },
275
+ shims: {
276
+ cjs: {
277
+ 'import.meta.url': true
278
+ },
279
+ esm: {
280
+ __filename: true,
281
+ __dirname: true,
282
+ require: true
283
+ }
284
+ },
285
+ // each entry should have unique name
286
+ umdName: __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(umdName, dist).replace(/\//g, '_')
287
+ };
288
+ if ('mf' === format) {
289
+ // default use boe
290
+ const cdn = CDN_MAP[process.env.REGION ?? ''] ?? CDN_MAP.boe;
291
+ const singleton = [
292
+ 'react',
293
+ 'react-dom'
294
+ ];
295
+ let shared = uiConfig.shared ?? {};
296
+ if (isEmpty(shared) && null !== uiConfig.shared) for (const type of [
297
+ 'dependencies',
298
+ 'peerDependencies'
299
+ ])Object.entries(pkgJson[type]).forEach(([name])=>{
300
+ shared[name] = {
301
+ singleton: singleton.includes(name)
302
+ };
303
+ });
304
+ merge(config, {
305
+ output: {
306
+ assetPrefix: `${cdn}${__WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(`${pkgJson.name}@${pkgJson.version}`, 'dist/mf', dist)}`
307
+ },
308
+ plugins: [
309
+ pluginModuleFederation({
310
+ name: umdName,
311
+ exposes: entries,
312
+ shared
313
+ })
314
+ ]
315
+ });
316
+ } else if ('umd' === format) merge(config, {
317
+ output: {
318
+ minify: true,
319
+ injectStyles: true
320
+ }
321
+ });
322
+ libs.push(merge(config, libConfig));
323
+ }
324
+ });
325
+ return merge({
326
+ lib: libs,
327
+ plugins: [
328
+ (0, __WEBPACK_EXTERNAL_MODULE__rsbuild_plugin_react__.pluginReact)(),
329
+ (0, __WEBPACK_EXTERNAL_MODULE__rsbuild_plugin_less__.pluginLess)()
330
+ ]
331
+ }, uiConfig.rslib ?? {}, {
332
+ _privateMeta: uiConfig._privateMeta
333
+ });
334
+ }
335
+ function getShareRsbuildConfig(uiConfig) {
336
+ const projectDir = (0, __WEBPACK_EXTERNAL_MODULE_node_path__.dirname)(uiConfig._privateMeta.configFilePath);
337
+ const previewDir = __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(projectDir, 'preview');
338
+ const entries = resolvePreviewEntries(previewDir);
339
+ if (isEmpty(entries)) throw new Error('preview folder is empty, maybe you should add index.page.tsx');
340
+ // virtual modules
341
+ const virtualMod = {};
342
+ const virtualDir = __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(projectDir, 'node_modules', '.cache', 'coze');
343
+ if (!__WEBPACK_EXTERNAL_MODULE_node_fs__["default"].existsSync(virtualDir)) __WEBPACK_EXTERNAL_MODULE_node_fs__["default"].mkdirSync(virtualDir, {
344
+ recursive: true
345
+ });
346
+ const prettierConfig = {
347
+ parser: 'babel',
348
+ singleQuote: true,
349
+ trailingComma: 'all'
350
+ };
351
+ Object.entries(entries).forEach(([name, absPath])=>{
352
+ const virtualPath = __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(virtualDir, `${name}.tsx`);
353
+ const virtualContent = __WEBPACK_EXTERNAL_MODULE_prettier__["default"].format(`
354
+ import Mod from "${absPath}";
355
+ import { createRoot } from 'react-dom/client';
356
+
357
+ const root = createRoot(document.getElementById('root'));
358
+ root.render(<Mod />);
359
+ `, prettierConfig);
360
+ __WEBPACK_EXTERNAL_MODULE_node_fs__["default"].writeFileSync(virtualPath, virtualContent);
361
+ virtualMod[name] = virtualPath;
362
+ });
363
+ return merge({
364
+ source: {
365
+ entry: virtualMod
366
+ },
367
+ output: {
368
+ distPath: {
369
+ root: __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(virtualDir, 'dist')
370
+ }
371
+ },
372
+ server: {
373
+ port: 6008,
374
+ proxy: {
375
+ '/dist': {
376
+ target: 'http://localhost:6007'
377
+ }
378
+ }
379
+ },
380
+ plugins: [
381
+ (0, __WEBPACK_EXTERNAL_MODULE__rsbuild_plugin_react__.pluginReact)(),
382
+ (0, __WEBPACK_EXTERNAL_MODULE__rsbuild_plugin_less__.pluginLess)()
383
+ ]
384
+ }, uiConfig.preview);
385
+ }
386
+ /**
387
+ * xx.page.{ts,tsx}
388
+ */ const rPageEntry = /\.page\.(js|ts|tsx|mjs|mts|cjs|cts)$/;
389
+ function resolvePreviewEntries(previewDir) {
390
+ const entries = {};
391
+ __WEBPACK_EXTERNAL_MODULE_node_fs__["default"].readdirSync(previewDir).forEach((file)=>{
392
+ const filePath = __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(previewDir, file);
393
+ const fileStat = __WEBPACK_EXTERNAL_MODULE_node_fs__["default"].statSync(filePath);
394
+ if (fileStat.isDirectory()) Object.assign(entries, resolvePreviewEntries(filePath));
395
+ else if (/\.page\.(js|ts|tsx|mjs|mts|cjs|cts)$/.test(file)) {
396
+ const relative = __WEBPACK_EXTERNAL_MODULE_node_path__["default"].relative(previewDir, filePath);
397
+ let dirname = __WEBPACK_EXTERNAL_MODULE_node_path__["default"].dirname(relative);
398
+ dirname = '.' === dirname ? '' : dirname;
399
+ const basename = __WEBPACK_EXTERNAL_MODULE_node_path__["default"].basename(filePath).replace(rPageEntry, '');
400
+ const route = dirname.split('/').concat(basename).filter(Boolean).join('_');
401
+ entries[route] = filePath;
402
+ }
403
+ });
404
+ return entries;
405
+ }
406
+ function resolveConfigPath(root, customConfig) {
407
+ if (customConfig) {
408
+ const customConfigPath = __WEBPACK_EXTERNAL_MODULE_node_path__["default"].isAbsolute(customConfig) ? customConfig : __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(root, customConfig);
409
+ if (__WEBPACK_EXTERNAL_MODULE_node_fs__["default"].existsSync(customConfigPath)) {
410
+ if (__WEBPACK_EXTERNAL_MODULE_node_fs__["default"].statSync(customConfigPath).isFile()) return customConfigPath;
411
+ root = customConfigPath;
412
+ } else throw new Error(`${CONFIG_FILE_NAME} not found in ${customConfigPath}`);
413
+ }
414
+ const configFilePath = CONFIG_FILE_EXTNAME.map((extname)=>`${__WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(root, CONFIG_FILE_NAME)}${extname}`).find((p)=>__WEBPACK_EXTERNAL_MODULE_node_fs__["default"].existsSync(p));
415
+ if (configFilePath) return configFilePath;
416
+ throw new Error(`${CONFIG_FILE_NAME} not found in ${root}`);
417
+ }
418
+ function resolveTsconfigPath(root) {
419
+ // Preferred tsconfig.build.json
420
+ if (__WEBPACK_EXTERNAL_MODULE_node_fs__["default"].existsSync(__WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(root, 'tsconfig.build.json'))) return 'tsconfig.build.json';
421
+ return 'tsconfig.json';
422
+ }
423
+ function resolveMainEntry(projectDir) {
424
+ const mainEntry = CONFIG_FILE_EXTNAME.map((extname)=>`index${extname}`).find((e)=>__WEBPACK_EXTERNAL_MODULE_node_fs__["default"].existsSync(__WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(projectDir, `src/${e}`)));
425
+ return mainEntry;
426
+ }
427
+ /**
428
+ * The `exports` field in `package.json` must adhere to the following format:
429
+ *
430
+ * ```
431
+ * exports: {
432
+ * ".": {
433
+ * ...
434
+ * "src": "./src/index.tsx"
435
+ * },
436
+ * "./button": {
437
+ * ...
438
+ * "src": "./src/button/index.tsx"
439
+ * }
440
+ * }
441
+ * ```
442
+ */ function resolveExports(uiConfig) {
443
+ const projectDir = (0, __WEBPACK_EXTERNAL_MODULE_node_path__.dirname)(uiConfig._privateMeta.configFilePath);
444
+ const srcEntry = resolveMainEntry(projectDir);
445
+ if (!srcEntry) throw new Error('entry not found, maybe you forget the "src/index.ts"?');
446
+ const pkgJson = JSON.parse(__WEBPACK_EXTERNAL_MODULE_node_fs__["default"].readFileSync(__WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(projectDir, 'package.json'), 'utf-8'));
447
+ let exposes = {};
448
+ Object.entries(pkgJson.exports ?? {}).forEach(([key, config])=>{
449
+ if (!config.src) {
450
+ logger.warning([
451
+ `exports.${key} does't have "src", the builder will ignore this export.`,
452
+ `you should add "src" field, such as:\n`,
453
+ 'exports: {\n',
454
+ ` "${key}": {\n`,
455
+ ' "src": "./src/index.tsx"\n',
456
+ ' }\n',
457
+ '}'
458
+ ].join(''));
459
+ return;
460
+ }
461
+ // mfplugin doesn't support "./"
462
+ const k = './' === key ? '.' : key;
463
+ exposes[k] = config.src;
464
+ });
465
+ // use default export
466
+ if (isEmpty(exposes)) exposes['.'] = `./src/${srcEntry}`;
467
+ return exposes;
468
+ }
469
+ /* eslint-disable security/detect-non-literal-fs-filename -- ignore */ const buildAction = async (options = {})=>{
470
+ const uiConfig = await loadConfig({
471
+ path: options.dir
472
+ });
473
+ const projectDir = (0, __WEBPACK_EXTERNAL_MODULE_node_path__.dirname)(uiConfig._privateMeta.configFilePath);
474
+ // esm/cjs/umd/mf
475
+ const prevCwd = process.cwd();
476
+ try {
477
+ process.chdir(projectDir);
478
+ const rslibConfig = getShareRslibConfig(uiConfig, options.libConfig);
479
+ await (0, __WEBPACK_EXTERNAL_MODULE__rslib_core__.build)(rslibConfig);
480
+ } catch (e) {} finally{
481
+ process.chdir(prevCwd);
482
+ }
483
+ };
484
+ const buildSpec = {
485
+ name: 'build',
486
+ description: 'build component',
487
+ action: buildAction,
488
+ options: [
489
+ new __WEBPACK_EXTERNAL_MODULE_commander__.Option('-d, --dir <componentDir>', 'the path of component')
490
+ ]
491
+ };
492
+ /* eslint-disable @typescript-eslint/no-explicit-any -- ignore */ /* eslint-disable security/detect-non-literal-fs-filename -- ignore */ /* eslint-disable no-magic-numbers -- ignore */ /* eslint-disable @typescript-eslint/no-magic-numbers -- ignore*/ const { isEmpty: ui_isEmpty } = __WEBPACK_EXTERNAL_MODULE_lodash__["default"];
493
+ async function publishUIAction(options) {
494
+ const prevCwd = process.cwd();
495
+ let pkgJson = {};
496
+ let projectDir = '';
497
+ // ctrl+c
498
+ process.on('SIGINT', ()=>{
499
+ ui_reset(projectDir, pkgJson);
500
+ process.chdir(prevCwd);
501
+ });
502
+ try {
503
+ projectDir = resolvePackageDir(options.dir);
504
+ process.chdir(projectDir);
505
+ pkgJson = resolvePackageJson(projectDir);
506
+ await check();
507
+ await version(projectDir);
508
+ await buildAction();
509
+ await test();
510
+ await publish();
511
+ } catch (error) {
512
+ ui_reset(projectDir, pkgJson);
513
+ logger.error('Failed to publish component:', error);
514
+ } finally{
515
+ process.chdir(prevCwd);
516
+ }
517
+ }
518
+ async function check() {
519
+ const registry = process.env.REGISTRY;
520
+ if (!registry || !Object.values(REGISTRY_HOST).includes(new URL(registry).host)) throw new Error(`NPM registry is not expected. ${registry}`);
521
+ const { stdout } = __WEBPACK_EXTERNAL_MODULE_cross_spawn__["default"].sync('git', [
522
+ 'status',
523
+ '--porcelain'
524
+ ], {
525
+ encoding: 'utf-8'
526
+ });
527
+ if (stdout) {
528
+ const anwser = await (0, __WEBPACK_EXTERNAL_MODULE__inquirer_prompts__.confirm)({
529
+ message: 'Git workspace is dirty, are you sure to continue?',
530
+ default: false
531
+ });
532
+ if (!anwser) throw new Error('dirty workspace');
533
+ }
534
+ }
535
+ async function version(projectDir) {
536
+ const pkgJson = resolvePackageJson(projectDir);
537
+ const anwser = await (0, __WEBPACK_EXTERNAL_MODULE__inquirer_prompts__.confirm)({
538
+ message: 'Whether to increase the package version?',
539
+ default: false
540
+ });
541
+ if (!anwser) return;
542
+ const type = await (0, __WEBPACK_EXTERNAL_MODULE__inquirer_prompts__.select)({
543
+ message: 'Choose publish type:',
544
+ choices: [
545
+ {
546
+ name: 'alpha',
547
+ value: 'alpha'
548
+ },
549
+ {
550
+ name: 'beta',
551
+ value: 'beta'
552
+ },
553
+ {
554
+ name: 'rc',
555
+ value: 'rc'
556
+ },
557
+ {
558
+ name: 'patch',
559
+ value: 'patch'
560
+ },
561
+ {
562
+ name: 'minor',
563
+ value: 'minor'
564
+ },
565
+ {
566
+ name: 'major',
567
+ value: 'major'
568
+ }
569
+ ],
570
+ default: 'alpha'
571
+ });
572
+ let nextVersion = pkgJson.version;
573
+ nextVersion = [
574
+ 'alpha',
575
+ 'beta',
576
+ 'rc'
577
+ ].includes(type) ? __WEBPACK_EXTERNAL_MODULE_semver__["default"].inc(nextVersion, 'prerelease', type) : __WEBPACK_EXTERNAL_MODULE_semver__["default"].inc(nextVersion, type);
578
+ nextVersion = await (0, __WEBPACK_EXTERNAL_MODULE__inquirer_prompts__.input)({
579
+ message: 'Are you sure to publish:',
580
+ default: nextVersion,
581
+ validate: (val)=>{
582
+ if (!val || !__WEBPACK_EXTERNAL_MODULE_semver__["default"].valid(val)) return 'version is not valid';
583
+ return true;
584
+ }
585
+ });
586
+ pkgJson.version = nextVersion;
587
+ __WEBPACK_EXTERNAL_MODULE_node_fs__["default"].writeFileSync(__WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(projectDir, 'package.json'), JSON.stringify(pkgJson, void 0, 2));
588
+ }
589
+ async function test() {
590
+ await __WEBPACK_EXTERNAL_MODULE_cross_spawn__["default"].sync('npm', [
591
+ 'run',
592
+ 'test'
593
+ ], {
594
+ stdio: 'inherit'
595
+ });
596
+ await __WEBPACK_EXTERNAL_MODULE_cross_spawn__["default"].sync('npm', [
597
+ 'run',
598
+ 'test:cov'
599
+ ], {
600
+ stdio: 'inherit'
601
+ });
602
+ }
603
+ async function publish() {
604
+ const registryKey = process.env.SCOPE ? `@${process.env.SCOPE}:registry` : 'registry';
605
+ await (0, __WEBPACK_EXTERNAL_MODULE_cross_spawn__["default"])('npm', [
606
+ 'publish',
607
+ `--${registryKey}=${process.env.REGISTRY}`
608
+ ], {
609
+ stdio: 'inherit'
610
+ });
611
+ }
612
+ function ui_reset(projectDir, pkgJson) {
613
+ if (ui_isEmpty(projectDir) || ui_isEmpty(pkgJson)) return;
614
+ __WEBPACK_EXTERNAL_MODULE_node_fs__["default"].writeFileSync(__WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(projectDir, 'package.json'), JSON.stringify(pkgJson, void 0, 2));
615
+ }
616
+ /* eslint-disable @typescript-eslint/no-explicit-any -- ignore */ /* eslint-disable security/detect-non-literal-fs-filename -- ignore */ /* eslint-disable @typescript-eslint/no-non-null-assertion -- ignore */ async function publishOceanAction(options = {}) {
617
+ const prevCwd = process.cwd();
618
+ // ctrl+c
619
+ process.on('SIGINT', ()=>{
620
+ process.chdir(prevCwd);
621
+ });
622
+ try {
623
+ const config = await loadUIConfig(options.dir);
624
+ const projectDir = (0, __WEBPACK_EXTERNAL_MODULE_node_path__.dirname)(config.uiConfig._privateMeta.configFilePath);
625
+ const pkgJson = resolvePackageJson(projectDir);
626
+ process.chdir(projectDir);
627
+ const deployment = await chooseDeployment();
628
+ await ocean_test(pkgJson);
629
+ const files = await build(pkgJson, projectDir);
630
+ await ocean_publish(files, config, deployment);
631
+ } catch (error) {
632
+ logger.error('Failed to publish component:', error);
633
+ } finally{
634
+ process.chdir(prevCwd);
635
+ }
636
+ }
637
+ async function loadUIConfig(dir) {
638
+ const uiConfig = await loadConfig({
639
+ path: dir
640
+ });
641
+ const npm = new NpmConfig();
642
+ const npmConfig = await npm.loadConfig();
643
+ if (!npmConfig.region) throw new Error('failed to parse region, maybe you should login first');
644
+ return {
645
+ uiConfig,
646
+ npmConfig
647
+ };
648
+ }
649
+ async function chooseDeployment() {
650
+ return await (0, __WEBPACK_EXTERNAL_MODULE__inquirer_prompts__.select)({
651
+ message: 'Choose deployment type:',
652
+ choices: [
653
+ {
654
+ name: 'canary',
655
+ value: 1
656
+ },
657
+ {
658
+ name: 'online',
659
+ value: 2
660
+ }
661
+ ],
662
+ default: 1
663
+ });
664
+ }
665
+ async function ocean_test(pkgJson) {
666
+ if (pkgJson.scripts?.test) await __WEBPACK_EXTERNAL_MODULE_cross_spawn__["default"].sync('npm', [
667
+ 'run',
668
+ 'test'
669
+ ], {
670
+ stdio: 'inherit'
671
+ });
672
+ }
673
+ async function build(pkgJson, projectDir) {
674
+ if (!pkgJson.scripts?.build) throw new Error('package.json should have build script');
675
+ const result = await __WEBPACK_EXTERNAL_MODULE_cross_spawn__["default"].sync('npm', [
676
+ 'run',
677
+ 'build'
678
+ ], {
679
+ stdio: 'inherit'
680
+ });
681
+ if (result.status) throw new Error('build failed');
682
+ // validate output
683
+ const outputDir = __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(projectDir, 'applet_output', 'coze');
684
+ const outputFiles = {
685
+ zip: [],
686
+ manifest: ''
687
+ };
688
+ __WEBPACK_EXTERNAL_MODULE_node_fs__["default"].readdirSync(outputDir).forEach((file)=>{
689
+ if ('.zip' === __WEBPACK_EXTERNAL_MODULE_node_path__["default"].extname(file)) outputFiles.zip.push(file);
690
+ else if ('manifest.json' === file) outputFiles.manifest = file;
691
+ });
692
+ if (outputFiles.manifest) {
693
+ if (outputFiles.zip.length) {
694
+ if (outputFiles.zip.length > 1) throw new Error(`multiple zip found in ${outputDir}`);
695
+ } else throw new Error(`zip not found in ${outputDir}`);
696
+ } else throw new Error(`manifest.json not found in ${outputDir}`);
697
+ return {
698
+ zip: __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(outputDir, outputFiles.zip[0]),
699
+ manifest: __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(outputDir, outputFiles.manifest)
700
+ };
701
+ }
702
+ async function ocean_publish(files, config, deployType) {
703
+ const { registryUrl } = config.npmConfig;
704
+ const data = new __WEBPACK_EXTERNAL_MODULE_form_data__["default"]();
705
+ data.append('manifest', __WEBPACK_EXTERNAL_MODULE_node_fs__["default"].createReadStream(files.manifest));
706
+ data.append('pkg', __WEBPACK_EXTERNAL_MODULE_node_fs__["default"].createReadStream(files.zip));
707
+ data.append('projectId', config.uiConfig.projectId);
708
+ data.append('deployType', deployType);
709
+ const res = await __WEBPACK_EXTERNAL_MODULE_axios__["default"].request({
710
+ method: 'post',
711
+ url: `${registryUrl}${registryUrl.endsWith('/') ? '' : '/'}api/ocean/publish`,
712
+ headers: {
713
+ Authorization: `Bearer ${config.npmConfig.authToken}`,
714
+ ...data.getHeaders()
715
+ },
716
+ data
717
+ });
718
+ if (res.data.code) logger.error(`publish failed: ${res.data.msg}`);
719
+ else logger.success(`publish success, deployId: ${res.data.deployId}`);
720
+ }
721
+ async function publishAction(options = {}) {
722
+ if ('ocean' === options.type) await publishOceanAction(options);
723
+ else await publishUIAction(options);
724
+ }
725
+ const publishSpec = {
726
+ name: 'publish',
727
+ description: 'publish component',
728
+ action: publishAction,
729
+ options: [
730
+ new __WEBPACK_EXTERNAL_MODULE_commander__.Option('-t, --type <name>', 'the component type').choices([
731
+ 'ocean'
732
+ ]),
733
+ new __WEBPACK_EXTERNAL_MODULE_commander__.Option('-d, --dir <componentDir>', 'the path of component')
734
+ ],
735
+ auth: true
736
+ };
737
+ /* eslint-disable no-magic-numbers -- ignore */ /* eslint-disable @typescript-eslint/no-magic-numbers -- ignore */ /* eslint-disable security/detect-non-literal-fs-filename -- ignore */ /* eslint-disable @typescript-eslint/no-non-null-assertion -- ignore */ const { isEqual, debounce } = __WEBPACK_EXTERNAL_MODULE_lodash__["default"];
738
+ const previewAction = async (options = {})=>{
739
+ const uiConfig = await loadConfig({
740
+ path: options.dir
741
+ });
742
+ const projectDir = (0, __WEBPACK_EXTERNAL_MODULE_node_path__.dirname)(uiConfig._privateMeta.configFilePath);
743
+ const previewDir = __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(projectDir, 'preview');
744
+ if (!__WEBPACK_EXTERNAL_MODULE_node_fs__["default"].existsSync(previewDir)) throw new Error(`${previewDir} does not exist`);
745
+ // build for preview
746
+ await buildAction({
747
+ dir: options.dir,
748
+ libConfig: {
749
+ output: {
750
+ assetPrefix: '/dist/mf'
751
+ }
752
+ }
753
+ });
754
+ const prevCwd = process.cwd();
755
+ // ctrl+c
756
+ process.on('SIGINT', ()=>{
757
+ process.chdir(prevCwd);
758
+ process.exit(1);
759
+ });
760
+ const serveDist = ()=>{
761
+ const app = (0, __WEBPACK_EXTERNAL_MODULE_express__["default"])();
762
+ app.use('/dist', __WEBPACK_EXTERNAL_MODULE_express__["default"].static(__WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(projectDir, 'dist')));
763
+ app.listen(6007);
764
+ };
765
+ let devServer = null;
766
+ const startDevServer = async ()=>{
767
+ try {
768
+ process.chdir(projectDir);
769
+ const rsbuildConfig = getShareRsbuildConfig(uiConfig);
770
+ const rsbuild = await (0, __WEBPACK_EXTERNAL_MODULE__rsbuild_core__.createRsbuild)({
771
+ rsbuildConfig
772
+ });
773
+ devServer = await rsbuild.startDevServer();
774
+ } catch (e) {
775
+ logger.error('failed', e);
776
+ process.chdir(prevCwd);
777
+ }
778
+ };
779
+ let prevEntries = resolvePreviewEntries(previewDir);
780
+ const reload = debounce(async ()=>{
781
+ const nextEntries = resolvePreviewEntries(previewDir);
782
+ if (!isEqual(prevEntries, nextEntries) && devServer) {
783
+ await devServer.server.close();
784
+ devServer = null;
785
+ prevEntries = nextEntries;
786
+ await startDevServer();
787
+ }
788
+ }, 300);
789
+ serveDist();
790
+ startDevServer();
791
+ const watcher = __WEBPACK_EXTERNAL_MODULE_chokidar__["default"].watch(previewDir, {
792
+ ignoreInitial: true
793
+ });
794
+ watcher.on('add', reload).on('unlink', reload);
795
+ };
796
+ const previewSpec = {
797
+ name: 'preview',
798
+ description: 'preview component',
799
+ action: previewAction,
800
+ options: [
801
+ new __WEBPACK_EXTERNAL_MODULE_commander__.Option('-d, --dir <componentDir>', 'the path of component')
802
+ ]
803
+ };
804
+ /* eslint-disable security/detect-non-literal-fs-filename -- ignore */ const createAction = async (options = {})=>{
805
+ if ('ocean' === options.type) {
806
+ const nameOrPath = await (0, __WEBPACK_EXTERNAL_MODULE__inquirer_prompts__.input)({
807
+ message: 'Project name or path:',
808
+ validate: (val)=>{
809
+ if (!val) return 'please input name or path';
810
+ return true;
811
+ }
812
+ });
813
+ const projectDir = resolvePackageDir(nameOrPath);
814
+ let { projectId } = options;
815
+ if (!projectId) projectId = await (0, __WEBPACK_EXTERNAL_MODULE__inquirer_prompts__.input)({
816
+ message: 'ProjectId of the ocean component:',
817
+ validate: (val)=>{
818
+ if (!val) return 'please input projectId';
819
+ return true;
820
+ }
821
+ });
822
+ // copy template
823
+ __WEBPACK_EXTERNAL_MODULE_cross_spawn__["default"].sync('npx', [
824
+ '@byted/create',
825
+ projectDir,
826
+ '--template',
827
+ '@ai-app/agent-scaffolding-coze-create@latest'
828
+ ], {
829
+ stdio: 'inherit'
830
+ });
831
+ // generate ui.config
832
+ const configFile = 'ui.config.ts';
833
+ const prettierConfig = {
834
+ parser: 'babel',
835
+ singleQuote: true,
836
+ trailingComma: 'all'
837
+ };
838
+ const configFilePath = __WEBPACK_EXTERNAL_MODULE_node_path__["default"].join(projectDir, configFile);
839
+ const content = __WEBPACK_EXTERNAL_MODULE_prettier__["default"].format(`
840
+ export default {
841
+ projectId: '${projectId}'
842
+ };
843
+ `, prettierConfig);
844
+ __WEBPACK_EXTERNAL_MODULE_node_fs__["default"].writeFileSync(configFilePath, content);
845
+ } else await (0, __WEBPACK_EXTERNAL_MODULE_cross_spawn__["default"])('npm', [
846
+ 'create',
847
+ '@coze-dev/ui@latest'
848
+ ], {
849
+ stdio: 'inherit'
850
+ });
851
+ };
852
+ const createSpec = {
853
+ name: 'create',
854
+ description: 'create componennt',
855
+ action: createAction,
856
+ auth: true,
857
+ options: [
858
+ new __WEBPACK_EXTERNAL_MODULE_commander__.Option('-t, --type <name>', 'the component type').choices([
859
+ 'ocean'
860
+ ]),
861
+ new __WEBPACK_EXTERNAL_MODULE_commander__.Option('--projectId <projectId>', 'the projectId of the ocean component')
862
+ ]
863
+ };
864
+ const uiSpec = {
865
+ name: 'ui',
866
+ description: 'subcommand for ui development',
867
+ subCommands: [
868
+ createSpec,
869
+ buildSpec,
870
+ previewSpec,
871
+ publishSpec
872
+ ]
873
+ };
874
+ async function logoutAction({ region, scope, source }) {
875
+ const npmConfig = new NpmConfig({
876
+ region,
877
+ scope,
878
+ source
879
+ });
880
+ const authClient = new OauthClient(region);
881
+ await authClient.deactivate(npmConfig);
882
+ }
883
+ const logoutSpec = {
884
+ name: 'logout',
885
+ description: 'log out of the hub',
886
+ action: logoutAction,
887
+ options: [
888
+ new __WEBPACK_EXTERNAL_MODULE_commander__.Option('-r, --region <name>', 'the region of hub').choices(Object.values(constants_Region)),
889
+ new __WEBPACK_EXTERNAL_MODULE_commander__.Option('-s, --scope <name>', 'the scope of package'),
890
+ new __WEBPACK_EXTERNAL_MODULE_commander__.Option('-b, --source <name>', 'the business source')
891
+ ]
892
+ };
893
+ async function loginAction({ region, scope, source }) {
894
+ const npmConfig = new NpmConfig({
895
+ scope,
896
+ region,
897
+ source
898
+ });
899
+ const authClient = new OauthClient(region);
900
+ await authClient.activate(npmConfig);
901
+ }
902
+ const loginSpec = {
903
+ name: 'login',
904
+ description: 'log in to the hub',
905
+ action: loginAction,
906
+ options: [
907
+ new __WEBPACK_EXTERNAL_MODULE_commander__.Option('-r, --region <name>', 'the region of hub').choices(Object.values(constants_Region)),
908
+ new __WEBPACK_EXTERNAL_MODULE_commander__.Option('-s, --scope <name>', 'the scope of package'),
909
+ new __WEBPACK_EXTERNAL_MODULE_commander__.Option('-b, --source <name>', 'the business source')
910
+ ]
911
+ };
912
+ /* eslint-disable @typescript-eslint/no-explicit-any -- ignore */ function addCommand({ program, spec, runAuth }) {
913
+ const command = program.command(spec.name);
914
+ command.description(spec.description);
915
+ (spec.arguments ?? []).forEach((argument)=>{
916
+ command.addArgument(argument);
917
+ });
918
+ (spec.options ?? []).forEach((option)=>{
919
+ command.addOption(option);
920
+ });
921
+ if (spec.action) command.action(async (...args)=>{
922
+ if (spec.auth && runAuth) await runAuth();
923
+ await spec.action?.(...args);
924
+ });
925
+ (spec.subCommands ?? []).forEach((subCommand)=>{
926
+ addCommand({
927
+ program: command,
928
+ spec: subCommand,
929
+ runAuth
930
+ });
931
+ });
932
+ }
933
+ const cli_program = new __WEBPACK_EXTERNAL_MODULE_commander__.Command();
934
+ cli_program.name('coze').version("0.0.1-alpha.11").description('A command-line tool for component development');
935
+ [
936
+ loginSpec,
937
+ logoutSpec,
938
+ uiSpec
939
+ ].forEach((spec)=>{
940
+ const runAuth = async ()=>{
941
+ // refresh token
942
+ const npmConfig = new NpmConfig();
943
+ const { region, registryUrl, scope } = await npmConfig.loadConfig();
944
+ const oauthClient = new OauthClient(region);
945
+ await oauthClient.activate(npmConfig);
946
+ // add env
947
+ process.env.REGION = region;
948
+ process.env.REGISTRY = registryUrl;
949
+ process.env.SCOPE = scope;
950
+ };
951
+ addCommand({
952
+ spec,
953
+ program: cli_program,
954
+ runAuth
955
+ });
956
+ });
957
+ cli_program.parse(process.argv);