@concord-consortium/object-storage 1.0.0-pre.4 → 1.0.0-pre.5
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/firebase-object-storage.d.ts +10 -0
- package/dist/firebase-object-storage.js +79 -4
- package/dist/index.d.ts +1 -1
- package/dist/typed-object.js +6 -1
- package/dist/types.d.ts +18 -2
- package/dist/types.js +1 -0
- package/package.json +3 -1
|
@@ -1,7 +1,17 @@
|
|
|
1
|
+
import "firebase/compat/auth";
|
|
2
|
+
import "firebase/compat/firestore";
|
|
1
3
|
import { FirebaseObjectStorageConfig, IObjectStorage, ObjectMetadata, ObjectData, StoredObject, ObjectWithId, MonitorCallback, DemonitorFunction, AddOptions } 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);
|
|
10
|
+
private initialize;
|
|
11
|
+
private ensureInitialized;
|
|
12
|
+
private createDocument;
|
|
13
|
+
private getPaths;
|
|
14
|
+
private getRefs;
|
|
5
15
|
/**
|
|
6
16
|
* Lists metadata documents for objects owned by the current user
|
|
7
17
|
*/
|
|
@@ -1,18 +1,79 @@
|
|
|
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
17
|
this.config = config;
|
|
18
|
+
this.app = app_1.default.initializeApp(this.config.app);
|
|
19
|
+
this.app.firestore().settings({
|
|
20
|
+
ignoreUndefinedProperties: true,
|
|
21
|
+
});
|
|
22
|
+
// Start initialization immediately in constructor
|
|
23
|
+
this.initPromise = this.initialize();
|
|
24
|
+
}
|
|
25
|
+
async initialize() {
|
|
26
|
+
if (this.initialized)
|
|
27
|
+
return;
|
|
28
|
+
if (this.config.user.type === "authenticated") {
|
|
29
|
+
// ensure any previous auth state is cleared before signing in
|
|
30
|
+
await this.app.auth().signOut();
|
|
31
|
+
await this.app.auth().signInWithCustomToken(this.config.user.jwt);
|
|
32
|
+
}
|
|
33
|
+
this.initialized = true;
|
|
34
|
+
}
|
|
35
|
+
async ensureInitialized() {
|
|
36
|
+
await this.initPromise;
|
|
37
|
+
}
|
|
38
|
+
createDocument(contents) {
|
|
39
|
+
if (this.config.user.type === "authenticated") {
|
|
40
|
+
const { contextId, platformId, platformUserId, resourceLinkId } = this.config.user;
|
|
41
|
+
return {
|
|
42
|
+
created_at: app_1.default.firestore.FieldValue.serverTimestamp(),
|
|
43
|
+
platform_id: platformId,
|
|
44
|
+
platform_user_id: platformUserId.toString(),
|
|
45
|
+
context_id: contextId,
|
|
46
|
+
resource_link_id: resourceLinkId,
|
|
47
|
+
run_key: "",
|
|
48
|
+
...contents
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
const { runKey } = this.config.user;
|
|
53
|
+
return {
|
|
54
|
+
created_at: app_1.default.firestore.FieldValue.serverTimestamp(),
|
|
55
|
+
run_key: runKey,
|
|
56
|
+
platform_user_id: runKey,
|
|
57
|
+
...contents
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
getPaths(objectId) {
|
|
62
|
+
const metadataPath = `${this.config.root}/object_store_metadata/${objectId}`;
|
|
63
|
+
const dataPath = `${this.config.root}/object_store_data/${objectId}`;
|
|
64
|
+
return { metadataPath, dataPath };
|
|
65
|
+
}
|
|
66
|
+
getRefs(objectId) {
|
|
67
|
+
const { metadataPath, dataPath } = this.getPaths(objectId);
|
|
68
|
+
const metadataRef = this.app.firestore().doc(metadataPath);
|
|
69
|
+
const dataRef = this.app.firestore().doc(dataPath);
|
|
70
|
+
return { metadataRef, dataRef };
|
|
11
71
|
}
|
|
12
72
|
/**
|
|
13
73
|
* Lists metadata documents for objects owned by the current user
|
|
14
74
|
*/
|
|
15
75
|
async listMine() {
|
|
76
|
+
await this.ensureInitialized();
|
|
16
77
|
// TODO: Implement Firebase query for user's own objects
|
|
17
78
|
return [];
|
|
18
79
|
}
|
|
@@ -20,6 +81,7 @@ class FirebaseObjectStorage {
|
|
|
20
81
|
* Lists metadata documents for objects linked to the current user
|
|
21
82
|
*/
|
|
22
83
|
async listLinked() {
|
|
84
|
+
await this.ensureInitialized();
|
|
23
85
|
// TODO: Implement Firebase query for linked objects
|
|
24
86
|
return [];
|
|
25
87
|
}
|
|
@@ -27,6 +89,7 @@ class FirebaseObjectStorage {
|
|
|
27
89
|
* Lists metadata documents for objects associated with specific question IDs
|
|
28
90
|
*/
|
|
29
91
|
async list(questionIds) {
|
|
92
|
+
await this.ensureInitialized();
|
|
30
93
|
// TODO: Implement Firebase query for objects by question IDs
|
|
31
94
|
return [];
|
|
32
95
|
}
|
|
@@ -36,6 +99,7 @@ class FirebaseObjectStorage {
|
|
|
36
99
|
* Returns a function to stop monitoring
|
|
37
100
|
*/
|
|
38
101
|
monitorMine(callback) {
|
|
102
|
+
// await this.ensureInitialized();
|
|
39
103
|
// TODO: Implement Firebase realtime listener for user's own objects
|
|
40
104
|
callback([]);
|
|
41
105
|
return () => {
|
|
@@ -48,6 +112,7 @@ class FirebaseObjectStorage {
|
|
|
48
112
|
* Returns a function to stop monitoring
|
|
49
113
|
*/
|
|
50
114
|
monitorLinked(callback) {
|
|
115
|
+
// await this.ensureInitialized();
|
|
51
116
|
// TODO: Implement Firebase realtime listener for linked objects
|
|
52
117
|
callback([]);
|
|
53
118
|
return () => {
|
|
@@ -60,6 +125,7 @@ class FirebaseObjectStorage {
|
|
|
60
125
|
* Returns a function to stop monitoring
|
|
61
126
|
*/
|
|
62
127
|
monitor(questionIds, callback) {
|
|
128
|
+
// await this.ensureInitialized();
|
|
63
129
|
// TODO: Implement Firebase realtime listener for objects by question IDs
|
|
64
130
|
callback([]);
|
|
65
131
|
return () => {
|
|
@@ -71,16 +137,23 @@ class FirebaseObjectStorage {
|
|
|
71
137
|
* Returns the generated object ID (nanoid) or the provided ID if specified in options
|
|
72
138
|
*/
|
|
73
139
|
async add(object, options) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
const
|
|
140
|
+
await this.ensureInitialized();
|
|
141
|
+
const newObjectId = options?.id ?? (0, nanoid_1.nanoid)();
|
|
142
|
+
const { data, metadata } = object;
|
|
143
|
+
const { metadataRef, dataRef } = this.getRefs(newObjectId);
|
|
144
|
+
const dataDoc = this.createDocument({ data });
|
|
145
|
+
const metadataDoc = this.createDocument({ metadata });
|
|
146
|
+
const batch = this.app.firestore().batch();
|
|
147
|
+
batch.set(dataRef, dataDoc);
|
|
148
|
+
batch.set(metadataRef, metadataDoc);
|
|
149
|
+
await batch.commit();
|
|
78
150
|
return newObjectId;
|
|
79
151
|
}
|
|
80
152
|
/**
|
|
81
153
|
* Reads both metadata and data documents for an object
|
|
82
154
|
*/
|
|
83
155
|
async read(objectId) {
|
|
156
|
+
await this.ensureInitialized();
|
|
84
157
|
// TODO: Read metadata document from Firebase
|
|
85
158
|
// TODO: Read data document from Firebase
|
|
86
159
|
return {
|
|
@@ -92,6 +165,7 @@ class FirebaseObjectStorage {
|
|
|
92
165
|
* Reads only the metadata document for an object
|
|
93
166
|
*/
|
|
94
167
|
async readMetadata(objectId) {
|
|
168
|
+
await this.ensureInitialized();
|
|
95
169
|
// TODO: Read metadata document from Firebase
|
|
96
170
|
return {};
|
|
97
171
|
}
|
|
@@ -99,6 +173,7 @@ class FirebaseObjectStorage {
|
|
|
99
173
|
* Reads only the data document for an object
|
|
100
174
|
*/
|
|
101
175
|
async readData(objectId) {
|
|
176
|
+
await this.ensureInitialized();
|
|
102
177
|
// TODO: Read data document from Firebase
|
|
103
178
|
return {};
|
|
104
179
|
}
|
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.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,10 +1,26 @@
|
|
|
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
|
+
platformUserId: string;
|
|
11
|
+
resourceLinkId: string;
|
|
4
12
|
}
|
|
13
|
+
export interface AnonymousUser {
|
|
14
|
+
type: "anonymous";
|
|
15
|
+
runKey: string;
|
|
16
|
+
}
|
|
17
|
+
export type FirebaseObjectStorageUser = AuthenticatedUser | AnonymousUser;
|
|
5
18
|
export interface FirebaseObjectStorageConfig {
|
|
6
|
-
type: "firebase";
|
|
7
19
|
version: 1;
|
|
20
|
+
type: "firebase";
|
|
21
|
+
app: any;
|
|
22
|
+
root: string;
|
|
23
|
+
user: FirebaseObjectStorageUser;
|
|
8
24
|
}
|
|
9
25
|
export type ObjectStorageConfig = DemoObjectStorageConfig | FirebaseObjectStorageConfig;
|
|
10
26
|
export interface AddOptions {
|
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.5",
|
|
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": {
|