@mxpicture/gcp-functions 0.1.1 → 0.1.3
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/README.md +1 -1
- package/dist/cjs/FunctionCollection.js +17 -0
- package/dist/cjs/base/BaseApi.js +38 -0
- package/dist/cjs/base/BaseFunction.js +22 -0
- package/dist/cjs/base/BaseHttp.js +106 -0
- package/dist/cjs/common/firebase.js +1 -168
- package/dist/cjs/demo/User.js +31 -0
- package/dist/cjs/lib.js +10 -9
- package/dist/{esm/store/IStore.js → cjs/store/Store.js} +28 -23
- package/dist/cjs/store/types.store.js +3 -8
- package/dist/cjs/types/types.apiRoutes.js +2 -0
- package/dist/cjs/types/types.common.js +2 -0
- package/dist/cjs/types/types.function.js +2 -0
- package/dist/cjs/types/types.httpHandler.js +2 -0
- package/dist/cjs/validation/Validation.js +38 -0
- package/dist/esm/FunctionCollection.js +17 -0
- package/dist/esm/base/BaseApi.js +38 -0
- package/dist/esm/base/BaseFunction.js +22 -0
- package/dist/esm/base/BaseHttp.js +106 -0
- package/dist/esm/common/firebase.js +1 -168
- package/dist/esm/demo/User.js +31 -0
- package/dist/esm/lib.js +10 -9
- package/dist/{cjs/store/IStore.js → esm/store/Store.js} +28 -23
- package/dist/esm/store/types.store.js +3 -8
- package/dist/esm/types/types.apiRoutes.js +2 -0
- package/dist/esm/types/types.common.js +2 -0
- package/dist/esm/types/types.function.js +2 -0
- package/dist/esm/types/types.httpHandler.js +2 -0
- package/dist/esm/validation/Validation.js +38 -0
- package/dist/types/FunctionCollection.d.ts +12 -0
- package/dist/types/base/BaseApi.d.ts +26 -0
- package/dist/types/base/BaseFunction.d.ts +10 -0
- package/dist/types/base/BaseHttp.d.ts +21 -0
- package/dist/types/common/firebase.d.ts +0 -9
- package/dist/types/demo/User.d.ts +24 -0
- package/dist/types/lib.d.ts +11 -10
- package/dist/types/store/Store.d.ts +24 -0
- package/dist/types/store/types.store.d.ts +3 -14
- package/dist/types/types/types.apiRoutes.d.ts +29 -0
- package/dist/types/types/types.common.d.ts +10 -0
- package/dist/types/types/types.function.d.ts +10 -0
- package/dist/types/types/types.httpHandler.d.ts +5 -0
- package/dist/types/validation/Validation.d.ts +14 -0
- package/package.json +2 -1
- package/dist/cjs/FunctionHandlers.js +0 -18
- package/dist/cjs/api/IApi.js +0 -52
- package/dist/cjs/common/http.js +0 -147
- package/dist/cjs/common/types.common.js +0 -30
- package/dist/cjs/handler/HttpHandler.js +0 -41
- package/dist/cjs/handler/IHttpHandlerItem.js +0 -169
- package/dist/esm/FunctionHandlers.js +0 -18
- package/dist/esm/api/IApi.js +0 -52
- package/dist/esm/common/http.js +0 -147
- package/dist/esm/common/types.common.js +0 -30
- package/dist/esm/handler/HttpHandler.js +0 -41
- package/dist/esm/handler/IHttpHandlerItem.js +0 -169
- package/dist/types/FunctionHandlers.d.ts +0 -12
- package/dist/types/api/IApi.d.ts +0 -27
- package/dist/types/common/http.d.ts +0 -20
- package/dist/types/common/types.common.d.ts +0 -31
- package/dist/types/handler/HttpHandler.d.ts +0 -15
- package/dist/types/handler/IHttpHandlerItem.d.ts +0 -23
- package/dist/types/store/IStore.d.ts +0 -25
package/README.md
CHANGED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FunctionCollection = void 0;
|
|
4
|
+
class FunctionCollection {
|
|
5
|
+
constructor() {
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7
|
+
this.funcs = {};
|
|
8
|
+
}
|
|
9
|
+
add(name, func) {
|
|
10
|
+
this.funcs[name] = func;
|
|
11
|
+
return this;
|
|
12
|
+
}
|
|
13
|
+
build() {
|
|
14
|
+
return this.funcs;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.FunctionCollection = FunctionCollection;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseApi = void 0;
|
|
4
|
+
const zod_meta_1 = require("@mxpicture/zod-meta");
|
|
5
|
+
class BaseApi {
|
|
6
|
+
constructor(store, validation, shape) {
|
|
7
|
+
this.store = store;
|
|
8
|
+
this.validation = validation;
|
|
9
|
+
this.shape = shape;
|
|
10
|
+
}
|
|
11
|
+
async delete(p) {
|
|
12
|
+
return this.store.delete(p.id);
|
|
13
|
+
}
|
|
14
|
+
async get(p) {
|
|
15
|
+
return this.store.get(p.id);
|
|
16
|
+
}
|
|
17
|
+
async query() {
|
|
18
|
+
return this.store.query();
|
|
19
|
+
}
|
|
20
|
+
async count() {
|
|
21
|
+
return { count: await this.store.count() };
|
|
22
|
+
}
|
|
23
|
+
async exists(p) {
|
|
24
|
+
return { exists: await this.store.exists(p.id) };
|
|
25
|
+
}
|
|
26
|
+
async meta() {
|
|
27
|
+
return new zod_meta_1.Meta(this.shape).items();
|
|
28
|
+
}
|
|
29
|
+
async create(data) {
|
|
30
|
+
const result = await this.validation.validate(data);
|
|
31
|
+
return this.store.create(result);
|
|
32
|
+
}
|
|
33
|
+
async update(p, data) {
|
|
34
|
+
const result = await this.validation.validatePartial(data);
|
|
35
|
+
return this.store.update(p.id, result);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.BaseApi = BaseApi;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseFunction = void 0;
|
|
4
|
+
const https_1 = require("firebase-functions/https");
|
|
5
|
+
const ts_transformer_keys_1 = require("ts-transformer-keys");
|
|
6
|
+
class BaseFunction {
|
|
7
|
+
constructor(http) {
|
|
8
|
+
this.http = http;
|
|
9
|
+
this.httpMethods = (0, ts_transformer_keys_1.keys)();
|
|
10
|
+
}
|
|
11
|
+
createFunction() {
|
|
12
|
+
return (0, https_1.onCall)({ cors: [/firebase\.com$/, /web\.app$/] }, async (req) => {
|
|
13
|
+
if (!this.httpMethods.find((m) => m === req.data.route))
|
|
14
|
+
throw new https_1.HttpsError("invalid-argument", `Route ${req.data.route} not available`);
|
|
15
|
+
return {
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
|
+
doc: await this.http[req.data.route](req.data),
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.BaseFunction = BaseFunction;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseHttp = void 0;
|
|
4
|
+
const https_1 = require("firebase-functions/https");
|
|
5
|
+
class BaseHttp {
|
|
6
|
+
constructor(api) {
|
|
7
|
+
this.api = api;
|
|
8
|
+
}
|
|
9
|
+
async delete(req) {
|
|
10
|
+
try {
|
|
11
|
+
const id = req.keys?.id;
|
|
12
|
+
if (!id)
|
|
13
|
+
throw new https_1.HttpsError("invalid-argument", "Id invalid");
|
|
14
|
+
await this.api.delete({ id });
|
|
15
|
+
}
|
|
16
|
+
catch (error) {
|
|
17
|
+
if (error instanceof https_1.HttpsError)
|
|
18
|
+
throw error;
|
|
19
|
+
throw new https_1.HttpsError("not-found", `Id ${req.keys?.id} not found`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
async get(req) {
|
|
23
|
+
try {
|
|
24
|
+
const id = req.keys?.id;
|
|
25
|
+
if (!id)
|
|
26
|
+
throw new https_1.HttpsError("invalid-argument", "Id invalid");
|
|
27
|
+
return this.api.get({ id });
|
|
28
|
+
}
|
|
29
|
+
catch (error) {
|
|
30
|
+
if (error instanceof https_1.HttpsError)
|
|
31
|
+
throw error;
|
|
32
|
+
throw new https_1.HttpsError("not-found", `Id ${req.keys?.id} not found`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async query() {
|
|
36
|
+
try {
|
|
37
|
+
return this.api.query();
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
if (error instanceof https_1.HttpsError)
|
|
41
|
+
throw error;
|
|
42
|
+
throw new https_1.HttpsError("unknown", "Unknown error");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async count() {
|
|
46
|
+
try {
|
|
47
|
+
return this.api.count();
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
if (error instanceof https_1.HttpsError)
|
|
51
|
+
throw error;
|
|
52
|
+
throw new https_1.HttpsError("unknown", "Unknown error");
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async exists(req) {
|
|
56
|
+
try {
|
|
57
|
+
const id = req.keys?.id;
|
|
58
|
+
if (!id)
|
|
59
|
+
throw new https_1.HttpsError("invalid-argument", "Id invalid");
|
|
60
|
+
return await this.api.exists({ id });
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (error instanceof https_1.HttpsError)
|
|
64
|
+
throw error;
|
|
65
|
+
throw new https_1.HttpsError("unknown", "Unknown error");
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async meta() {
|
|
69
|
+
try {
|
|
70
|
+
return this.api.meta();
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
if (error instanceof https_1.HttpsError)
|
|
74
|
+
throw error;
|
|
75
|
+
throw new https_1.HttpsError("unknown", "Unknown error");
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
async create(req) {
|
|
79
|
+
try {
|
|
80
|
+
if (!req.content)
|
|
81
|
+
throw new https_1.HttpsError("invalid-argument", "Content is invalid");
|
|
82
|
+
return this.api.create(req.content);
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
if (error instanceof https_1.HttpsError)
|
|
86
|
+
throw error;
|
|
87
|
+
throw new https_1.HttpsError("unknown", "Unknown error");
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
async update(req) {
|
|
91
|
+
try {
|
|
92
|
+
const id = req.keys?.id;
|
|
93
|
+
if (!id)
|
|
94
|
+
throw new https_1.HttpsError("invalid-argument", "Id invalid");
|
|
95
|
+
if (!req.content)
|
|
96
|
+
throw new https_1.HttpsError("invalid-argument", "Content is invalid");
|
|
97
|
+
return this.api.update({ id }, req.content);
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
if (error instanceof https_1.HttpsError)
|
|
101
|
+
throw error;
|
|
102
|
+
throw new https_1.HttpsError("unknown", "Unknown error");
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.BaseHttp = BaseHttp;
|
|
@@ -1,174 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
const auth_1 = require("firebase-admin/auth");
|
|
3
|
+
exports.db = exports.app = void 0;
|
|
5
4
|
const firestore_1 = require("firebase-admin/firestore");
|
|
6
5
|
const app_1 = require("firebase-admin/app");
|
|
7
6
|
exports.app = (0, app_1.initializeApp)();
|
|
8
7
|
exports.db = (0, firestore_1.getFirestore)();
|
|
9
|
-
const extractToken = (request) => {
|
|
10
|
-
const auth = request.headers["authorization"];
|
|
11
|
-
if (!auth)
|
|
12
|
-
return;
|
|
13
|
-
// Read the ID Token from the Authorization header.
|
|
14
|
-
if (auth && auth.startsWith("Bearer "))
|
|
15
|
-
return auth.split("Bearer ")[1];
|
|
16
|
-
// Read the ID Token from cookie.
|
|
17
|
-
if (request.cookies)
|
|
18
|
-
return request.cookies.__session;
|
|
19
|
-
return;
|
|
20
|
-
};
|
|
21
|
-
exports.extractToken = extractToken;
|
|
22
|
-
// Express middleware that validates Firebase ID Tokens passed in the Authorization HTTP header.
|
|
23
|
-
// The Firebase ID token needs to be passed as a Bearer token in the Authorization HTTP header like this:
|
|
24
|
-
// `Authorization: Bearer <Firebase ID Token>`.
|
|
25
|
-
// when decoded successfully, the ID Token content will be added as `request.user`.
|
|
26
|
-
const verifyToken = (request, response, next) => {
|
|
27
|
-
const token = (0, exports.extractToken)(request);
|
|
28
|
-
if (!token) {
|
|
29
|
-
response
|
|
30
|
-
.status(401)
|
|
31
|
-
.json({ status: "unauthorized", message: "Unauthorized" });
|
|
32
|
-
return;
|
|
33
|
-
}
|
|
34
|
-
(0, auth_1.getAuth)()
|
|
35
|
-
.verifyIdToken(token)
|
|
36
|
-
.then((decodedIdToken) => {
|
|
37
|
-
// Only process if the user just signed in in the last 5 minutes.
|
|
38
|
-
if (Date.now() / 1000 - decodedIdToken.auth_time >= 5 * 60)
|
|
39
|
-
return response.status(401).json({
|
|
40
|
-
status: "unauthorized",
|
|
41
|
-
message: "Recent sign in required!",
|
|
42
|
-
});
|
|
43
|
-
request.user = decodedIdToken;
|
|
44
|
-
request.headers["x-id-token"] = token;
|
|
45
|
-
return next();
|
|
46
|
-
}, (error) => {
|
|
47
|
-
response.status(401).json({
|
|
48
|
-
status: "unauthorized",
|
|
49
|
-
message: JSON.stringify(error),
|
|
50
|
-
});
|
|
51
|
-
})
|
|
52
|
-
.catch((error) => {
|
|
53
|
-
response.status(401).json({
|
|
54
|
-
status: "unauthorized",
|
|
55
|
-
message: `Error while verifying Firebase ID token: ${error}`,
|
|
56
|
-
});
|
|
57
|
-
});
|
|
58
|
-
};
|
|
59
|
-
exports.verifyToken = verifyToken;
|
|
60
|
-
const verifySessionCookie = (request, response, next) => {
|
|
61
|
-
const sessionCookie =
|
|
62
|
-
// request.cookies.session ||
|
|
63
|
-
// request.cookies.zsession ||
|
|
64
|
-
request.cookies.__session || request.headers.zsession || "";
|
|
65
|
-
// Verify the session cookie. In this case an additional check is added to detect
|
|
66
|
-
// if the user's Firebase session was revoked, user deleted/disabled, etc.
|
|
67
|
-
(0, auth_1.getAuth)()
|
|
68
|
-
.verifySessionCookie(sessionCookie, true /** checkRevoked */)
|
|
69
|
-
.then(() => {
|
|
70
|
-
next();
|
|
71
|
-
}, (error) => {
|
|
72
|
-
response.status(401).json({
|
|
73
|
-
status: "unauthorized",
|
|
74
|
-
message: JSON.stringify(error),
|
|
75
|
-
});
|
|
76
|
-
})
|
|
77
|
-
.catch((error) => {
|
|
78
|
-
response.status(401).json({
|
|
79
|
-
status: "unauthorized",
|
|
80
|
-
message: JSON.stringify(error),
|
|
81
|
-
});
|
|
82
|
-
});
|
|
83
|
-
};
|
|
84
|
-
exports.verifySessionCookie = verifySessionCookie;
|
|
85
|
-
const verifyAuthAll = (token) => {
|
|
86
|
-
return (request, response, next) => {
|
|
87
|
-
const t = token();
|
|
88
|
-
// connection token
|
|
89
|
-
const id = request.headers["x-connection-token"];
|
|
90
|
-
if (typeof id === "string") {
|
|
91
|
-
if (id === t)
|
|
92
|
-
return next();
|
|
93
|
-
return response.status(401).json({
|
|
94
|
-
status: "unauthorized",
|
|
95
|
-
message: "",
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
// message connection token
|
|
99
|
-
if ((0, exports.extractToken)(request))
|
|
100
|
-
return (0, exports.verifyToken)(request, response, next);
|
|
101
|
-
// session cookie
|
|
102
|
-
return (0, exports.verifySessionCookie)(request, response, next);
|
|
103
|
-
};
|
|
104
|
-
};
|
|
105
|
-
exports.verifyAuthAll = verifyAuthAll;
|
|
106
|
-
const sessionLogin = (request, response) => {
|
|
107
|
-
// Get the ID token passed and the CSRF token.
|
|
108
|
-
const idToken = `${request.headers["x-id-token"]}`;
|
|
109
|
-
// Set session expiration to 5 days.
|
|
110
|
-
const expiresIn = 60 * 60 * 24 * 5 * 1000;
|
|
111
|
-
// Create the session cookie. This will also verify the ID token in the process.
|
|
112
|
-
// The session cookie will have the same claims as the ID token.
|
|
113
|
-
// To only allow session cookie setting on recent sign-in, auth_time in ID token
|
|
114
|
-
// can be checked to ensure user was recently signed in before creating a session cookie.
|
|
115
|
-
(0, auth_1.getAuth)()
|
|
116
|
-
.createSessionCookie(idToken, { expiresIn })
|
|
117
|
-
.then((sessionCookie) => {
|
|
118
|
-
// Set cookie policy for session cookie.
|
|
119
|
-
// cloud functions will only allow __session (issue only deployed)
|
|
120
|
-
response.cookie("__session", sessionCookie, {
|
|
121
|
-
maxAge: expiresIn,
|
|
122
|
-
httpOnly: true,
|
|
123
|
-
secure: true,
|
|
124
|
-
});
|
|
125
|
-
// const now = new Date();
|
|
126
|
-
// const zsession =
|
|
127
|
-
// "zsession=" +
|
|
128
|
-
// sessionCookie +
|
|
129
|
-
// "; expires=" +
|
|
130
|
-
// now.toUTCString() +
|
|
131
|
-
// "; path=/";
|
|
132
|
-
response.end(JSON.stringify({
|
|
133
|
-
status: "success",
|
|
134
|
-
// zsession: zsession,
|
|
135
|
-
}));
|
|
136
|
-
}, (error) => {
|
|
137
|
-
response.status(401).json({
|
|
138
|
-
status: "unauthorized",
|
|
139
|
-
message: JSON.stringify(error),
|
|
140
|
-
});
|
|
141
|
-
})
|
|
142
|
-
.catch((error) => {
|
|
143
|
-
response.status(401).json({
|
|
144
|
-
status: "unauthorized",
|
|
145
|
-
message: JSON.stringify(error),
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
};
|
|
149
|
-
exports.sessionLogin = sessionLogin;
|
|
150
|
-
const sessionLogout = (request, response) => {
|
|
151
|
-
response.clearCookie("session");
|
|
152
|
-
response.clearCookie("zsession");
|
|
153
|
-
response.clearCookie("__session");
|
|
154
|
-
};
|
|
155
|
-
exports.sessionLogout = sessionLogout;
|
|
156
|
-
const verifyConnectionToken = (token) => {
|
|
157
|
-
return async (request, response, next) => {
|
|
158
|
-
const id = request.headers["x-connection-token"];
|
|
159
|
-
if (id === token()) {
|
|
160
|
-
next();
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
response.status(401).json({
|
|
164
|
-
status: "unauthorized",
|
|
165
|
-
message: "",
|
|
166
|
-
});
|
|
167
|
-
};
|
|
168
|
-
};
|
|
169
|
-
exports.verifyConnectionToken = verifyConnectionToken;
|
|
170
|
-
const round = (value, digits = 3) => {
|
|
171
|
-
const factor = Math.pow(10, digits);
|
|
172
|
-
return Math.round(value * factor) / factor;
|
|
173
|
-
};
|
|
174
|
-
exports.round = round;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.UserStore = exports.UserHttp = exports.UserFunction = exports.UserApi = exports.userSchema = exports.userShape = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const BaseApi_1 = require("../base/BaseApi");
|
|
6
|
+
const BaseFunction_1 = require("../base/BaseFunction");
|
|
7
|
+
const BaseHttp_1 = require("../base/BaseHttp");
|
|
8
|
+
const Store_1 = require("../store/Store");
|
|
9
|
+
const Validation_1 = require("../validation/Validation");
|
|
10
|
+
exports.userShape = {
|
|
11
|
+
name: zod_1.z.string(),
|
|
12
|
+
};
|
|
13
|
+
exports.userSchema = zod_1.z.object(exports.userShape);
|
|
14
|
+
class UserApi extends BaseApi_1.BaseApi {
|
|
15
|
+
constructor(store, validation) {
|
|
16
|
+
super(store, validation ?? new Validation_1.Validation(store, exports.userShape), exports.userShape);
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.UserApi = UserApi;
|
|
20
|
+
class UserFunction extends BaseFunction_1.BaseFunction {
|
|
21
|
+
}
|
|
22
|
+
exports.UserFunction = UserFunction;
|
|
23
|
+
class UserHttp extends BaseHttp_1.BaseHttp {
|
|
24
|
+
}
|
|
25
|
+
exports.UserHttp = UserHttp;
|
|
26
|
+
class UserStore extends Store_1.Store {
|
|
27
|
+
constructor(converter) {
|
|
28
|
+
super("users", converter);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.UserStore = UserStore;
|
package/dist/cjs/lib.js
CHANGED
|
@@ -14,12 +14,13 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
14
14
|
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
-
__exportStar(require("./
|
|
18
|
-
__exportStar(require("./
|
|
19
|
-
__exportStar(require("./
|
|
20
|
-
__exportStar(require("./common/firebase"), exports);
|
|
21
|
-
__exportStar(require("./
|
|
22
|
-
__exportStar(require("./
|
|
23
|
-
__exportStar(require("./
|
|
24
|
-
__exportStar(require("./
|
|
25
|
-
__exportStar(require("./store/types.store"), exports);
|
|
17
|
+
__exportStar(require("./types/types.common.js"), exports);
|
|
18
|
+
__exportStar(require("./types/types.function.js"), exports);
|
|
19
|
+
__exportStar(require("./types/types.apiRoutes.js"), exports);
|
|
20
|
+
__exportStar(require("./common/firebase.js"), exports);
|
|
21
|
+
__exportStar(require("./lib.js"), exports);
|
|
22
|
+
__exportStar(require("./index.js"), exports);
|
|
23
|
+
__exportStar(require("./validation/Validation.js"), exports);
|
|
24
|
+
__exportStar(require("./package.js"), exports);
|
|
25
|
+
__exportStar(require("./store/types.store.js"), exports);
|
|
26
|
+
__exportStar(require("./store/Store.js"), exports);
|
|
@@ -33,36 +33,35 @@ var __importStar = (this && this.__importStar) || (function () {
|
|
|
33
33
|
};
|
|
34
34
|
})();
|
|
35
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.
|
|
36
|
+
exports.Store = void 0;
|
|
37
37
|
const firebase_js_1 = require("../common/firebase.js");
|
|
38
38
|
const uuid = __importStar(require("short-uuid"));
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return doc;
|
|
42
|
-
return {
|
|
43
|
-
...doc.data(),
|
|
44
|
-
createTime: doc.createTime,
|
|
45
|
-
updateTime: doc.updateTime,
|
|
46
|
-
id: doc.id,
|
|
47
|
-
};
|
|
48
|
-
};
|
|
49
|
-
exports.convertDocObject = convertDocObject;
|
|
50
|
-
class IStore {
|
|
51
|
-
constructor(collectionName) {
|
|
39
|
+
class Store {
|
|
40
|
+
constructor(collectionName, converter, namespace = "picpad") {
|
|
52
41
|
this.collectionName = collectionName;
|
|
42
|
+
this.converter = converter;
|
|
43
|
+
this.namespace = namespace;
|
|
53
44
|
}
|
|
54
45
|
db() {
|
|
55
46
|
if (!this._db)
|
|
56
|
-
this.
|
|
57
|
-
|
|
58
|
-
|
|
47
|
+
if (this.converter)
|
|
48
|
+
this._db = firebase_js_1.db
|
|
49
|
+
.collection(`${this.namespace}.${this.collectionName}`)
|
|
50
|
+
.withConverter(this.converter);
|
|
51
|
+
else
|
|
52
|
+
this._db = firebase_js_1.db.collection(`${this.namespace}.${this.collectionName}`);
|
|
59
53
|
return this._db;
|
|
60
54
|
}
|
|
61
55
|
async query(p) {
|
|
62
56
|
const snapshot = p && p.parentId
|
|
63
57
|
? await this.refByParent(p.parentId).get()
|
|
64
58
|
: await this.db().get();
|
|
65
|
-
return snapshot.docs.map((
|
|
59
|
+
return snapshot.docs.map((doc) => ({
|
|
60
|
+
...doc.data(),
|
|
61
|
+
id: doc.id,
|
|
62
|
+
createTime: doc.createTime.toDate(),
|
|
63
|
+
updateTime: doc.updateTime.toDate(),
|
|
64
|
+
}));
|
|
66
65
|
}
|
|
67
66
|
async count(p) {
|
|
68
67
|
const snapshot = p && p.parentId
|
|
@@ -77,16 +76,22 @@ class IStore {
|
|
|
77
76
|
const snapshot = await this.ref(id).get();
|
|
78
77
|
if (!snapshot.exists)
|
|
79
78
|
throw new Error(`Id ${id} does not exist`);
|
|
80
|
-
|
|
79
|
+
const data = snapshot.data();
|
|
80
|
+
if (!data)
|
|
81
|
+
throw new Error(`Id ${id}: data invalid`);
|
|
82
|
+
data.id = snapshot.id;
|
|
83
|
+
data.updateTime = snapshot.updateTime?.toDate();
|
|
84
|
+
data.createTime = snapshot.createTime?.toDate();
|
|
85
|
+
return data;
|
|
81
86
|
}
|
|
82
87
|
async exists(id) {
|
|
83
88
|
return (await this.ref(id).get()).exists;
|
|
84
89
|
}
|
|
85
90
|
async create(doc) {
|
|
86
|
-
|
|
87
|
-
const ref = this.ref(
|
|
91
|
+
const id = uuid.generate();
|
|
92
|
+
const ref = this.ref(id);
|
|
88
93
|
await ref.set(doc);
|
|
89
|
-
return this.get(
|
|
94
|
+
return this.get(id);
|
|
90
95
|
}
|
|
91
96
|
async update(id, doc) {
|
|
92
97
|
const entry = this.ref(id);
|
|
@@ -104,4 +109,4 @@ class IStore {
|
|
|
104
109
|
return this.db().where("parentId", "==", parentId);
|
|
105
110
|
}
|
|
106
111
|
}
|
|
107
|
-
exports.
|
|
112
|
+
exports.Store = Store;
|
|
@@ -1,15 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.storeSchema = exports.storeSchemaShape = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
|
-
exports.
|
|
5
|
+
exports.storeSchemaShape = {
|
|
6
6
|
id: zod_1.z.string().optional(),
|
|
7
7
|
createTime: zod_1.z.date().optional(),
|
|
8
8
|
updateTime: zod_1.z.date().optional(),
|
|
9
9
|
};
|
|
10
|
-
exports.
|
|
11
|
-
...exports.storeBaseSchemaShape,
|
|
12
|
-
id: zod_1.z.string(),
|
|
13
|
-
};
|
|
14
|
-
exports.storeBaseSchema = zod_1.z.object(exports.storeBaseSchemaShape);
|
|
15
|
-
exports.storePersistSchema = zod_1.z.object(exports.storePersistSchemaShape);
|
|
10
|
+
exports.storeSchema = zod_1.z.object(exports.storeSchemaShape);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Validation = void 0;
|
|
4
|
+
const zod_1 = require("zod");
|
|
5
|
+
const https_1 = require("firebase-functions/https");
|
|
6
|
+
class Validation {
|
|
7
|
+
constructor(store, shape) {
|
|
8
|
+
this.store = store;
|
|
9
|
+
this.shape = shape;
|
|
10
|
+
this.createSchema = zod_1.z.object(shape);
|
|
11
|
+
this.updateSchema = this.createSchema.partial();
|
|
12
|
+
}
|
|
13
|
+
async validate(doc) {
|
|
14
|
+
const result = this.createSchema.safeParse(doc);
|
|
15
|
+
if (!result.success)
|
|
16
|
+
throw new https_1.HttpsError("invalid-argument", "Invalid request data", {
|
|
17
|
+
fields: this.issuesToFieldErrors(result.error.issues),
|
|
18
|
+
});
|
|
19
|
+
return result.data;
|
|
20
|
+
}
|
|
21
|
+
async validatePartial(doc) {
|
|
22
|
+
const result = this.updateSchema.safeParse(doc);
|
|
23
|
+
if (!result.success)
|
|
24
|
+
throw new https_1.HttpsError("invalid-argument", "Invalid request data", {
|
|
25
|
+
fields: this.issuesToFieldErrors(result.error.issues),
|
|
26
|
+
});
|
|
27
|
+
return result.data;
|
|
28
|
+
}
|
|
29
|
+
issuesToFieldErrors(issues) {
|
|
30
|
+
const fields = {};
|
|
31
|
+
for (const issue of issues) {
|
|
32
|
+
const path = issue.path.length ? issue.path.join(".") : "_form";
|
|
33
|
+
(fields[path] ?? (fields[path] = [])).push(issue.message);
|
|
34
|
+
}
|
|
35
|
+
return fields;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.Validation = Validation;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FunctionCollection = void 0;
|
|
4
|
+
class FunctionCollection {
|
|
5
|
+
constructor() {
|
|
6
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
7
|
+
this.funcs = {};
|
|
8
|
+
}
|
|
9
|
+
add(name, func) {
|
|
10
|
+
this.funcs[name] = func;
|
|
11
|
+
return this;
|
|
12
|
+
}
|
|
13
|
+
build() {
|
|
14
|
+
return this.funcs;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
exports.FunctionCollection = FunctionCollection;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseApi = void 0;
|
|
4
|
+
const zod_meta_1 = require("@mxpicture/zod-meta");
|
|
5
|
+
class BaseApi {
|
|
6
|
+
constructor(store, validation, shape) {
|
|
7
|
+
this.store = store;
|
|
8
|
+
this.validation = validation;
|
|
9
|
+
this.shape = shape;
|
|
10
|
+
}
|
|
11
|
+
async delete(p) {
|
|
12
|
+
return this.store.delete(p.id);
|
|
13
|
+
}
|
|
14
|
+
async get(p) {
|
|
15
|
+
return this.store.get(p.id);
|
|
16
|
+
}
|
|
17
|
+
async query() {
|
|
18
|
+
return this.store.query();
|
|
19
|
+
}
|
|
20
|
+
async count() {
|
|
21
|
+
return { count: await this.store.count() };
|
|
22
|
+
}
|
|
23
|
+
async exists(p) {
|
|
24
|
+
return { exists: await this.store.exists(p.id) };
|
|
25
|
+
}
|
|
26
|
+
async meta() {
|
|
27
|
+
return new zod_meta_1.Meta(this.shape).items();
|
|
28
|
+
}
|
|
29
|
+
async create(data) {
|
|
30
|
+
const result = await this.validation.validate(data);
|
|
31
|
+
return this.store.create(result);
|
|
32
|
+
}
|
|
33
|
+
async update(p, data) {
|
|
34
|
+
const result = await this.validation.validatePartial(data);
|
|
35
|
+
return this.store.update(p.id, result);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
exports.BaseApi = BaseApi;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BaseFunction = void 0;
|
|
4
|
+
const https_1 = require("firebase-functions/https");
|
|
5
|
+
const ts_transformer_keys_1 = require("ts-transformer-keys");
|
|
6
|
+
class BaseFunction {
|
|
7
|
+
constructor(http) {
|
|
8
|
+
this.http = http;
|
|
9
|
+
this.httpMethods = (0, ts_transformer_keys_1.keys)();
|
|
10
|
+
}
|
|
11
|
+
createFunction() {
|
|
12
|
+
return (0, https_1.onCall)({ cors: [/firebase\.com$/, /web\.app$/] }, async (req) => {
|
|
13
|
+
if (!this.httpMethods.find((m) => m === req.data.route))
|
|
14
|
+
throw new https_1.HttpsError("invalid-argument", `Route ${req.data.route} not available`);
|
|
15
|
+
return {
|
|
16
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
17
|
+
doc: await this.http[req.data.route](req.data),
|
|
18
|
+
};
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.BaseFunction = BaseFunction;
|