@degenerate/generic 0.7.1 → 0.9.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.
Files changed (52) hide show
  1. package/LICENSE.md +12 -60
  2. package/README.md +15 -0
  3. package/dist/_settings/application-settings.d.ts +1 -0
  4. package/dist/_settings/application-settings.d.ts.map +1 -1
  5. package/dist/_settings/application-settings.js +5 -0
  6. package/dist/_settings/authorization-settings.d.ts +2 -2
  7. package/dist/application/database/firestore/generics/add-items-to-database.d.ts.map +1 -1
  8. package/dist/application/database/firestore/generics/add-items-to-database.js +2 -36
  9. package/dist/application/database/firestore/generics/add-or-update-items-to-database.d.ts.map +1 -1
  10. package/dist/application/database/firestore/generics/add-or-update-items-to-database.js +2 -36
  11. package/dist/application/database/firestore/generics/delete-items-on-database.d.ts.map +1 -1
  12. package/dist/application/database/firestore/generics/delete-items-on-database.js +2 -36
  13. package/dist/application/database/firestore/generics/get-item-from-database.d.ts.map +1 -1
  14. package/dist/application/database/firestore/generics/get-item-from-database.js +2 -36
  15. package/dist/application/database/firestore/generics/get-items-different-path-on-database.d.ts.map +1 -1
  16. package/dist/application/database/firestore/generics/get-items-different-path-on-database.js +2 -36
  17. package/dist/application/database/firestore/generics/get-items-from-database.d.ts +9 -4
  18. package/dist/application/database/firestore/generics/get-items-from-database.d.ts.map +1 -1
  19. package/dist/application/database/firestore/generics/get-items-from-database.js +180 -61
  20. package/dist/application/database/firestore/generics/update-items-on-database.d.ts.map +1 -1
  21. package/dist/application/database/firestore/generics/update-items-on-database.js +2 -36
  22. package/dist/application/database/firestore/generics/update-items-properties-on-database.d.ts.map +1 -1
  23. package/dist/application/database/firestore/generics/update-items-properties-on-database.js +2 -36
  24. package/dist/application/database/firestore/page-cursor/page-cursor.d.ts +33 -0
  25. package/dist/application/database/firestore/page-cursor/page-cursor.d.ts.map +1 -0
  26. package/dist/application/database/firestore/page-cursor/page-cursor.js +206 -0
  27. package/dist/application/database/firestore/path-references/audit-log/create-audit-log-col-ref.d.ts.map +1 -1
  28. package/dist/application/database/firestore/path-references/audit-log/create-audit-log-col-ref.js +2 -36
  29. package/dist/application/database/index.d.ts +1 -0
  30. package/dist/application/database/index.d.ts.map +1 -1
  31. package/dist/application/database/index.js +3 -0
  32. package/dist/application/index.d.ts +1 -0
  33. package/dist/application/index.d.ts.map +1 -1
  34. package/dist/application/index.js +3 -0
  35. package/dist/authorization/jwt/sign/create-jwt-options.d.ts +2 -2
  36. package/dist/authorization/jwt/sign/create-jwt-options.d.ts.map +1 -1
  37. package/dist/errors/base-error.d.ts +3 -1
  38. package/dist/errors/base-error.d.ts.map +1 -1
  39. package/dist/errors/base-error.js +5 -1
  40. package/dist/errors/database/database-errors.d.ts +28 -0
  41. package/dist/errors/database/database-errors.d.ts.map +1 -1
  42. package/dist/errors/database/database-errors.js +35 -1
  43. package/dist/helpers/firestore/firestore-id-helpers.d.ts +25 -0
  44. package/dist/helpers/firestore/firestore-id-helpers.d.ts.map +1 -0
  45. package/dist/helpers/firestore/firestore-id-helpers.js +39 -0
  46. package/dist/helpers/index.d.ts +1 -0
  47. package/dist/helpers/index.d.ts.map +1 -1
  48. package/dist/helpers/index.js +1 -0
  49. package/dist/models/application/database/firestore-models.d.ts +35 -14
  50. package/dist/models/application/database/firestore-models.d.ts.map +1 -1
  51. package/dist/models/application/database/firestore-models.js +64 -46
  52. package/package.json +13 -4
@@ -1,43 +1,48 @@
1
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
2
  Object.defineProperty(exports, "__esModule", { value: true });
