@abtnode/core 1.16.16 → 1.16.17-beta-8cacb9b3
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/manager/disk.js +93 -12
- package/lib/blocklet/manager/helper/install-component-from-url.js +11 -12
- package/lib/blocklet/project/index.js +325 -0
- package/lib/blocklet/project/logo.png +0 -0
- package/lib/index.js +11 -0
- package/lib/router/helper.js +4 -0
- package/lib/states/project.js +45 -0
- package/lib/states/release.js +46 -0
- package/lib/team/manager.js +11 -0
- package/lib/util/blocklet.js +4 -0
- package/lib/util/store.js +1 -1
- package/lib/validators/project.js +29 -0
- package/package.json +32 -31
|
@@ -167,6 +167,17 @@ const { sessionConfigSchema } = require('../../validators/util');
|
|
|
167
167
|
|
|
168
168
|
const request = require('../../util/request');
|
|
169
169
|
const ConfigSynchronizer = require('./config-synchronizer');
|
|
170
|
+
const {
|
|
171
|
+
createProject,
|
|
172
|
+
getProject,
|
|
173
|
+
getProjects,
|
|
174
|
+
updateProject,
|
|
175
|
+
deleteProject,
|
|
176
|
+
createRelease,
|
|
177
|
+
getReleases,
|
|
178
|
+
getRelease,
|
|
179
|
+
deleteRelease,
|
|
180
|
+
} = require('../project');
|
|
170
181
|
|
|
171
182
|
const { formatEnvironments, getBlockletMeta, validateOwner, isCLI } = util;
|
|
172
183
|
|
|
@@ -1521,8 +1532,14 @@ class DiskBlockletManager extends BaseBlockletManager {
|
|
|
1521
1532
|
return getBlocklet({ ...opts, states, dataDirs: this.dataDirs, did, ensureIntegrity: true });
|
|
1522
1533
|
}
|
|
1523
1534
|
|
|
1524
|
-
getBlocklet(did, opts = {}) {
|
|
1525
|
-
|
|
1535
|
+
async getBlocklet(did, opts = {}) {
|
|
1536
|
+
if (opts.useCache && this.cachedBlocklets.has(did)) {
|
|
1537
|
+
return this.cachedBlocklets.get(did);
|
|
1538
|
+
}
|
|
1539
|
+
|
|
1540
|
+
const blocklet = await getBlocklet({ ...opts, states, dataDirs: this.dataDirs, did, ensureIntegrity: false });
|
|
1541
|
+
this.cachedBlocklets.set(did, blocklet);
|
|
1542
|
+
return blocklet;
|
|
1526
1543
|
}
|
|
1527
1544
|
|
|
1528
1545
|
hasBlocklet({ did }) {
|
|
@@ -1869,10 +1886,55 @@ class DiskBlockletManager extends BaseBlockletManager {
|
|
|
1869
1886
|
return this.configSynchronizer.syncAppConfig(did, { serverVersion });
|
|
1870
1887
|
}
|
|
1871
1888
|
|
|
1889
|
+
createProject({ did, ...params } = {}) {
|
|
1890
|
+
return createProject({ did, ...params, manager: this });
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
getProjects({ did } = {}) {
|
|
1894
|
+
return getProjects({ did, manager: this });
|
|
1895
|
+
}
|
|
1896
|
+
|
|
1897
|
+
getProject({ did, projectId } = {}) {
|
|
1898
|
+
return getProject({ did, projectId, manager: this });
|
|
1899
|
+
}
|
|
1900
|
+
|
|
1901
|
+
updateProject({ did, projectId, ...params } = {}) {
|
|
1902
|
+
return updateProject({ did, projectId, ...params, manager: this });
|
|
1903
|
+
}
|
|
1904
|
+
|
|
1905
|
+
deleteProject({ did, projectId } = {}) {
|
|
1906
|
+
return deleteProject({ did, projectId, manager: this });
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
// eslint-disable-next-line no-unused-vars
|
|
1910
|
+
createRelease({ did, projectId, ...params } = {}, context) {
|
|
1911
|
+
return createRelease({ did, projectId, ...params, manager: this });
|
|
1912
|
+
}
|
|
1913
|
+
|
|
1914
|
+
getReleases({ did, projectId } = {}) {
|
|
1915
|
+
return getReleases({ did, projectId, manager: this });
|
|
1916
|
+
}
|
|
1917
|
+
|
|
1918
|
+
getRelease({ did, projectId, releaseId } = {}) {
|
|
1919
|
+
return getRelease({ did, projectId, releaseId, manager: this });
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
deleteRelease({ did, projectId, releaseId } = {}) {
|
|
1923
|
+
return deleteRelease({ did, projectId, releaseId, manager: this });
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1872
1926
|
// ============================================================================================
|
|
1873
1927
|
// Private API that are used by self of helper function
|
|
1874
1928
|
// ============================================================================================
|
|
1875
1929
|
|
|
1930
|
+
_getProjectState(did) {
|
|
1931
|
+
return this.teamManager.getProjectState(did);
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1934
|
+
_getSessionState(did) {
|
|
1935
|
+
return this.teamManager.getSessionState(did);
|
|
1936
|
+
}
|
|
1937
|
+
|
|
1876
1938
|
/**
|
|
1877
1939
|
*
|
|
1878
1940
|
*
|
|
@@ -2747,17 +2809,36 @@ class DiskBlockletManager extends BaseBlockletManager {
|
|
|
2747
2809
|
}
|
|
2748
2810
|
logger.info('done migration on upgrading', { did, componentDids });
|
|
2749
2811
|
|
|
2750
|
-
if (
|
|
2751
|
-
|
|
2752
|
-
await this.start({ did, componentDids }, context);
|
|
2753
|
-
logger.info('started blocklet for upgrading', { did, version, componentDids });
|
|
2754
|
-
} catch (error) {
|
|
2755
|
-
logger.error('failed to start blocklet for upgrading', { did, version, componentDids, error });
|
|
2756
|
-
}
|
|
2812
|
+
if (action === INSTALL_ACTIONS.INSTALL_COMPONENT) {
|
|
2813
|
+
await states.blocklet.setBlockletStatus(did, BlockletStatus.installed, { componentDids });
|
|
2757
2814
|
} else {
|
|
2758
|
-
const
|
|
2759
|
-
|
|
2760
|
-
|
|
2815
|
+
const runningDids = [];
|
|
2816
|
+
const stoppedDids = [];
|
|
2817
|
+
const installedDids = [];
|
|
2818
|
+
for (const componentDid of componentDids) {
|
|
2819
|
+
const old = oldBlocklet.children.find((x) => x.meta.did === componentDid);
|
|
2820
|
+
if (old?.status === BlockletStatus.running) {
|
|
2821
|
+
runningDids.push(componentDid);
|
|
2822
|
+
} else if (old?.status === BlockletStatus.installed) {
|
|
2823
|
+
installedDids.push(componentDid);
|
|
2824
|
+
} else {
|
|
2825
|
+
stoppedDids.push(componentDid);
|
|
2826
|
+
}
|
|
2827
|
+
}
|
|
2828
|
+
if (runningDids.length) {
|
|
2829
|
+
try {
|
|
2830
|
+
await this.start({ did, componentDids: runningDids }, context);
|
|
2831
|
+
logger.info('started blocklet for upgrading', { did, version, runningDids });
|
|
2832
|
+
} catch (error) {
|
|
2833
|
+
logger.error('failed to start blocklet for upgrading', { did, version, runningDids, error });
|
|
2834
|
+
}
|
|
2835
|
+
}
|
|
2836
|
+
if (stoppedDids.length) {
|
|
2837
|
+
await states.blocklet.setBlockletStatus(did, BlockletStatus.stopped, { componentDids: stoppedDids });
|
|
2838
|
+
}
|
|
2839
|
+
if (installedDids.length) {
|
|
2840
|
+
await states.blocklet.setBlockletStatus(did, BlockletStatus.installed, { componentDids: installedDids });
|
|
2841
|
+
}
|
|
2761
2842
|
}
|
|
2762
2843
|
|
|
2763
2844
|
blocklet = await this.getBlocklet(did, context);
|
|
@@ -2,7 +2,7 @@ const { sign } = require('@arcblock/jwt');
|
|
|
2
2
|
|
|
3
3
|
const logger = require('@abtnode/logger')('@abtnode/core:install-component-url');
|
|
4
4
|
|
|
5
|
-
const { isFreeBlocklet
|
|
5
|
+
const { isFreeBlocklet } = require('@blocklet/meta/lib/util');
|
|
6
6
|
const { titleSchema } = require('@blocklet/meta/lib/schema');
|
|
7
7
|
const hasReservedKey = require('@blocklet/meta/lib/has-reserved-key');
|
|
8
8
|
|
|
@@ -40,7 +40,7 @@ const installComponentFromUrl = async ({
|
|
|
40
40
|
|
|
41
41
|
checkStructVersion(blocklet);
|
|
42
42
|
|
|
43
|
-
const { inStore } = await StoreUtil.parseSourceUrl(url);
|
|
43
|
+
const { inStore, registryUrl } = await StoreUtil.parseSourceUrl(url);
|
|
44
44
|
|
|
45
45
|
const meta = await getBlockletMetaFromUrl(url);
|
|
46
46
|
|
|
@@ -66,14 +66,6 @@ const installComponentFromUrl = async ({
|
|
|
66
66
|
};
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
if (!isComponentBlocklet(meta)) {
|
|
70
|
-
throw new Error(
|
|
71
|
-
`The blocklet cannot be a component : ${
|
|
72
|
-
meta.title || meta.name
|
|
73
|
-
}. The reason may be that the developer set capabilities.component to false in blocklet.yml`
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
69
|
if (title) {
|
|
78
70
|
meta.title = await titleSchema.validateAsync(title);
|
|
79
71
|
}
|
|
@@ -84,7 +76,14 @@ const installComponentFromUrl = async ({
|
|
|
84
76
|
const newChild = {
|
|
85
77
|
meta: newChildMeta,
|
|
86
78
|
mountPoint: mountPoint || formatName(newChildMeta.name),
|
|
87
|
-
bundleSource:
|
|
79
|
+
bundleSource: inStore
|
|
80
|
+
? {
|
|
81
|
+
store: registryUrl,
|
|
82
|
+
name: meta.bundleName || meta.name,
|
|
83
|
+
// FIXME @linchen version should be specified
|
|
84
|
+
version: 'latest',
|
|
85
|
+
}
|
|
86
|
+
: { url },
|
|
88
87
|
};
|
|
89
88
|
|
|
90
89
|
const { dynamicComponents } = await parseComponents(newChild);
|
|
@@ -110,7 +109,7 @@ const installComponentFromUrl = async ({
|
|
|
110
109
|
checkVersionCompatibility(blocklet.children);
|
|
111
110
|
|
|
112
111
|
const oldBlocklet = await manager._getBlockletForInstallation(rootDid);
|
|
113
|
-
const action = index
|
|
112
|
+
const action = index >= 0 ? INSTALL_ACTIONS.UPGRADE_COMPONENT : INSTALL_ACTIONS.INSTALL_COMPONENT;
|
|
114
113
|
try {
|
|
115
114
|
// add component to db
|
|
116
115
|
await states.blocklet.addChildren(rootDid, newChildren);
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const fs = require('fs-extra');
|
|
3
|
+
const createArchive = require('archiver');
|
|
4
|
+
const { slugify } = require('transliteration');
|
|
5
|
+
const { BLOCKLET_META_FILE, PROJECT } = require('@blocklet/constant');
|
|
6
|
+
const { update: updateMetaFile } = require('@blocklet/meta/lib/file');
|
|
7
|
+
const { createRelease: createBlockletRelease } = require('@abtnode/util/lib/create-blocklet-release');
|
|
8
|
+
const { titleSchema } = require('@blocklet/meta/lib/schema');
|
|
9
|
+
const { validateNewDid } = require('@blocklet/meta/lib/name');
|
|
10
|
+
const urlPathFriendly = require('@blocklet/meta/lib/url-path-friendly').default;
|
|
11
|
+
|
|
12
|
+
const logger = require('@abtnode/logger')('create-resource-blocklet');
|
|
13
|
+
|
|
14
|
+
const { createReleaseSchema } = require('../../validators/project');
|
|
15
|
+
|
|
16
|
+
const createRandomStr = () => Math.random().toString(36).substring(2, 8);
|
|
17
|
+
|
|
18
|
+
// project
|
|
19
|
+
|
|
20
|
+
const createProject = async ({ did, type, blockletTitle, blockletDid, manager }) => {
|
|
21
|
+
await titleSchema.validateAsync(blockletTitle);
|
|
22
|
+
validateNewDid(blockletDid);
|
|
23
|
+
if (!PROJECT.TYPES[type]) {
|
|
24
|
+
throw new Error(`type is invalid: ${type}`);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const blocklet = await manager.getBlocklet(did, { useCache: true });
|
|
28
|
+
const { projectState } = await manager._getProjectState(did);
|
|
29
|
+
|
|
30
|
+
const project = await projectState.createProject({ blockletTitle, blockletDid, type });
|
|
31
|
+
|
|
32
|
+
// create project dir
|
|
33
|
+
const projectDir = path.join(blocklet.env.dataDir, PROJECT.DIR, `${project.id}`);
|
|
34
|
+
const releasesDir = path.join(projectDir, PROJECT.RELEASE_DIR);
|
|
35
|
+
const tmpResourceDir = path.join(projectDir, PROJECT.RESOURCE_DIR);
|
|
36
|
+
const assetDir = path.join(projectDir, PROJECT.ASSET_DIR);
|
|
37
|
+
await fs.ensureDir(releasesDir);
|
|
38
|
+
await fs.ensureDir(tmpResourceDir);
|
|
39
|
+
await fs.ensureDir(assetDir);
|
|
40
|
+
|
|
41
|
+
return project;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const getProjects = async ({ did, manager }) => {
|
|
45
|
+
const { projectState } = await manager._getProjectState(did);
|
|
46
|
+
const projects = await projectState.getProjects();
|
|
47
|
+
return { projects };
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
const getProject = async ({ did, projectId, manager }) => {
|
|
51
|
+
const { projectState } = await manager._getProjectState(did);
|
|
52
|
+
const project = await projectState.findOne({ id: projectId });
|
|
53
|
+
return project;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const updateProject = async ({ did, projectId, manager, ...params }) => {
|
|
57
|
+
const { projectState } = await manager._getProjectState(did);
|
|
58
|
+
const project = await projectState.updateProject(projectId, params);
|
|
59
|
+
return project;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const deleteProject = async ({ did, projectId, manager }) => {
|
|
63
|
+
if (!projectId) {
|
|
64
|
+
throw new Error('projectId is required');
|
|
65
|
+
}
|
|
66
|
+
const { projectState, releaseState } = await manager._getProjectState(did);
|
|
67
|
+
const blocklet = await manager.getBlocklet(did);
|
|
68
|
+
const projectDir = path.join(blocklet.env.dataDir, PROJECT.DIR, `${projectId}`);
|
|
69
|
+
|
|
70
|
+
await projectState.remove({ id: projectId });
|
|
71
|
+
await releaseState.remove({ projectId });
|
|
72
|
+
await fs.remove(projectDir);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
// release
|
|
76
|
+
const getReleases = async ({ did, projectId, manager }) => {
|
|
77
|
+
const { releaseState } = await manager._getProjectState(did);
|
|
78
|
+
const releases = await releaseState.getReleases({ projectId });
|
|
79
|
+
return { releases };
|
|
80
|
+
};
|
|
81
|
+
const getRelease = async ({ did, projectId, releaseId, manager }) => {
|
|
82
|
+
const { releaseState } = await manager._getProjectState(did);
|
|
83
|
+
const release = await releaseState.findOne({ projectId, id: releaseId });
|
|
84
|
+
return release;
|
|
85
|
+
};
|
|
86
|
+
const deleteRelease = async ({ did, projectId, releaseId, manager }) => {
|
|
87
|
+
if (!projectId) {
|
|
88
|
+
throw new Error('projectId is required');
|
|
89
|
+
}
|
|
90
|
+
if (!releaseId) {
|
|
91
|
+
throw new Error('releaseId is required');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const blocklet = await manager.getBlocklet(did);
|
|
95
|
+
const { releaseState } = await manager._getProjectState(did);
|
|
96
|
+
const releaseDir = path.join(blocklet.env.dataDir, PROJECT.DIR, `${projectId}`, PROJECT.RELEASE_DIR, `${releaseId}`);
|
|
97
|
+
|
|
98
|
+
await releaseState.remove({ projectId, id: releaseId });
|
|
99
|
+
await fs.remove(releaseDir);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
const createRelease = async ({
|
|
103
|
+
did,
|
|
104
|
+
projectId,
|
|
105
|
+
releaseId,
|
|
106
|
+
blockletTitle,
|
|
107
|
+
blockletDescription,
|
|
108
|
+
blockletVersion,
|
|
109
|
+
blockletIntroduction,
|
|
110
|
+
blockletLogo,
|
|
111
|
+
blockletScreenshots,
|
|
112
|
+
note,
|
|
113
|
+
manager,
|
|
114
|
+
status,
|
|
115
|
+
}) => {
|
|
116
|
+
if (!projectId) {
|
|
117
|
+
throw new Error('projectId is required');
|
|
118
|
+
}
|
|
119
|
+
if (!PROJECT.RELEASE_STATUS[status]) {
|
|
120
|
+
throw new Error(`status is invalid: ${status}`);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const params = {
|
|
124
|
+
blockletVersion,
|
|
125
|
+
blockletTitle,
|
|
126
|
+
blockletDescription,
|
|
127
|
+
blockletLogo,
|
|
128
|
+
blockletIntroduction,
|
|
129
|
+
blockletScreenshots,
|
|
130
|
+
note,
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
const releaseSchema = createReleaseSchema(status);
|
|
134
|
+
await releaseSchema.validateAsync(params);
|
|
135
|
+
|
|
136
|
+
const blocklet = await manager.getBlocklet(did);
|
|
137
|
+
const { projectState, releaseState } = await manager._getProjectState(did);
|
|
138
|
+
|
|
139
|
+
const project = await projectState.findOne({ id: projectId });
|
|
140
|
+
if (!project) {
|
|
141
|
+
throw new Error('project not found');
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const action = releaseId ? 'update' : 'create';
|
|
145
|
+
|
|
146
|
+
if (action === 'update') {
|
|
147
|
+
const release = await releaseState.findOne({ projectId, id: releaseId });
|
|
148
|
+
if (!release) {
|
|
149
|
+
throw new Error('release not found');
|
|
150
|
+
}
|
|
151
|
+
if (release.status !== 'draft') {
|
|
152
|
+
throw new Error('Can not update a published release');
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const existVersion = await releaseState.findOne({ projectId, blockletVersion });
|
|
157
|
+
if (existVersion && (action === 'create' || existVersion.id !== releaseId)) {
|
|
158
|
+
throw new Error(`blockletVersion ${blockletVersion} already exists`);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
const { blockletDid } = project;
|
|
162
|
+
|
|
163
|
+
params.blockletDid = blockletDid;
|
|
164
|
+
|
|
165
|
+
const release = await releaseState.upsertRelease({
|
|
166
|
+
...params,
|
|
167
|
+
projectId,
|
|
168
|
+
releaseId,
|
|
169
|
+
status,
|
|
170
|
+
});
|
|
171
|
+
await projectState.updateProject(projectId, params);
|
|
172
|
+
|
|
173
|
+
const _releaseId = release.id;
|
|
174
|
+
|
|
175
|
+
const projectDir = path.join(blocklet.env.dataDir, PROJECT.DIR, `${projectId}`);
|
|
176
|
+
const tmpDir = path.join(manager.dataDirs.tmp, PROJECT.DIR, `${blockletDid}-${createRandomStr()}`);
|
|
177
|
+
const releaseDir = path.join(projectDir, PROJECT.RELEASE_DIR, `${_releaseId}`);
|
|
178
|
+
const resourceDir = path.join(releaseDir, PROJECT.RESOURCE_DIR);
|
|
179
|
+
const tmpResourceDir = path.join(projectDir, PROJECT.RESOURCE_DIR);
|
|
180
|
+
|
|
181
|
+
await fs.ensureDir(releaseDir);
|
|
182
|
+
|
|
183
|
+
// move tmp resource to release
|
|
184
|
+
if (action === 'create') {
|
|
185
|
+
await fs.ensureDir(tmpResourceDir);
|
|
186
|
+
await fs.remove(releaseDir);
|
|
187
|
+
await fs.ensureDir(releaseDir);
|
|
188
|
+
await fs.move(tmpResourceDir, resourceDir);
|
|
189
|
+
await fs.ensureDir(tmpResourceDir);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (status === PROJECT.RELEASE_STATUS.draft) {
|
|
193
|
+
return release;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
// create a release
|
|
197
|
+
if (fs.existsSync(tmpDir)) {
|
|
198
|
+
await fs.remove(tmpDir);
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const tmpExportDir = path.join(tmpDir, 'export');
|
|
202
|
+
const tmpBundleDir = path.join(tmpExportDir, 'bundle');
|
|
203
|
+
|
|
204
|
+
const moniker = (urlPathFriendly(slugify(release.blockletTitle)) || 'blocklet').toLowerCase();
|
|
205
|
+
const releaseFileName = `${moniker}-${release.blockletVersion}.zip`;
|
|
206
|
+
const releaseFile = path.join(releaseDir, releaseFileName);
|
|
207
|
+
if (fs.existsSync(releaseFile)) {
|
|
208
|
+
logger.error('release file already exists, remove it', releaseFile);
|
|
209
|
+
await fs.remove(releaseFile);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
try {
|
|
213
|
+
await fs.ensureDir(tmpBundleDir);
|
|
214
|
+
|
|
215
|
+
// create logo
|
|
216
|
+
const logoFile = project.blockletLogo
|
|
217
|
+
? path.join(projectDir, PROJECT.ASSET_DIR, project.blockletLogo)
|
|
218
|
+
: path.join(__dirname, 'logo.png');
|
|
219
|
+
const logoExt = path.extname(logoFile);
|
|
220
|
+
const logoFileName = `logo${logoExt}`;
|
|
221
|
+
await fs.copy(logoFile, path.join(tmpBundleDir, logoFileName));
|
|
222
|
+
|
|
223
|
+
// create screenshots
|
|
224
|
+
const screenshotsDistDir = path.join(tmpBundleDir, 'screenshots');
|
|
225
|
+
await fs.ensureDir(screenshotsDistDir);
|
|
226
|
+
if (project.blockletScreenshots?.length) {
|
|
227
|
+
await Promise.all(
|
|
228
|
+
project.blockletScreenshots.map(async (screenshot) => {
|
|
229
|
+
const screenshotFile = path.join(projectDir, PROJECT.ASSET_DIR, screenshot);
|
|
230
|
+
await fs.copy(screenshotFile, path.join(screenshotsDistDir, screenshot));
|
|
231
|
+
})
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
// create readme
|
|
236
|
+
if (blockletIntroduction) {
|
|
237
|
+
await fs.outputFile(path.join(tmpBundleDir, 'README.md'), blockletIntroduction);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// create blocklet.yml
|
|
241
|
+
const meta = {
|
|
242
|
+
did: blockletDid,
|
|
243
|
+
name: blockletDid,
|
|
244
|
+
title: blockletTitle,
|
|
245
|
+
description: blockletDescription,
|
|
246
|
+
version: blockletVersion,
|
|
247
|
+
logo: logoFileName,
|
|
248
|
+
resources: ['/resource'],
|
|
249
|
+
components: [],
|
|
250
|
+
files: ['screenshots'],
|
|
251
|
+
screenshots: project.blockletScreenshots || [],
|
|
252
|
+
};
|
|
253
|
+
|
|
254
|
+
await updateMetaFile(path.join(tmpBundleDir, BLOCKLET_META_FILE), meta);
|
|
255
|
+
|
|
256
|
+
// changelog
|
|
257
|
+
const changelogDistFile = path.join(tmpBundleDir, 'CHANGELOG.md');
|
|
258
|
+
const releases = await releaseState.getReleases({ projectId, status: PROJECT.RELEASE_STATUS.published });
|
|
259
|
+
const changelog = releases.map((_release) => {
|
|
260
|
+
const { blockletVersion: version, note: content } = _release;
|
|
261
|
+
return `## ${version}\n\n${content}`;
|
|
262
|
+
});
|
|
263
|
+
await fs.outputFile(changelogDistFile, changelog.join('\n\n'));
|
|
264
|
+
|
|
265
|
+
// create resource
|
|
266
|
+
await fs.ensureDir(resourceDir);
|
|
267
|
+
await fs.copy(resourceDir, path.join(tmpBundleDir, 'resource'));
|
|
268
|
+
|
|
269
|
+
// copy resource to tmpResourceDir
|
|
270
|
+
await fs.remove(tmpResourceDir);
|
|
271
|
+
await fs.copy(resourceDir, tmpResourceDir);
|
|
272
|
+
|
|
273
|
+
// create release
|
|
274
|
+
await createBlockletRelease(tmpExportDir, { printError: logger.error, printInfo: logger.info });
|
|
275
|
+
|
|
276
|
+
// archive
|
|
277
|
+
const archive = createArchive('zip', { zlib: { level: 9 } });
|
|
278
|
+
const writeStream = fs.createWriteStream(releaseFile);
|
|
279
|
+
|
|
280
|
+
await new Promise((resolve, reject) => {
|
|
281
|
+
archive
|
|
282
|
+
.directory(tmpExportDir, false)
|
|
283
|
+
.on('error', (err) => reject(err))
|
|
284
|
+
.pipe(writeStream);
|
|
285
|
+
|
|
286
|
+
writeStream.on('close', () => resolve(releaseFile));
|
|
287
|
+
archive.finalize();
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
const res2 = await releaseState.upsertRelease({
|
|
291
|
+
projectId,
|
|
292
|
+
releaseId: _releaseId,
|
|
293
|
+
files: [releaseFileName],
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
await fs.remove(tmpDir);
|
|
297
|
+
|
|
298
|
+
logger.info('create release success', res2);
|
|
299
|
+
|
|
300
|
+
return res2;
|
|
301
|
+
} catch (error) {
|
|
302
|
+
await fs.remove(tmpDir);
|
|
303
|
+
await fs.remove(releaseFile);
|
|
304
|
+
if (action === 'create') {
|
|
305
|
+
await fs.remove(releaseDir);
|
|
306
|
+
await releaseState.remove({ projectId, id: _releaseId });
|
|
307
|
+
} else {
|
|
308
|
+
await releaseState.update({ id: _releaseId }, { $set: { status: PROJECT.RELEASE_STATUS.draft } });
|
|
309
|
+
}
|
|
310
|
+
logger.error(`export ${project.type} error`, error);
|
|
311
|
+
throw error;
|
|
312
|
+
}
|
|
313
|
+
};
|
|
314
|
+
|
|
315
|
+
module.exports = {
|
|
316
|
+
createProject,
|
|
317
|
+
getProjects,
|
|
318
|
+
getProject,
|
|
319
|
+
updateProject,
|
|
320
|
+
deleteProject,
|
|
321
|
+
createRelease,
|
|
322
|
+
getReleases,
|
|
323
|
+
getRelease,
|
|
324
|
+
deleteRelease,
|
|
325
|
+
};
|
|
Binary file
|
package/lib/index.js
CHANGED
|
@@ -278,6 +278,17 @@ function ABTNode(options) {
|
|
|
278
278
|
migrateApplicationToStructV2: blockletManager.migrateApplicationToStructV2.bind(blockletManager),
|
|
279
279
|
syncAppConfig: blockletManager.syncAppConfig.bind(blockletManager),
|
|
280
280
|
|
|
281
|
+
// blocklet project
|
|
282
|
+
createProject: blockletManager.createProject.bind(blockletManager),
|
|
283
|
+
deleteProject: blockletManager.deleteProject.bind(blockletManager),
|
|
284
|
+
getProjects: blockletManager.getProjects.bind(blockletManager),
|
|
285
|
+
getProject: blockletManager.getProject.bind(blockletManager),
|
|
286
|
+
updateProject: blockletManager.updateProject.bind(blockletManager),
|
|
287
|
+
createRelease: blockletManager.createRelease.bind(blockletManager),
|
|
288
|
+
getReleases: blockletManager.getReleases.bind(blockletManager),
|
|
289
|
+
getRelease: blockletManager.getRelease.bind(blockletManager),
|
|
290
|
+
deleteRelease: blockletManager.deleteRelease.bind(blockletManager),
|
|
291
|
+
|
|
281
292
|
// For diagnose purpose
|
|
282
293
|
syncBlockletStatus: blockletManager.status.bind(blockletManager),
|
|
283
294
|
ensureBlockletIntegrity: blockletManager.ensureBlocklet.bind(blockletManager),
|
package/lib/router/helper.js
CHANGED
|
@@ -1209,6 +1209,8 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
1209
1209
|
|
|
1210
1210
|
const providers = {}; // we need to keep reference for different router instances
|
|
1211
1211
|
const handleRouting = async (nodeInfo) => {
|
|
1212
|
+
const now = Date.now();
|
|
1213
|
+
logger.info('start handle routing');
|
|
1212
1214
|
const providerName = get(nodeInfo, 'routing.provider', null);
|
|
1213
1215
|
const httpsEnabled = get(nodeInfo, 'routing.https', true);
|
|
1214
1216
|
logger.debug('handle routing', { providerName, httpsEnabled });
|
|
@@ -1272,6 +1274,8 @@ module.exports = function getRouterHelpers({ dataDirs, routingSnapshot, routerMa
|
|
|
1272
1274
|
|
|
1273
1275
|
await providers[providerName].start();
|
|
1274
1276
|
}
|
|
1277
|
+
|
|
1278
|
+
logger.info('done handle routing', { cost: Date.now() - now });
|
|
1275
1279
|
};
|
|
1276
1280
|
|
|
1277
1281
|
const rotateRouterLog = async () => {
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const pickBy = require('lodash/pickBy');
|
|
2
|
+
const pick = require('lodash/pick');
|
|
3
|
+
const BaseState = require('./base');
|
|
4
|
+
|
|
5
|
+
const isUndefinedOrNull = (x) => x === undefined || x === null;
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* @extends BaseState<import('@abtnode/models').ProjectState>
|
|
9
|
+
*/
|
|
10
|
+
class Project extends BaseState {
|
|
11
|
+
createProject({ type, blockletDid, blockletTitle }) {
|
|
12
|
+
return this.insert({ id: blockletDid, type, blockletDid, blockletTitle });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
getProjects() {
|
|
16
|
+
return this.find(
|
|
17
|
+
{},
|
|
18
|
+
{},
|
|
19
|
+
{
|
|
20
|
+
createdAt: -1,
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
async updateProject(id, params) {
|
|
26
|
+
const _params = pickBy(
|
|
27
|
+
pick(params, [
|
|
28
|
+
'name',
|
|
29
|
+
'blockletLogo',
|
|
30
|
+
'blockletVersion',
|
|
31
|
+
'blockletIntroduction',
|
|
32
|
+
'blockletTitle',
|
|
33
|
+
'blockletDescription',
|
|
34
|
+
'blockletDid',
|
|
35
|
+
'blockletScreenshots',
|
|
36
|
+
]),
|
|
37
|
+
(x) => !isUndefinedOrNull(x)
|
|
38
|
+
);
|
|
39
|
+
|
|
40
|
+
const [, [updated]] = await this.update({ id }, { $set: _params });
|
|
41
|
+
return updated;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
module.exports = Project;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
const pick = require('lodash/pick');
|
|
2
|
+
const BaseState = require('./base');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @extends BaseState<import('@abtnode/models').ReleaseState>
|
|
6
|
+
*/
|
|
7
|
+
class Release extends BaseState {
|
|
8
|
+
getReleases({ projectId, status } = {}) {
|
|
9
|
+
const query = { projectId };
|
|
10
|
+
if (status) {
|
|
11
|
+
query.status = status;
|
|
12
|
+
}
|
|
13
|
+
return this.find(
|
|
14
|
+
query,
|
|
15
|
+
{},
|
|
16
|
+
{
|
|
17
|
+
createdAt: -1,
|
|
18
|
+
}
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async upsertRelease({ releaseId, ...params }) {
|
|
23
|
+
const _params = pick(params, [
|
|
24
|
+
'projectId',
|
|
25
|
+
'blockletDid',
|
|
26
|
+
'blockletVersion',
|
|
27
|
+
'blockletTitle',
|
|
28
|
+
'blockletDescription',
|
|
29
|
+
'blockletLogo',
|
|
30
|
+
'blockletIntroduction',
|
|
31
|
+
'blockletScreenshots',
|
|
32
|
+
'note',
|
|
33
|
+
'status',
|
|
34
|
+
'files',
|
|
35
|
+
]);
|
|
36
|
+
|
|
37
|
+
if (!releaseId) {
|
|
38
|
+
return this.insert(_params);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const [, [updated]] = await this.update({ id: releaseId }, { $set: _params });
|
|
42
|
+
return updated;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
module.exports = Release;
|
package/lib/team/manager.js
CHANGED
|
@@ -32,6 +32,8 @@ const States = {
|
|
|
32
32
|
ConnectedAccount: require('../states/connect-account'),
|
|
33
33
|
Session: require('../states/session'),
|
|
34
34
|
Tag: require('../states/tag'),
|
|
35
|
+
Project: require('../states/project'),
|
|
36
|
+
Release: require('../states/release'),
|
|
35
37
|
};
|
|
36
38
|
|
|
37
39
|
const getDefaultTeamState = () => ({
|
|
@@ -41,6 +43,8 @@ const getDefaultTeamState = () => ({
|
|
|
41
43
|
connectedAccount: null,
|
|
42
44
|
session: null,
|
|
43
45
|
tag: null,
|
|
46
|
+
project: null,
|
|
47
|
+
release: null,
|
|
44
48
|
});
|
|
45
49
|
|
|
46
50
|
class TeamManager extends EventEmitter {
|
|
@@ -119,6 +123,13 @@ class TeamManager extends EventEmitter {
|
|
|
119
123
|
return this.getState(teamDid, 'session');
|
|
120
124
|
}
|
|
121
125
|
|
|
126
|
+
async getProjectState(teamDid) {
|
|
127
|
+
return {
|
|
128
|
+
projectState: await this.getState(teamDid, 'project'),
|
|
129
|
+
releaseState: await this.getState(teamDid, 'release'),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
122
133
|
async getState(teamDid, key) {
|
|
123
134
|
const pid = await this.getPid(teamDid);
|
|
124
135
|
if (!pid) {
|
package/lib/util/blocklet.js
CHANGED
package/lib/util/store.js
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const { Joi, titleSchema, descriptionSchema } = require('@blocklet/meta/lib/schema');
|
|
2
|
+
const { PROJECT } = require('@blocklet/constant');
|
|
3
|
+
|
|
4
|
+
const note = Joi.string().min(1).max(1000);
|
|
5
|
+
const blockletIntroduction = Joi.string().max(3000).allow('').allow(null);
|
|
6
|
+
const blockletScreenshots = Joi.array().items(Joi.string().min(1).max(200));
|
|
7
|
+
const blockletLogo = Joi.string().max(200).allow(null).allow('');
|
|
8
|
+
|
|
9
|
+
const createReleaseSchema = (status) =>
|
|
10
|
+
Joi.object({
|
|
11
|
+
note: status === PROJECT.RELEASE_STATUS.published ? note.required() : note.allow(''),
|
|
12
|
+
blockletVersion: Joi.semver().valid().required(),
|
|
13
|
+
blockletTitle: titleSchema.required(),
|
|
14
|
+
blockletDescription:
|
|
15
|
+
status === PROJECT.RELEASE_STATUS.published
|
|
16
|
+
? descriptionSchema.required()
|
|
17
|
+
: descriptionSchema.allow('').allow(null),
|
|
18
|
+
blockletScreenshots,
|
|
19
|
+
blockletIntroduction,
|
|
20
|
+
blockletLogo,
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
module.exports = {
|
|
24
|
+
note,
|
|
25
|
+
blockletIntroduction,
|
|
26
|
+
blockletScreenshots,
|
|
27
|
+
blockletLogo,
|
|
28
|
+
createReleaseSchema,
|
|
29
|
+
};
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "1.16.
|
|
6
|
+
"version": "1.16.17-beta-8cacb9b3",
|
|
7
7
|
"description": "",
|
|
8
8
|
"main": "lib/index.js",
|
|
9
9
|
"files": [
|
|
@@ -19,39 +19,39 @@
|
|
|
19
19
|
"author": "wangshijun <wangshijun2010@gmail.com> (http://github.com/wangshijun)",
|
|
20
20
|
"license": "Apache-2.0",
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@abtnode/analytics": "1.16.
|
|
23
|
-
"@abtnode/auth": "1.16.
|
|
24
|
-
"@abtnode/certificate-manager": "1.16.
|
|
25
|
-
"@abtnode/constant": "1.16.
|
|
26
|
-
"@abtnode/cron": "1.16.
|
|
27
|
-
"@abtnode/logger": "1.16.
|
|
28
|
-
"@abtnode/models": "1.16.
|
|
29
|
-
"@abtnode/queue": "1.16.
|
|
30
|
-
"@abtnode/rbac": "1.16.
|
|
31
|
-
"@abtnode/router-provider": "1.16.
|
|
32
|
-
"@abtnode/static-server": "1.16.
|
|
33
|
-
"@abtnode/timemachine": "1.16.
|
|
34
|
-
"@abtnode/util": "1.16.
|
|
35
|
-
"@arcblock/did": "1.18.
|
|
36
|
-
"@arcblock/did-auth": "1.18.
|
|
37
|
-
"@arcblock/did-ext": "^1.18.
|
|
22
|
+
"@abtnode/analytics": "1.16.17-beta-8cacb9b3",
|
|
23
|
+
"@abtnode/auth": "1.16.17-beta-8cacb9b3",
|
|
24
|
+
"@abtnode/certificate-manager": "1.16.17-beta-8cacb9b3",
|
|
25
|
+
"@abtnode/constant": "1.16.17-beta-8cacb9b3",
|
|
26
|
+
"@abtnode/cron": "1.16.17-beta-8cacb9b3",
|
|
27
|
+
"@abtnode/logger": "1.16.17-beta-8cacb9b3",
|
|
28
|
+
"@abtnode/models": "1.16.17-beta-8cacb9b3",
|
|
29
|
+
"@abtnode/queue": "1.16.17-beta-8cacb9b3",
|
|
30
|
+
"@abtnode/rbac": "1.16.17-beta-8cacb9b3",
|
|
31
|
+
"@abtnode/router-provider": "1.16.17-beta-8cacb9b3",
|
|
32
|
+
"@abtnode/static-server": "1.16.17-beta-8cacb9b3",
|
|
33
|
+
"@abtnode/timemachine": "1.16.17-beta-8cacb9b3",
|
|
34
|
+
"@abtnode/util": "1.16.17-beta-8cacb9b3",
|
|
35
|
+
"@arcblock/did": "1.18.91",
|
|
36
|
+
"@arcblock/did-auth": "1.18.91",
|
|
37
|
+
"@arcblock/did-ext": "^1.18.91",
|
|
38
38
|
"@arcblock/did-motif": "^1.1.13",
|
|
39
|
-
"@arcblock/did-util": "1.18.
|
|
40
|
-
"@arcblock/event-hub": "1.18.
|
|
41
|
-
"@arcblock/jwt": "^1.18.
|
|
39
|
+
"@arcblock/did-util": "1.18.91",
|
|
40
|
+
"@arcblock/event-hub": "1.18.91",
|
|
41
|
+
"@arcblock/jwt": "^1.18.91",
|
|
42
42
|
"@arcblock/pm2-events": "^0.0.5",
|
|
43
|
-
"@arcblock/validator": "^1.18.
|
|
44
|
-
"@arcblock/vc": "1.18.
|
|
45
|
-
"@blocklet/constant": "1.16.
|
|
46
|
-
"@blocklet/env": "1.16.
|
|
47
|
-
"@blocklet/meta": "1.16.
|
|
48
|
-
"@blocklet/resolver": "1.16.
|
|
49
|
-
"@blocklet/sdk": "1.16.
|
|
43
|
+
"@arcblock/validator": "^1.18.91",
|
|
44
|
+
"@arcblock/vc": "1.18.91",
|
|
45
|
+
"@blocklet/constant": "1.16.17-beta-8cacb9b3",
|
|
46
|
+
"@blocklet/env": "1.16.17-beta-8cacb9b3",
|
|
47
|
+
"@blocklet/meta": "1.16.17-beta-8cacb9b3",
|
|
48
|
+
"@blocklet/resolver": "1.16.17-beta-8cacb9b3",
|
|
49
|
+
"@blocklet/sdk": "1.16.17-beta-8cacb9b3",
|
|
50
50
|
"@did-space/client": "^0.3.8",
|
|
51
51
|
"@fidm/x509": "^1.2.1",
|
|
52
|
-
"@ocap/mcrypto": "1.18.
|
|
53
|
-
"@ocap/util": "1.18.
|
|
54
|
-
"@ocap/wallet": "1.18.
|
|
52
|
+
"@ocap/mcrypto": "1.18.91",
|
|
53
|
+
"@ocap/util": "1.18.91",
|
|
54
|
+
"@ocap/wallet": "1.18.91",
|
|
55
55
|
"@slack/webhook": "^5.0.4",
|
|
56
56
|
"archiver": "^5.3.1",
|
|
57
57
|
"axios": "^0.27.2",
|
|
@@ -70,6 +70,7 @@
|
|
|
70
70
|
"is-base64": "^1.1.0",
|
|
71
71
|
"is-url": "^1.2.4",
|
|
72
72
|
"joi": "17.7.0",
|
|
73
|
+
"joi-extension-semver": "^5.0.0",
|
|
73
74
|
"js-yaml": "^4.1.0",
|
|
74
75
|
"kill-port": "^2.0.1",
|
|
75
76
|
"lodash": "^4.17.21",
|
|
@@ -100,5 +101,5 @@
|
|
|
100
101
|
"jest": "^27.5.1",
|
|
101
102
|
"unzipper": "^0.10.11"
|
|
102
103
|
},
|
|
103
|
-
"gitHead": "
|
|
104
|
+
"gitHead": "0e3266f543b6d419a004ca94ee9efb572e3d9809"
|
|
104
105
|
}
|