react-native-update-cli 2.8.5 → 2.9.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/lib/api.d.ts +18 -0
- package/lib/app.d.ts +38 -0
- package/lib/app.js +5 -4
- package/lib/bundle-pack.d.ts +1 -0
- package/lib/bundle-pack.js +104 -0
- package/lib/bundle-runner.d.ts +20 -0
- package/lib/bundle-runner.js +404 -0
- package/lib/bundle.d.ts +6 -0
- package/lib/bundle.js +73 -471
- package/lib/diff.d.ts +13 -0
- package/lib/diff.js +144 -123
- package/lib/exports.d.ts +12 -0
- package/lib/index.d.ts +5 -0
- package/lib/index.js +5 -13
- package/lib/install.d.ts +4 -0
- package/lib/locales/en.d.ts +137 -0
- package/lib/locales/zh.d.ts +136 -0
- package/lib/module-manager.d.ts +20 -0
- package/lib/module-manager.js +3 -9
- package/lib/modules/app-module.d.ts +2 -0
- package/lib/modules/app-module.js +84 -44
- package/lib/modules/bundle-module.d.ts +2 -0
- package/lib/modules/bundle-module.js +7 -8
- package/lib/modules/index.d.ts +6 -0
- package/lib/modules/package-module.d.ts +2 -0
- package/lib/modules/user-module.d.ts +2 -0
- package/lib/modules/user-module.js +55 -44
- package/lib/modules/version-module.d.ts +2 -0
- package/lib/package.d.ts +59 -0
- package/lib/package.js +110 -139
- package/lib/provider.d.ts +26 -0
- package/lib/provider.js +115 -217
- package/lib/types.d.ts +120 -0
- package/lib/user.d.ts +8 -0
- package/lib/utils/add-gitignore.d.ts +1 -0
- package/lib/utils/app-info-parser/aab.d.ts +22 -0
- package/lib/utils/app-info-parser/aab.js +0 -4
- package/lib/utils/app-info-parser/apk.d.ts +14 -0
- package/lib/utils/app-info-parser/apk.js +6 -4
- package/lib/utils/app-info-parser/app.d.ts +4 -0
- package/lib/utils/app-info-parser/app.js +3 -0
- package/lib/utils/app-info-parser/index.d.ts +16 -0
- package/lib/utils/app-info-parser/index.js +2 -0
- package/lib/utils/app-info-parser/ipa.d.ts +14 -0
- package/lib/utils/app-info-parser/ipa.js +1 -1
- package/lib/utils/app-info-parser/resource-finder.d.ts +49 -0
- package/lib/utils/app-info-parser/utils.d.ts +31 -0
- package/lib/utils/app-info-parser/utils.js +1 -0
- package/lib/utils/app-info-parser/xml-parser/binary.d.ts +56 -0
- package/lib/utils/app-info-parser/xml-parser/manifest.d.ts +10 -0
- package/lib/utils/app-info-parser/zip.d.ts +18 -0
- package/lib/utils/app-info-parser/zip.js +7 -9
- package/lib/utils/check-lockfile.d.ts +1 -0
- package/lib/utils/check-plugin.d.ts +7 -0
- package/lib/utils/command-result.d.ts +3 -0
- package/lib/utils/command-result.js +35 -0
- package/lib/utils/constants.d.ts +9 -0
- package/lib/utils/dep-versions.d.ts +1 -0
- package/lib/utils/git.d.ts +8 -0
- package/lib/utils/http-helper.d.ts +4 -0
- package/lib/utils/i18n.d.ts +12 -0
- package/lib/utils/index.d.ts +22 -0
- package/lib/utils/index.js +52 -22
- package/lib/utils/latest-version/cli.d.ts +1 -0
- package/lib/utils/latest-version/cli.js +24 -60
- package/lib/utils/latest-version/index.d.ts +146 -0
- package/lib/utils/latest-version/index.js +22 -22
- package/lib/utils/options.d.ts +4 -0
- package/lib/utils/options.js +63 -0
- package/lib/utils/plugin-config.d.ts +9 -0
- package/lib/utils/zip-entries.d.ts +3 -0
- package/lib/versions.d.ts +43 -0
- package/lib/workflow-runner.d.ts +2 -0
- package/lib/workflow-runner.js +25 -0
- package/package.json +20 -5
- package/src/api.ts +1 -1
- package/src/app.ts +20 -11
- package/src/bundle-pack.ts +51 -0
- package/src/bundle-runner.ts +463 -0
- package/src/bundle.ts +184 -571
- package/src/diff.ts +208 -174
- package/src/index.ts +15 -17
- package/src/module-manager.ts +15 -15
- package/src/modules/app-module.ts +120 -48
- package/src/modules/bundle-module.ts +21 -11
- package/src/modules/package-module.ts +0 -1
- package/src/modules/user-module.ts +117 -58
- package/src/package.ts +163 -138
- package/src/provider.ts +164 -240
- package/src/types.ts +13 -8
- package/src/utils/app-info-parser/aab.ts +0 -7
- package/src/utils/app-info-parser/apk.ts +9 -6
- package/src/utils/app-info-parser/app.ts +5 -1
- package/src/utils/app-info-parser/index.ts +11 -6
- package/src/utils/app-info-parser/ipa.ts +1 -1
- package/src/utils/app-info-parser/utils.ts +3 -0
- package/src/utils/app-info-parser/xml-parser/manifest.ts +3 -1
- package/src/utils/app-info-parser/zip.ts +12 -14
- package/src/utils/command-result.ts +24 -0
- package/src/utils/index.ts +138 -39
- package/src/utils/latest-version/cli.ts +22 -20
- package/src/utils/latest-version/index.ts +20 -20
- package/src/utils/options.ts +56 -0
- package/src/utils/zip-entries.ts +1 -1
- package/src/workflow-runner.ts +24 -0
- package/index.js +0 -1
package/src/package.ts
CHANGED
|
@@ -18,6 +18,127 @@ import { depVersions } from './utils/dep-versions';
|
|
|
18
18
|
import { getCommitInfo } from './utils/git';
|
|
19
19
|
import { t } from './utils/i18n';
|
|
20
20
|
|
|
21
|
+
type PackageCommandOptions = Record<string, unknown> & {
|
|
22
|
+
version?: string;
|
|
23
|
+
includeAllSplits?: boolean | string;
|
|
24
|
+
splits?: string;
|
|
25
|
+
output?: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
type PackageVersionRef = {
|
|
29
|
+
id?: string | number;
|
|
30
|
+
name?: string | number;
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
type NativePackageInfo = {
|
|
34
|
+
versionName?: string | number;
|
|
35
|
+
buildTime?: string | number;
|
|
36
|
+
appId?: string;
|
|
37
|
+
appKey?: string;
|
|
38
|
+
[key: string]: unknown;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
type NativeUploadConfig = {
|
|
42
|
+
extension: '.ipa' | '.apk' | '.app';
|
|
43
|
+
platform: Platform;
|
|
44
|
+
appIdMismatchKey: string;
|
|
45
|
+
appKeyMismatchKey: string;
|
|
46
|
+
successKey: string;
|
|
47
|
+
getInfo: (filePath: string) => Promise<NativePackageInfo>;
|
|
48
|
+
normalizeBuildTime?: (
|
|
49
|
+
buildTime: NativePackageInfo['buildTime'],
|
|
50
|
+
) => string | number | undefined;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export function normalizeUploadBuildTime(value: unknown): string {
|
|
54
|
+
return String(value);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function ensureFileByExt(
|
|
58
|
+
filePath: string | undefined,
|
|
59
|
+
extension: NativeUploadConfig['extension'] | '.aab',
|
|
60
|
+
usageKey: string,
|
|
61
|
+
): string {
|
|
62
|
+
if (!filePath || !filePath.endsWith(extension)) {
|
|
63
|
+
throw new Error(t(usageKey));
|
|
64
|
+
}
|
|
65
|
+
return filePath;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function parseBooleanOption(value: unknown): boolean {
|
|
69
|
+
return value === true || value === 'true';
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function parseCsvOption(value: unknown): string[] | null {
|
|
73
|
+
if (typeof value !== 'string') {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
const parsed = value
|
|
77
|
+
.split(',')
|
|
78
|
+
.map((item) => item.trim())
|
|
79
|
+
.filter(Boolean);
|
|
80
|
+
return parsed.length > 0 ? parsed : null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function getVersionBinding(version: unknown): PackageVersionRef | undefined {
|
|
84
|
+
if (!version || typeof version !== 'object') {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const v = version as PackageVersionRef;
|
|
89
|
+
return { id: v.id, name: v.name };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async function uploadNativePackage(
|
|
93
|
+
filePath: string,
|
|
94
|
+
options: PackageCommandOptions,
|
|
95
|
+
config: NativeUploadConfig,
|
|
96
|
+
): Promise<void> {
|
|
97
|
+
const info = await config.getInfo(filePath);
|
|
98
|
+
const { versionName: extractedVersionName, buildTime } = info;
|
|
99
|
+
const { appId: appIdInPkg, appKey: appKeyInPkg } = info;
|
|
100
|
+
const { appId, appKey } = await getSelectedApp(config.platform);
|
|
101
|
+
|
|
102
|
+
if (appIdInPkg && appIdInPkg != appId) {
|
|
103
|
+
throw new Error(t(config.appIdMismatchKey, { appIdInPkg, appId }));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (appKeyInPkg && appKeyInPkg !== appKey) {
|
|
107
|
+
throw new Error(t(config.appKeyMismatchKey, { appKeyInPkg, appKey }));
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
const customVersion =
|
|
111
|
+
typeof options.version === 'string' && options.version
|
|
112
|
+
? options.version
|
|
113
|
+
: undefined;
|
|
114
|
+
const versionName = customVersion ?? extractedVersionName;
|
|
115
|
+
if (customVersion !== undefined) {
|
|
116
|
+
console.log(t('usingCustomVersion', { version: versionName }));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const { hash } = await uploadFile(filePath);
|
|
120
|
+
const normalizedBuildTime = config.normalizeBuildTime
|
|
121
|
+
? config.normalizeBuildTime(buildTime)
|
|
122
|
+
: buildTime;
|
|
123
|
+
const uploadBuildTime = normalizeUploadBuildTime(normalizedBuildTime);
|
|
124
|
+
|
|
125
|
+
const { id } = await post(`/app/${appId}/package/create`, {
|
|
126
|
+
name: versionName,
|
|
127
|
+
hash,
|
|
128
|
+
buildTime: uploadBuildTime,
|
|
129
|
+
deps: depVersions,
|
|
130
|
+
commit: await getCommitInfo(),
|
|
131
|
+
});
|
|
132
|
+
saveToLocal(filePath, `${appId}/package/${id}${config.extension}`);
|
|
133
|
+
console.log(
|
|
134
|
+
t(config.successKey, {
|
|
135
|
+
id,
|
|
136
|
+
version: versionName,
|
|
137
|
+
buildTime: uploadBuildTime,
|
|
138
|
+
}),
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
|
|
21
142
|
export async function listPackage(appId: string) {
|
|
22
143
|
const allPkgs = (await getAllPackages(appId)) || [];
|
|
23
144
|
|
|
@@ -30,10 +151,10 @@ export async function listPackage(appId: string) {
|
|
|
30
151
|
const { version } = pkg;
|
|
31
152
|
let versionInfo = '';
|
|
32
153
|
if (version) {
|
|
33
|
-
const versionObj = version
|
|
154
|
+
const versionObj = getVersionBinding(version);
|
|
34
155
|
versionInfo = t('boundTo', {
|
|
35
|
-
name: versionObj
|
|
36
|
-
id: versionObj
|
|
156
|
+
name: versionObj?.name ?? version,
|
|
157
|
+
id: versionObj?.id ?? version,
|
|
37
158
|
});
|
|
38
159
|
}
|
|
39
160
|
let output = pkg.name;
|
|
@@ -70,112 +191,51 @@ export const packageCommands = {
|
|
|
70
191
|
options,
|
|
71
192
|
}: {
|
|
72
193
|
args: string[];
|
|
73
|
-
options:
|
|
194
|
+
options: PackageCommandOptions;
|
|
74
195
|
}) => {
|
|
75
|
-
const fn = args[0];
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
const { appId, appKey } = await getSelectedApp('ios');
|
|
84
|
-
|
|
85
|
-
if (appIdInPkg && appIdInPkg != appId) {
|
|
86
|
-
throw new Error(t('appIdMismatchIpa', { appIdInPkg, appId }));
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (appKeyInPkg && appKeyInPkg !== appKey) {
|
|
90
|
-
throw new Error(t('appKeyMismatchIpa', { appKeyInPkg, appKey }));
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// Use custom version if provided, otherwise use extracted version
|
|
94
|
-
const versionName = options.version || extractedVersionName;
|
|
95
|
-
if (options.version) {
|
|
96
|
-
console.log(t('usingCustomVersion', { version: versionName }));
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
const { hash } = await uploadFile(fn);
|
|
100
|
-
|
|
101
|
-
const { id } = await post(`/app/${appId}/package/create`, {
|
|
102
|
-
name: versionName,
|
|
103
|
-
hash,
|
|
104
|
-
buildTime,
|
|
105
|
-
deps: depVersions,
|
|
106
|
-
commit: await getCommitInfo(),
|
|
196
|
+
const fn = ensureFileByExt(args[0], '.ipa', 'usageUploadIpa');
|
|
197
|
+
await uploadNativePackage(fn, options, {
|
|
198
|
+
extension: '.ipa',
|
|
199
|
+
platform: 'ios',
|
|
200
|
+
appIdMismatchKey: 'appIdMismatchIpa',
|
|
201
|
+
appKeyMismatchKey: 'appKeyMismatchIpa',
|
|
202
|
+
successKey: 'ipaUploadSuccess',
|
|
203
|
+
getInfo: (filePath) => getIpaInfo(filePath),
|
|
107
204
|
});
|
|
108
|
-
saveToLocal(fn, `${appId}/package/${id}.ipa`);
|
|
109
|
-
console.log(t('ipaUploadSuccess', { id, version: versionName, buildTime }));
|
|
110
205
|
},
|
|
111
206
|
uploadApk: async ({
|
|
112
207
|
args,
|
|
113
208
|
options,
|
|
114
209
|
}: {
|
|
115
210
|
args: string[];
|
|
116
|
-
options:
|
|
211
|
+
options: PackageCommandOptions;
|
|
117
212
|
}) => {
|
|
118
|
-
const fn = args[0];
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
const { appId, appKey } = await getSelectedApp('android');
|
|
127
|
-
|
|
128
|
-
if (appIdInPkg && appIdInPkg != appId) {
|
|
129
|
-
throw new Error(t('appIdMismatchApk', { appIdInPkg, appId }));
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
if (appKeyInPkg && appKeyInPkg !== appKey) {
|
|
133
|
-
throw new Error(t('appKeyMismatchApk', { appKeyInPkg, appKey }));
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Use custom version if provided, otherwise use extracted version
|
|
137
|
-
const versionName = options.version || extractedVersionName;
|
|
138
|
-
if (options.version) {
|
|
139
|
-
console.log(t('usingCustomVersion', { version: versionName }));
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
const { hash } = await uploadFile(fn);
|
|
143
|
-
|
|
144
|
-
const { id } = await post(`/app/${appId}/package/create`, {
|
|
145
|
-
name: versionName,
|
|
146
|
-
hash,
|
|
147
|
-
buildTime,
|
|
148
|
-
deps: depVersions,
|
|
149
|
-
commit: await getCommitInfo(),
|
|
213
|
+
const fn = ensureFileByExt(args[0], '.apk', 'usageUploadApk');
|
|
214
|
+
await uploadNativePackage(fn, options, {
|
|
215
|
+
extension: '.apk',
|
|
216
|
+
platform: 'android',
|
|
217
|
+
appIdMismatchKey: 'appIdMismatchApk',
|
|
218
|
+
appKeyMismatchKey: 'appKeyMismatchApk',
|
|
219
|
+
successKey: 'apkUploadSuccess',
|
|
220
|
+
getInfo: (filePath) => getApkInfo(filePath),
|
|
150
221
|
});
|
|
151
|
-
saveToLocal(fn, `${appId}/package/${id}.apk`);
|
|
152
|
-
console.log(t('apkUploadSuccess', { id, version: versionName, buildTime }));
|
|
153
222
|
},
|
|
154
223
|
uploadAab: async ({
|
|
155
224
|
args,
|
|
156
225
|
options,
|
|
157
226
|
}: {
|
|
158
227
|
args: string[];
|
|
159
|
-
options:
|
|
228
|
+
options: PackageCommandOptions;
|
|
160
229
|
}) => {
|
|
161
|
-
const source = args[0];
|
|
162
|
-
if (!source || !source.endsWith('.aab')) {
|
|
163
|
-
throw new Error(t('usageUploadAab'));
|
|
164
|
-
}
|
|
230
|
+
const source = ensureFileByExt(args[0], '.aab', 'usageUploadAab');
|
|
165
231
|
|
|
166
232
|
const output = path.join(
|
|
167
233
|
os.tmpdir(),
|
|
168
234
|
`${path.basename(source, path.extname(source))}-${Date.now()}.apk`,
|
|
169
235
|
);
|
|
170
236
|
|
|
171
|
-
const includeAllSplits =
|
|
172
|
-
|
|
173
|
-
const splits = options.splits
|
|
174
|
-
? String(options.splits)
|
|
175
|
-
.split(',')
|
|
176
|
-
.map((item) => item.trim())
|
|
177
|
-
.filter(Boolean)
|
|
178
|
-
: null;
|
|
237
|
+
const includeAllSplits = parseBooleanOption(options.includeAllSplits);
|
|
238
|
+
const splits = parseCsvOption(options.splits);
|
|
179
239
|
|
|
180
240
|
const parser = new AabParser(source);
|
|
181
241
|
try {
|
|
@@ -198,43 +258,18 @@ export const packageCommands = {
|
|
|
198
258
|
options,
|
|
199
259
|
}: {
|
|
200
260
|
args: string[];
|
|
201
|
-
options:
|
|
261
|
+
options: PackageCommandOptions;
|
|
202
262
|
}) => {
|
|
203
|
-
const fn = args[0];
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
if (appIdInPkg && appIdInPkg != appId) {
|
|
214
|
-
throw new Error(t('appIdMismatchApp', { appIdInPkg, appId }));
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
if (appKeyInPkg && appKeyInPkg !== appKey) {
|
|
218
|
-
throw new Error(t('appKeyMismatchApp', { appKeyInPkg, appKey }));
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
// Use custom version if provided, otherwise use extracted version
|
|
222
|
-
const versionName = options.version || extractedVersionName;
|
|
223
|
-
if (options.version) {
|
|
224
|
-
console.log(t('usingCustomVersion', { version: versionName }));
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
const { hash } = await uploadFile(fn);
|
|
228
|
-
|
|
229
|
-
const { id } = await post(`/app/${appId}/package/create`, {
|
|
230
|
-
name: versionName,
|
|
231
|
-
hash,
|
|
232
|
-
buildTime: String(buildTime),
|
|
233
|
-
deps: depVersions,
|
|
234
|
-
commit: await getCommitInfo(),
|
|
263
|
+
const fn = ensureFileByExt(args[0], '.app', 'usageUploadApp');
|
|
264
|
+
await uploadNativePackage(fn, options, {
|
|
265
|
+
extension: '.app',
|
|
266
|
+
platform: 'harmony',
|
|
267
|
+
appIdMismatchKey: 'appIdMismatchApp',
|
|
268
|
+
appKeyMismatchKey: 'appKeyMismatchApp',
|
|
269
|
+
successKey: 'appUploadSuccess',
|
|
270
|
+
getInfo: (filePath) => getAppInfo(filePath),
|
|
271
|
+
normalizeBuildTime: (buildTime) => String(buildTime),
|
|
235
272
|
});
|
|
236
|
-
saveToLocal(fn, `${appId}/package/${id}.app`);
|
|
237
|
-
console.log(t('appUploadSuccess', { id, version: versionName, buildTime }));
|
|
238
273
|
},
|
|
239
274
|
parseApp: async ({ args }: { args: string[] }) => {
|
|
240
275
|
const fn = args[0];
|
|
@@ -269,12 +304,9 @@ export const packageCommands = {
|
|
|
269
304
|
options,
|
|
270
305
|
}: {
|
|
271
306
|
args: string[];
|
|
272
|
-
options:
|
|
307
|
+
options: PackageCommandOptions;
|
|
273
308
|
}) => {
|
|
274
|
-
const source = args[0];
|
|
275
|
-
if (!source || !source.endsWith('.aab')) {
|
|
276
|
-
throw new Error(t('usageExtractApk'));
|
|
277
|
-
}
|
|
309
|
+
const source = ensureFileByExt(args[0], '.aab', 'usageExtractApk');
|
|
278
310
|
|
|
279
311
|
const output =
|
|
280
312
|
options.output ||
|
|
@@ -283,14 +315,8 @@ export const packageCommands = {
|
|
|
283
315
|
`${path.basename(source, path.extname(source))}.apk`,
|
|
284
316
|
);
|
|
285
317
|
|
|
286
|
-
const includeAllSplits =
|
|
287
|
-
|
|
288
|
-
const splits = options.splits
|
|
289
|
-
? String(options.splits)
|
|
290
|
-
.split(',')
|
|
291
|
-
.map((item) => item.trim())
|
|
292
|
-
.filter(Boolean)
|
|
293
|
-
: null;
|
|
318
|
+
const includeAllSplits = parseBooleanOption(options.includeAllSplits);
|
|
319
|
+
const splits = parseCsvOption(options.splits);
|
|
294
320
|
|
|
295
321
|
const parser = new AabParser(source);
|
|
296
322
|
await parser.extractApk(output, {
|
|
@@ -355,10 +381,9 @@ export const packageCommands = {
|
|
|
355
381
|
try {
|
|
356
382
|
await doDelete(`/app/${appId}/package/${packageId}`);
|
|
357
383
|
console.log(t('deletePackageSuccess', { packageId }));
|
|
358
|
-
} catch (error
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
);
|
|
384
|
+
} catch (error) {
|
|
385
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
386
|
+
throw new Error(t('deletePackageError', { packageId, error: message }));
|
|
362
387
|
}
|
|
363
388
|
},
|
|
364
389
|
};
|