36
- exports.IDatabaseDeleteItemSchema = exports.IDatabaseGetInformationSchema = exports.IDatabaseQueryFieldsSchema = exports.IDatabaseOrderBySchema = exports.IDatabaseGetItemSchema = exports.WhereFilterOpSchema = exports.OrderByDirectionSchema = exports.IDatabaseUpdatesSchema = exports.IDatabaseRecordAndRefSchema = exports.IDatabasePropertyChangeInformationSchema = exports.IDatabaseChangeInformationSchema = exports.IDatabaseAuditLogUpdatesSchema = void 0;
37
- const admin = __importStar(require("firebase-admin"));
3
+ exports.IDatabaseDeleteItemSchema = exports.IDatabaseGetInformationSchema = exports.IDatabasePageCursorSchema = exports.IDatabaseQueryFieldsSchema = exports.IDatabaseOrderBySchema = exports.IDatabaseGetItemSchema = exports.WhereFilterOpSchema = exports.OrderByDirectionSchema = exports.IDatabaseUpdatesSchema = exports.IDatabaseRecordAndRefSchema = exports.IDatabasePropertyChangeInformationSchema = exports.IDatabaseChangeInformationSchema = exports.IDatabaseAuditLogUpdatesSchema = void 0;
38
4
  const zod_1 = require("zod");
39
- const firestore_1 = require("firebase-admin/firestore");
5
+ const application_settings_1 = require("../../../_settings/application-settings");
40
6
  const application_audit_log_models_1 = require("../audit-log/application-audit-log-models");
7
+ // The lazily loaded module: undefined until a check first tries to load it, then the module, or
8
+ // null when firebase-admin isn't installed (remembered for the life of the process).
9
+ let firestoreModule;
10
+ // Whether a failed load means firebase-admin itself isn't installed, as opposed to a broken install
11
+ // (a dependency missing inside an installed copy), which should surface. Node names the module it
12
+ // couldn't find on the message's first line; Yarn PnP names it in `data.dependencyName`.
13
+ const NODE_NOT_FOUND = /^Cannot find module 'firebase-admin(\/[^']*)?'/;
14
+ const isFirebaseAdminMissing = (error) => {
15
+ if (!(error instanceof Error) || !('code' in error) || error.code !== 'MODULE_NOT_FOUND') {
16
+ return false;
17
+ }
18
+ if ('data' in error && typeof error.data === 'object' && error.data !== null && 'dependencyName' in error.data) {
19
+ return error.data.dependencyName === 'firebase-admin';
20
+ }
21
+ return NODE_NOT_FOUND.test(error.message);
22
+ };
23
+ const tryLoadFirestore = () => {
24
+ try {
25
+ // eslint-disable-next-line @typescript-eslint/no-require-imports -- loaded on first use, see above
26
+ return require('firebase-admin/firestore');
27
+ }
28
+ catch (error) {
29
+ if (!isFirebaseAdminMissing(error)) {
30
+ throw error;
31
+ }
32
+ return null;
33
+ }
34
+ };
35
+ const loadFirestore = () => {
36
+ if (firestoreModule === undefined) {
37
+ firestoreModule = tryLoadFirestore();
38
+ }
39
+ return firestoreModule;
40
+ };
41
+ const isFirestoreInstance = (className) => (arg) => {
42
+ const firestore = loadFirestore();
43
+ return firestore !== null && arg instanceof firestore[className];
44
+ };
45
+ //#endregion Firestore classes
41
46
  //#region Backend Data Models
42
47
  //#region Audit Log Information
