@blocklet/meta 1.16.21-beta-7b40ffb4 → 1.16.21-beta-420f105a
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/blocklet.d.ts +7 -4
- package/lib/blocklet.js +15 -8
- package/lib/schema.d.ts +3 -1
- package/lib/schema.js +20 -1
- package/lib/types/schema.d.ts +14 -1
- package/lib/util.d.ts +11 -3
- package/lib/util.js +9 -7
- package/package.json +4 -4
package/lib/blocklet.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { BlockletState
|
|
1
|
+
import type { BlockletState } from '@abtnode/client';
|
|
2
2
|
type TComponentInternalInfo = {
|
|
3
3
|
title: string;
|
|
4
4
|
did: string;
|
|
@@ -8,12 +8,15 @@ type TComponentInternalInfo = {
|
|
|
8
8
|
status?: number;
|
|
9
9
|
port?: number;
|
|
10
10
|
resources?: string[];
|
|
11
|
+
resourcesV2?: {
|
|
12
|
+
path: string;
|
|
13
|
+
public?: boolean;
|
|
14
|
+
}[];
|
|
15
|
+
group?: string;
|
|
11
16
|
};
|
|
12
|
-
declare const getComponentResourcesPath: (component: ComponentState) => string[];
|
|
13
17
|
declare const getComponentsInternalInfo: (app: BlockletState) => Array<TComponentInternalInfo>;
|
|
14
|
-
export { getComponentsInternalInfo,
|
|
18
|
+
export { getComponentsInternalInfo, TComponentInternalInfo };
|
|
15
19
|
declare const _default: {
|
|
16
20
|
getComponentsInternalInfo: (app: BlockletState) => TComponentInternalInfo[];
|
|
17
|
-
getComponentResourcesPath: (component: ComponentState) => string[];
|
|
18
21
|
};
|
|
19
22
|
export default _default;
|
package/lib/blocklet.js
CHANGED
|
@@ -3,26 +3,32 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.getComponentsInternalInfo = void 0;
|
|
7
7
|
const path_1 = __importDefault(require("path"));
|
|
8
|
+
const constant_1 = require("@blocklet/constant");
|
|
8
9
|
const util_1 = require("./util");
|
|
10
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
9
11
|
const getComponentResourcesPath = (component) => {
|
|
12
|
+
return [];
|
|
13
|
+
};
|
|
14
|
+
const getComponentResourcesPathV2 = (component) => {
|
|
10
15
|
const appDir = (component.environments || []).find((y) => y.key === 'BLOCKLET_APP_DIR')?.value;
|
|
11
16
|
if (!appDir) {
|
|
12
17
|
return [];
|
|
13
18
|
}
|
|
14
|
-
|
|
19
|
+
const resourceDir = path_1.default.join(appDir, constant_1.BLOCKLET_RESOURCE_DIR);
|
|
20
|
+
return (component.meta?.resource?.bundles || [])
|
|
15
21
|
.map((y) => {
|
|
16
|
-
const
|
|
17
|
-
|
|
22
|
+
const { did, type, public: isPublic } = y;
|
|
23
|
+
const res = path_1.default.join(resourceDir, did, type);
|
|
24
|
+
if (!res.startsWith(resourceDir)) {
|
|
18
25
|
// Invalid resource path
|
|
19
|
-
return
|
|
26
|
+
return null;
|
|
20
27
|
}
|
|
21
|
-
return res;
|
|
28
|
+
return { path: res, public: isPublic };
|
|
22
29
|
})
|
|
23
30
|
.filter(Boolean);
|
|
24
31
|
};
|
|
25
|
-
exports.getComponentResourcesPath = getComponentResourcesPath;
|
|
26
32
|
const getComponentsInternalInfo = (app) => {
|
|
27
33
|
const components = [];
|
|
28
34
|
if (!app) {
|
|
@@ -38,6 +44,8 @@ const getComponentsInternalInfo = (app) => {
|
|
|
38
44
|
status: x.status,
|
|
39
45
|
port: 0,
|
|
40
46
|
resources: getComponentResourcesPath(x),
|
|
47
|
+
resourcesV2: getComponentResourcesPathV2(x),
|
|
48
|
+
group: x.meta.group,
|
|
41
49
|
};
|
|
42
50
|
const webInterface = (0, util_1.findWebInterface)(x);
|
|
43
51
|
if (webInterface && (x.environments || []).find((y) => y.key === webInterface.port)) {
|
|
@@ -50,5 +58,4 @@ const getComponentsInternalInfo = (app) => {
|
|
|
50
58
|
exports.getComponentsInternalInfo = getComponentsInternalInfo;
|
|
51
59
|
exports.default = {
|
|
52
60
|
getComponentsInternalInfo,
|
|
53
|
-
getComponentResourcesPath,
|
|
54
61
|
};
|
package/lib/schema.d.ts
CHANGED
|
@@ -25,6 +25,7 @@ declare const navigationItemSchema: JOI.ObjectSchema<any>;
|
|
|
25
25
|
declare const navigationSchema: JOI.ArraySchema<any[]>;
|
|
26
26
|
declare const themeSchema: JOI.ObjectSchema<any>;
|
|
27
27
|
declare const authConfigSchema: JOI.ObjectSchema<any>;
|
|
28
|
+
declare const resourceBundleSchema: JOI.ObjectSchema<any>;
|
|
28
29
|
declare const blockletMetaSchema: JOI.ObjectSchema<any>;
|
|
29
30
|
declare const createBlockletSchema: (baseDir: string, { ensureFiles, ensureDist, ensureComponentStore, ensureName, skipValidateDidName, ...schemaOptions }?: {
|
|
30
31
|
ensureFiles?: boolean;
|
|
@@ -33,7 +34,7 @@ declare const createBlockletSchema: (baseDir: string, { ensureFiles, ensureDist,
|
|
|
33
34
|
ensureName?: boolean;
|
|
34
35
|
skipValidateDidName?: boolean;
|
|
35
36
|
}) => JOI.ObjectSchema;
|
|
36
|
-
export { blockletMetaSchema, blockletNameSchema, componentSchema, createBlockletSchema, descriptionSchema, distSchema, endpointSchema, engineSchema, environmentSchema, environmentNameSchema, interfaceSchema, logoSchema, mountPointSchema, updateMountPointSchema, navigationItemSchema, navigationSchema, personSchema, scriptsSchema, serviceSchema, signatureSchema, themeSchema, titleSchema, statsSchema, cacheableSchema, authConfigSchema, Joi, };
|
|
37
|
+
export { blockletMetaSchema, blockletNameSchema, componentSchema, createBlockletSchema, descriptionSchema, distSchema, endpointSchema, engineSchema, environmentSchema, environmentNameSchema, interfaceSchema, logoSchema, mountPointSchema, updateMountPointSchema, navigationItemSchema, navigationSchema, personSchema, scriptsSchema, serviceSchema, signatureSchema, themeSchema, titleSchema, statsSchema, cacheableSchema, authConfigSchema, resourceBundleSchema, Joi, };
|
|
37
38
|
declare const _default: {
|
|
38
39
|
blockletNameSchema: JOI.StringSchema<string>;
|
|
39
40
|
componentSchema: JOI.ObjectSchema<any>;
|
|
@@ -60,6 +61,7 @@ declare const _default: {
|
|
|
60
61
|
mountPointSchema: JOI.StringSchema<string>;
|
|
61
62
|
updateMountPointSchema: JOI.StringSchema<string>;
|
|
62
63
|
authConfigSchema: JOI.ObjectSchema<any>;
|
|
64
|
+
resourceBundleSchema: JOI.ObjectSchema<any>;
|
|
63
65
|
Joi: JOI.Root & {
|
|
64
66
|
[key: string]: Function;
|
|
65
67
|
};
|
package/lib/schema.js
CHANGED
|
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
26
26
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
27
|
};
|
|
28
28
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
|
-
exports.Joi = exports.authConfigSchema = exports.cacheableSchema = exports.statsSchema = exports.titleSchema = exports.themeSchema = exports.signatureSchema = exports.serviceSchema = exports.scriptsSchema = exports.personSchema = exports.navigationSchema = exports.navigationItemSchema = exports.updateMountPointSchema = exports.mountPointSchema = exports.logoSchema = exports.interfaceSchema = exports.environmentNameSchema = exports.environmentSchema = exports.engineSchema = exports.endpointSchema = exports.distSchema = exports.descriptionSchema = exports.createBlockletSchema = exports.componentSchema = exports.blockletNameSchema = exports.blockletMetaSchema = void 0;
|
|
29
|
+
exports.Joi = exports.resourceBundleSchema = exports.authConfigSchema = exports.cacheableSchema = exports.statsSchema = exports.titleSchema = exports.themeSchema = exports.signatureSchema = exports.serviceSchema = exports.scriptsSchema = exports.personSchema = exports.navigationSchema = exports.navigationItemSchema = exports.updateMountPointSchema = exports.mountPointSchema = exports.logoSchema = exports.interfaceSchema = exports.environmentNameSchema = exports.environmentSchema = exports.engineSchema = exports.endpointSchema = exports.distSchema = exports.descriptionSchema = exports.createBlockletSchema = exports.componentSchema = exports.blockletNameSchema = exports.blockletMetaSchema = void 0;
|
|
30
30
|
const fs_1 = __importDefault(require("fs"));
|
|
31
31
|
const joi_1 = __importDefault(require("joi"));
|
|
32
32
|
const cjk_length_1 = __importDefault(require("cjk-length"));
|
|
@@ -467,6 +467,19 @@ const authConfigSchema = Joi.object({
|
|
|
467
467
|
unknownType: 'any',
|
|
468
468
|
});
|
|
469
469
|
exports.authConfigSchema = authConfigSchema;
|
|
470
|
+
const resourceTypeSchema = Joi.object({
|
|
471
|
+
type: Joi.string().trim().min(1).required(),
|
|
472
|
+
description: Joi.string().trim().min(1),
|
|
473
|
+
});
|
|
474
|
+
const resourceBundleSchema = Joi.object({
|
|
475
|
+
did: Joi.DID().trim().required(),
|
|
476
|
+
type: Joi.string().trim().min(1).required(),
|
|
477
|
+
public: Joi.boolean(),
|
|
478
|
+
}).meta({
|
|
479
|
+
className: 'TResourceBundle',
|
|
480
|
+
unknownType: 'any',
|
|
481
|
+
});
|
|
482
|
+
exports.resourceBundleSchema = resourceBundleSchema;
|
|
470
483
|
const blockletMetaProps = {
|
|
471
484
|
did: Joi.DID().trim().required(),
|
|
472
485
|
version: Joi.semver().valid().required(),
|
|
@@ -636,6 +649,11 @@ const blockletMetaProps = {
|
|
|
636
649
|
// Other contents to be included in the bundle
|
|
637
650
|
files: Joi.array().items(Joi.string().trim()).optional(),
|
|
638
651
|
resources: Joi.array().items(Joi.string().trim().required()),
|
|
652
|
+
resource: Joi.object({
|
|
653
|
+
exportApi: Joi.string().trim(),
|
|
654
|
+
bundles: Joi.array().items(resourceBundleSchema),
|
|
655
|
+
types: Joi.array().items(resourceTypeSchema).max(10),
|
|
656
|
+
}),
|
|
639
657
|
// TODO: this field should be refactored in future version
|
|
640
658
|
engine: Joi.alternatives().try(engineSchema, Joi.array().items(engineSchema)).optional(),
|
|
641
659
|
// NOTE: following fields are appended by registry or bundling process
|
|
@@ -741,5 +759,6 @@ exports.default = {
|
|
|
741
759
|
mountPointSchema,
|
|
742
760
|
updateMountPointSchema,
|
|
743
761
|
authConfigSchema,
|
|
762
|
+
resourceBundleSchema,
|
|
744
763
|
Joi,
|
|
745
764
|
};
|
package/lib/types/schema.d.ts
CHANGED
|
@@ -47,7 +47,7 @@ export interface TBlockletMeta {
|
|
|
47
47
|
environments?: TEnvironment[];
|
|
48
48
|
files?: string[];
|
|
49
49
|
gitHash?: string;
|
|
50
|
-
group?: 'dapp' | 'static' | 'gateway';
|
|
50
|
+
group?: 'dapp' | 'static' | 'gateway' | 'pack';
|
|
51
51
|
homepage?: string;
|
|
52
52
|
htmlAst?: any;
|
|
53
53
|
interfaces?: TInterface[];
|
|
@@ -96,6 +96,14 @@ export interface TBlockletMeta {
|
|
|
96
96
|
os?: '*' | 'aix' | 'darwin' | 'freebsd' | 'linux' | 'openbsd' | 'sunos' | 'win32' | ('aix' | 'darwin' | 'freebsd' | 'linux' | 'openbsd' | 'sunos' | 'win32')[];
|
|
97
97
|
server?: string;
|
|
98
98
|
};
|
|
99
|
+
resource?: {
|
|
100
|
+
bundles?: TResourceBundle[];
|
|
101
|
+
exportApi?: string;
|
|
102
|
+
types?: {
|
|
103
|
+
description?: string;
|
|
104
|
+
type: string;
|
|
105
|
+
}[];
|
|
106
|
+
};
|
|
99
107
|
resources?: string[];
|
|
100
108
|
screenshots?: string[];
|
|
101
109
|
scripts?: TScripts;
|
|
@@ -240,6 +248,11 @@ export interface TPerson {
|
|
|
240
248
|
name: string;
|
|
241
249
|
url?: string;
|
|
242
250
|
}
|
|
251
|
+
export interface TResourceBundle {
|
|
252
|
+
did: string;
|
|
253
|
+
public?: boolean;
|
|
254
|
+
type: string;
|
|
255
|
+
}
|
|
243
256
|
export interface TScripts {
|
|
244
257
|
dev?: string;
|
|
245
258
|
e2eDev?: string;
|
package/lib/util.d.ts
CHANGED
|
@@ -99,6 +99,7 @@ declare const isFreeComponent: (meta: TBlockletMeta) => boolean;
|
|
|
99
99
|
declare const wipeSensitiveData: (blocklet?: BlockletState) => BlockletState;
|
|
100
100
|
declare const isDeletableBlocklet: (blocklet?: BlockletState) => boolean;
|
|
101
101
|
declare const isGatewayBlocklet: (meta: TBlockletMeta) => boolean;
|
|
102
|
+
declare const isPackBlocklet: (meta: TBlockletMeta) => boolean;
|
|
102
103
|
declare const hasRunnableComponent: (blocklet: BlockletState) => boolean;
|
|
103
104
|
/**
|
|
104
105
|
* 获取 blocklet 的 name
|
|
@@ -147,8 +148,11 @@ declare const isInProgress: (status: string | number) => boolean;
|
|
|
147
148
|
declare const isBeforeInstalled: (status: string | number) => boolean;
|
|
148
149
|
declare const isRunning: (status: string | number) => boolean;
|
|
149
150
|
declare const isAccessible: (status: string | number) => boolean;
|
|
150
|
-
declare const hasResourceType: (component: ComponentState,
|
|
151
|
-
|
|
151
|
+
declare const hasResourceType: (component: ComponentState, { type, did }?: {
|
|
152
|
+
type: string;
|
|
153
|
+
did: string;
|
|
154
|
+
}) => boolean;
|
|
155
|
+
export { isFreeBlocklet, isFreeComponent, forEachBlocklet, forEachBlockletSync, forEachChild, forEachChildSync, forEachComponentV2, forEachComponentV2Sync, isDeletableBlocklet, getSharedConfigObj, getAppMissingConfigs, getComponentMissingConfigs, isEnvShareableToClient, isEnvShareable, wipeSensitiveData, hasRunnableComponent, getAppName, getAppName as getDisplayName, getAppDescription, fixBlockletStatus, findWebInterface, findWebInterfacePort, findServiceFromMeta, getWhoCanAccess, getComponentWhoCanAccess, replaceSlotToIp, getComponentId, getComponentName, getComponentBundleId, findComponent, findComponentById, findComponentV2, findComponentByIdV2, filterComponentsV2, getParentComponentName, getConnectAppUrl, getChainInfo, getBlockletChainInfo, isExternalBlocklet, isPreferenceKey, getRolesFromAuthConfig, getBlockletAppIdList, getBlockletServices, isInProgress, isBeforeInstalled, isRunning, isAccessible, isGatewayBlocklet, isPackBlocklet, hasStartEngine, hasResourceType, };
|
|
152
156
|
declare const _default: {
|
|
153
157
|
isFreeBlocklet: (meta: TBlockletMeta) => boolean;
|
|
154
158
|
isFreeComponent: (meta: TBlockletMeta) => boolean;
|
|
@@ -256,7 +260,11 @@ declare const _default: {
|
|
|
256
260
|
isRunning: (status: string | number) => boolean;
|
|
257
261
|
isAccessible: (status: string | number) => boolean;
|
|
258
262
|
isGatewayBlocklet: (meta: TBlockletMeta) => boolean;
|
|
263
|
+
isPackBlocklet: (meta: TBlockletMeta) => boolean;
|
|
259
264
|
hasStartEngine: (meta: TBlockletMeta | import("@abtnode/client").BlockletMeta) => boolean;
|
|
260
|
-
hasResourceType: (component: ComponentState,
|
|
265
|
+
hasResourceType: (component: ComponentState, { type, did }?: {
|
|
266
|
+
type: string;
|
|
267
|
+
did: string;
|
|
268
|
+
}) => boolean;
|
|
261
269
|
};
|
|
262
270
|
export default _default;
|
package/lib/util.js
CHANGED
|
@@ -3,7 +3,8 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
6
|
+
exports.hasStartEngine = exports.isPackBlocklet = exports.isGatewayBlocklet = exports.isAccessible = exports.isRunning = exports.isBeforeInstalled = exports.isInProgress = exports.getBlockletServices = exports.getBlockletAppIdList = exports.getRolesFromAuthConfig = exports.isPreferenceKey = exports.isExternalBlocklet = exports.getBlockletChainInfo = exports.getChainInfo = exports.getConnectAppUrl = exports.getParentComponentName = exports.filterComponentsV2 = exports.findComponentByIdV2 = exports.findComponentV2 = exports.findComponentById = exports.findComponent = exports.getComponentBundleId = exports.getComponentName = exports.getComponentId = exports.replaceSlotToIp = exports.getComponentWhoCanAccess = exports.getWhoCanAccess = exports.findServiceFromMeta = exports.findWebInterfacePort = exports.findWebInterface = exports.fixBlockletStatus = exports.getAppDescription = exports.getDisplayName = exports.getAppName = exports.hasRunnableComponent = exports.wipeSensitiveData = exports.isEnvShareable = exports.isEnvShareableToClient = exports.getComponentMissingConfigs = exports.getAppMissingConfigs = exports.getSharedConfigObj = exports.isDeletableBlocklet = exports.forEachComponentV2Sync = exports.forEachComponentV2 = exports.forEachChildSync = exports.forEachChild = exports.forEachBlockletSync = exports.forEachBlocklet = exports.isFreeComponent = exports.isFreeBlocklet = void 0;
|
|
7
|
+
exports.hasResourceType = void 0;
|
|
7
8
|
/* eslint-disable no-await-in-loop */
|
|
8
9
|
const get_1 = __importDefault(require("lodash/get"));
|
|
9
10
|
const uniq_1 = __importDefault(require("lodash/uniq"));
|
|
@@ -417,10 +418,10 @@ const isDeletableBlocklet = (blocklet) => {
|
|
|
417
418
|
return config.value === 'yes';
|
|
418
419
|
};
|
|
419
420
|
exports.isDeletableBlocklet = isDeletableBlocklet;
|
|
420
|
-
const isGatewayBlocklet = (meta) =>
|
|
421
|
-
// @ts-ignore
|
|
422
|
-
meta?.group === constant_2.BlockletGroup.gateway || meta?.group === 'gateway';
|
|
421
|
+
const isGatewayBlocklet = (meta) => meta?.group === constant_2.BlockletGroup.gateway;
|
|
423
422
|
exports.isGatewayBlocklet = isGatewayBlocklet;
|
|
423
|
+
const isPackBlocklet = (meta) => meta?.group === constant_2.BlockletGroup.pack;
|
|
424
|
+
exports.isPackBlocklet = isPackBlocklet;
|
|
424
425
|
const hasRunnableComponent = (blocklet) => {
|
|
425
426
|
let has = false;
|
|
426
427
|
forEachBlockletSync(blocklet, (x) => {
|
|
@@ -690,13 +691,13 @@ const isAccessible = (status) => [
|
|
|
690
691
|
'downloading',
|
|
691
692
|
].includes(status);
|
|
692
693
|
exports.isAccessible = isAccessible;
|
|
693
|
-
const hasResourceType = (component,
|
|
694
|
+
const hasResourceType = (component, { type, did } = { type: '', did: '' }) => {
|
|
694
695
|
if (!component) {
|
|
695
696
|
return false;
|
|
696
697
|
}
|
|
697
698
|
return (!(0, has_start_engine_1.default)(component.meta) &&
|
|
698
|
-
component.meta?.
|
|
699
|
-
(
|
|
699
|
+
component.meta?.resource?.bundles?.length > 0 &&
|
|
700
|
+
(component.meta.resource.bundles || []).some((y) => y.type === type && y.did === did));
|
|
700
701
|
};
|
|
701
702
|
exports.hasResourceType = hasResourceType;
|
|
702
703
|
exports.default = {
|
|
@@ -747,6 +748,7 @@ exports.default = {
|
|
|
747
748
|
isRunning,
|
|
748
749
|
isAccessible,
|
|
749
750
|
isGatewayBlocklet,
|
|
751
|
+
isPackBlocklet,
|
|
750
752
|
hasStartEngine: has_start_engine_1.default,
|
|
751
753
|
hasResourceType,
|
|
752
754
|
};
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.16.21-beta-
|
|
6
|
+
"version": "1.16.21-beta-420f105a",
|
|
7
7
|
"description": "Library to parse/validate/fix blocklet meta",
|
|
8
8
|
"main": "./lib/index.js",
|
|
9
9
|
"typings": "./lib/index.d.ts",
|
|
@@ -24,12 +24,12 @@
|
|
|
24
24
|
"author": "wangshijun <wangshijun2020@gmail.com> (http://github.com/wangshijun)",
|
|
25
25
|
"license": "Apache-2.0",
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@abtnode/constant": "1.16.21-beta-
|
|
27
|
+
"@abtnode/constant": "1.16.21-beta-420f105a",
|
|
28
28
|
"@arcblock/did": "1.18.107",
|
|
29
29
|
"@arcblock/did-ext": "1.18.107",
|
|
30
30
|
"@arcblock/did-util": "1.18.107",
|
|
31
31
|
"@arcblock/jwt": "1.18.107",
|
|
32
|
-
"@blocklet/constant": "1.16.21-beta-
|
|
32
|
+
"@blocklet/constant": "1.16.21-beta-420f105a",
|
|
33
33
|
"@ocap/asset": "1.18.107",
|
|
34
34
|
"@ocap/mcrypto": "1.18.107",
|
|
35
35
|
"@ocap/types": "1.18.107",
|
|
@@ -78,5 +78,5 @@
|
|
|
78
78
|
"ts-node": "^10.9.1",
|
|
79
79
|
"typescript": "^5.0.4"
|
|
80
80
|
},
|
|
81
|
-
"gitHead": "
|
|
81
|
+
"gitHead": "f38219e9051563984543127087d6d88fc8b1be98"
|
|
82
82
|
}
|