@blocklet/meta 1.8.33 → 1.8.35
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/channel.d.ts +27 -0
- package/lib/channel.js +32 -32
- package/lib/constants.d.ts +2 -0
- package/lib/constants.js +6 -3
- package/lib/did.d.ts +10 -0
- package/lib/did.js +18 -24
- package/lib/engine.d.ts +7 -0
- package/lib/engine.js +21 -25
- package/lib/entry.d.ts +3 -0
- package/lib/entry.js +51 -64
- package/lib/extension.d.ts +10 -0
- package/lib/extension.js +78 -77
- package/lib/file.d.ts +21 -0
- package/lib/file.js +44 -39
- package/lib/fix.d.ts +33 -0
- package/lib/fix.js +218 -208
- package/lib/get-component-process-id.d.ts +5 -0
- package/lib/get-component-process-id.js +13 -14
- package/lib/has-reserved-key.d.ts +3 -0
- package/lib/has-reserved-key.js +10 -9
- package/lib/index.d.ts +82 -0
- package/lib/index.js +51 -34
- package/lib/info.d.ts +13 -0
- package/lib/info.js +58 -60
- package/lib/name.d.ts +5 -0
- package/lib/name.js +14 -7
- package/lib/nft-templates.d.ts +86 -0
- package/lib/nft-templates.js +47 -42
- package/lib/parse-navigation.d.ts +3 -0
- package/lib/parse-navigation.js +168 -209
- package/lib/parse.d.ts +22 -0
- package/lib/parse.js +71 -82
- package/lib/payment/index.d.ts +254 -0
- package/lib/payment/index.js +13 -6
- package/lib/payment/v1.d.ts +185 -0
- package/lib/payment/v1.js +80 -81
- package/lib/payment/v2.d.ts +242 -0
- package/lib/payment/v2.js +453 -531
- package/lib/schema.d.ts +50 -0
- package/lib/schema.js +405 -397
- package/lib/service-configs/auth.json +61 -61
- package/lib/service.d.ts +26 -0
- package/lib/service.js +69 -85
- package/lib/types/index.d.ts +1 -0
- package/lib/types/index.js +18 -0
- package/lib/types/schema.d.ts +241 -0
- package/lib/types/schema.js +3 -0
- package/lib/util-meta.d.ts +42 -0
- package/lib/util-meta.js +138 -158
- package/lib/util.d.ts +185 -0
- package/lib/util.js +359 -414
- package/lib/validate.d.ts +10 -0
- package/lib/validate.js +28 -34
- package/lib/verify-multi-sig.d.ts +3 -0
- package/lib/verify-multi-sig.js +94 -101
- package/lib/wallet.d.ts +9 -0
- package/lib/wallet.js +17 -27
- package/package.json +41 -18
package/lib/schema.js
CHANGED
|
@@ -1,526 +1,534 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.statsSchema = exports.titleSchema = exports.themeSchema = exports.signatureSchema = exports.serviceSchema = exports.scriptsSchema = exports.personSchema = exports.navigationSchema = exports.navigationItemSchema = exports.mountPointSchema = exports.logoSchema = exports.interfaceSchema = exports.environmentSchema = exports.engineSchema = exports.endpointSchema = exports.distSchema = exports.descriptionSchema = exports.createBlockletSchema = exports.componentSchema = exports.blockletNameSchema = exports.blockletMetaSchema = void 0;
|
|
18
|
+
const fs_1 = __importDefault(require("fs"));
|
|
19
|
+
const joi_1 = __importDefault(require("joi"));
|
|
20
|
+
// eslint-disable-next-line import/no-named-default
|
|
21
|
+
const cjk_length_1 = __importDefault(require("cjk-length"));
|
|
22
|
+
const is_glob_1 = __importDefault(require("is-glob"));
|
|
23
|
+
const joi_extension_semver_1 = require("joi-extension-semver");
|
|
24
|
+
const extension_1 = require("./extension");
|
|
25
|
+
const name_1 = require("./name");
|
|
26
|
+
const constants_1 = __importDefault(require("./constants"));
|
|
27
|
+
const cjkLength = cjk_length_1.default.default;
|
|
28
|
+
const { BLOCKLET_GROUPS, BLOCKLET_PLATFORMS, BLOCKLET_ARCHITECTURES, BLOCKLET_INTERFACE_TYPES, BLOCKLET_INTERFACE_PROTOCOLS, BLOCKLET_ENTRY_FILE, BLOCKLET_BUNDLE_FILE, BLOCKLET_DEFAULT_PORT_NAME, BLOCKLET_DYNAMIC_PATH_PREFIX, BlockletGroup, BLOCKLET_LATEST_REQUIREMENT_SERVER, BLOCKLET_INTERFACE_TYPE_WEB, BLOCKLET_INTERFACE_TYPE_WELLKNOWN, BLOCKLET_APP_STORAGE_ENDPOINTS, } = constants_1.default;
|
|
26
29
|
const WELLKNOWN_PATH_PREFIX = '/.well-known';
|
|
27
30
|
const MAX_TITLE_LENGTH = 24;
|
|
28
31
|
const MAX_NAME_LENGTH = 32;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
const Joi = joi_1.default.extend(joi_extension_semver_1.semver)
|
|
33
|
+
.extend(joi_extension_semver_1.semverRange)
|
|
34
|
+
.extend(extension_1.fileExtension)
|
|
35
|
+
.extend(extension_1.didExtension);
|
|
32
36
|
const titleSchema = Joi.string()
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
37
|
+
.trim()
|
|
38
|
+
.min(1)
|
|
39
|
+
.custom((value) => {
|
|
36
40
|
if (cjkLength(value) > MAX_TITLE_LENGTH) {
|
|
37
|
-
|
|
38
|
-
`title length should not exceed ${MAX_TITLE_LENGTH} (see: https://www.npmjs.com/package/cjk-length)`
|
|
39
|
-
);
|
|
41
|
+
throw new Error(`title length should not exceed ${MAX_TITLE_LENGTH} (see: https://www.npmjs.com/package/cjk-length)`);
|
|
40
42
|
}
|
|
41
|
-
|
|
42
43
|
return value;
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
})
|
|
45
|
+
.meta({ className: 'TTitle' });
|
|
46
|
+
exports.titleSchema = titleSchema;
|
|
47
|
+
const descriptionSchema = Joi.string().trim().min(3).max(160).meta({ className: 'TDescription' });
|
|
48
|
+
exports.descriptionSchema = descriptionSchema;
|
|
45
49
|
const logoSchema = Joi.string()
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
.uri({ scheme: ['http', 'https'], allowRelative: true })
|
|
51
|
+
.allow('')
|
|
52
|
+
.meta({ className: 'TLogo' });
|
|
53
|
+
exports.logoSchema = logoSchema;
|
|
54
|
+
const mountPointSchema = Joi.string().trim().min(1).meta({ className: 'TMountPoint' });
|
|
55
|
+
exports.mountPointSchema = mountPointSchema;
|
|
50
56
|
const blockletNameSchema = Joi.string()
|
|
51
|
-
|
|
52
|
-
validateName(value);
|
|
57
|
+
.custom((value) => {
|
|
58
|
+
(0, name_1.validateName)(value);
|
|
53
59
|
return value;
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
60
|
+
})
|
|
61
|
+
.max(MAX_NAME_LENGTH)
|
|
62
|
+
.meta({ className: 'TBlockletName' });
|
|
63
|
+
exports.blockletNameSchema = blockletNameSchema;
|
|
57
64
|
const environmentSchema = Joi.object({
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
})
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
name: Joi.string().trim().required(),
|
|
66
|
+
description: Joi.string().trim().required(),
|
|
67
|
+
default: Joi.string().optional().allow('').default(''),
|
|
68
|
+
required: Joi.boolean().default(false),
|
|
69
|
+
secure: Joi.boolean().default(false),
|
|
70
|
+
validation: Joi.string().optional(),
|
|
71
|
+
shared: Joi.boolean().default((parent) => !parent.secure),
|
|
72
|
+
})
|
|
73
|
+
.custom((x, helper) => {
|
|
74
|
+
if (x.secure && x.default) {
|
|
75
|
+
// @ts-expect-error
|
|
76
|
+
return helper.message(`Cannot declare default value for secure env ${x.name}`);
|
|
77
|
+
}
|
|
78
|
+
return x;
|
|
79
|
+
})
|
|
80
|
+
.meta({
|
|
81
|
+
className: 'TEnvironment',
|
|
82
|
+
unknownType: 'any',
|
|
71
83
|
});
|
|
72
|
-
|
|
84
|
+
exports.environmentSchema = environmentSchema;
|
|
73
85
|
const scriptsSchema = Joi.object({
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
86
|
+
dev: Joi.string().trim().min(1),
|
|
87
|
+
e2eDev: Joi.string().trim().min(1),
|
|
88
|
+
preInstall: Joi.string().trim().min(1),
|
|
89
|
+
postInstall: Joi.string().trim().min(1),
|
|
90
|
+
preStart: Joi.string().trim().min(1),
|
|
91
|
+
postStart: Joi.string().trim().min(1),
|
|
92
|
+
preStop: Joi.string().trim().min(1),
|
|
93
|
+
preUninstall: Joi.string().trim().min(1),
|
|
94
|
+
preConfig: Joi.string().trim().min(1),
|
|
83
95
|
})
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
96
|
+
.rename('pre-install', 'preInstall')
|
|
97
|
+
.rename('post-install', 'postInstall')
|
|
98
|
+
.rename('pre-start', 'preStart')
|
|
99
|
+
.rename('post-start', 'postStart')
|
|
100
|
+
.rename('pre-stop', 'preStop')
|
|
101
|
+
.rename('pre-uninstall', 'preUninstall')
|
|
102
|
+
.rename('pre-config', 'preConfig')
|
|
103
|
+
.optional()
|
|
104
|
+
.meta({
|
|
105
|
+
className: 'TScripts',
|
|
106
|
+
unknownType: 'any',
|
|
107
|
+
});
|
|
108
|
+
exports.scriptsSchema = scriptsSchema;
|
|
93
109
|
// Different services have different config schema
|
|
94
110
|
// - Auth: https://github.com/ArcBlock/abtnode-docs/blob/master/src/developer/auth-service/index.md
|
|
95
111
|
const serviceSchema = Joi.object({
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
})
|
|
99
|
-
|
|
112
|
+
name: Joi.string().required().trim(),
|
|
113
|
+
config: Joi.object().optional().default({}),
|
|
114
|
+
})
|
|
115
|
+
.unknown(true)
|
|
116
|
+
.meta({
|
|
117
|
+
className: 'TService',
|
|
118
|
+
unknownType: 'any',
|
|
119
|
+
});
|
|
120
|
+
exports.serviceSchema = serviceSchema;
|
|
100
121
|
const endpointSchema = Joi.object({
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
122
|
+
type: Joi.string().trim(true).min(1).required(),
|
|
123
|
+
path: Joi.string().required(),
|
|
124
|
+
meta: Joi.object({
|
|
125
|
+
vcType: Joi.string(),
|
|
126
|
+
payable: Joi.boolean(),
|
|
127
|
+
params: Joi.array().items({
|
|
128
|
+
name: Joi.string().required().trim(),
|
|
129
|
+
description: Joi.string().required().trim(),
|
|
130
|
+
}),
|
|
109
131
|
}),
|
|
110
|
-
|
|
132
|
+
}).meta({
|
|
133
|
+
className: 'TEndpoint',
|
|
134
|
+
unknownType: 'any',
|
|
111
135
|
});
|
|
112
|
-
|
|
136
|
+
exports.endpointSchema = endpointSchema;
|
|
113
137
|
const interfaceSchema = Joi.object({
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
.
|
|
130
|
-
|
|
131
|
-
.default('http'),
|
|
132
|
-
|
|
133
|
-
// Can be a string or an object
|
|
134
|
-
port: Joi.alternatives()
|
|
135
|
-
.try(
|
|
136
|
-
Joi.string().uppercase().default(BLOCKLET_DEFAULT_PORT_NAME),
|
|
137
|
-
Joi.object({
|
|
138
|
+
type: Joi.string()
|
|
139
|
+
.lowercase()
|
|
140
|
+
.valid(...BLOCKLET_INTERFACE_TYPES)
|
|
141
|
+
.required(),
|
|
142
|
+
// Human readable name of the interface, such as `public_url`
|
|
143
|
+
name: Joi.string().trim().required(),
|
|
144
|
+
// The path where the interface is served from the blocklet
|
|
145
|
+
path: Joi.string().trim().default('/'),
|
|
146
|
+
// `*` means the interface can be mounted at any path prefix
|
|
147
|
+
prefix: Joi.string().trim().min(1).default(BLOCKLET_DYNAMIC_PATH_PREFIX),
|
|
148
|
+
protocol: Joi.string()
|
|
149
|
+
.lowercase()
|
|
150
|
+
.valid(...BLOCKLET_INTERFACE_PROTOCOLS)
|
|
151
|
+
.default('http'),
|
|
152
|
+
// Can be a string or an object
|
|
153
|
+
port: Joi.alternatives()
|
|
154
|
+
.try(Joi.string().uppercase().default(BLOCKLET_DEFAULT_PORT_NAME), Joi.object({
|
|
138
155
|
internal: Joi.string().uppercase().required(),
|
|
139
156
|
external: Joi.number().port().required(),
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
.
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
157
|
+
}))
|
|
158
|
+
.default(BLOCKLET_DEFAULT_PORT_NAME),
|
|
159
|
+
services: Joi.array().items(serviceSchema).unique('name'),
|
|
160
|
+
endpoints: Joi.array().items(endpointSchema).unique('type'),
|
|
161
|
+
}).meta({
|
|
162
|
+
className: 'TInterface',
|
|
163
|
+
unknownType: 'any',
|
|
146
164
|
});
|
|
147
|
-
|
|
165
|
+
exports.interfaceSchema = interfaceSchema;
|
|
148
166
|
const engineSchema = Joi.object({
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
167
|
+
platform: Joi.string()
|
|
168
|
+
.valid(...BLOCKLET_PLATFORMS)
|
|
169
|
+
.optional(),
|
|
170
|
+
interpreter: Joi.string().valid('binary', 'node').default('node'),
|
|
171
|
+
script: Joi.string().required(),
|
|
172
|
+
args: Joi.array().items(Joi.string()).optional().default([]),
|
|
173
|
+
}).meta({
|
|
174
|
+
className: 'TEngine',
|
|
175
|
+
unknownType: 'any',
|
|
155
176
|
});
|
|
156
|
-
|
|
177
|
+
exports.engineSchema = engineSchema;
|
|
157
178
|
const personSchema = Joi.object({
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
179
|
+
name: Joi.string().min(1).required(),
|
|
180
|
+
email: Joi.string().email().optional(),
|
|
181
|
+
url: Joi.string().uri().optional(),
|
|
182
|
+
}).meta({
|
|
183
|
+
className: 'TPerson',
|
|
184
|
+
unknownType: 'any',
|
|
161
185
|
});
|
|
162
|
-
|
|
186
|
+
exports.personSchema = personSchema;
|
|
163
187
|
const distSchema = Joi.object({
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
188
|
+
tarball: Joi.alternatives().try(Joi.string().uri(), Joi.string()).required(),
|
|
189
|
+
integrity: Joi.string().required(),
|
|
190
|
+
size: Joi.number().optional(),
|
|
191
|
+
}).meta({
|
|
192
|
+
className: 'TDist',
|
|
193
|
+
unknownType: 'any',
|
|
167
194
|
});
|
|
168
|
-
|
|
195
|
+
exports.distSchema = distSchema;
|
|
169
196
|
const statsSchema = Joi.object({
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
197
|
+
downloads: Joi.number().integer().greater(-1),
|
|
198
|
+
star: Joi.number().default(0),
|
|
199
|
+
purchases: Joi.number().default(0),
|
|
200
|
+
}).meta({
|
|
201
|
+
className: 'TStats',
|
|
202
|
+
unknownType: 'any',
|
|
173
203
|
});
|
|
174
|
-
|
|
175
|
-
const
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
resolved: Joi.alternatives().try(Joi.string().uri(), Joi.string()), // deprecated
|
|
193
|
-
mountPoints: Joi.array() // deprecated
|
|
194
|
-
.items(
|
|
195
|
-
Joi.object({
|
|
204
|
+
exports.statsSchema = statsSchema;
|
|
205
|
+
const componentSchema = Joi.object({
|
|
206
|
+
name: blockletNameSchema.required(),
|
|
207
|
+
title: titleSchema,
|
|
208
|
+
description: descriptionSchema,
|
|
209
|
+
mountPoint: mountPointSchema,
|
|
210
|
+
services: Joi.array().items(serviceSchema).unique('name'),
|
|
211
|
+
source: Joi.alternatives().try(Joi.object({
|
|
212
|
+
url: Joi.alternatives().try(Joi.string().uri(), Joi.array().items(Joi.string().uri()).min(1)).required(),
|
|
213
|
+
}), Joi.object({
|
|
214
|
+
store: Joi.alternatives().try(Joi.string().uri(), Joi.array().items(Joi.string().uri()).min(1)).required(),
|
|
215
|
+
name: blockletNameSchema.required(),
|
|
216
|
+
// TODO 目前只能支持锁死的版本号,接下载需要支持自适应的版本号,比如 4.x
|
|
217
|
+
version: Joi.alternatives().try(Joi.string().valid('latest'), Joi.semver().valid()).default('latest'),
|
|
218
|
+
})),
|
|
219
|
+
resolved: Joi.alternatives().try(Joi.string().uri(), Joi.string()),
|
|
220
|
+
mountPoints: Joi.array() // deprecated
|
|
221
|
+
.items(Joi.object({
|
|
196
222
|
root: Joi.object({
|
|
197
|
-
|
|
198
|
-
|
|
223
|
+
interfaceName: Joi.string().trim().required(),
|
|
224
|
+
prefix: Joi.string().trim().min(1).required(),
|
|
199
225
|
}).required(),
|
|
200
226
|
child: Joi.object({
|
|
201
|
-
|
|
227
|
+
interfaceName: Joi.string().trim().required(),
|
|
202
228
|
}).required(),
|
|
203
229
|
services: Joi.array().items(serviceSchema).unique('name'),
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
230
|
+
}))
|
|
231
|
+
.optional(),
|
|
232
|
+
})
|
|
233
|
+
.custom((value, helper) => {
|
|
234
|
+
if (!value.mountPoint && (!value.mountPoints || !value.mountPoints.length)) {
|
|
235
|
+
// @ts-expect-error
|
|
236
|
+
return helper.message('child mountPoint is required');
|
|
237
|
+
}
|
|
238
|
+
if (!value.source && !value.resolved) {
|
|
239
|
+
// @ts-expect-error
|
|
240
|
+
return helper.message('child source is required');
|
|
241
|
+
}
|
|
242
|
+
return value;
|
|
243
|
+
})
|
|
244
|
+
.meta({
|
|
245
|
+
className: 'TComponent',
|
|
246
|
+
unknownType: 'any',
|
|
217
247
|
});
|
|
218
|
-
|
|
248
|
+
exports.componentSchema = componentSchema;
|
|
219
249
|
const signatureSchema = Joi.object({
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
250
|
+
type: Joi.string().required(),
|
|
251
|
+
name: Joi.string().required(),
|
|
252
|
+
signer: Joi.string().required(),
|
|
253
|
+
pk: Joi.string().required(),
|
|
254
|
+
created: Joi.string().isoDate().required(),
|
|
255
|
+
sig: Joi.string().required(),
|
|
256
|
+
excludes: Joi.array().items(Joi.string()).optional(),
|
|
257
|
+
appended: Joi.array().items(Joi.string()).optional(),
|
|
258
|
+
// delegation token 校验所需字段
|
|
259
|
+
delegatee: Joi.string(),
|
|
260
|
+
delegateePk: Joi.string(),
|
|
261
|
+
delegation: Joi.string(),
|
|
262
|
+
}).meta({
|
|
263
|
+
className: 'TSignature',
|
|
264
|
+
unknownType: 'any',
|
|
232
265
|
});
|
|
233
|
-
|
|
234
|
-
const
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
266
|
+
exports.signatureSchema = signatureSchema;
|
|
267
|
+
const navigationItemProps = {
|
|
268
|
+
title: Joi.alternatives()
|
|
269
|
+
.try(Joi.string(), Joi.object({
|
|
270
|
+
zh: Joi.string(),
|
|
271
|
+
en: Joi.string(),
|
|
272
|
+
}).min(1))
|
|
273
|
+
.required(),
|
|
274
|
+
link: Joi.alternatives().try(Joi.string(), Joi.object({
|
|
239
275
|
zh: Joi.string(),
|
|
240
276
|
en: Joi.string(),
|
|
241
|
-
|
|
242
|
-
)
|
|
243
|
-
.
|
|
244
|
-
|
|
245
|
-
Joi.string(),
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
items: Joi.array().items(navigationItemSchema),
|
|
260
|
-
})
|
|
261
|
-
);
|
|
262
|
-
|
|
277
|
+
}).min(1)),
|
|
278
|
+
component: Joi.string().min(1),
|
|
279
|
+
section: Joi.array().items(Joi.string().min(1)).single(),
|
|
280
|
+
role: Joi.array().items(Joi.string().min(1)).single(),
|
|
281
|
+
icon: Joi.string().min(1),
|
|
282
|
+
};
|
|
283
|
+
const navigationItemSchema = Joi.object(Object.assign(Object.assign({}, navigationItemProps), { items: Joi.array().items(Joi.object(Object.assign({}, navigationItemProps)).rename('child', 'component')) }))
|
|
284
|
+
.rename('child', 'component')
|
|
285
|
+
.meta({
|
|
286
|
+
className: 'TNavigationItem',
|
|
287
|
+
unknownType: 'any',
|
|
288
|
+
});
|
|
289
|
+
exports.navigationItemSchema = navigationItemSchema;
|
|
290
|
+
const navigationSchema = Joi.array().items(navigationItemSchema).meta({
|
|
291
|
+
className: 'TNavigation',
|
|
292
|
+
unknownType: 'any',
|
|
293
|
+
});
|
|
294
|
+
exports.navigationSchema = navigationSchema;
|
|
263
295
|
const themeSchema = Joi.object({
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
296
|
+
background: Joi.alternatives().try(Joi.string().min(1), Joi.object({
|
|
297
|
+
header: Joi.string().min(1),
|
|
298
|
+
footer: Joi.string().min(1),
|
|
299
|
+
default: Joi.string().min(1),
|
|
300
|
+
}).min(1)),
|
|
301
|
+
}).meta({
|
|
302
|
+
className: 'TTheme',
|
|
303
|
+
unknownType: 'any',
|
|
272
304
|
});
|
|
273
|
-
|
|
274
|
-
const
|
|
275
|
-
baseDir,
|
|
276
|
-
{ ensureMain = false, ensureFiles = false, ensureDist = false, ...schemaOptions } = {}
|
|
277
|
-
) => {
|
|
278
|
-
if (!baseDir || !fs.existsSync(baseDir)) {
|
|
279
|
-
// eslint-disable-next-line no-param-reassign
|
|
280
|
-
ensureFiles = false;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
return Joi.object({
|
|
305
|
+
exports.themeSchema = themeSchema;
|
|
306
|
+
const blockletMetaProps = {
|
|
284
307
|
did: Joi.DID().trim().required(),
|
|
285
308
|
version: Joi.semver().valid().required(),
|
|
286
309
|
name: blockletNameSchema.required(),
|
|
287
310
|
description: descriptionSchema.required(),
|
|
288
|
-
group: Joi.string()
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
otherwise: ensureMain ? Joi.file().exists({ baseDir }).required() : Joi.string().trim().required(),
|
|
293
|
-
}),
|
|
311
|
+
group: Joi.string()
|
|
312
|
+
.valid(...BLOCKLET_GROUPS)
|
|
313
|
+
.required(),
|
|
314
|
+
main: Joi.string().trim().required(),
|
|
294
315
|
title: titleSchema.optional().allow(''),
|
|
295
|
-
logo:
|
|
316
|
+
logo: Joi.string().trim().optional(),
|
|
296
317
|
specVersion: Joi.semver().valid().gte('1.0.0').optional(),
|
|
297
|
-
|
|
298
318
|
author: personSchema.optional(),
|
|
299
319
|
contributors: Joi.array().items(personSchema).optional(),
|
|
300
320
|
maintainers: Joi.array().items(personSchema).optional(),
|
|
301
|
-
|
|
302
321
|
community: Joi.string().uri().optional().allow('').default(''),
|
|
303
322
|
documentation: Joi.string().uri().optional().allow('').default(''),
|
|
304
323
|
homepage: Joi.string().uri().optional().allow('').default(''),
|
|
305
324
|
license: Joi.string().optional().allow('').default(''),
|
|
306
325
|
support: Joi.alternatives().try(Joi.string().uri(), Joi.string().email()).optional(),
|
|
307
|
-
|
|
308
326
|
// which asset factory to mint blocklet purchase nft
|
|
309
327
|
// This is usually created and maintained by `blocklet publish` command
|
|
310
328
|
nftFactory: Joi.DID().optional().allow('').default(''),
|
|
311
|
-
|
|
312
329
|
// Set the price and share of the blocklet
|
|
313
330
|
payment: Joi.object({
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
Joi.object({
|
|
331
|
+
// Currently only supports 1 token
|
|
332
|
+
price: Joi.array()
|
|
333
|
+
.max(1)
|
|
334
|
+
.items(Joi.object({
|
|
319
335
|
value: Joi.number().greater(0).required(),
|
|
320
336
|
address: Joi.DID().required(), // token address
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
.items(
|
|
333
|
-
Joi.object({
|
|
337
|
+
}))
|
|
338
|
+
.default([]),
|
|
339
|
+
// List of beneficiaries that share the token earns from blocklet purchase
|
|
340
|
+
// If left empty, blocklet publish workflow will enforce both the developer and the registry account
|
|
341
|
+
// If not, the blocklet publish workflow will enforce the registry account
|
|
342
|
+
// In theory, the developer can split as many share as he wants
|
|
343
|
+
// Such as, some developers coauthored the blocklet, and their income get instant settlement on blocklet purchase
|
|
344
|
+
// For performance reasons, we need to set a hard limit for share count
|
|
345
|
+
share: Joi.array()
|
|
346
|
+
.max(4)
|
|
347
|
+
.items(Joi.object({
|
|
334
348
|
name: Joi.string().required(),
|
|
335
349
|
address: Joi.DID().required(),
|
|
336
350
|
value: Joi.number().greater(0).max(1).required(),
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
351
|
+
}))
|
|
352
|
+
.default([])
|
|
353
|
+
.custom((value) => {
|
|
354
|
+
// If share is not empty, the total value should be 1
|
|
355
|
+
if (value.length === 0) {
|
|
356
|
+
return value;
|
|
357
|
+
}
|
|
358
|
+
const total = value.reduce((acc, cur) => acc + cur.value, 0);
|
|
359
|
+
if (total !== 1) {
|
|
360
|
+
throw new Error(`Invalid blocklet payment share config: total share must be 1, got ${total}`);
|
|
361
|
+
}
|
|
343
362
|
return value;
|
|
344
|
-
}
|
|
345
|
-
const total = value.reduce((acc, cur) => acc + cur.value, 0);
|
|
346
|
-
if (total !== 1) {
|
|
347
|
-
throw new Error(`Invalid blocklet payment share config: total share must be 1, got ${total}`);
|
|
348
|
-
}
|
|
349
|
-
return value;
|
|
350
363
|
}, 'invalid blocklet share'),
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
Joi.object({
|
|
364
|
+
componentPrice: Joi.array()
|
|
365
|
+
.items(Joi.object({
|
|
354
366
|
parentPriceRange: Joi.array()
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
367
|
+
.items(Joi.number())
|
|
368
|
+
// FIXME
|
|
369
|
+
// 1. 有重叠的区间时
|
|
370
|
+
// 2. 区间不连续时
|
|
371
|
+
// 3. 区间边界
|
|
372
|
+
.custom((value, helper) => {
|
|
361
373
|
if (value.length !== 2) {
|
|
362
|
-
|
|
374
|
+
// @ts-expect-error
|
|
375
|
+
return helper.message('length of range should be 2');
|
|
363
376
|
}
|
|
364
|
-
|
|
365
377
|
if (value[0] < 0) {
|
|
366
|
-
|
|
378
|
+
// @ts-expect-error
|
|
379
|
+
return helper.message('the first value should not less than 0 in range');
|
|
367
380
|
}
|
|
368
|
-
|
|
369
381
|
if (value[1] <= value[0]) {
|
|
370
|
-
|
|
382
|
+
// @ts-expect-error
|
|
383
|
+
return helper.message('the second value should greater than the first value in range');
|
|
371
384
|
}
|
|
372
|
-
|
|
373
385
|
return value;
|
|
374
|
-
|
|
386
|
+
}),
|
|
375
387
|
type: Joi.string().valid('fixed', 'percentage').required(),
|
|
376
388
|
value: Joi.number().greater(0).required(),
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
.single(),
|
|
389
|
+
}))
|
|
390
|
+
.single(),
|
|
380
391
|
}).default({ price: [], share: [] }),
|
|
381
|
-
|
|
382
392
|
keywords: Joi.alternatives()
|
|
383
|
-
|
|
384
|
-
|
|
393
|
+
.try(Joi.string().trim().min(1), Joi.array().items(Joi.string().min(1)))
|
|
394
|
+
.optional(),
|
|
385
395
|
tags: Joi.alternatives()
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
396
|
+
.try(Joi.string().trim().min(1), Joi.array().items(Joi.string().min(1)))
|
|
397
|
+
.optional(),
|
|
389
398
|
gitHash: Joi.string().optional().allow(''),
|
|
390
399
|
repository: Joi.alternatives()
|
|
391
|
-
|
|
392
|
-
Joi.string().
|
|
393
|
-
Joi.
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
})
|
|
398
|
-
)
|
|
399
|
-
.optional(),
|
|
400
|
-
|
|
400
|
+
.try(Joi.string().min(1), Joi.object({
|
|
401
|
+
type: Joi.string().valid('git', 'https', 'svn').required(),
|
|
402
|
+
url: Joi.string().uri().required(),
|
|
403
|
+
directory: Joi.string(),
|
|
404
|
+
}))
|
|
405
|
+
.optional(),
|
|
401
406
|
timeout: Joi.object({
|
|
402
|
-
|
|
407
|
+
start: Joi.number().min(10).max(600), // start check timeout, 10 seconds ~ 10 minutes
|
|
403
408
|
}).default({ start: 60 }),
|
|
404
|
-
|
|
405
409
|
requirements: Joi.object({
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
Joi.object({
|
|
422
|
-
endpoint: Joi.string().trim().required(),
|
|
423
|
-
address: Joi.string().trim(),
|
|
424
|
-
value: Joi.string().trim().required(),
|
|
425
|
-
reason: Joi.string().trim().required(),
|
|
426
|
-
})
|
|
427
|
-
),
|
|
428
|
-
nodejs: Joi.semverRange().valid(),
|
|
410
|
+
abtnode: Joi.semverRange().valid(),
|
|
411
|
+
server: Joi.semverRange().valid(),
|
|
412
|
+
os: Joi.alternatives().try(Joi.string().valid('*', ...BLOCKLET_PLATFORMS), Joi.array()
|
|
413
|
+
.items(Joi.string().valid(...BLOCKLET_PLATFORMS))
|
|
414
|
+
.min(1)),
|
|
415
|
+
cpu: Joi.alternatives().try(Joi.string().valid('*', ...BLOCKLET_ARCHITECTURES), Joi.array()
|
|
416
|
+
.items(Joi.string().valid(...BLOCKLET_ARCHITECTURES))
|
|
417
|
+
.min(1)),
|
|
418
|
+
fuels: Joi.array().items(Joi.object({
|
|
419
|
+
endpoint: Joi.string().trim().required(),
|
|
420
|
+
address: Joi.string().trim(),
|
|
421
|
+
value: Joi.string().trim().required(),
|
|
422
|
+
reason: Joi.string().trim().required(),
|
|
423
|
+
})),
|
|
424
|
+
nodejs: Joi.semverRange().valid(),
|
|
429
425
|
}).default({ server: BLOCKLET_LATEST_REQUIREMENT_SERVER, os: '*', cpu: '*', nodejs: '*' }),
|
|
430
|
-
|
|
431
426
|
// interfaces: https://github.com/blocklet/blocklet-specification/issues/2
|
|
432
427
|
interfaces: Joi.array()
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
428
|
+
.items(interfaceSchema)
|
|
429
|
+
.unique('name')
|
|
430
|
+
.min(1)
|
|
431
|
+
.custom((value, helper) => {
|
|
437
432
|
const webItems = value.filter((x) => x.type === BLOCKLET_INTERFACE_TYPE_WEB);
|
|
438
433
|
if (webItems.length > 1) {
|
|
439
|
-
|
|
434
|
+
// @ts-expect-error
|
|
435
|
+
return helper.message(`Only one ${BLOCKLET_INTERFACE_TYPE_WEB} interface can be declared`);
|
|
440
436
|
}
|
|
441
|
-
|
|
442
437
|
const wellknownItems = value.filter((x) => x.type === BLOCKLET_INTERFACE_TYPE_WELLKNOWN);
|
|
443
438
|
for (const x of wellknownItems) {
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
439
|
+
if (!x.prefix.startsWith(WELLKNOWN_PATH_PREFIX)) {
|
|
440
|
+
// @ts-expect-error
|
|
441
|
+
return helper.message(`Wellknown path prefix must start with: ${WELLKNOWN_PATH_PREFIX}`);
|
|
442
|
+
}
|
|
447
443
|
}
|
|
448
|
-
|
|
449
444
|
return value;
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
445
|
+
})
|
|
446
|
+
.default([]),
|
|
453
447
|
// environments
|
|
454
448
|
environments: Joi.array().items(environmentSchema).default([]).optional(),
|
|
455
|
-
|
|
456
449
|
// scripts & hooks
|
|
457
450
|
scripts: scriptsSchema,
|
|
458
|
-
|
|
459
451
|
// capabilities
|
|
460
452
|
capabilities: Joi.object({
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
453
|
+
clusterMode: Joi.boolean().default(false),
|
|
454
|
+
// added in 1.2.2
|
|
455
|
+
component: Joi.boolean().default(true),
|
|
456
|
+
didStorage: Joi.string()
|
|
457
|
+
.valid(...Object.values(BLOCKLET_APP_STORAGE_ENDPOINTS))
|
|
458
|
+
.optional(),
|
|
465
459
|
}).default({
|
|
466
|
-
|
|
467
|
-
|
|
460
|
+
clusterMode: false,
|
|
461
|
+
component: true,
|
|
468
462
|
}),
|
|
469
|
-
|
|
470
463
|
// Other contents to be included in the bundle
|
|
471
|
-
files: Joi.array()
|
|
472
|
-
.items(
|
|
473
|
-
ensureFiles
|
|
474
|
-
? // eslint-disable-next-line
|
|
475
|
-
Joi.file().exists({ baseDir, canSkip: (dir, name) => [BLOCKLET_ENTRY_FILE, BLOCKLET_BUNDLE_FILE].includes(name) || isGlob(name) }) // prettier-ignore
|
|
476
|
-
: Joi.string().trim()
|
|
477
|
-
)
|
|
478
|
-
.optional(),
|
|
479
|
-
|
|
464
|
+
files: Joi.array().items(Joi.string().trim()).optional(),
|
|
480
465
|
// TODO: this field should be refactored in future version
|
|
481
466
|
engine: Joi.alternatives().try(engineSchema, Joi.array().items(engineSchema)).optional(),
|
|
482
|
-
|
|
483
467
|
// NOTE: following fields are appended by registry or bundling process
|
|
484
468
|
screenshots: Joi.array().items(Joi.string().min(1)).optional().default([]),
|
|
485
469
|
logoUrl: Joi.string().optional().allow(''),
|
|
486
|
-
dist:
|
|
470
|
+
dist: distSchema.optional(),
|
|
487
471
|
stats: statsSchema.optional(),
|
|
488
472
|
htmlAst: Joi.any().optional(),
|
|
489
473
|
path: Joi.string().optional(),
|
|
490
474
|
signatures: Joi.array().items(signatureSchema).optional(),
|
|
491
475
|
lastPublishedAt: Joi.string().isoDate().optional(),
|
|
492
|
-
|
|
493
476
|
// blocklet component support
|
|
494
|
-
components: Joi.array().items(
|
|
495
|
-
|
|
477
|
+
components: Joi.array().items(componentSchema).unique('name').optional().default([]),
|
|
496
478
|
// navigation & theme
|
|
497
479
|
navigation: navigationSchema,
|
|
498
480
|
theme: themeSchema,
|
|
499
481
|
copyright: Joi.object({
|
|
500
|
-
|
|
501
|
-
|
|
482
|
+
owner: Joi.string().min(1),
|
|
483
|
+
year: Joi.alternatives().try(Joi.string(), Joi.number()),
|
|
502
484
|
}),
|
|
503
|
-
|
|
504
485
|
// NOTE: following fields only exist in blocklet server and cannot be set manually
|
|
505
486
|
bundleName: Joi.string(),
|
|
506
487
|
bundleDid: Joi.DID().trim(),
|
|
507
488
|
storeId: Joi.string(),
|
|
508
|
-
})
|
|
509
|
-
.options({ stripUnknown: true, noDefaults: false, ...schemaOptions })
|
|
510
|
-
.rename('children', 'components');
|
|
511
489
|
};
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
490
|
+
const blockletMetaSchema = Joi.object(blockletMetaProps).options({ stripUnknown: true, noDefaults: false }).meta({
|
|
491
|
+
className: 'TBlockletMeta',
|
|
492
|
+
unknownType: 'any',
|
|
493
|
+
});
|
|
494
|
+
exports.blockletMetaSchema = blockletMetaSchema;
|
|
495
|
+
const createBlockletSchema = (baseDir, _a = {}) => {
|
|
496
|
+
var { ensureMain = false, ensureFiles = false, ensureDist = false } = _a, schemaOptions = __rest(_a, ["ensureMain", "ensureFiles", "ensureDist"]);
|
|
497
|
+
if (!baseDir || !fs_1.default.existsSync(baseDir)) {
|
|
498
|
+
// eslint-disable-next-line no-param-reassign
|
|
499
|
+
ensureFiles = false;
|
|
500
|
+
}
|
|
501
|
+
return Joi.object(Object.assign(Object.assign({}, blockletMetaProps), { main: Joi.when('group', {
|
|
502
|
+
is: Joi.valid(BlockletGroup.gateway),
|
|
503
|
+
then: Joi.forbidden(),
|
|
504
|
+
otherwise: ensureMain ? Joi.file().exists({ baseDir }).required() : Joi.string().trim().required(),
|
|
505
|
+
}), logo: ensureFiles ? Joi.file().trim().exists({ baseDir }).optional() : Joi.string().trim().optional(),
|
|
506
|
+
// Other contents to be included in the bundle
|
|
507
|
+
files: Joi.array()
|
|
508
|
+
.items(ensureFiles
|
|
509
|
+
? // eslint-disable-next-line
|
|
510
|
+
Joi.file().exists({ baseDir, canSkip: (dir, name) => [BLOCKLET_ENTRY_FILE, BLOCKLET_BUNDLE_FILE].includes(name) || (0, is_glob_1.default)(name) }) // prettier-ignore
|
|
511
|
+
: Joi.string().trim())
|
|
512
|
+
.optional(), dist: ensureDist ? distSchema.required() : distSchema.optional() }))
|
|
513
|
+
.options(Object.assign({ stripUnknown: true, noDefaults: false }, schemaOptions))
|
|
514
|
+
.rename('children', 'components');
|
|
515
|
+
};
|
|
516
|
+
exports.createBlockletSchema = createBlockletSchema;
|
|
517
|
+
exports.default = {
|
|
518
|
+
blockletNameSchema,
|
|
519
|
+
componentSchema,
|
|
520
|
+
endpointSchema,
|
|
521
|
+
serviceSchema,
|
|
522
|
+
createBlockletSchema,
|
|
523
|
+
interfaceSchema,
|
|
524
|
+
environmentSchema,
|
|
525
|
+
scriptsSchema,
|
|
526
|
+
personSchema,
|
|
527
|
+
distSchema,
|
|
528
|
+
titleSchema,
|
|
529
|
+
descriptionSchema,
|
|
530
|
+
logoSchema,
|
|
531
|
+
navigationSchema,
|
|
532
|
+
themeSchema,
|
|
533
|
+
mountPointSchema,
|
|
526
534
|
};
|