43
48
  /**
@@ -56,7 +61,7 @@ exports.IDatabaseChangeInformationSchema = zod_1.z.object({
56
61
  alai: zod_1.z.array(application_audit_log_models_1.AdditionalApplicationAuditLogIdsSchema), // the additional application audit log ids
57
62
  auditLogSubType: application_audit_log_models_1.ApplicationAuditLogSubTypeSchema, // the audit log sub type
58
63
  item: zod_1.z.unknown(), // the item to add to the database
59
- itemDocRef: zod_1.z.custom(arg => arg instanceof firestore_1.DocumentReference), // the item document reference (where to add the item to the database)
64
+ itemDocRef: zod_1.z.custom(isFirestoreInstance('DocumentReference')), // the item document reference (where to add the item to the database)
60
65
  });
61
66
  /**
62
67
  * This contains the information that is needed to pass a change to the generic database functions.
@@ -67,14 +72,14 @@ exports.IDatabasePropertyChangeInformationSchema = zod_1.z.object({
67
72
  alai: zod_1.z.array(application_audit_log_models_1.AdditionalApplicationAuditLogIdsSchema), // the additional application audit log ids
68
73
  auditLogSubType: application_audit_log_models_1.ApplicationAuditLogSubTypeSchema, // the audit log sub type
69
74
  partialObjectUpdate: zod_1.z.any(), // the partial object to update
70
- itemDocRef: zod_1.z.custom(arg => arg instanceof firestore_1.DocumentReference), // the item document reference (where to add the item to the database)
75
+ itemDocRef: zod_1.z.custom(isFirestoreInstance('DocumentReference')), // the item document reference (where to add the item to the database)
71
76
  });
72
77
  /**
73
78
  * This contains the information for a record and its reference
74
79
  */
75
80
  exports.IDatabaseRecordAndRefSchema = zod_1.z.object({
76
81
  record: zod_1.z.unknown(), // the record to update
77
- recordDocRef: zod_1.z.custom(arg => arg instanceof firestore_1.DocumentReference), // the record document reference
82
+ recordDocRef: zod_1.z.custom(isFirestoreInstance('DocumentReference')), // the record document reference
78
83
  });
79
84
  /**
80
85
  * This contains the information records and audit logs for database changes
@@ -93,40 +98,53 @@ exports.WhereFilterOpSchema = zod_1.z.enum(['<', '<=', '==', '!=', '>=', '>', 'a
93
98
  * This contains the information to get a single item from the database.
94
99
  */
95
100
  exports.IDatabaseGetItemSchema = exports.IDatabaseAuditLogUpdatesSchema.extend({
96
- itemDocRef: zod_1.z.custom(arg => arg instanceof firestore_1.DocumentReference), // the document reference to get the item from
101
+ itemDocRef: zod_1.z.custom(isFirestoreInstance('DocumentReference')), // the document reference to get the item from
97
102
  throwErrorOnNotFound: zod_1.z.boolean(), // if true, then throw an error if the item is not found.
98
103
  });
99
104
  /**
100
105
  * This contains the information that is needed to get information from the database.
101
106
  */
102
107
  exports.IDatabaseOrderBySchema = zod_1.z.object({
103
- fieldPath: zod_1.z.union([zod_1.z.string(), zod_1.z.instanceof(admin.firestore.FieldPath)]), // the field to order by
108
+ fieldPath: zod_1.z.union([zod_1.z.string(), zod_1.z.custom(isFirestoreInstance('FieldPath'))]), // the field to order by
104
109
  direction: exports.OrderByDirectionSchema, // the direction to order by
105
110
  });
106
111
  /**
107
112
  * This contains the query information for the database if it is required
108
113
  */
109
114
  exports.IDatabaseQueryFieldsSchema = zod_1.z.object({
110
- fieldPath: zod_1.z.union([zod_1.z.string(), zod_1.z.instanceof(admin.firestore.FieldPath)]),
115
+ fieldPath: zod_1.z.union([zod_1.z.string(), zod_1.z.custom(isFirestoreInstance('FieldPath'))]),
111
116
  opStr: exports.WhereFilterOpSchema,
112
117
  value: zod_1.z.any(),
113
118
  });
119
+ /**
120
+ * A page cursor: an opaque token that getItemsFromDatabase returns as a page's nextCursor. Pass it
121
+ * back unchanged, with the same filters and orderBy, for the next page. It is a plain string of
122
+ * URL-safe characters, about 4/3 the size of the last item's ordered values as tagged JSON plus the
123
+ * list's field paths, and inside it those values keep their Firestore types. A small cursor fits
124
+ * a URL or JSON body; a large one may not (a default express.json() body takes about 100 KB, a URL
125
+ * or header about 16 KiB), so size the transport for the ordered fields in use.
126
+ *
127
+ * Opaque is not secret: the token is encoded, not encrypted. It holds the last item's value for
128
+ * every field the list is ordered by (its orderBy and every inequality filter's field), and those
129
+ * fields' names. Only hand a cursor to someone who may see those values for that item.
130
+ */
131
+ exports.IDatabasePageCursorSchema = zod_1.z.string().min(1).max(application_settings_1.ApplicationSettings.SystemValues.MaxPageCursorLength);
114
132
  /**
115
133
  * This contains the information that is needed to get multiple items from the database.
116
134
  */
