@blocklet/meta 1.8.34 → 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 +167 -228
- 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 -402
- 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 +40 -18
package/lib/schema.js
CHANGED
|
@@ -1,531 +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
|
-
|
|
26
|
-
|
|
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;
|
|
27
29
|
const WELLKNOWN_PATH_PREFIX = '/.well-known';
|
|
28
30
|
const MAX_TITLE_LENGTH = 24;
|
|
29
31
|
const MAX_NAME_LENGTH = 32;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
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);
|
|
33
36
|
const titleSchema = Joi.string()
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
+
.trim()
|
|
38
|
+
.min(1)
|
|
39
|
+
.custom((value) => {
|
|
37
40
|
if (cjkLength(value) > MAX_TITLE_LENGTH) {
|
|
38
|
-
|
|
39
|
-
`title length should not exceed ${MAX_TITLE_LENGTH} (see: https://www.npmjs.com/package/cjk-length)`
|
|
40
|
-
);
|
|
41
|
+
throw new Error(`title length should not exceed ${MAX_TITLE_LENGTH} (see: https://www.npmjs.com/package/cjk-length)`);
|
|
41
42
|
}
|
|
42
|
-
|
|
43
43
|
return value;
|
|
44
|
-
|
|
45
|
-
|
|
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;
|
|
46
49
|
const logoSchema = Joi.string()
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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;
|
|
51
56
|
const blockletNameSchema = Joi.string()
|
|
52
|
-
|
|
53
|
-
validateName(value);
|
|
57
|
+
.custom((value) => {
|
|
58
|
+
(0, name_1.validateName)(value);
|
|
54
59
|
return value;
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
60
|
+
})
|
|
61
|
+
.max(MAX_NAME_LENGTH)
|
|
62
|
+
.meta({ className: 'TBlockletName' });
|
|
63
|
+
exports.blockletNameSchema = blockletNameSchema;
|
|
58
64
|
const environmentSchema = Joi.object({
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
})
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
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',
|
|
72
83
|
});
|
|
73
|
-
|
|
84
|
+
exports.environmentSchema = environmentSchema;
|
|
74
85
|
const scriptsSchema = Joi.object({
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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),
|
|
84
95
|
})
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
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;
|
|
94
109
|
// Different services have different config schema
|
|
95
110
|
// - Auth: https://github.com/ArcBlock/abtnode-docs/blob/master/src/developer/auth-service/index.md
|
|
96
111
|
const serviceSchema = Joi.object({
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
})
|
|
100
|
-
|
|
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;
|
|
101
121
|
const endpointSchema = Joi.object({
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
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
|
+
}),
|
|
110
131
|
}),
|
|
111
|
-
|
|
132
|
+
}).meta({
|
|
133
|
+
className: 'TEndpoint',
|
|
134
|
+
unknownType: 'any',
|
|
112
135
|
});
|
|
113
|
-
|
|
136
|
+
exports.endpointSchema = endpointSchema;
|
|
114
137
|
const interfaceSchema = Joi.object({
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
.
|
|
131
|
-
|
|
132
|
-
.default('http'),
|
|
133
|
-
|
|
134
|
-
// Can be a string or an object
|
|
135
|
-
port: Joi.alternatives()
|
|
136
|
-
.try(
|
|
137
|
-
Joi.string().uppercase().default(BLOCKLET_DEFAULT_PORT_NAME),
|
|
138
|
-
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({
|
|
139
155
|
internal: Joi.string().uppercase().required(),
|
|
140
156
|
external: Joi.number().port().required(),
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
.
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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',
|
|
147
164
|
});
|
|
148
|
-
|
|
165
|
+
exports.interfaceSchema = interfaceSchema;
|
|
149
166
|
const engineSchema = Joi.object({
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
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',
|
|
156
176
|
});
|
|
157
|
-
|
|
177
|
+
exports.engineSchema = engineSchema;
|
|
158
178
|
const personSchema = Joi.object({
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
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',
|
|
162
185
|
});
|
|
163
|
-
|
|
186
|
+
exports.personSchema = personSchema;
|
|
164
187
|
const distSchema = Joi.object({
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
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',
|
|
168
194
|
});
|
|
169
|
-
|
|
195
|
+
exports.distSchema = distSchema;
|
|
170
196
|
const statsSchema = Joi.object({
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
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',
|
|
174
203
|
});
|
|
175
|
-
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
resolved: Joi.alternatives().try(Joi.string().uri(), Joi.string()), // deprecated
|
|
194
|
-
mountPoints: Joi.array() // deprecated
|
|
195
|
-
.items(
|
|
196
|
-
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({
|
|
197
222
|
root: Joi.object({
|
|
198
|
-
|
|
199
|
-
|
|
223
|
+
interfaceName: Joi.string().trim().required(),
|
|
224
|
+
prefix: Joi.string().trim().min(1).required(),
|
|
200
225
|
}).required(),
|
|
201
226
|
child: Joi.object({
|
|
202
|
-
|
|
227
|
+
interfaceName: Joi.string().trim().required(),
|
|
203
228
|
}).required(),
|
|
204
229
|
services: Joi.array().items(serviceSchema).unique('name'),
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
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',
|
|
218
247
|
});
|
|
219
|
-
|
|
248
|
+
exports.componentSchema = componentSchema;
|
|
220
249
|
const signatureSchema = Joi.object({
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
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',
|
|
233
265
|
});
|
|
234
|
-
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
Joi.string(),
|
|
239
|
-
Joi.object({
|
|
266
|
+
exports.signatureSchema = signatureSchema;
|
|
267
|
+
const navigationItemProps = {
|
|
268
|
+
title: Joi.alternatives()
|
|
269
|
+
.try(Joi.string(), Joi.object({
|
|
240
270
|
zh: Joi.string(),
|
|
241
271
|
en: Joi.string(),
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
.
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
272
|
+
}).min(1))
|
|
273
|
+
.required(),
|
|
274
|
+
link: Joi.alternatives().try(Joi.string(), Joi.object({
|
|
275
|
+
zh: Joi.string(),
|
|
276
|
+
en: Joi.string(),
|
|
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;
|
|
264
295
|
const themeSchema = Joi.object({
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
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',
|
|
273
304
|
});
|
|
274
|
-
|
|
275
|
-
const
|
|
276
|
-
baseDir,
|
|
277
|
-
{ ensureMain = false, ensureFiles = false, ensureDist = false, ...schemaOptions } = {}
|
|
278
|
-
) => {
|
|
279
|
-
if (!baseDir || !fs.existsSync(baseDir)) {
|
|
280
|
-
// eslint-disable-next-line no-param-reassign
|
|
281
|
-
ensureFiles = false;
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
return Joi.object({
|
|
305
|
+
exports.themeSchema = themeSchema;
|
|
306
|
+
const blockletMetaProps = {
|
|
285
307
|
did: Joi.DID().trim().required(),
|
|
286
308
|
version: Joi.semver().valid().required(),
|
|
287
309
|
name: blockletNameSchema.required(),
|
|
288
310
|
description: descriptionSchema.required(),
|
|
289
|
-
group: Joi.string()
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
otherwise: ensureMain ? Joi.file().exists({ baseDir }).required() : Joi.string().trim().required(),
|
|
294
|
-
}),
|
|
311
|
+
group: Joi.string()
|
|
312
|
+
.valid(...BLOCKLET_GROUPS)
|
|
313
|
+
.required(),
|
|
314
|
+
main: Joi.string().trim().required(),
|
|
295
315
|
title: titleSchema.optional().allow(''),
|
|
296
|
-
logo:
|
|
316
|
+
logo: Joi.string().trim().optional(),
|
|
297
317
|
specVersion: Joi.semver().valid().gte('1.0.0').optional(),
|
|
298
|
-
|
|
299
318
|
author: personSchema.optional(),
|
|
300
319
|
contributors: Joi.array().items(personSchema).optional(),
|
|
301
320
|
maintainers: Joi.array().items(personSchema).optional(),
|
|
302
|
-
|
|
303
321
|
community: Joi.string().uri().optional().allow('').default(''),
|
|
304
322
|
documentation: Joi.string().uri().optional().allow('').default(''),
|
|
305
323
|
homepage: Joi.string().uri().optional().allow('').default(''),
|
|
306
324
|
license: Joi.string().optional().allow('').default(''),
|
|
307
325
|
support: Joi.alternatives().try(Joi.string().uri(), Joi.string().email()).optional(),
|
|
308
|
-
|
|
309
326
|
// which asset factory to mint blocklet purchase nft
|
|
310
327
|
// This is usually created and maintained by `blocklet publish` command
|
|
311
328
|
nftFactory: Joi.DID().optional().allow('').default(''),
|
|
312
|
-
|
|
313
329
|
// Set the price and share of the blocklet
|
|
314
330
|
payment: Joi.object({
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
Joi.object({
|
|
331
|
+
// Currently only supports 1 token
|
|
332
|
+
price: Joi.array()
|
|
333
|
+
.max(1)
|
|
334
|
+
.items(Joi.object({
|
|
320
335
|
value: Joi.number().greater(0).required(),
|
|
321
336
|
address: Joi.DID().required(), // token address
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
.items(
|
|
334
|
-
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({
|
|
335
348
|
name: Joi.string().required(),
|
|
336
349
|
address: Joi.DID().required(),
|
|
337
350
|
value: Joi.number().greater(0).max(1).required(),
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
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
|
+
}
|
|
344
362
|
return value;
|
|
345
|
-
}
|
|
346
|
-
const total = value.reduce((acc, cur) => acc + cur.value, 0);
|
|
347
|
-
if (total !== 1) {
|
|
348
|
-
throw new Error(`Invalid blocklet payment share config: total share must be 1, got ${total}`);
|
|
349
|
-
}
|
|
350
|
-
return value;
|
|
351
363
|
}, 'invalid blocklet share'),
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
Joi.object({
|
|
364
|
+
componentPrice: Joi.array()
|
|
365
|
+
.items(Joi.object({
|
|
355
366
|
parentPriceRange: Joi.array()
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
367
|
+
.items(Joi.number())
|
|
368
|
+
// FIXME
|
|
369
|
+
// 1. 有重叠的区间时
|
|
370
|
+
// 2. 区间不连续时
|
|
371
|
+
// 3. 区间边界
|
|
372
|
+
.custom((value, helper) => {
|
|
362
373
|
if (value.length !== 2) {
|
|
363
|
-
|
|
374
|
+
// @ts-expect-error
|
|
375
|
+
return helper.message('length of range should be 2');
|
|
364
376
|
}
|
|
365
|
-
|
|
366
377
|
if (value[0] < 0) {
|
|
367
|
-
|
|
378
|
+
// @ts-expect-error
|
|
379
|
+
return helper.message('the first value should not less than 0 in range');
|
|
368
380
|
}
|
|
369
|
-
|
|
370
381
|
if (value[1] <= value[0]) {
|
|
371
|
-
|
|
382
|
+
// @ts-expect-error
|
|
383
|
+
return helper.message('the second value should greater than the first value in range');
|
|
372
384
|
}
|
|
373
|
-
|
|
374
385
|
return value;
|
|
375
|
-
|
|
386
|
+
}),
|
|
376
387
|
type: Joi.string().valid('fixed', 'percentage').required(),
|
|
377
388
|
value: Joi.number().greater(0).required(),
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
.single(),
|
|
389
|
+
}))
|
|
390
|
+
.single(),
|
|
381
391
|
}).default({ price: [], share: [] }),
|
|
382
|
-
|
|
383
392
|
keywords: Joi.alternatives()
|
|
384
|
-
|
|
385
|
-
|
|
393
|
+
.try(Joi.string().trim().min(1), Joi.array().items(Joi.string().min(1)))
|
|
394
|
+
.optional(),
|
|
386
395
|
tags: Joi.alternatives()
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
396
|
+
.try(Joi.string().trim().min(1), Joi.array().items(Joi.string().min(1)))
|
|
397
|
+
.optional(),
|
|
390
398
|
gitHash: Joi.string().optional().allow(''),
|
|
391
399
|
repository: Joi.alternatives()
|
|
392
|
-
|
|
393
|
-
Joi.string().
|
|
394
|
-
Joi.
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
})
|
|
399
|
-
)
|
|
400
|
-
.optional(),
|
|
401
|
-
|
|
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(),
|
|
402
406
|
timeout: Joi.object({
|
|
403
|
-
|
|
407
|
+
start: Joi.number().min(10).max(600), // start check timeout, 10 seconds ~ 10 minutes
|
|
404
408
|
}).default({ start: 60 }),
|
|
405
|
-
|
|
406
409
|
requirements: Joi.object({
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
Joi.object({
|
|
423
|
-
endpoint: Joi.string().trim().required(),
|
|
424
|
-
address: Joi.string().trim(),
|
|
425
|
-
value: Joi.string().trim().required(),
|
|
426
|
-
reason: Joi.string().trim().required(),
|
|
427
|
-
})
|
|
428
|
-
),
|
|
429
|
-
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(),
|
|
430
425
|
}).default({ server: BLOCKLET_LATEST_REQUIREMENT_SERVER, os: '*', cpu: '*', nodejs: '*' }),
|
|
431
|
-
|
|
432
426
|
// interfaces: https://github.com/blocklet/blocklet-specification/issues/2
|
|
433
427
|
interfaces: Joi.array()
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
428
|
+
.items(interfaceSchema)
|
|
429
|
+
.unique('name')
|
|
430
|
+
.min(1)
|
|
431
|
+
.custom((value, helper) => {
|
|
438
432
|
const webItems = value.filter((x) => x.type === BLOCKLET_INTERFACE_TYPE_WEB);
|
|
439
433
|
if (webItems.length > 1) {
|
|
440
|
-
|
|
434
|
+
// @ts-expect-error
|
|
435
|
+
return helper.message(`Only one ${BLOCKLET_INTERFACE_TYPE_WEB} interface can be declared`);
|
|
441
436
|
}
|
|
442
|
-
|
|
443
437
|
const wellknownItems = value.filter((x) => x.type === BLOCKLET_INTERFACE_TYPE_WELLKNOWN);
|
|
444
438
|
for (const x of wellknownItems) {
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
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
|
+
}
|
|
448
443
|
}
|
|
449
|
-
|
|
450
444
|
return value;
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
445
|
+
})
|
|
446
|
+
.default([]),
|
|
454
447
|
// environments
|
|
455
448
|
environments: Joi.array().items(environmentSchema).default([]).optional(),
|
|
456
|
-
|
|
457
449
|
// scripts & hooks
|
|
458
450
|
scripts: scriptsSchema,
|
|
459
|
-
|
|
460
451
|
// capabilities
|
|
461
452
|
capabilities: Joi.object({
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
.valid(...Object.values(BLOCKLET_APP_STORAGE_ENDPOINTS))
|
|
469
|
-
.optional(),
|
|
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(),
|
|
470
459
|
}).default({
|
|
471
|
-
|
|
472
|
-
|
|
460
|
+
clusterMode: false,
|
|
461
|
+
component: true,
|
|
473
462
|
}),
|
|
474
|
-
|
|
475
463
|
// Other contents to be included in the bundle
|
|
476
|
-
files: Joi.array()
|
|
477
|
-
.items(
|
|
478
|
-
ensureFiles
|
|
479
|
-
? // eslint-disable-next-line
|
|
480
|
-
Joi.file().exists({ baseDir, canSkip: (dir, name) => [BLOCKLET_ENTRY_FILE, BLOCKLET_BUNDLE_FILE].includes(name) || isGlob(name) }) // prettier-ignore
|
|
481
|
-
: Joi.string().trim()
|
|
482
|
-
)
|
|
483
|
-
.optional(),
|
|
484
|
-
|
|
464
|
+
files: Joi.array().items(Joi.string().trim()).optional(),
|
|
485
465
|
// TODO: this field should be refactored in future version
|
|
486
466
|
engine: Joi.alternatives().try(engineSchema, Joi.array().items(engineSchema)).optional(),
|
|
487
|
-
|
|
488
467
|
// NOTE: following fields are appended by registry or bundling process
|
|
489
468
|
screenshots: Joi.array().items(Joi.string().min(1)).optional().default([]),
|
|
490
469
|
logoUrl: Joi.string().optional().allow(''),
|
|
491
|
-
dist:
|
|
470
|
+
dist: distSchema.optional(),
|
|
492
471
|
stats: statsSchema.optional(),
|
|
493
472
|
htmlAst: Joi.any().optional(),
|
|
494
473
|
path: Joi.string().optional(),
|
|
495
474
|
signatures: Joi.array().items(signatureSchema).optional(),
|
|
496
475
|
lastPublishedAt: Joi.string().isoDate().optional(),
|
|
497
|
-
|
|
498
476
|
// blocklet component support
|
|
499
|
-
components: Joi.array().items(
|
|
500
|
-
|
|
477
|
+
components: Joi.array().items(componentSchema).unique('name').optional().default([]),
|
|
501
478
|
// navigation & theme
|
|
502
479
|
navigation: navigationSchema,
|
|
503
480
|
theme: themeSchema,
|
|
504
481
|
copyright: Joi.object({
|
|
505
|
-
|
|
506
|
-
|
|
482
|
+
owner: Joi.string().min(1),
|
|
483
|
+
year: Joi.alternatives().try(Joi.string(), Joi.number()),
|
|
507
484
|
}),
|
|
508
|
-
|
|
509
485
|
// NOTE: following fields only exist in blocklet server and cannot be set manually
|
|
510
486
|
bundleName: Joi.string(),
|
|
511
487
|
bundleDid: Joi.DID().trim(),
|
|
512
488
|
storeId: Joi.string(),
|
|
513
|
-
})
|
|
514
|
-
.options({ stripUnknown: true, noDefaults: false, ...schemaOptions })
|
|
515
|
-
.rename('children', 'components');
|
|
516
489
|
};
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
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,
|
|
531
534
|
};
|