@did-space/core 0.5.18 → 0.5.19
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/dist/model/object-collection.d.ts +1 -1
- package/dist/model/object-collection.js +2 -2
- package/dist/model/object.d.ts +1 -1
- package/dist/model/object.js +2 -2
- package/dist/model/space.d.ts +21 -0
- package/dist/model/space.js +7 -0
- package/dist/model/tree.d.ts +11 -9
- package/dist/model/tree.js +3 -3
- package/dist/protocols/space.d.ts +3 -1
- package/dist/space/global-space.js +5 -5
- package/dist/space/object-space.d.ts +8 -5
- package/dist/space/object-space.js +131 -138
- package/dist/space/space.d.ts +3 -1
- package/dist/space/space.js +3 -1
- package/package.json +3 -3
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ObjectCollectionRepositoryClass = void 0;
|
|
4
|
-
const
|
|
5
|
-
class ObjectCollectionRepositoryClass extends
|
|
4
|
+
const sequelize_1 = require("sequelize");
|
|
5
|
+
class ObjectCollectionRepositoryClass extends sequelize_1.Model {
|
|
6
6
|
}
|
|
7
7
|
exports.ObjectCollectionRepositoryClass = ObjectCollectionRepositoryClass;
|
package/dist/model/object.d.ts
CHANGED
package/dist/model/object.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ObjectRepositoryClass = void 0;
|
|
4
|
-
const
|
|
5
|
-
class ObjectRepositoryClass extends
|
|
4
|
+
const sequelize_1 = require("sequelize");
|
|
5
|
+
class ObjectRepositoryClass extends sequelize_1.Model {
|
|
6
6
|
}
|
|
7
7
|
exports.ObjectRepositoryClass = ObjectRepositoryClass;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Model } from 'sequelize';
|
|
2
|
+
import type { LiteralUnion } from 'type-fest';
|
|
3
|
+
export declare class SpaceRepositoryClass extends Model<SpaceRepositoryClass, SpaceRepositoryClass> {
|
|
4
|
+
id: string;
|
|
5
|
+
drive: string;
|
|
6
|
+
did: string;
|
|
7
|
+
type: LiteralUnion<'default' | 'buy', string>;
|
|
8
|
+
name: string;
|
|
9
|
+
description: string;
|
|
10
|
+
size: number;
|
|
11
|
+
assetDid: string;
|
|
12
|
+
metadata: {
|
|
13
|
+
usageReportId?: string;
|
|
14
|
+
usedUnit?: number;
|
|
15
|
+
};
|
|
16
|
+
createAt: Date;
|
|
17
|
+
updateAt: Date | string;
|
|
18
|
+
expireAt: Date;
|
|
19
|
+
ownerDid: string;
|
|
20
|
+
}
|
|
21
|
+
export type SpaceRepository = typeof SpaceRepositoryClass;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SpaceRepositoryClass = void 0;
|
|
4
|
+
const sequelize_1 = require("sequelize");
|
|
5
|
+
class SpaceRepositoryClass extends sequelize_1.Model {
|
|
6
|
+
}
|
|
7
|
+
exports.SpaceRepositoryClass = SpaceRepositoryClass;
|
package/dist/model/tree.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Model } from '
|
|
1
|
+
import { Model } from 'sequelize';
|
|
2
2
|
import { ObjectModel } from './object';
|
|
3
3
|
export interface TreeModel {
|
|
4
4
|
/**
|
|
@@ -17,7 +17,6 @@ export interface TreeModel {
|
|
|
17
17
|
spaceDid: string;
|
|
18
18
|
/**
|
|
19
19
|
* @description 当且仅当,指向文件夹的时候才为空
|
|
20
|
-
* @type {string}
|
|
21
20
|
* @column {DataTypes.CHAR(64)}
|
|
22
21
|
* @memberof Tree
|
|
23
22
|
*/
|
|
@@ -25,11 +24,10 @@ export interface TreeModel {
|
|
|
25
24
|
/**
|
|
26
25
|
* @description 绑定对象的上一级目录的 id
|
|
27
26
|
* @example /abc/
|
|
28
|
-
* @type {string}
|
|
29
27
|
* @column {DataTypes.BIGINT.UNSIGNED}
|
|
30
28
|
* @memberof Tree
|
|
31
29
|
*/
|
|
32
|
-
parentId: string;
|
|
30
|
+
parentId: null | string;
|
|
33
31
|
/**
|
|
34
32
|
* @description 等价于文件夹和文件的路径,注意不包含 SpaceDid
|
|
35
33
|
* @example /app 或 /app/objects
|
|
@@ -60,14 +58,16 @@ export interface TreeModel {
|
|
|
60
58
|
* @column {DataTypes.DATE}
|
|
61
59
|
* @memberof Tree
|
|
62
60
|
*/
|
|
63
|
-
createdAt: string;
|
|
61
|
+
createdAt: Date | string;
|
|
64
62
|
/**
|
|
65
63
|
* @description
|
|
66
64
|
* @type {string}
|
|
67
65
|
* @column {DataTypes.DATE}
|
|
68
66
|
* @memberof Tree
|
|
69
67
|
*/
|
|
70
|
-
updatedAt: string;
|
|
68
|
+
updatedAt: Date | string;
|
|
69
|
+
size?: number;
|
|
70
|
+
count?: number;
|
|
71
71
|
}
|
|
72
72
|
export interface TreeModelMeta {
|
|
73
73
|
}
|
|
@@ -80,10 +80,12 @@ export declare class TreeRepositoryClass extends Model<TreeModel, CreationTreeMo
|
|
|
80
80
|
key: string;
|
|
81
81
|
type: number;
|
|
82
82
|
meta: TreeModelMeta;
|
|
83
|
-
createdAt:
|
|
84
|
-
updatedAt:
|
|
83
|
+
createdAt: Date;
|
|
84
|
+
updatedAt: Date;
|
|
85
|
+
size: number;
|
|
86
|
+
count: number;
|
|
85
87
|
Object: ObjectModel;
|
|
86
|
-
static deepCreate(
|
|
88
|
+
static deepCreate(_data: CreationTreeModel): Promise<TreeModel>;
|
|
87
89
|
[key: string]: any;
|
|
88
90
|
}
|
|
89
91
|
export type TreeRepository = typeof TreeRepositoryClass;
|
package/dist/model/tree.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.TreeModelDefaultMeta = exports.TreeModelType = exports.TreeRepositoryClass = void 0;
|
|
4
|
-
const
|
|
5
|
-
class TreeRepositoryClass extends
|
|
4
|
+
const sequelize_1 = require("sequelize");
|
|
5
|
+
class TreeRepositoryClass extends sequelize_1.Model {
|
|
6
6
|
// 不需要实现,只需要类型提示而已
|
|
7
7
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
8
|
-
static deepCreate(
|
|
8
|
+
static deepCreate(_data) {
|
|
9
9
|
throw new Error('not implemented');
|
|
10
10
|
}
|
|
11
11
|
}
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import type EventEmitter from 'events';
|
|
1
3
|
import { BaseSpaceProtocol } from './base-space';
|
|
2
4
|
import { DriverProtocol } from './driver';
|
|
3
|
-
export interface SpaceProtocol extends BaseSpaceProtocol {
|
|
5
|
+
export interface SpaceProtocol extends BaseSpaceProtocol, EventEmitter {
|
|
4
6
|
readonly driver: DriverProtocol;
|
|
5
7
|
}
|
|
@@ -14,7 +14,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.GlobalSpace = void 0;
|
|
16
16
|
const lodash_1 = require("lodash");
|
|
17
|
-
const
|
|
17
|
+
const sequelize_1 = require("sequelize");
|
|
18
18
|
const mime_types_1 = __importDefault(require("mime-types"));
|
|
19
19
|
const debug_1 = __importDefault(require("debug"));
|
|
20
20
|
const p_all_1 = __importDefault(require("p-all"));
|
|
@@ -118,11 +118,11 @@ class GlobalSpace {
|
|
|
118
118
|
objectId: hash,
|
|
119
119
|
};
|
|
120
120
|
debug('delete.$where', JSON.stringify(where));
|
|
121
|
-
const
|
|
121
|
+
const treeRefCount = yield this.treeRepository.count({
|
|
122
122
|
where,
|
|
123
123
|
});
|
|
124
|
-
debug('delete.$
|
|
125
|
-
if (
|
|
124
|
+
debug('delete.$treeRefCount', treeRefCount);
|
|
125
|
+
if (treeRefCount) {
|
|
126
126
|
yield this.objectCollectionRepository.destroy({ where: { id: hash } });
|
|
127
127
|
return;
|
|
128
128
|
}
|
|
@@ -143,7 +143,7 @@ class GlobalSpace {
|
|
|
143
143
|
const objects = yield this.objectCollectionRepository.findAll({
|
|
144
144
|
where: {
|
|
145
145
|
createdAt: {
|
|
146
|
-
[
|
|
146
|
+
[sequelize_1.Op.lt]: (0, dayjs_1.default)().subtract(10, 'm').toDate(),
|
|
147
147
|
},
|
|
148
148
|
},
|
|
149
149
|
attributes: ['id'],
|
|
@@ -1,23 +1,27 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
2
3
|
import { Stream } from 'stream';
|
|
4
|
+
import EventEmitter from 'events';
|
|
3
5
|
import { SpaceConfig } from '../configuration';
|
|
4
|
-
import { Object, Data } from '../meta';
|
|
6
|
+
import type { Object, Data } from '../meta';
|
|
5
7
|
import { AppSpaceOptions, DeleteOptions, DriverProtocol, GetHashOptions, KeyStatus, ListOptions, ListsOptions, PermissionOptions, ReadAsOwnerOptions, ReadOptions, SpaceProtocol, WriteAsOwnerOptions, WriteOptions } from '../protocols';
|
|
6
8
|
import { ObjectCollectionRepository, ObjectRepository, TreeRepository } from '../model';
|
|
7
9
|
import { GlobalSpace } from './global-space';
|
|
10
|
+
import type { SpaceRepository } from '../model/space';
|
|
8
11
|
export type ObjectSpaceOptions = {
|
|
9
12
|
driver: DriverProtocol;
|
|
10
13
|
spaceDid: string;
|
|
11
14
|
treeRepository: TreeRepository;
|
|
12
15
|
objectRepository: ObjectRepository;
|
|
13
16
|
objectCollectionRepository: ObjectCollectionRepository;
|
|
17
|
+
spaceRepository: SpaceRepository;
|
|
14
18
|
/**
|
|
15
19
|
* @description 忽略存储容量限制吗?
|
|
16
20
|
* @type {(false | true)}
|
|
17
21
|
*/
|
|
18
22
|
ignoreStorageLimit?: false | true;
|
|
19
23
|
};
|
|
20
|
-
export declare class ObjectSpace implements SpaceProtocol {
|
|
24
|
+
export declare class ObjectSpace extends EventEmitter implements SpaceProtocol {
|
|
21
25
|
readonly options: ObjectSpaceOptions;
|
|
22
26
|
readonly globalSpace: GlobalSpace;
|
|
23
27
|
readonly driver: DriverProtocol;
|
|
@@ -42,7 +46,6 @@ export declare class ObjectSpace implements SpaceProtocol {
|
|
|
42
46
|
*/
|
|
43
47
|
destroyAppSpace(options: AppSpaceOptions): Promise<void>;
|
|
44
48
|
getAppSpacePath(options: AppSpaceOptions): Promise<string>;
|
|
45
|
-
private verifySpace;
|
|
46
49
|
write(options: WriteOptions): Promise<void>;
|
|
47
50
|
delete(options: DeleteOptions): Promise<void>;
|
|
48
51
|
read(options: ReadOptions): Promise<Stream>;
|
|
@@ -75,8 +78,8 @@ export declare class ObjectSpace implements SpaceProtocol {
|
|
|
75
78
|
* @memberof ObjectSpace
|
|
76
79
|
*/
|
|
77
80
|
writeAsOwner(key: string, data: Data, options?: WriteAsOwnerOptions): Promise<void>;
|
|
78
|
-
private
|
|
79
|
-
private
|
|
81
|
+
private _updateAsOwner;
|
|
82
|
+
private _createAsOwner;
|
|
80
83
|
private updateMetadata;
|
|
81
84
|
deleteAsOwner(key: string): Promise<void>;
|
|
82
85
|
readAsOwner(key: string, options?: ReadAsOwnerOptions): Promise<Stream>;
|
|
@@ -14,14 +14,14 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.ObjectSpace = void 0;
|
|
16
16
|
const debug_1 = __importDefault(require("debug"));
|
|
17
|
-
const
|
|
17
|
+
const sequelize_1 = require("sequelize");
|
|
18
18
|
const js_yaml_1 = __importDefault(require("js-yaml"));
|
|
19
19
|
const path_1 = require("path");
|
|
20
20
|
const isEmpty_1 = __importDefault(require("lodash/isEmpty"));
|
|
21
21
|
const isUndefined_1 = __importDefault(require("lodash/isUndefined"));
|
|
22
22
|
const omit_1 = __importDefault(require("lodash/omit"));
|
|
23
|
-
const xbytes_1 = __importDefault(require("xbytes"));
|
|
24
23
|
const lodash_1 = require("lodash");
|
|
24
|
+
const events_1 = __importDefault(require("events"));
|
|
25
25
|
const configuration_1 = require("../configuration");
|
|
26
26
|
const model_1 = require("../model");
|
|
27
27
|
const utils_1 = require("../utils");
|
|
@@ -30,8 +30,9 @@ const constants_1 = require("../constants");
|
|
|
30
30
|
const stream_1 = require("../utils/stream");
|
|
31
31
|
const global_space_1 = require("./global-space");
|
|
32
32
|
const debug = (0, debug_1.default)('@did-space/core:ObjectSpace');
|
|
33
|
-
class ObjectSpace {
|
|
33
|
+
class ObjectSpace extends events_1.default {
|
|
34
34
|
constructor(options) {
|
|
35
|
+
super();
|
|
35
36
|
const { error } = schemas_1.ObjectSpaceOptionsSchema.validate(options, {
|
|
36
37
|
allowUnknown: true,
|
|
37
38
|
stripUnknown: true,
|
|
@@ -59,15 +60,14 @@ class ObjectSpace {
|
|
|
59
60
|
isSpaceCreated() {
|
|
60
61
|
return __awaiter(this, void 0, void 0, function* () {
|
|
61
62
|
const where = {
|
|
62
|
-
|
|
63
|
-
key: '/config.yml',
|
|
63
|
+
did: this.options.spaceDid,
|
|
64
64
|
};
|
|
65
65
|
debug('isSpaceCreated.before', JSON.stringify(where));
|
|
66
|
-
const created =
|
|
66
|
+
const created = yield this.options.spaceRepository.count({
|
|
67
67
|
where,
|
|
68
|
-
})
|
|
68
|
+
});
|
|
69
69
|
debug('isSpaceCreated.after', JSON.stringify({ created }));
|
|
70
|
-
return created;
|
|
70
|
+
return Boolean(created);
|
|
71
71
|
});
|
|
72
72
|
}
|
|
73
73
|
/**
|
|
@@ -118,34 +118,6 @@ class ObjectSpace {
|
|
|
118
118
|
// @ts-expect-error
|
|
119
119
|
return (0, path_1.join)(`/${constants_1.APPS}`, `${options.appDid}/`);
|
|
120
120
|
}
|
|
121
|
-
verifySpace(size = 0) {
|
|
122
|
-
var _a, _b;
|
|
123
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
124
|
-
debug('verifySpace.before', { size });
|
|
125
|
-
// 创建的时候怎么做空间大小检测呢?目前是跳过检测的
|
|
126
|
-
if (!(yield this.isSpaceCreated())) {
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
// 如果忽略了存储限制,直接不用校验了
|
|
130
|
-
if (this.options.ignoreStorageLimit) {
|
|
131
|
-
return;
|
|
132
|
-
}
|
|
133
|
-
const [did, capacity, usedCapacity] = yield Promise.all([
|
|
134
|
-
this.options.spaceDid,
|
|
135
|
-
// @FIXME: 此处应该用 cache 层的数据,可以加速查询
|
|
136
|
-
this.get('size'),
|
|
137
|
-
this.getSpaceSize(),
|
|
138
|
-
]);
|
|
139
|
-
const whiteList = ((_b = (_a = process.env) === null || _a === void 0 ? void 0 : _a.SPACE_WHITE_LIST) !== null && _b !== void 0 ? _b : '')
|
|
140
|
-
.split(',')
|
|
141
|
-
.map((s) => s.trim())
|
|
142
|
-
.filter(Boolean);
|
|
143
|
-
debug('verifySpace.before', { did, capacity, usedCapacity });
|
|
144
|
-
if (capacity && usedCapacity + size >= capacity && !whiteList.includes(did)) {
|
|
145
|
-
throw new Error(`Insufficient free space, total capacity is ${(0, xbytes_1.default)(capacity, { iec: true })}, used capacity is ${(0, xbytes_1.default)(usedCapacity, { iec: true })}`);
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
121
|
write(options) {
|
|
150
122
|
return __awaiter(this, void 0, void 0, function* () {
|
|
151
123
|
debug('write.before', JSON.stringify((0, omit_1.default)(options, 'data')));
|
|
@@ -156,10 +128,6 @@ class ObjectSpace {
|
|
|
156
128
|
if (error) {
|
|
157
129
|
throw error;
|
|
158
130
|
}
|
|
159
|
-
// @note: 只有新增的时候才会触发检测
|
|
160
|
-
if (!(yield this.exists(options))) {
|
|
161
|
-
yield this.verifySpace(options === null || options === void 0 ? void 0 : options.size);
|
|
162
|
-
}
|
|
163
131
|
const key = (0, path_1.join)(yield this.getAppSpacePath(options), options.key);
|
|
164
132
|
// @ts-expect-error
|
|
165
133
|
yield this.writeAsOwner(key, options.data, options);
|
|
@@ -195,7 +163,11 @@ class ObjectSpace {
|
|
|
195
163
|
if (!(yield this.exists(options))) {
|
|
196
164
|
throw new Error(`Object(${key}) not exists`);
|
|
197
165
|
}
|
|
198
|
-
const tree = yield this.options.treeRepository.findOne({
|
|
166
|
+
const tree = yield this.options.treeRepository.findOne({
|
|
167
|
+
where,
|
|
168
|
+
attributes: ['objectId'],
|
|
169
|
+
raw: true,
|
|
170
|
+
});
|
|
199
171
|
return tree.objectId;
|
|
200
172
|
});
|
|
201
173
|
}
|
|
@@ -215,6 +187,7 @@ class ObjectSpace {
|
|
|
215
187
|
debug('listsOneLevel.before', JSON.stringify(options));
|
|
216
188
|
const parentTree = yield this.options.treeRepository.findOne({
|
|
217
189
|
where,
|
|
190
|
+
attributes: ['id'],
|
|
218
191
|
raw: true,
|
|
219
192
|
});
|
|
220
193
|
debug('listsOneLevel.$parentTree', JSON.stringify(parentTree, null, 2));
|
|
@@ -228,7 +201,6 @@ class ObjectSpace {
|
|
|
228
201
|
return Promise.all(trees.map((x) => __awaiter(this, void 0, void 0, function* () {
|
|
229
202
|
const absolutePath = (0, path_1.join)(x.spaceDid, x.key);
|
|
230
203
|
if (x.type === model_1.TreeModelType.FOLDER) {
|
|
231
|
-
// @FIXME: 如果追求极速,此处是一个优化的点,文件夹不一定需要看到 更新时间和大小,S3 就是这么做的,默认是不展示的
|
|
232
204
|
const { size, lastModified } = yield this.getStatusAsOwner(x.key);
|
|
233
205
|
return {
|
|
234
206
|
key: x.key,
|
|
@@ -263,7 +235,7 @@ class ObjectSpace {
|
|
|
263
235
|
const where = {
|
|
264
236
|
spaceDid: this.options.spaceDid,
|
|
265
237
|
key: {
|
|
266
|
-
[
|
|
238
|
+
[sequelize_1.Op.like]: `${options.key}%`,
|
|
267
239
|
},
|
|
268
240
|
type: model_1.TreeModelType.FILE,
|
|
269
241
|
};
|
|
@@ -327,20 +299,20 @@ class ObjectSpace {
|
|
|
327
299
|
spaceDid: this.options.spaceDid,
|
|
328
300
|
key: options.key,
|
|
329
301
|
};
|
|
330
|
-
const
|
|
302
|
+
const tree = yield this.options.treeRepository.findOne({
|
|
331
303
|
where,
|
|
332
304
|
include: this.options.objectRepository,
|
|
333
305
|
});
|
|
334
306
|
return {
|
|
335
|
-
key:
|
|
336
|
-
name: (0, path_1.basename)(
|
|
337
|
-
isDir:
|
|
338
|
-
size:
|
|
339
|
-
lastModified: new Date(
|
|
307
|
+
key: tree.key,
|
|
308
|
+
name: (0, path_1.basename)(tree.key),
|
|
309
|
+
isDir: tree.type === model_1.TreeModelType.FOLDER,
|
|
310
|
+
size: tree.type === model_1.TreeModelType.FOLDER ? 0 : tree.Object.size,
|
|
311
|
+
lastModified: new Date(tree.updatedAt).getTime(),
|
|
340
312
|
editable: true,
|
|
341
|
-
mimeType:
|
|
342
|
-
absolutePath: (0, path_1.join)(
|
|
343
|
-
metadata:
|
|
313
|
+
mimeType: tree.type === model_1.TreeModelType.FOLDER ? null : tree.Object.meta.mimeType,
|
|
314
|
+
absolutePath: (0, path_1.join)(tree.spaceDid, tree.key),
|
|
315
|
+
metadata: tree.meta,
|
|
344
316
|
};
|
|
345
317
|
});
|
|
346
318
|
}
|
|
@@ -372,22 +344,30 @@ class ObjectSpace {
|
|
|
372
344
|
throw new Error('Hash and size cannot be empty');
|
|
373
345
|
}
|
|
374
346
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
347
|
+
try {
|
|
348
|
+
const exists = yield this.existsAsOwner(key);
|
|
349
|
+
debug('writeAsOwner.$exists', exists);
|
|
350
|
+
if (exists) {
|
|
351
|
+
// 更新对象
|
|
352
|
+
yield this._updateAsOwner(key, data, options);
|
|
353
|
+
}
|
|
354
|
+
else {
|
|
355
|
+
// 添加新对象
|
|
356
|
+
yield this._createAsOwner(key, data, options);
|
|
357
|
+
}
|
|
380
358
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
359
|
+
catch (err) {
|
|
360
|
+
utils_1.logger.error('writeAsOwner.$options', options);
|
|
361
|
+
utils_1.logger.error('writeAsOwner.$error', err);
|
|
362
|
+
throw err;
|
|
363
|
+
}
|
|
364
|
+
finally {
|
|
365
|
+
this.emit('space.writeAsOwner.after', { spaceDid: this.options.spaceDid, key });
|
|
366
|
+
debug('writeAsOwner.after', JSON.stringify({ key, options: (0, omit_1.default)(options, 'data') }));
|
|
386
367
|
}
|
|
387
|
-
debug('writeAsOwner.after', JSON.stringify({ key, options: (0, omit_1.default)(options, 'data') }));
|
|
388
368
|
});
|
|
389
369
|
}
|
|
390
|
-
|
|
370
|
+
_updateAsOwner(key, data, options) {
|
|
391
371
|
return __awaiter(this, void 0, void 0, function* () {
|
|
392
372
|
debug('updateAsOwner.before', { key, options: (0, omit_1.default)(options, 'data') });
|
|
393
373
|
yield this.updateMetadata(key, data, options);
|
|
@@ -401,12 +381,10 @@ class ObjectSpace {
|
|
|
401
381
|
spaceDid: this.options.spaceDid,
|
|
402
382
|
key,
|
|
403
383
|
};
|
|
404
|
-
debug('updateAsOwner.before', JSON.stringify({ key, options: (0, omit_1.default)(options, 'data'), where }));
|
|
405
384
|
const oldTree = yield this.options.treeRepository.findOne({
|
|
406
385
|
where,
|
|
407
386
|
include: this.options.objectRepository,
|
|
408
387
|
});
|
|
409
|
-
debug('updateAsOwner.$oldTree', JSON.stringify(oldTree));
|
|
410
388
|
const listObject = yield this.driver.list({
|
|
411
389
|
key: (0, utils_1.getHashPath)(options.hash),
|
|
412
390
|
useGlobal: true,
|
|
@@ -415,9 +393,10 @@ class ObjectSpace {
|
|
|
415
393
|
if (oldTree.objectId === options.hash &&
|
|
416
394
|
oldTree.Object.size === options.size &&
|
|
417
395
|
(listObject === null || listObject === void 0 ? void 0 : listObject.size) === options.size) {
|
|
418
|
-
//
|
|
396
|
+
// 内容不变,不需要再次存储对象,只需要更新对象的更新时间即可
|
|
419
397
|
yield this.options.treeRepository.update({
|
|
420
398
|
updatedAt: new Date().toISOString(),
|
|
399
|
+
size: options.size,
|
|
421
400
|
}, {
|
|
422
401
|
where: {
|
|
423
402
|
id: oldTree.id,
|
|
@@ -428,8 +407,9 @@ class ObjectSpace {
|
|
|
428
407
|
yield this.globalSpace.add(key, data, options);
|
|
429
408
|
// 更新 tree 记录
|
|
430
409
|
yield this.options.treeRepository.update({
|
|
431
|
-
updatedAt: new Date().toISOString(),
|
|
432
410
|
objectId: options.hash,
|
|
411
|
+
size: options.size,
|
|
412
|
+
updatedAt: new Date().toISOString(),
|
|
433
413
|
}, {
|
|
434
414
|
where: {
|
|
435
415
|
id: oldTree.id,
|
|
@@ -439,7 +419,7 @@ class ObjectSpace {
|
|
|
439
419
|
yield this.globalSpace.mark(oldTree.objectId);
|
|
440
420
|
});
|
|
441
421
|
}
|
|
442
|
-
|
|
422
|
+
_createAsOwner(key, data, options) {
|
|
443
423
|
return __awaiter(this, void 0, void 0, function* () {
|
|
444
424
|
debug('createAsOwner.before', JSON.stringify({ key, options: (0, omit_1.default)(options, 'data') }));
|
|
445
425
|
const isDir = key.endsWith('/');
|
|
@@ -451,24 +431,28 @@ class ObjectSpace {
|
|
|
451
431
|
parentId: null,
|
|
452
432
|
key,
|
|
453
433
|
type: model_1.TreeModelType.FOLDER,
|
|
434
|
+
count: 0,
|
|
435
|
+
size: 0,
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
else {
|
|
439
|
+
// 存储新对象到全局存储区
|
|
440
|
+
yield this.globalSpace.add(key, data, options);
|
|
441
|
+
// 添加 tree 记录
|
|
442
|
+
yield this.options.treeRepository.deepCreate({
|
|
443
|
+
spaceDid: this.options.spaceDid,
|
|
444
|
+
objectId: options.hash,
|
|
445
|
+
parentId: null,
|
|
446
|
+
key,
|
|
447
|
+
type: model_1.TreeModelType.FILE,
|
|
448
|
+
count: 1,
|
|
449
|
+
size: options.size,
|
|
454
450
|
});
|
|
455
|
-
yield this.updateMetadata(key, data, options);
|
|
456
|
-
return;
|
|
457
451
|
}
|
|
458
|
-
// 存储新对象到全局存储区
|
|
459
|
-
yield this.globalSpace.add(key, data, options);
|
|
460
|
-
// 添加 tree 记录
|
|
461
|
-
yield this.options.treeRepository.deepCreate({
|
|
462
|
-
spaceDid: this.options.spaceDid,
|
|
463
|
-
objectId: options.hash,
|
|
464
|
-
parentId: null,
|
|
465
|
-
key,
|
|
466
|
-
type: key.endsWith('/') ? model_1.TreeModelType.FOLDER : model_1.TreeModelType.FILE,
|
|
467
|
-
});
|
|
468
452
|
yield this.updateMetadata(key, data, options);
|
|
469
453
|
});
|
|
470
454
|
}
|
|
471
|
-
updateMetadata(key,
|
|
455
|
+
updateMetadata(key, _data, options) {
|
|
472
456
|
return __awaiter(this, void 0, void 0, function* () {
|
|
473
457
|
debug('updateMetadata.before', { key, options: (0, omit_1.default)(options, 'data') });
|
|
474
458
|
const where = {
|
|
@@ -479,11 +463,14 @@ class ObjectSpace {
|
|
|
479
463
|
debug('updateMetadata.before', JSON.stringify({ key, options: (0, omit_1.default)(options, 'data'), where }));
|
|
480
464
|
const oldTree = yield this.options.treeRepository.findOne({
|
|
481
465
|
where,
|
|
466
|
+
attributes: ['meta'],
|
|
467
|
+
raw: true,
|
|
482
468
|
});
|
|
483
469
|
debug('updateMetadata.$oldTree', JSON.stringify(oldTree));
|
|
484
470
|
if (!(0, isEmpty_1.default)(options.metadata)) {
|
|
485
471
|
yield oldTree.update({
|
|
486
472
|
meta: Object.assign(Object.assign({}, oldTree.meta), options.metadata),
|
|
473
|
+
updatedAt: new Date().toISOString(),
|
|
487
474
|
});
|
|
488
475
|
}
|
|
489
476
|
});
|
|
@@ -501,40 +488,51 @@ class ObjectSpace {
|
|
|
501
488
|
throw new Error(`Object ${key} cannot be deleted`);
|
|
502
489
|
}
|
|
503
490
|
const isDir = key.endsWith('/');
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
491
|
+
try {
|
|
492
|
+
if (isDir) {
|
|
493
|
+
// 删除文件夹
|
|
494
|
+
const whereForDeleteFolder = {
|
|
495
|
+
spaceDid: this.options.spaceDid,
|
|
496
|
+
// 删除以 key 开头的记录
|
|
497
|
+
key: {
|
|
498
|
+
[sequelize_1.Op.like]: `${key}%`,
|
|
499
|
+
},
|
|
500
|
+
};
|
|
501
|
+
debug('deleteAsOwner.$whereForDeleteFolder', JSON.stringify(whereForDeleteFolder));
|
|
502
|
+
const trees = yield this.options.treeRepository.findAll({
|
|
503
|
+
where: whereForDeleteFolder,
|
|
504
|
+
attributes: ['objectId'],
|
|
505
|
+
raw: true,
|
|
506
|
+
});
|
|
507
|
+
yield this.options.treeRepository.destroy({
|
|
508
|
+
where: whereForDeleteFolder,
|
|
509
|
+
});
|
|
510
|
+
yield this.globalSpace.mark(...trees.map((x) => x.objectId));
|
|
511
|
+
}
|
|
512
|
+
else {
|
|
513
|
+
const where = {
|
|
514
|
+
spaceDid: this.options.spaceDid,
|
|
515
|
+
key,
|
|
516
|
+
};
|
|
517
|
+
const tree = yield this.options.treeRepository.findOne({
|
|
518
|
+
where,
|
|
519
|
+
attributes: ['objectId'],
|
|
520
|
+
raw: true,
|
|
521
|
+
});
|
|
522
|
+
yield this.options.treeRepository.destroy({
|
|
523
|
+
where,
|
|
524
|
+
});
|
|
525
|
+
yield this.globalSpace.mark(tree.objectId);
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
catch (err) {
|
|
529
|
+
utils_1.logger.error('deleteAsOwner.$key', key);
|
|
530
|
+
utils_1.logger.error('deleteAsOwner.$error', err);
|
|
531
|
+
throw err;
|
|
532
|
+
}
|
|
533
|
+
finally {
|
|
534
|
+
this.emit('space.deleteAsOwner.after', { spaceDid: this.options.spaceDid, key });
|
|
524
535
|
}
|
|
525
|
-
const where = {
|
|
526
|
-
spaceDid: this.options.spaceDid,
|
|
527
|
-
key,
|
|
528
|
-
};
|
|
529
|
-
const tree = yield this.options.treeRepository.findOne({
|
|
530
|
-
where,
|
|
531
|
-
attributes: ['objectId'],
|
|
532
|
-
raw: true,
|
|
533
|
-
});
|
|
534
|
-
yield this.options.treeRepository.destroy({
|
|
535
|
-
where,
|
|
536
|
-
});
|
|
537
|
-
yield this.globalSpace.mark(tree.objectId);
|
|
538
536
|
});
|
|
539
537
|
}
|
|
540
538
|
readAsOwner(key, options) {
|
|
@@ -547,6 +545,8 @@ class ObjectSpace {
|
|
|
547
545
|
debug('readAsOwner.$where', JSON.stringify(where));
|
|
548
546
|
const tree = yield this.options.treeRepository.findOne({
|
|
549
547
|
where,
|
|
548
|
+
attributes: ['objectId'],
|
|
549
|
+
raw: true,
|
|
550
550
|
});
|
|
551
551
|
if (!tree) {
|
|
552
552
|
throw new Error(`Object(${key}) not exists`);
|
|
@@ -570,38 +570,31 @@ class ObjectSpace {
|
|
|
570
570
|
}
|
|
571
571
|
getStatusAsOwner(key) {
|
|
572
572
|
return __awaiter(this, void 0, void 0, function* () {
|
|
573
|
-
debug('getStatusAsOwner.before', JSON.stringify({
|
|
574
|
-
spaceDid: this.options.spaceDid,
|
|
575
|
-
key,
|
|
576
|
-
}));
|
|
577
573
|
const { error } = schemas_1.OwnerOperatorKeySchema.validate(key);
|
|
578
574
|
if (error) {
|
|
579
575
|
throw error;
|
|
580
576
|
}
|
|
581
577
|
const where = {
|
|
582
578
|
spaceDid: this.options.spaceDid,
|
|
583
|
-
key
|
|
584
|
-
|
|
585
|
-
},
|
|
586
|
-
type: model_1.TreeModelType.FILE,
|
|
579
|
+
key,
|
|
580
|
+
type: model_1.TreeModelType.FOLDER,
|
|
587
581
|
};
|
|
588
|
-
|
|
589
|
-
const objects = yield this.options.treeRepository.count({ where });
|
|
590
|
-
const lastModified = yield this.options.treeRepository.max('updatedAt', {
|
|
582
|
+
const tree = yield this.options.treeRepository.findOne({
|
|
591
583
|
where,
|
|
584
|
+
attributes: ['updatedAt', 'size', 'count'],
|
|
585
|
+
raw: true,
|
|
592
586
|
});
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
}));
|
|
587
|
+
if (!tree) {
|
|
588
|
+
return {
|
|
589
|
+
objects: 0,
|
|
590
|
+
size: 0,
|
|
591
|
+
lastModified: 0,
|
|
592
|
+
};
|
|
593
|
+
}
|
|
594
|
+
// @note: 我们采用了逐级冒泡的方式,从叶子节点自下而上的更新 folder 的更新时间,对象数,size
|
|
595
|
+
const objects = tree.count;
|
|
596
|
+
const lastModified = new Date(tree.updatedAt).getTime();
|
|
597
|
+
const { size } = tree;
|
|
605
598
|
return {
|
|
606
599
|
objects,
|
|
607
600
|
size,
|
package/dist/space/space.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
/// <reference types="node" />
|
|
2
3
|
import { Stream } from 'stream';
|
|
4
|
+
import EventEmitter from 'events';
|
|
3
5
|
import { SpaceConfig } from '../configuration';
|
|
4
6
|
import { Data, Object } from '../meta';
|
|
5
7
|
import { WriteOptions, ReadOptions, SpaceProtocol, DriverProtocol, AppSpaceOptions, PermissionOptions, DeleteOptions, ListOptions, ListsOptions, GetHashOptions, KeyStatus, ReadAsOwnerOptions, ExistsAsOwnerOptions } from '../protocols';
|
|
6
|
-
export declare class Space implements SpaceProtocol {
|
|
8
|
+
export declare class Space extends EventEmitter implements SpaceProtocol {
|
|
7
9
|
readonly driver: DriverProtocol;
|
|
8
10
|
static readonly READONLY_OBJECT_KEYS: string[];
|
|
9
11
|
constructor(driver: DriverProtocol);
|
package/dist/space/space.js
CHANGED
|
@@ -14,8 +14,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.Space = void 0;
|
|
16
16
|
const xbytes_1 = __importDefault(require("xbytes"));
|
|
17
|
-
|
|
17
|
+
const events_1 = __importDefault(require("events"));
|
|
18
|
+
class Space extends events_1.default {
|
|
18
19
|
constructor(driver) {
|
|
20
|
+
super();
|
|
19
21
|
this.driver = driver;
|
|
20
22
|
}
|
|
21
23
|
createSpace(spaceConfiguration) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@did-space/core",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.19",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
"mime-types": "^2.1.35",
|
|
40
40
|
"multiformats": "9",
|
|
41
41
|
"p-all": "3.0.0",
|
|
42
|
-
"
|
|
42
|
+
"sequelize": "^6.37.3",
|
|
43
43
|
"xbytes": "^1.9.1"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
@@ -53,5 +53,5 @@
|
|
|
53
53
|
"ts-jest": "^28.0.8",
|
|
54
54
|
"typescript": "^4.9.5"
|
|
55
55
|
},
|
|
56
|
-
"gitHead": "
|
|
56
|
+
"gitHead": "cf6bb7b57bf3391fead97351996e7f6f135b0e24"
|
|
57
57
|
}
|