117
135
  exports.IDatabaseGetInformationSchema = exports.IDatabaseAuditLogUpdatesSchema.extend({
118
- itemColRef: zod_1.z.custom(arg => arg instanceof firestore_1.CollectionReference), // the collection reference to get the items from
119
- lastId: zod_1.z.string(), // the last id to get the next set of items.
136
+ itemColRef: zod_1.z.custom(isFirestoreInstance('CollectionReference')), // the collection reference to get the items from
137
+ cursor: exports.IDatabasePageCursorSchema.optional(), // where the page starts: the previous page's nextCursor; omitted for the first page
120
138
  orderBy: exports.IDatabaseOrderBySchema.optional(), // how to order the items
121
139
  queryFields: zod_1.z.array(exports.IDatabaseQueryFieldsSchema), // the fields to query
122
140
  isMaxSizeDocumentSet: zod_1.z.boolean().optional(), // if true, then the max size document the max number of docs to return
123
- });
141
+ }).strict(); // strict, so input still carrying the old lastId fails rather than having it dropped
124
142
  //#endregion Database Get Information
125
143
  //#region Database Delete Information
126
144
  /**
127
145
  * This contains the information to delete a single item from the database.
128
146
  */
129
147
  exports.IDatabaseDeleteItemSchema = exports.IDatabaseAuditLogUpdatesSchema.extend({
130
- itemDocRef: zod_1.z.custom(arg => arg instanceof firestore_1.DocumentReference), // the document reference to get the item to delete
148
+ itemDocRef: zod_1.z.custom(isFirestoreInstance('DocumentReference')), // the document reference to get the item to delete
131
149
  throwErrorOnNotFound: zod_1.z.boolean(), // if true, then throw an error if the item is not found.
132
150
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@degenerate/generic",
3
- "version": "0.7.1",
3
+ "version": "0.9.1",
4
4
  "description": "This contains the generic information needed for the ShareData Adaptive Framework Ecosystem (SAFE) network",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -16,6 +16,7 @@
16
16
  "scripts": {
17
17
  "build": "rm -rf dist/* && tsc -p tsconfig.pkg.json",
18
18
  "compile": "rm -rf dist/* && tsc -p tsconfig.pkg.json",
19
+ "typecheck": "tsc -p tsconfig.test.json --noEmit",
19
20
  "test": "jest --forceExit --detectOpenHandles --verbose --silent=false --env node",
20
21
  "test:coverage": "jest --forceExit --coverage --detectOpenHandles --verbose --silent=false --env node ",
21
22
  "test:clearCache": "jest --clearCache"
@@ -40,11 +41,10 @@
40
41
  "dependencies": {
41
42
  "@noble/ed25519": "3.1.0",
42
43
  "bip39": "^3.1.0",
43
- "firebase-admin": "^13.9.0",
44
44
  "jsonwebtoken": "^9.0.3",
45
- "zod": "^4.4.3"
45
+ "zod": "^4.6.6"
46
46
  },
47
- "gitHead": "5e9a8b3f1d17f6913ccac216ca1a64ad30c30ee5",
47
+ "gitHead": "ebb2ab0634ac9c4da50e584d11153625e2cc3999",
48
48
  "devDependencies": {
49
49
  "@eslint/js": "^10.0.1",
50
50
  "@types/eslint__js": "^8.42.3",
@@ -55,6 +55,7 @@
55
55
  "eslint": "^10.3.0",
56
56
  "eslint-import-resolver-typescript": "^4.4.4",
57
57
  "eslint-plugin-import": "^2.32.0",
58
+ "firebase-admin": "^14.5.0",
58
59
  "jest": "^30.4.2",
59
60
  "jest-environment-jsdom": "^30.4.1",
60
61
  "ts-jest": "^29.4.9",
@@ -62,6 +63,14 @@
62
63
  "typescript": "^6.0.3",
63
64
  "typescript-eslint": "^8.59.3"
64
65
  },
66
+ "peerDependencies": {
67
+ "firebase-admin": "^13.9.0 || ^14.0.0"
68
+ },
69
+ "peerDependenciesMeta": {
70
+ "firebase-admin": {
71
+ "optional": true
72
+ }
73
+ },
65
74
  "engines": {
66
75
  "node": ">=22"
67
76
  }