@concord-consortium/object-storage 1.0.0-pre.4 → 1.0.0-pre.6
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/demo-object-storage.d.ts +4 -23
- package/dist/demo-object-storage.js +16 -64
- package/dist/firebase-object-storage.d.ts +23 -23
- package/dist/firebase-object-storage.js +152 -55
- package/dist/index.d.ts +1 -1
- package/dist/typed-object.d.ts +1 -1
- package/dist/typed-object.js +6 -1
- package/dist/types.d.ts +33 -10
- package/dist/types.js +1 -0
- package/package.json +3 -1
|
@@ -1,39 +1,20 @@
|
|
|
1
|
-
import { DemoObjectStorageConfig, IObjectStorage, ObjectMetadata, ObjectData, StoredObject,
|
|
1
|
+
import { DemoObjectStorageConfig, IObjectStorage, ObjectMetadata, ObjectData, StoredObject, MonitorCallback, DemonitorFunction, AddOptions, ObjectMetadataWithId } from './types';
|
|
2
2
|
export declare class DemoObjectStorage implements IObjectStorage {
|
|
3
3
|
private config;
|
|
4
4
|
private objects;
|
|
5
5
|
private monitors;
|
|
6
6
|
constructor(config: DemoObjectStorageConfig);
|
|
7
|
-
|
|
8
|
-
* Lists metadata documents for objects owned by the current user
|
|
9
|
-
*/
|
|
10
|
-
listMine(): Promise<ObjectWithId[]>;
|
|
11
|
-
/**
|
|
12
|
-
* Lists metadata documents for objects linked to the current user
|
|
13
|
-
*/
|
|
14
|
-
listLinked(): Promise<ObjectWithId[]>;
|
|
7
|
+
private getQuestionMetadata;
|
|
15
8
|
/**
|
|
16
9
|
* Lists metadata documents for objects associated with specific question IDs
|
|
17
10
|
*/
|
|
18
|
-
list(
|
|
19
|
-
/**
|
|
20
|
-
* Monitors metadata documents for objects owned by the current user
|
|
21
|
-
* Invokes callback at start and on any change
|
|
22
|
-
* Returns a function to stop monitoring
|
|
23
|
-
*/
|
|
24
|
-
monitorMine(callback: MonitorCallback): DemonitorFunction;
|
|
25
|
-
/**
|
|
26
|
-
* Monitors metadata documents for objects linked to the current user
|
|
27
|
-
* Invokes callback at start and on any change
|
|
28
|
-
* Returns a function to stop monitoring
|
|
29
|
-
*/
|
|
30
|
-
monitorLinked(callback: MonitorCallback): DemonitorFunction;
|
|
11
|
+
list(questionId: string): Promise<ObjectMetadataWithId[]>;
|
|
31
12
|
/**
|
|
32
13
|
* Monitors metadata documents for objects associated with specific question IDs
|
|
33
14
|
* Invokes callback at start and on any change
|
|
34
15
|
* Returns a function to stop monitoring
|
|
35
16
|
*/
|
|
36
|
-
monitor(
|
|
17
|
+
monitor(questionId: string, callback: MonitorCallback): DemonitorFunction;
|
|
37
18
|
/**
|
|
38
19
|
* Adds both metadata and data documents for a new object
|
|
39
20
|
* Returns the generated object ID (nanoid) or the provided ID if specified in options
|
|
@@ -11,76 +11,33 @@ class DemoObjectStorage {
|
|
|
11
11
|
this.objects = new Map();
|
|
12
12
|
this.monitors = new Map();
|
|
13
13
|
}
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
/**
|
|
21
|
-
* Lists metadata documents for objects linked to the current user
|
|
22
|
-
*/
|
|
23
|
-
async listLinked() {
|
|
24
|
-
// not applicable in demo storage
|
|
25
|
-
return [];
|
|
14
|
+
getQuestionMetadata() {
|
|
15
|
+
// In demo mode, just return all objects since there are no other questions
|
|
16
|
+
// that can use this storage instance
|
|
17
|
+
return Array.from(this.objects.entries()).map(([id, obj]) => {
|
|
18
|
+
return { id, metadata: obj.metadata };
|
|
19
|
+
});
|
|
26
20
|
}
|
|
27
21
|
/**
|
|
28
22
|
* Lists metadata documents for objects associated with specific question IDs
|
|
29
23
|
*/
|
|
30
|
-
async list(
|
|
31
|
-
|
|
32
|
-
return Array.from(this.objects.values());
|
|
33
|
-
}
|
|
34
|
-
/**
|
|
35
|
-
* Monitors metadata documents for objects owned by the current user
|
|
36
|
-
* Invokes callback at start and on any change
|
|
37
|
-
* Returns a function to stop monitoring
|
|
38
|
-
*/
|
|
39
|
-
monitorMine(callback) {
|
|
40
|
-
const key = 'mine';
|
|
41
|
-
if (!this.monitors.has(key)) {
|
|
42
|
-
this.monitors.set(key, []);
|
|
43
|
-
}
|
|
44
|
-
this.monitors.get(key).push(callback);
|
|
45
|
-
// Invoke callback immediately with current state
|
|
46
|
-
callback(Array.from(this.objects.values()));
|
|
47
|
-
return () => {
|
|
48
|
-
const callbacks = this.monitors.get(key);
|
|
49
|
-
if (callbacks) {
|
|
50
|
-
const index = callbacks.indexOf(callback);
|
|
51
|
-
if (index > -1) {
|
|
52
|
-
callbacks.splice(index, 1);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Monitors metadata documents for objects linked to the current user
|
|
59
|
-
* Invokes callback at start and on any change
|
|
60
|
-
* Returns a function to stop monitoring
|
|
61
|
-
*/
|
|
62
|
-
monitorLinked(callback) {
|
|
63
|
-
// not applicable in demo storage
|
|
64
|
-
callback([]);
|
|
65
|
-
return () => {
|
|
66
|
-
// no-op
|
|
67
|
-
};
|
|
24
|
+
async list(questionId) {
|
|
25
|
+
return this.getQuestionMetadata();
|
|
68
26
|
}
|
|
69
27
|
/**
|
|
70
28
|
* Monitors metadata documents for objects associated with specific question IDs
|
|
71
29
|
* Invokes callback at start and on any change
|
|
72
30
|
* Returns a function to stop monitoring
|
|
73
31
|
*/
|
|
74
|
-
monitor(
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
this.monitors.set(key, []);
|
|
32
|
+
monitor(questionId, callback) {
|
|
33
|
+
if (!this.monitors.has(questionId)) {
|
|
34
|
+
this.monitors.set(questionId, []);
|
|
78
35
|
}
|
|
79
|
-
this.monitors.get(
|
|
36
|
+
this.monitors.get(questionId).push(callback);
|
|
80
37
|
// Invoke callback immediately with current state
|
|
81
|
-
callback(
|
|
38
|
+
callback(this.getQuestionMetadata());
|
|
82
39
|
return () => {
|
|
83
|
-
const callbacks = this.monitors.get(
|
|
40
|
+
const callbacks = this.monitors.get(questionId);
|
|
84
41
|
if (callbacks) {
|
|
85
42
|
const index = callbacks.indexOf(callback);
|
|
86
43
|
if (index > -1) {
|
|
@@ -95,12 +52,7 @@ class DemoObjectStorage {
|
|
|
95
52
|
*/
|
|
96
53
|
async add(object, options) {
|
|
97
54
|
const id = options?.id ?? (0, nanoid_1.nanoid)();
|
|
98
|
-
|
|
99
|
-
id,
|
|
100
|
-
metadata: object.metadata,
|
|
101
|
-
data: object.data
|
|
102
|
-
};
|
|
103
|
-
this.objects.set(id, objectWithId);
|
|
55
|
+
this.objects.set(id, object);
|
|
104
56
|
// Notify all monitors
|
|
105
57
|
this.notifyMonitors();
|
|
106
58
|
return id;
|
|
@@ -151,7 +103,7 @@ class DemoObjectStorage {
|
|
|
151
103
|
* Notifies all active monitors of changes
|
|
152
104
|
*/
|
|
153
105
|
notifyMonitors() {
|
|
154
|
-
const allObjects =
|
|
106
|
+
const allObjects = this.getQuestionMetadata();
|
|
155
107
|
this.monitors.forEach(callbacks => {
|
|
156
108
|
callbacks.forEach(callback => callback(allObjects));
|
|
157
109
|
});
|
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "firebase/compat/auth";
|
|
2
|
+
import "firebase/compat/firestore";
|
|
3
|
+
import { FirebaseObjectStorageConfig, IObjectStorage, ObjectMetadata, ObjectData, StoredObject, MonitorCallback, DemonitorFunction, AddOptions, ObjectMetadataWithId } from './types';
|
|
2
4
|
export declare class FirebaseObjectStorage implements IObjectStorage {
|
|
3
5
|
private config;
|
|
6
|
+
private initPromise;
|
|
7
|
+
private initialized;
|
|
8
|
+
private app;
|
|
4
9
|
constructor(config: FirebaseObjectStorageConfig);
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
private initialize;
|
|
11
|
+
private ensureInitialized;
|
|
12
|
+
private createDocument;
|
|
13
|
+
private getPaths;
|
|
14
|
+
private getRefs;
|
|
15
|
+
private getMetadataQuery;
|
|
16
|
+
/**
|
|
17
|
+
* Ensures the provided ID is in question ID format as opposed to reference ID format
|
|
18
|
+
*
|
|
19
|
+
* eg: "404-MWInteractive" transforms to "mw_interactive_404"
|
|
20
|
+
*
|
|
21
|
+
* @param questionOrRefId
|
|
22
|
+
* @returns
|
|
23
|
+
*/
|
|
24
|
+
private ensureIdIsQuestionId;
|
|
13
25
|
/**
|
|
14
26
|
* Lists metadata documents for objects associated with specific question IDs
|
|
15
27
|
*/
|
|
16
|
-
list(
|
|
17
|
-
/**
|
|
18
|
-
* Monitors metadata documents for objects owned by the current user
|
|
19
|
-
* Invokes callback at start and on any change
|
|
20
|
-
* Returns a function to stop monitoring
|
|
21
|
-
*/
|
|
22
|
-
monitorMine(callback: MonitorCallback): DemonitorFunction;
|
|
23
|
-
/**
|
|
24
|
-
* Monitors metadata documents for objects linked to the current user
|
|
25
|
-
* Invokes callback at start and on any change
|
|
26
|
-
* Returns a function to stop monitoring
|
|
27
|
-
*/
|
|
28
|
-
monitorLinked(callback: MonitorCallback): DemonitorFunction;
|
|
28
|
+
list(questionOrRefId: string): Promise<ObjectMetadataWithId[]>;
|
|
29
29
|
/**
|
|
30
30
|
* Monitors metadata documents for objects associated with specific question IDs
|
|
31
31
|
* Invokes callback at start and on any change
|
|
32
32
|
* Returns a function to stop monitoring
|
|
33
33
|
*/
|
|
34
|
-
monitor(
|
|
34
|
+
monitor(questionOrRefId: string, callback: MonitorCallback): DemonitorFunction;
|
|
35
35
|
/**
|
|
36
36
|
* Adds both metadata and data documents for a new object
|
|
37
37
|
* Returns the generated object ID (nanoid) or the provided ID if specified in options
|
|
@@ -1,69 +1,146 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.FirebaseObjectStorage = void 0;
|
|
4
7
|
const nanoid_1 = require("nanoid");
|
|
8
|
+
const app_1 = __importDefault(require("firebase/compat/app"));
|
|
9
|
+
require("firebase/compat/auth");
|
|
10
|
+
require("firebase/compat/firestore");
|
|
5
11
|
class FirebaseObjectStorage {
|
|
6
12
|
constructor(config) {
|
|
13
|
+
this.initialized = false;
|
|
7
14
|
if (config.version !== 1) {
|
|
8
15
|
throw new Error(`Unsupported config version: ${config.version}. Expected version 1.`);
|
|
9
16
|
}
|
|
10
|
-
this.config = config;
|
|
17
|
+
this.config = { ...config };
|
|
18
|
+
// ensure the question id is in the correct format
|
|
19
|
+
this.config.questionId = this.ensureIdIsQuestionId(this.config.questionId);
|
|
20
|
+
this.app = app_1.default.initializeApp(this.config.app);
|
|
21
|
+
this.app.firestore().settings({
|
|
22
|
+
ignoreUndefinedProperties: true,
|
|
23
|
+
});
|
|
24
|
+
// Start initialization immediately in constructor
|
|
25
|
+
this.initPromise = this.initialize();
|
|
11
26
|
}
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
27
|
+
async initialize() {
|
|
28
|
+
if (this.initialized)
|
|
29
|
+
return;
|
|
30
|
+
if (this.config.user.type === "authenticated") {
|
|
31
|
+
// ensure any previous auth state is cleared before signing in
|
|
32
|
+
await this.app.auth().signOut();
|
|
33
|
+
await this.app.auth().signInWithCustomToken(this.config.user.jwt);
|
|
34
|
+
}
|
|
35
|
+
this.initialized = true;
|
|
18
36
|
}
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
*/
|
|
22
|
-
async listLinked() {
|
|
23
|
-
// TODO: Implement Firebase query for linked objects
|
|
24
|
-
return [];
|
|
37
|
+
async ensureInitialized() {
|
|
38
|
+
await this.initPromise;
|
|
25
39
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
40
|
+
createDocument(contents) {
|
|
41
|
+
const { questionId } = this.config;
|
|
42
|
+
if (this.config.user.type === "authenticated") {
|
|
43
|
+
const { contextId, platformId, platformUserId, resourceLinkId } = this.config.user;
|
|
44
|
+
return {
|
|
45
|
+
created_at: app_1.default.firestore.FieldValue.serverTimestamp(),
|
|
46
|
+
context_id: contextId,
|
|
47
|
+
platform_id: platformId,
|
|
48
|
+
platform_user_id: platformUserId,
|
|
49
|
+
resource_link_id: resourceLinkId,
|
|
50
|
+
run_key: "",
|
|
51
|
+
question_id: questionId,
|
|
52
|
+
...contents
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
const { runKey } = this.config.user;
|
|
57
|
+
return {
|
|
58
|
+
created_at: app_1.default.firestore.FieldValue.serverTimestamp(),
|
|
59
|
+
run_key: runKey,
|
|
60
|
+
platform_user_id: runKey,
|
|
61
|
+
question_id: questionId,
|
|
62
|
+
...contents
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
getPaths(objectId) {
|
|
67
|
+
const metadataPath = `${this.config.root}/object_store_metadata${objectId ? `/${objectId}` : ''}`;
|
|
68
|
+
const dataPath = `${this.config.root}/object_store_data${objectId ? `/${objectId}` : ''}`;
|
|
69
|
+
return { metadataPath, dataPath };
|
|
70
|
+
}
|
|
71
|
+
getRefs(objectId) {
|
|
72
|
+
const { metadataPath, dataPath } = this.getPaths(objectId);
|
|
73
|
+
const metadataRef = this.app.firestore().doc(metadataPath);
|
|
74
|
+
const dataRef = this.app.firestore().doc(dataPath);
|
|
75
|
+
return { metadataRef, dataRef };
|
|
76
|
+
}
|
|
77
|
+
getMetadataQuery(questionOrRefId) {
|
|
78
|
+
const questionId = this.ensureIdIsQuestionId(questionOrRefId);
|
|
79
|
+
const { metadataPath } = this.getPaths();
|
|
80
|
+
let query = this.app.firestore().collection(metadataPath)
|
|
81
|
+
.where("question_id", "==", questionId);
|
|
82
|
+
if (this.config.user.type === "authenticated") { // logged in user
|
|
83
|
+
const { contextId, platformId, resourceLinkId, platformUserId } = this.config.user;
|
|
84
|
+
query = query
|
|
85
|
+
.where("context_id", "==", contextId)
|
|
86
|
+
.where("platform_id", "==", platformId)
|
|
87
|
+
.where("platform_user_id", "==", platformUserId.toString())
|
|
88
|
+
.where("resource_link_id", "==", resourceLinkId);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
query = query.where("run_key", "==", this.config.user.runKey);
|
|
92
|
+
}
|
|
93
|
+
query = query.orderBy("created_at", "asc");
|
|
94
|
+
return query;
|
|
32
95
|
}
|
|
33
96
|
/**
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
97
|
+
* Ensures the provided ID is in question ID format as opposed to reference ID format
|
|
98
|
+
*
|
|
99
|
+
* eg: "404-MWInteractive" transforms to "mw_interactive_404"
|
|
100
|
+
*
|
|
101
|
+
* @param questionOrRefId
|
|
102
|
+
* @returns
|
|
37
103
|
*/
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
104
|
+
ensureIdIsQuestionId(questionOrRefId) {
|
|
105
|
+
const refIdRegEx = /(\d*)-(\D*)/g;
|
|
106
|
+
const parsed = refIdRegEx.exec(questionOrRefId);
|
|
107
|
+
if (parsed?.length) {
|
|
108
|
+
const [, embeddableId, embeddableType] = parsed;
|
|
109
|
+
const snakeCased = embeddableType.replace(/(?!^)([A-Z])/g, "_$1").toLowerCase();
|
|
110
|
+
return `${snakeCased}_${embeddableId}`;
|
|
111
|
+
}
|
|
112
|
+
return questionOrRefId;
|
|
44
113
|
}
|
|
45
114
|
/**
|
|
46
|
-
*
|
|
47
|
-
* Invokes callback at start and on any change
|
|
48
|
-
* Returns a function to stop monitoring
|
|
115
|
+
* Lists metadata documents for objects associated with specific question IDs
|
|
49
116
|
*/
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
117
|
+
async list(questionOrRefId) {
|
|
118
|
+
await this.ensureInitialized();
|
|
119
|
+
const query = this.getMetadataQuery(questionOrRefId);
|
|
120
|
+
const querySnapshot = await query.get();
|
|
121
|
+
const results = [];
|
|
122
|
+
querySnapshot.forEach(doc => {
|
|
123
|
+
results.push({ id: doc.id, metadata: doc.data().metadata });
|
|
124
|
+
});
|
|
125
|
+
return results;
|
|
56
126
|
}
|
|
57
127
|
/**
|
|
58
128
|
* Monitors metadata documents for objects associated with specific question IDs
|
|
59
129
|
* Invokes callback at start and on any change
|
|
60
130
|
* Returns a function to stop monitoring
|
|
61
131
|
*/
|
|
62
|
-
monitor(
|
|
63
|
-
//
|
|
64
|
-
|
|
132
|
+
monitor(questionOrRefId, callback) {
|
|
133
|
+
// await this.ensureInitialized();
|
|
134
|
+
const query = this.getMetadataQuery(questionOrRefId);
|
|
135
|
+
const unsub = query.onSnapshot(snapshot => {
|
|
136
|
+
const results = [];
|
|
137
|
+
snapshot.forEach(doc => {
|
|
138
|
+
results.push({ id: doc.id, metadata: doc.data().metadata });
|
|
139
|
+
});
|
|
140
|
+
callback(results);
|
|
141
|
+
});
|
|
65
142
|
return () => {
|
|
66
|
-
|
|
143
|
+
unsub();
|
|
67
144
|
};
|
|
68
145
|
}
|
|
69
146
|
/**
|
|
@@ -71,36 +148,56 @@ class FirebaseObjectStorage {
|
|
|
71
148
|
* Returns the generated object ID (nanoid) or the provided ID if specified in options
|
|
72
149
|
*/
|
|
73
150
|
async add(object, options) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const
|
|
151
|
+
await this.ensureInitialized();
|
|
152
|
+
const newObjectId = options?.id ?? (0, nanoid_1.nanoid)();
|
|
153
|
+
const { data, metadata } = object;
|
|
154
|
+
const { metadataRef, dataRef } = this.getRefs(newObjectId);
|
|
155
|
+
const dataDoc = this.createDocument({ data });
|
|
156
|
+
const metadataDoc = this.createDocument({ metadata });
|
|
157
|
+
const batch = this.app.firestore().batch();
|
|
158
|
+
batch.set(dataRef, dataDoc);
|
|
159
|
+
batch.set(metadataRef, metadataDoc);
|
|
160
|
+
await batch.commit();
|
|
78
161
|
return newObjectId;
|
|
79
162
|
}
|
|
80
163
|
/**
|
|
81
164
|
* Reads both metadata and data documents for an object
|
|
82
165
|
*/
|
|
83
166
|
async read(objectId) {
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
167
|
+
await this.ensureInitialized();
|
|
168
|
+
const metadata = await this.readMetadata(objectId);
|
|
169
|
+
if (!metadata) {
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
const data = await this.readData(objectId);
|
|
173
|
+
if (!data) {
|
|
174
|
+
return undefined;
|
|
175
|
+
}
|
|
176
|
+
return { metadata, data };
|
|
90
177
|
}
|
|
91
178
|
/**
|
|
92
179
|
* Reads only the metadata document for an object
|
|
93
180
|
*/
|
|
94
181
|
async readMetadata(objectId) {
|
|
95
|
-
|
|
96
|
-
|
|
182
|
+
await this.ensureInitialized();
|
|
183
|
+
const { metadataRef } = this.getRefs(objectId);
|
|
184
|
+
const metadataSnapshot = await metadataRef.get();
|
|
185
|
+
if (!metadataSnapshot.exists) {
|
|
186
|
+
return undefined;
|
|
187
|
+
}
|
|
188
|
+
return metadataSnapshot.data()?.metadata ?? {};
|
|
97
189
|
}
|
|
98
190
|
/**
|
|
99
191
|
* Reads only the data document for an object
|
|
100
192
|
*/
|
|
101
193
|
async readData(objectId) {
|
|
102
|
-
|
|
103
|
-
|
|
194
|
+
await this.ensureInitialized();
|
|
195
|
+
const { dataRef } = this.getRefs(objectId);
|
|
196
|
+
const dataSnapshot = await dataRef.get();
|
|
197
|
+
if (!dataSnapshot.exists) {
|
|
198
|
+
return undefined;
|
|
199
|
+
}
|
|
200
|
+
return dataSnapshot.data()?.data ?? {};
|
|
104
201
|
}
|
|
105
202
|
/**
|
|
106
203
|
* Generates a new unique ID using nanoid
|
package/dist/index.d.ts
CHANGED
|
@@ -2,5 +2,5 @@ export { DemoObjectStorage } from './demo-object-storage';
|
|
|
2
2
|
export { FirebaseObjectStorage } from './firebase-object-storage';
|
|
3
3
|
export { createObjectStorage } from './object-storage';
|
|
4
4
|
export { ObjectStorageProvider, useObjectStorage } from './object-storage-context';
|
|
5
|
-
export { IObjectStorage, ObjectStorageConfig, DemoObjectStorageConfig, FirebaseObjectStorageConfig, ObjectMetadata, ObjectData, StoredObject, ObjectWithId, MonitorCallback, DemonitorFunction } from './types';
|
|
5
|
+
export { IObjectStorage, ObjectStorageConfig, DemoObjectStorageConfig, FirebaseObjectStorageUser, FirebaseObjectStorageConfig, ObjectMetadata, ObjectData, StoredObject, ObjectWithId, MonitorCallback, DemonitorFunction } from './types';
|
|
6
6
|
export * from './typed-object';
|
package/dist/typed-object.d.ts
CHANGED
|
@@ -64,7 +64,7 @@ export declare class TypedObject implements StoredObject {
|
|
|
64
64
|
data: TypedData;
|
|
65
65
|
constructor(options?: TypedObjectOptions);
|
|
66
66
|
static IsSupportedTypedObject(storedObject: StoredObject): boolean;
|
|
67
|
-
static IsSupportedTypedObjectMetadata(storedObjectMetadata?: StoredObject["metadata"]):
|
|
67
|
+
static IsSupportedTypedObjectMetadata(storedObjectMetadata?: StoredObject["metadata"]): storedObjectMetadata is TypedMetadata;
|
|
68
68
|
static FromStoredObject(id: string, storedObject: StoredObject): TypedObject;
|
|
69
69
|
addImage(options: AddImageOptions): void;
|
|
70
70
|
addDataTable(options: AddDataTableOptions): void;
|
package/dist/typed-object.js
CHANGED
|
@@ -69,8 +69,13 @@ class TypedObject {
|
|
|
69
69
|
if (options.description !== undefined) {
|
|
70
70
|
this.metadata.items[id].description = options.description;
|
|
71
71
|
}
|
|
72
|
+
// firebase does not support nested arrays well, so we store rows as an object with numeric keys
|
|
73
|
+
const rowsObj = {};
|
|
74
|
+
options.rows.forEach((row, index) => {
|
|
75
|
+
rowsObj[index.toString()] = row;
|
|
76
|
+
});
|
|
72
77
|
this.data[id] = {
|
|
73
|
-
rows:
|
|
78
|
+
rows: rowsObj
|
|
74
79
|
};
|
|
75
80
|
}
|
|
76
81
|
addText(options) {
|
package/dist/types.d.ts
CHANGED
|
@@ -1,22 +1,35 @@
|
|
|
1
1
|
export interface DemoObjectStorageConfig {
|
|
2
|
-
type: "demo";
|
|
3
2
|
version: 1;
|
|
3
|
+
type: "demo";
|
|
4
|
+
}
|
|
5
|
+
export interface AuthenticatedUser {
|
|
6
|
+
type: "authenticated";
|
|
7
|
+
jwt: string;
|
|
8
|
+
contextId: string;
|
|
9
|
+
platformId: string;
|
|
10
|
+
resourceLinkId: string;
|
|
11
|
+
platformUserId: string;
|
|
12
|
+
}
|
|
13
|
+
export interface AnonymousUser {
|
|
14
|
+
type: "anonymous";
|
|
15
|
+
runKey: string;
|
|
4
16
|
}
|
|
17
|
+
export type FirebaseObjectStorageUser = AuthenticatedUser | AnonymousUser;
|
|
5
18
|
export interface FirebaseObjectStorageConfig {
|
|
6
|
-
type: "firebase";
|
|
7
19
|
version: 1;
|
|
20
|
+
type: "firebase";
|
|
21
|
+
app: Object;
|
|
22
|
+
root: string;
|
|
23
|
+
user: FirebaseObjectStorageUser;
|
|
24
|
+
questionId: string;
|
|
8
25
|
}
|
|
9
26
|
export type ObjectStorageConfig = DemoObjectStorageConfig | FirebaseObjectStorageConfig;
|
|
10
27
|
export interface AddOptions {
|
|
11
28
|
id?: string;
|
|
12
29
|
}
|
|
13
30
|
export interface IObjectStorage {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
list(questionIds: string[]): Promise<ObjectWithId[]>;
|
|
17
|
-
monitorMine(callback: MonitorCallback): DemonitorFunction;
|
|
18
|
-
monitorLinked(callback: MonitorCallback): DemonitorFunction;
|
|
19
|
-
monitor(questionIds: string[], callback: MonitorCallback): DemonitorFunction;
|
|
31
|
+
list(questionOrRefId: string): Promise<ObjectMetadataWithId[]>;
|
|
32
|
+
monitor(questionOrRefId: string, callback: MonitorCallback): DemonitorFunction;
|
|
20
33
|
add(object: StoredObject, options?: AddOptions): Promise<string>;
|
|
21
34
|
read(objectId: string): Promise<StoredObject | undefined>;
|
|
22
35
|
readMetadata(objectId: string): Promise<ObjectMetadata | undefined>;
|
|
@@ -33,8 +46,18 @@ export interface StoredObject {
|
|
|
33
46
|
metadata: ObjectMetadata;
|
|
34
47
|
data: ObjectData;
|
|
35
48
|
}
|
|
36
|
-
export interface
|
|
49
|
+
export interface ObjectMetadataWithId {
|
|
50
|
+
id: string;
|
|
51
|
+
metadata: ObjectMetadata;
|
|
52
|
+
}
|
|
53
|
+
export interface ObjectDataWithId {
|
|
54
|
+
id: string;
|
|
55
|
+
data: ObjectData;
|
|
56
|
+
}
|
|
57
|
+
export interface ObjectWithId {
|
|
37
58
|
id: string;
|
|
59
|
+
metadata: ObjectMetadata;
|
|
60
|
+
data: ObjectData;
|
|
38
61
|
}
|
|
39
|
-
export type MonitorCallback = (objects:
|
|
62
|
+
export type MonitorCallback = (objects: ObjectMetadataWithId[]) => void;
|
|
40
63
|
export type DemonitorFunction = () => void;
|
package/dist/types.js
CHANGED
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@concord-consortium/object-storage",
|
|
3
|
-
"version": "1.0.0-pre.
|
|
3
|
+
"version": "1.0.0-pre.6",
|
|
4
4
|
"description": "A TypeScript library for object storage",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"scripts": {
|
|
8
8
|
"build": "tsc",
|
|
9
|
+
"build:watch": "tsc --watch",
|
|
9
10
|
"test": "jest",
|
|
10
11
|
"test:watch": "jest --watch",
|
|
11
12
|
"test:coverage": "jest --coverage",
|
|
@@ -25,6 +26,7 @@
|
|
|
25
26
|
"access": "public"
|
|
26
27
|
},
|
|
27
28
|
"dependencies": {
|
|
29
|
+
"firebase": "^9.8.1",
|
|
28
30
|
"nanoid": "^3.3.7"
|
|
29
31
|
},
|
|
30
32
|
"peerDependencies": {
|