@did-space/core 0.2.173 → 0.3.1
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/drivers/base.d.ts +5 -5
- package/dist/drivers/base.js +8 -8
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/meta/object.d.ts +5 -0
- package/dist/model/index.d.ts +3 -0
- package/dist/model/index.js +19 -0
- package/dist/model/object-collection.d.ts +28 -0
- package/dist/model/object-collection.js +7 -0
- package/dist/model/object.d.ts +59 -0
- package/dist/model/object.js +7 -0
- package/dist/model/tree.d.ts +94 -0
- package/dist/model/tree.js +18 -0
- package/dist/protocols/space-operator.d.ts +2 -0
- package/dist/protocols/space-owner-operator.d.ts +30 -4
- package/dist/schemas/global-space.d.ts +2 -0
- package/dist/schemas/global-space.js +21 -0
- package/dist/schemas/index.d.ts +1 -0
- package/dist/schemas/index.js +1 -0
- package/dist/schemas/object-space.d.ts +6 -0
- package/dist/schemas/object-space.js +39 -0
- package/dist/space/global-space.d.ts +43 -0
- package/dist/space/global-space.js +153 -0
- package/dist/space/index.d.ts +3 -45
- package/dist/space/index.js +16 -187
- package/dist/space/object-space.d.ts +111 -0
- package/dist/space/object-space.js +652 -0
- package/dist/space/space.d.ts +45 -0
- package/dist/space/space.js +190 -0
- package/dist/utils/common.d.ts +3 -0
- package/dist/utils/common.js +17 -0
- package/dist/utils/hash.d.ts +20 -0
- package/dist/utils/hash.js +60 -0
- package/dist/utils/index.d.ts +3 -2
- package/dist/utils/index.js +3 -2
- package/dist/utils/{string-to-stream.d.ts → stream.d.ts} +2 -0
- package/dist/utils/stream.js +23 -0
- package/package.json +12 -3
- package/dist/utils/stream-to-string.d.ts +0 -1
- package/dist/utils/stream-to-string.js +0 -10
- package/dist/utils/string-to-stream.js +0 -11
package/dist/drivers/base.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { Stream } from 'stream';
|
|
3
3
|
import { SpaceConfig } from '../configuration';
|
|
4
4
|
import { Data, Object } from '../meta';
|
|
5
|
-
import { AppSpaceOptions, DeleteOptions, DriverOptions, DriverProtocol, GetHashOptions, KeyStatus, ListOptions, ListsOptions, PermissionOptions, ReadOptions, SpaceConfigProtocol, SpaceOperatorProtocol, WriteOptions } from '../protocols';
|
|
5
|
+
import { AppSpaceOptions, DeleteOptions, DriverOptions, DriverProtocol, ExistsAsOwnerOptions, GetHashOptions, KeyStatus, ListOptions, ListsOptions, PermissionOptions, ReadAsOwnerOptions, ReadOptions, SpaceConfigProtocol, SpaceOperatorProtocol, WriteAsOwnerOptions, WriteOptions } from '../protocols';
|
|
6
6
|
export declare abstract class BaseDriver implements DriverProtocol {
|
|
7
7
|
readonly options: DriverOptions;
|
|
8
8
|
constructor(options: DriverOptions);
|
|
@@ -32,9 +32,9 @@ export declare abstract class BaseDriver implements DriverProtocol {
|
|
|
32
32
|
exists(options: ReadOptions): Promise<boolean>;
|
|
33
33
|
lists(options: ListsOptions): Promise<Object[]>;
|
|
34
34
|
list(options: ListOptions): Promise<Object>;
|
|
35
|
-
writeAsOwner(key: string, data: Data): Promise<void>;
|
|
36
|
-
deleteAsOwner(key: string): Promise<void>;
|
|
37
|
-
readAsOwner(key: string): Promise<Stream>;
|
|
38
|
-
existsAsOwner(key: string): Promise<boolean>;
|
|
35
|
+
writeAsOwner(key: string, data: Data, options?: WriteAsOwnerOptions): Promise<void>;
|
|
36
|
+
deleteAsOwner(key: string, options?: ReadAsOwnerOptions): Promise<void>;
|
|
37
|
+
readAsOwner(key: string, options?: ReadAsOwnerOptions): Promise<Stream>;
|
|
38
|
+
existsAsOwner(key: string, options?: ExistsAsOwnerOptions): Promise<boolean>;
|
|
39
39
|
getStatusAsOwner(key: string): Promise<KeyStatus>;
|
|
40
40
|
}
|
package/dist/drivers/base.js
CHANGED
|
@@ -134,17 +134,17 @@ class BaseDriver {
|
|
|
134
134
|
list(options) {
|
|
135
135
|
return this.spaceOperator.list(options);
|
|
136
136
|
}
|
|
137
|
-
writeAsOwner(key, data) {
|
|
138
|
-
return this.spaceOperator.writeAsOwner(key, data);
|
|
137
|
+
writeAsOwner(key, data, options) {
|
|
138
|
+
return this.spaceOperator.writeAsOwner(key, data, options);
|
|
139
139
|
}
|
|
140
|
-
deleteAsOwner(key) {
|
|
141
|
-
return this.spaceOperator.deleteAsOwner(key);
|
|
140
|
+
deleteAsOwner(key, options) {
|
|
141
|
+
return this.spaceOperator.deleteAsOwner(key, options);
|
|
142
142
|
}
|
|
143
|
-
readAsOwner(key) {
|
|
144
|
-
return this.spaceOperator.readAsOwner(key);
|
|
143
|
+
readAsOwner(key, options) {
|
|
144
|
+
return this.spaceOperator.readAsOwner(key, options);
|
|
145
145
|
}
|
|
146
|
-
existsAsOwner(key) {
|
|
147
|
-
return this.spaceOperator.existsAsOwner(key);
|
|
146
|
+
existsAsOwner(key, options) {
|
|
147
|
+
return this.spaceOperator.existsAsOwner(key, options);
|
|
148
148
|
}
|
|
149
149
|
getStatusAsOwner(key) {
|
|
150
150
|
return this.spaceOperator.getStatusAsOwner(key);
|
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -18,6 +18,7 @@ __exportStar(require("./configuration"), exports);
|
|
|
18
18
|
__exportStar(require("./constants"), exports);
|
|
19
19
|
__exportStar(require("./drivers"), exports);
|
|
20
20
|
__exportStar(require("./meta"), exports);
|
|
21
|
+
__exportStar(require("./model"), exports);
|
|
21
22
|
__exportStar(require("./protocols"), exports);
|
|
22
23
|
__exportStar(require("./schemas"), exports);
|
|
23
24
|
__exportStar(require("./space"), exports);
|
package/dist/meta/object.d.ts
CHANGED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./tree"), exports);
|
|
18
|
+
__exportStar(require("./object"), exports);
|
|
19
|
+
__exportStar(require("./object-collection"), exports);
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Model } from 'skypesky-sequelize';
|
|
2
|
+
/**
|
|
3
|
+
* @description 存储的是对象的信息,不保存结构,创建之初就确定了,只能增加,删除
|
|
4
|
+
* @export
|
|
5
|
+
* @interface ObjectModel
|
|
6
|
+
*/
|
|
7
|
+
export interface ObjectCollectionModel {
|
|
8
|
+
/**
|
|
9
|
+
* @primaryKey
|
|
10
|
+
* @description 对象的唯一标识,格式是 ipfs cid v1
|
|
11
|
+
* @type {string}
|
|
12
|
+
* @column {DataTypes.CHAR(64)}
|
|
13
|
+
* @memberof ObjectCollectionModel
|
|
14
|
+
*/
|
|
15
|
+
id: string;
|
|
16
|
+
/**
|
|
17
|
+
* @description 对象的创建时间
|
|
18
|
+
* @type {string}
|
|
19
|
+
* @column {DataTypes.DATE}
|
|
20
|
+
* @memberof ObjectCollectionModel
|
|
21
|
+
*/
|
|
22
|
+
createdAt: string;
|
|
23
|
+
}
|
|
24
|
+
export declare class ObjectCollectionRepositoryClass extends Model<ObjectCollectionModel> implements ObjectCollectionModel {
|
|
25
|
+
id: string;
|
|
26
|
+
createdAt: string;
|
|
27
|
+
}
|
|
28
|
+
export type ObjectCollectionRepository = typeof ObjectCollectionRepositoryClass;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ObjectCollectionRepositoryClass = void 0;
|
|
4
|
+
const skypesky_sequelize_1 = require("skypesky-sequelize");
|
|
5
|
+
class ObjectCollectionRepositoryClass extends skypesky_sequelize_1.Model {
|
|
6
|
+
}
|
|
7
|
+
exports.ObjectCollectionRepositoryClass = ObjectCollectionRepositoryClass;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Model } from 'skypesky-sequelize';
|
|
2
|
+
/**
|
|
3
|
+
* @description 存储的是对象的信息,不保存结构,创建之初就确定了,只能增加,删除
|
|
4
|
+
* @export
|
|
5
|
+
* @interface ObjectModel
|
|
6
|
+
*/
|
|
7
|
+
export interface ObjectModel {
|
|
8
|
+
/**
|
|
9
|
+
* @primaryKey
|
|
10
|
+
* @description 对象的唯一标识,格式是 ipfs cid v1
|
|
11
|
+
* @type {string}
|
|
12
|
+
* @column {DataTypes.STRING(59)}
|
|
13
|
+
* @memberof ObjectModel
|
|
14
|
+
*/
|
|
15
|
+
id: string;
|
|
16
|
+
/**
|
|
17
|
+
* @description 对象的大小
|
|
18
|
+
* @type {number}
|
|
19
|
+
* @column {DataTypes.BIGINT.UNSIGNED}
|
|
20
|
+
* @memberof ObjectModel
|
|
21
|
+
*/
|
|
22
|
+
size: number;
|
|
23
|
+
/**
|
|
24
|
+
* @description 存储对象的元数据
|
|
25
|
+
* @type {ObjectModelMeta}
|
|
26
|
+
* @column {DataTypes.JSON}
|
|
27
|
+
* @memberof ObjectModel
|
|
28
|
+
*/
|
|
29
|
+
meta: ObjectModelMeta;
|
|
30
|
+
/**
|
|
31
|
+
* @description 对象的创建时间
|
|
32
|
+
* @type {string}
|
|
33
|
+
* @column {DataTypes.DATE}
|
|
34
|
+
* @memberof ObjectModel
|
|
35
|
+
*/
|
|
36
|
+
createdAt: string;
|
|
37
|
+
}
|
|
38
|
+
export interface ObjectModelMeta {
|
|
39
|
+
/**
|
|
40
|
+
*
|
|
41
|
+
* @description 对象的 hash,如果对象是文件夹则为 null,否则必须有值
|
|
42
|
+
* @type {string}
|
|
43
|
+
* @memberof ObjectModelMeta
|
|
44
|
+
*/
|
|
45
|
+
mimeType: string;
|
|
46
|
+
/**
|
|
47
|
+
* @description 保存这个对象第一次出现的文件名
|
|
48
|
+
* @type {string}
|
|
49
|
+
* @memberof ObjectModelMeta
|
|
50
|
+
*/
|
|
51
|
+
key: string;
|
|
52
|
+
}
|
|
53
|
+
export declare class ObjectRepositoryClass extends Model<ObjectModel> implements ObjectModel {
|
|
54
|
+
id: string;
|
|
55
|
+
size: number;
|
|
56
|
+
meta: ObjectModelMeta;
|
|
57
|
+
createdAt: string;
|
|
58
|
+
}
|
|
59
|
+
export type ObjectRepository = typeof ObjectRepositoryClass;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ObjectRepositoryClass = void 0;
|
|
4
|
+
const skypesky_sequelize_1 = require("skypesky-sequelize");
|
|
5
|
+
class ObjectRepositoryClass extends skypesky_sequelize_1.Model {
|
|
6
|
+
}
|
|
7
|
+
exports.ObjectRepositoryClass = ObjectRepositoryClass;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { Model } from 'skypesky-sequelize';
|
|
2
|
+
import { ObjectModel } from './object';
|
|
3
|
+
export interface TreeModel {
|
|
4
|
+
/**
|
|
5
|
+
* @description uuidv4
|
|
6
|
+
* @type {string}
|
|
7
|
+
* @column {DataTypes.BIGINT.UNSIGNED}
|
|
8
|
+
* @memberof Tree
|
|
9
|
+
*/
|
|
10
|
+
id: string;
|
|
11
|
+
/**
|
|
12
|
+
* @description Space 的 DID
|
|
13
|
+
* @type {string}
|
|
14
|
+
* @column {DataTypes.STRING(40)}
|
|
15
|
+
* @memberof Tree
|
|
16
|
+
*/
|
|
17
|
+
spaceDid: string;
|
|
18
|
+
/**
|
|
19
|
+
* @description 当且仅当,指向文件夹的时候才为空
|
|
20
|
+
* @type {string}
|
|
21
|
+
* @column {DataTypes.CHAR(64)}
|
|
22
|
+
* @memberof Tree
|
|
23
|
+
*/
|
|
24
|
+
objectId: null | string;
|
|
25
|
+
/**
|
|
26
|
+
* @description 绑定对象的上一级目录的 id
|
|
27
|
+
* @example /abc/
|
|
28
|
+
* @type {string}
|
|
29
|
+
* @column {DataTypes.BIGINT.UNSIGNED}
|
|
30
|
+
* @memberof Tree
|
|
31
|
+
*/
|
|
32
|
+
parentId: string;
|
|
33
|
+
/**
|
|
34
|
+
* @description 等价于文件夹和文件的路径,注意不包含 SpaceDid
|
|
35
|
+
* @example /app 或 /app/objects
|
|
36
|
+
* @type {string}
|
|
37
|
+
* @column {DataTypes.STRING(1024)}
|
|
38
|
+
* @memberof Tree
|
|
39
|
+
*/
|
|
40
|
+
key: string;
|
|
41
|
+
/**
|
|
42
|
+
* @description folder or file
|
|
43
|
+
* @type {number}
|
|
44
|
+
* @column {DataTypes.TINYINT.UNSIGNED({ length: 1 })}
|
|
45
|
+
* @memberof Tree
|
|
46
|
+
*/
|
|
47
|
+
type: number;
|
|
48
|
+
/**
|
|
49
|
+
*
|
|
50
|
+
* @description
|
|
51
|
+
* @default {{}}
|
|
52
|
+
* @type {TreeMeta}
|
|
53
|
+
* @column {DataTypes.JSON}
|
|
54
|
+
* @memberof Tree
|
|
55
|
+
*/
|
|
56
|
+
meta: TreeModelMeta;
|
|
57
|
+
/**
|
|
58
|
+
* @description
|
|
59
|
+
* @type {string}
|
|
60
|
+
* @column {DataTypes.DATE}
|
|
61
|
+
* @memberof Tree
|
|
62
|
+
*/
|
|
63
|
+
createdAt: string;
|
|
64
|
+
/**
|
|
65
|
+
* @description
|
|
66
|
+
* @type {string}
|
|
67
|
+
* @column {DataTypes.DATE}
|
|
68
|
+
* @memberof Tree
|
|
69
|
+
*/
|
|
70
|
+
updatedAt: string;
|
|
71
|
+
}
|
|
72
|
+
export interface TreeModelMeta {
|
|
73
|
+
}
|
|
74
|
+
export type CreationTreeModel = Omit<TreeModel, 'id' | 'createdAt' | 'updatedAt' | 'meta'>;
|
|
75
|
+
export declare class TreeRepositoryClass extends Model<TreeModel, CreationTreeModel> implements TreeModel {
|
|
76
|
+
id: string;
|
|
77
|
+
spaceDid: string;
|
|
78
|
+
objectId: string;
|
|
79
|
+
parentId: string;
|
|
80
|
+
key: string;
|
|
81
|
+
type: number;
|
|
82
|
+
meta: TreeModelMeta;
|
|
83
|
+
createdAt: string;
|
|
84
|
+
updatedAt: string;
|
|
85
|
+
Object: ObjectModel;
|
|
86
|
+
static deepCreate(data: CreationTreeModel): Promise<TreeModel>;
|
|
87
|
+
[key: string]: any;
|
|
88
|
+
}
|
|
89
|
+
export type TreeRepository = typeof TreeRepositoryClass;
|
|
90
|
+
export declare enum TreeModelType {
|
|
91
|
+
FOLDER = 0,
|
|
92
|
+
FILE = 1
|
|
93
|
+
}
|
|
94
|
+
export declare const TreeModelDefaultMeta: {};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TreeModelDefaultMeta = exports.TreeModelType = exports.TreeRepositoryClass = void 0;
|
|
4
|
+
const skypesky_sequelize_1 = require("skypesky-sequelize");
|
|
5
|
+
class TreeRepositoryClass extends skypesky_sequelize_1.Model {
|
|
6
|
+
// 不需要实现,只需要类型提示而已
|
|
7
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
8
|
+
static deepCreate(data) {
|
|
9
|
+
throw new Error('not implemented');
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
exports.TreeRepositoryClass = TreeRepositoryClass;
|
|
13
|
+
var TreeModelType;
|
|
14
|
+
(function (TreeModelType) {
|
|
15
|
+
TreeModelType[TreeModelType["FOLDER"] = 0] = "FOLDER";
|
|
16
|
+
TreeModelType[TreeModelType["FILE"] = 1] = "FILE";
|
|
17
|
+
})(TreeModelType = exports.TreeModelType || (exports.TreeModelType = {}));
|
|
18
|
+
exports.TreeModelDefaultMeta = {};
|
|
@@ -10,6 +10,7 @@ export interface WriteOptions extends AppSpaceOptions {
|
|
|
10
10
|
key: string;
|
|
11
11
|
data: Data;
|
|
12
12
|
hash?: string;
|
|
13
|
+
size?: string;
|
|
13
14
|
}
|
|
14
15
|
export interface DeleteOptions extends AppSpaceOptions {
|
|
15
16
|
key: string;
|
|
@@ -40,6 +41,7 @@ export interface ListsOptions {
|
|
|
40
41
|
* @memberof ListOptions
|
|
41
42
|
*/
|
|
42
43
|
ignoreDirectories?: boolean;
|
|
44
|
+
useGlobal?: false | true;
|
|
43
45
|
}
|
|
44
46
|
export interface SpaceOperatorProtocol extends SpaceOwnerOperatorProtocol {
|
|
45
47
|
createSpace(spaceConfig: SpaceConfig): Promise<void>;
|
|
@@ -2,14 +2,40 @@
|
|
|
2
2
|
import { Stream } from 'stream';
|
|
3
3
|
import { Data } from '../meta';
|
|
4
4
|
export type KeyStatus = {
|
|
5
|
+
/**
|
|
6
|
+
* @description 文件夹已存储的对象个数
|
|
7
|
+
* @type {number}
|
|
8
|
+
*/
|
|
5
9
|
objects: number;
|
|
10
|
+
/**
|
|
11
|
+
* @description 文件夹的最新修改时间
|
|
12
|
+
* @type {number}
|
|
13
|
+
*/
|
|
6
14
|
lastModified: number;
|
|
15
|
+
/**
|
|
16
|
+
* @description 文件夹的总大小
|
|
17
|
+
* @type {number}
|
|
18
|
+
*/
|
|
7
19
|
size: number;
|
|
8
20
|
};
|
|
21
|
+
export type WriteAsOwnerOptions = {
|
|
22
|
+
hash: string;
|
|
23
|
+
size: number;
|
|
24
|
+
useGlobal?: false | true;
|
|
25
|
+
};
|
|
26
|
+
export type ReadAsOwnerOptions = {
|
|
27
|
+
useGlobal?: false | true;
|
|
28
|
+
};
|
|
29
|
+
export type DeleteAsOwnerOptions = {
|
|
30
|
+
useGlobal?: false | true;
|
|
31
|
+
};
|
|
32
|
+
export type ExistsAsOwnerOptions = {
|
|
33
|
+
useGlobal?: false | true;
|
|
34
|
+
};
|
|
9
35
|
export interface SpaceOwnerOperatorProtocol {
|
|
10
|
-
writeAsOwner(key: string, data: Data): Promise<void>;
|
|
11
|
-
deleteAsOwner(key: string): Promise<void>;
|
|
12
|
-
readAsOwner(key: string): Promise<Stream>;
|
|
13
|
-
existsAsOwner(key: string): Promise<boolean>;
|
|
36
|
+
writeAsOwner(key: string, data: Data, options?: WriteAsOwnerOptions): Promise<void>;
|
|
37
|
+
deleteAsOwner(key: string, options?: DeleteAsOwnerOptions): Promise<void>;
|
|
38
|
+
readAsOwner(key: string, options?: ReadAsOwnerOptions): Promise<Stream>;
|
|
39
|
+
existsAsOwner(key: string, options?: ExistsAsOwnerOptions): Promise<boolean>;
|
|
14
40
|
getStatusAsOwner(key: string): Promise<KeyStatus>;
|
|
15
41
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.HashSchema = exports.GlobalSpaceOptionsSchema = void 0;
|
|
4
|
+
const validator_1 = require("@arcblock/validator");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
exports.GlobalSpaceOptionsSchema = validator_1.Joi.object({
|
|
7
|
+
driver: validator_1.Joi.any().required(),
|
|
8
|
+
treeRepository: validator_1.Joi.any().required(),
|
|
9
|
+
objectRepository: validator_1.Joi.any().required(),
|
|
10
|
+
objectCollectionRepository: validator_1.Joi.any().required(),
|
|
11
|
+
gcMaxCount: validator_1.Joi.number().integer().optional().default(100),
|
|
12
|
+
gcMaxConcurrency: validator_1.Joi.number().integer().optional().default(8),
|
|
13
|
+
});
|
|
14
|
+
exports.HashSchema = validator_1.Joi.string()
|
|
15
|
+
.custom((value, helper) => {
|
|
16
|
+
if (!(0, utils_1.isCidV1)(value)) {
|
|
17
|
+
return helper.error(`Invalid hash(${value})`);
|
|
18
|
+
}
|
|
19
|
+
return value;
|
|
20
|
+
})
|
|
21
|
+
.required();
|
package/dist/schemas/index.d.ts
CHANGED
package/dist/schemas/index.js
CHANGED
|
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./space-options"), exports);
|
|
18
18
|
__exportStar(require("./space-configuration"), exports);
|
|
19
|
+
__exportStar(require("./object-space"), exports);
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const KeySchema: import("joi").StringSchema<string>;
|
|
2
|
+
export declare const WriteAsOwnerOptionsSchema: import("joi").ObjectSchema<any>;
|
|
3
|
+
export declare const ObjectSpaceOptionsSchema: import("joi").ObjectSchema<any>;
|
|
4
|
+
export declare const DeleteAsOwnerOptionsSchema: import("joi").ObjectSchema<any>;
|
|
5
|
+
export declare const WriteOptionsSchema: import("joi").ObjectSchema<any>;
|
|
6
|
+
export declare const GetHashOptionsSchema: import("joi").ObjectSchema<any>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GetHashOptionsSchema = exports.WriteOptionsSchema = exports.DeleteAsOwnerOptionsSchema = exports.ObjectSpaceOptionsSchema = exports.WriteAsOwnerOptionsSchema = exports.KeySchema = void 0;
|
|
4
|
+
const validator_1 = require("@arcblock/validator");
|
|
5
|
+
exports.KeySchema = validator_1.Joi.string().regex(/^\//).required();
|
|
6
|
+
const WriteAsOwnerOptionsByFolderSchema = {
|
|
7
|
+
is: validator_1.Joi.string().regex(/\/$/),
|
|
8
|
+
then: validator_1.Joi.valid(null).default(null),
|
|
9
|
+
otherwise: validator_1.Joi.required(),
|
|
10
|
+
};
|
|
11
|
+
exports.WriteAsOwnerOptionsSchema = validator_1.Joi.object({
|
|
12
|
+
key: exports.KeySchema,
|
|
13
|
+
data: validator_1.Joi.any().when('key', WriteAsOwnerOptionsByFolderSchema),
|
|
14
|
+
// @FIXME: 当 key 是文件夹 或者 data 不是一个 stream 的时候,hash, size 是可选的,现在的规则尝试之后没能做到这么精细化(使用 when 无法满足要求) @jianchao
|
|
15
|
+
hash: validator_1.Joi.string().optional().allow(null).default(null),
|
|
16
|
+
size: validator_1.Joi.number().integer().optional().allow(null).default(null),
|
|
17
|
+
useGlobal: validator_1.Joi.boolean().optional().default(false),
|
|
18
|
+
});
|
|
19
|
+
exports.ObjectSpaceOptionsSchema = validator_1.Joi.object({
|
|
20
|
+
driver: validator_1.Joi.any().required(),
|
|
21
|
+
spaceDid: validator_1.Joi.DID().required(),
|
|
22
|
+
treeRepository: validator_1.Joi.any().required(),
|
|
23
|
+
objectRepository: validator_1.Joi.any().required(),
|
|
24
|
+
objectCollectionRepository: validator_1.Joi.any().required(),
|
|
25
|
+
});
|
|
26
|
+
exports.DeleteAsOwnerOptionsSchema = validator_1.Joi.object({
|
|
27
|
+
key: exports.KeySchema,
|
|
28
|
+
});
|
|
29
|
+
exports.WriteOptionsSchema = validator_1.Joi.object({
|
|
30
|
+
appDid: validator_1.Joi.DID().required(),
|
|
31
|
+
key: validator_1.Joi.string().required(),
|
|
32
|
+
data: validator_1.Joi.any().required(),
|
|
33
|
+
hash: validator_1.Joi.string().optional().allow(null).default(null),
|
|
34
|
+
size: validator_1.Joi.number().integer().optional().allow(null).default(null),
|
|
35
|
+
});
|
|
36
|
+
exports.GetHashOptionsSchema = validator_1.Joi.object({
|
|
37
|
+
appDid: validator_1.Joi.DID().required(),
|
|
38
|
+
key: validator_1.Joi.string().required(),
|
|
39
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Data } from '../meta';
|
|
2
|
+
import { DriverProtocol, WriteAsOwnerOptions } from '../protocols';
|
|
3
|
+
import { ObjectCollectionRepository, ObjectRepository, TreeRepository } from '../model';
|
|
4
|
+
export type GlobalSpaceOptions = {
|
|
5
|
+
driver: DriverProtocol;
|
|
6
|
+
treeRepository: TreeRepository;
|
|
7
|
+
objectRepository: ObjectRepository;
|
|
8
|
+
objectCollectionRepository: ObjectCollectionRepository;
|
|
9
|
+
gcMaxCount?: 100 | number;
|
|
10
|
+
gcMaxConcurrency?: 8 | number;
|
|
11
|
+
};
|
|
12
|
+
export declare class GlobalSpace {
|
|
13
|
+
readonly driver: DriverProtocol;
|
|
14
|
+
readonly treeRepository: TreeRepository;
|
|
15
|
+
readonly objectRepository: ObjectRepository;
|
|
16
|
+
readonly objectCollectionRepository: ObjectCollectionRepository;
|
|
17
|
+
readonly gcMaxCount: number;
|
|
18
|
+
readonly gcMaxConcurrency: number;
|
|
19
|
+
constructor(options: GlobalSpaceOptions);
|
|
20
|
+
/**
|
|
21
|
+
* @description 存储新对象到全局存储区
|
|
22
|
+
* @param {string} key
|
|
23
|
+
* @param {Data} data
|
|
24
|
+
* @param {WriteAsOwnerOptions} options
|
|
25
|
+
* @return {*} {Promise<void>}
|
|
26
|
+
* @memberof GlobalSpace
|
|
27
|
+
*/
|
|
28
|
+
add(key: string, data: Data, options: WriteAsOwnerOptions): Promise<void>;
|
|
29
|
+
delete(hash: string): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* @description 清理未被使用的对象
|
|
32
|
+
* @return {Promise<void>} {Promise<void>}
|
|
33
|
+
* @memberof GlobalSpace
|
|
34
|
+
*/
|
|
35
|
+
gc(): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* @description 标记一个对象,以备之后回收
|
|
38
|
+
* @param {...string[]} hashList
|
|
39
|
+
* @return {Promise<void>} {Promise<void>}
|
|
40
|
+
* @memberof GlobalSpace
|
|
41
|
+
*/
|
|
42
|
+
mark(...hashList: string[]): Promise<void>;
|
|
43
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.GlobalSpace = void 0;
|
|
16
|
+
const lodash_1 = require("lodash");
|
|
17
|
+
const mime_types_1 = __importDefault(require("mime-types"));
|
|
18
|
+
const debug_1 = __importDefault(require("debug"));
|
|
19
|
+
const p_all_1 = __importDefault(require("p-all"));
|
|
20
|
+
const utils_1 = require("../utils");
|
|
21
|
+
const global_space_1 = require("../schemas/global-space");
|
|
22
|
+
const schemas_1 = require("../schemas");
|
|
23
|
+
const debug = (0, debug_1.default)('@did-space/core:GlobalSpace');
|
|
24
|
+
class GlobalSpace {
|
|
25
|
+
constructor(options) {
|
|
26
|
+
debug('GlobalSpace.constructor', JSON.stringify({ options: (0, lodash_1.pick)(options, 'gcMaxCount', 'gcMaxConcurrency') }));
|
|
27
|
+
const { error, value } = global_space_1.GlobalSpaceOptionsSchema.validate(options);
|
|
28
|
+
if (error) {
|
|
29
|
+
throw error;
|
|
30
|
+
}
|
|
31
|
+
this.driver = value.driver;
|
|
32
|
+
this.treeRepository = value.treeRepository;
|
|
33
|
+
this.objectRepository = value.objectRepository;
|
|
34
|
+
this.objectCollectionRepository = value.objectCollectionRepository;
|
|
35
|
+
this.gcMaxCount = value.gcMaxCount;
|
|
36
|
+
this.gcMaxConcurrency = value.gcMaxConcurrency;
|
|
37
|
+
debug('GlobalSpace.constructor', JSON.stringify({ gcMaxCount: value.gcMaxCount, gcMaxConcurrency: value.gcMaxConcurrency }));
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* @description 存储新对象到全局存储区
|
|
41
|
+
* @param {string} key
|
|
42
|
+
* @param {Data} data
|
|
43
|
+
* @param {WriteAsOwnerOptions} options
|
|
44
|
+
* @return {*} {Promise<void>}
|
|
45
|
+
* @memberof GlobalSpace
|
|
46
|
+
*/
|
|
47
|
+
add(key, data, options) {
|
|
48
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
49
|
+
// @note: 注意此处必须存储到全局存储区
|
|
50
|
+
// eslint-disable-next-line no-param-reassign
|
|
51
|
+
options = (0, lodash_1.merge)(options, { useGlobal: true });
|
|
52
|
+
debug('add.before', JSON.stringify({ key, options }));
|
|
53
|
+
const { error } = schemas_1.WriteAsOwnerOptionsSchema.validate(Object.assign(Object.assign({}, options), { key,
|
|
54
|
+
data }), { allowUnknown: true, stripUnknown: true });
|
|
55
|
+
if (error) {
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
const where = {
|
|
59
|
+
id: options.hash,
|
|
60
|
+
};
|
|
61
|
+
debug('add.$where', JSON.stringify(where));
|
|
62
|
+
const objectRecord = yield this.objectRepository.findOne({
|
|
63
|
+
where,
|
|
64
|
+
raw: true,
|
|
65
|
+
});
|
|
66
|
+
debug('add.$objectRecord', JSON.stringify(objectRecord));
|
|
67
|
+
if (objectRecord) {
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
// 存储新对象到全局存储区
|
|
71
|
+
const newKey = (0, utils_1.getHashPath)(options.hash);
|
|
72
|
+
yield this.driver.writeAsOwner(newKey, data, options);
|
|
73
|
+
// 添加 object 记录
|
|
74
|
+
yield this.objectRepository.create({
|
|
75
|
+
id: options.hash,
|
|
76
|
+
size: options.size,
|
|
77
|
+
meta: {
|
|
78
|
+
mimeType: mime_types_1.default.lookup(key) || null,
|
|
79
|
+
key,
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
debug('add.after', JSON.stringify({ objectRecord }));
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
delete(hash) {
|
|
86
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
87
|
+
const { error } = global_space_1.HashSchema.validate(hash);
|
|
88
|
+
if (error) {
|
|
89
|
+
throw error;
|
|
90
|
+
}
|
|
91
|
+
debug('delete.before', JSON.stringify({ hash }));
|
|
92
|
+
const where = {
|
|
93
|
+
objectId: hash,
|
|
94
|
+
};
|
|
95
|
+
debug('delete.$where', JSON.stringify(where));
|
|
96
|
+
const count = yield this.treeRepository.count({
|
|
97
|
+
where,
|
|
98
|
+
});
|
|
99
|
+
debug('delete.$count', count);
|
|
100
|
+
if (count) {
|
|
101
|
+
yield this.objectCollectionRepository.destroy({ where: { id: hash } });
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
yield this.driver.deleteAsOwner((0, utils_1.getHashPath)(hash), { useGlobal: true });
|
|
105
|
+
yield this.objectRepository.destroy({ where: { id: hash } });
|
|
106
|
+
yield this.objectCollectionRepository.destroy({ where: { id: hash } });
|
|
107
|
+
debug('delete.after', { hash });
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* @description 清理未被使用的对象
|
|
112
|
+
* @return {Promise<void>} {Promise<void>}
|
|
113
|
+
* @memberof GlobalSpace
|
|
114
|
+
*/
|
|
115
|
+
gc() {
|
|
116
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
117
|
+
debug('gc.before', 'start gc...');
|
|
118
|
+
const objects = yield this.objectCollectionRepository.findAll({
|
|
119
|
+
attributes: ['id'],
|
|
120
|
+
order: [['createdAt', 'ASC']],
|
|
121
|
+
limit: this.gcMaxCount,
|
|
122
|
+
});
|
|
123
|
+
debug('gc.$objects.length', objects.length);
|
|
124
|
+
const actions = objects.map((x) => {
|
|
125
|
+
return () => this.delete(x.id);
|
|
126
|
+
});
|
|
127
|
+
// 限制并发数量
|
|
128
|
+
yield (0, p_all_1.default)(actions, { concurrency: this.gcMaxConcurrency });
|
|
129
|
+
debug('gc.after', true);
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* @description 标记一个对象,以备之后回收
|
|
134
|
+
* @param {...string[]} hashList
|
|
135
|
+
* @return {Promise<void>} {Promise<void>}
|
|
136
|
+
* @memberof GlobalSpace
|
|
137
|
+
*/
|
|
138
|
+
mark(...hashList) {
|
|
139
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
140
|
+
debug('mark.before', true);
|
|
141
|
+
debug('mark.$hashList.length', hashList.length);
|
|
142
|
+
yield this.objectCollectionRepository.bulkCreate(hashList.map((hash) => {
|
|
143
|
+
return {
|
|
144
|
+
id: hash,
|
|
145
|
+
};
|
|
146
|
+
}), {
|
|
147
|
+
ignoreDuplicates: true,
|
|
148
|
+
});
|
|
149
|
+
debug('mark.after', true);
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
exports.GlobalSpace = GlobalSpace;
|