@pbvision/firestore-orm 0.0.6 → 0.0.8

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 CHANGED
@@ -8,6 +8,8 @@ high-level abstractions to structure data and prevent race conditions.
8
8
  - [Minimal Example](#minimal-example)
9
9
  - [Collections](#collections)
10
10
  - [Keys](#keys)
11
+ - [Semantic Keys](#semantic-keys)
12
+ - [Random Keys](#random-keys)
11
13
  - [Fields](#fields)
12
14
  - [Schema Enforcement](#schema-enforcement)
13
15
  - [Custom Methods](#custom-methods)
@@ -117,6 +119,7 @@ Access each component of a key just like any other field:
117
119
  }
118
120
  ```
119
121
 
122
+ #### Semantic Keys
120
123
  It is best practice for keys to have semantic meaning whenever possible. In
121
124
  this example, each runner finishes each race just one time so making the key a
122
125
  combination of those values is ideal. This is better than a meaningless random
@@ -133,6 +136,13 @@ value because this:
133
136
  Note: Keys are collection-specific. Two different docs in different collections may have
134
137
  the same key.
135
138
 
139
+ #### Random Keys
140
+ If keys are random, then you can use `db.makeAutoIdSchema()` to generate a
141
+ schema for validating them. That schema object also has a `newId()` method
142
+ which generates IDs which conform to that schema. You can configure the length
143
+ of the IDs (20 by default) and whether uppercase letters are included (false by
144
+ default) by passing parameters to the `makeAutoIdSchema()` function.
145
+
136
146
 
137
147
  ### Fields
138
148
  Fields are pieces of data attached to a doc. They are defined similar to
package/environment.js CHANGED
@@ -1,2 +1 @@
1
- process.env.INDEBUGGER = 1
2
1
  process.env.FIRESTORE_EMULATOR_HOST = '[::1]:8404'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pbvision/firestore-orm",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "description": "Firestore ORM Library",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",
@@ -11,7 +11,7 @@
11
11
  "scripts": {
12
12
  "build-doc": "./docs/build.sh",
13
13
  "check-markdown-link": "./scripts/ci/markdown-link.sh",
14
- "debug": "yarn start-local-db && ./node_modules/nodemon/bin/nodemon.js --no-lazy --legacy-watch --watch ./src --watch ./example --watch ./test --inspect=9229 ./node_modules/jest/bin/jest.js --coverage --config=./jest.config.json --runInBand",
14
+ "debug": "yarn start-local-db && INDEBUGGER=1 ./node_modules/nodemon/bin/nodemon.js --no-lazy --legacy-watch --watch ./src --watch ./example --watch ./test --inspect=9229 ./node_modules/jest/bin/jest.js --coverage --config=./jest.config.json --runInBand",
15
15
  "lint": "./scripts/ci/lint-format-js.sh",
16
16
  "setup": "yarn install --frozen-lockfile && pip install -r requirements.txt",
17
17
  "start-local-db": "./scripts/start-local-db.sh",
@@ -40,7 +40,7 @@
40
40
  ],
41
41
  "dependencies": {
42
42
  "@google-cloud/firestore": "^7.1.0",
43
- "@pbvision/schema": "^0.2.15",
43
+ "@pbvision/schema": "^0.2.22",
44
44
  "deep-object-diff": "^1.1.7",
45
45
  "fast-deep-equal": "^3.1.3",
46
46
  "fast-json-stable-stringify": "^2.1.0",
package/src/context.js CHANGED
@@ -103,9 +103,9 @@ export class Context {
103
103
  return {
104
104
  readOnly: false,
105
105
  consistentReads: true,
106
- initialBackoff: process.env.INDEBUGGER ? 1 : 500,
106
+ initialBackoff: process.env.FIRESTORE_EMULATOR_HOST ? 1 : 500,
107
107
  maxBackoff: 10000,
108
- retries: process.env.INDEBUGGER ? 0 : 4, // no retry by default in unit tests for speed
108
+ retries: process.env.FIRESTORE_EMULATOR_HOST ? 0 : 4, // no retry by default in unit tests for speed
109
109
  cacheModels: false
110
110
  }
111
111
  }
package/src/firestore.js CHANGED
@@ -1,3 +1,5 @@
1
+ import assert from 'node:assert'
2
+
1
3
  import S from '@pbvision/schema'
2
4
 
3
5
  import {
@@ -38,6 +40,57 @@ import { Model } from './models.js'
38
40
  * @private
39
41
  */
40
42
  export default function setup (firestoreDB) {
43
+ /**
44
+ * Generates a globally unique ID.
45
+ *
46
+ * newId() generates IDs that are statistically globally unique using
47
+ * firestoreDB's AutoId class. These IDs by default are 20 characters long
48
+ * and may include numbers and letters (both lowercase and uppercase). This
49
+ * function allows a shorter string to be returned for cases where the
50
+ * identifier doesn't need to be so long. Of course, if it's too short and
51
+ * too many are generated then duplicates may be generated. For
52
+ * implementation details see https://github.com/googleapis/nodejs-firestore
53
+ *
54
+ * @param {Object} params
55
+ * @param {integer} [len=20] can be modified to shorten the IDs length (at
56
+ * the expense of curtailing its statistical global uniqueness guarantee)
57
+ * @param {boolean} [lowercaseOnly=true] whether to include only lowercase
58
+ * letters and digits in the generated ID (defaults to true)
59
+ * @returns {string} the new ID string
60
+ */
61
+ function newId (len = 20, lowercaseOnly = true) {
62
+ let id = firestoreDB.collection('tmp').doc().id
63
+ assert(id.length >= len,
64
+ `AutoId does not support generating ${len} length IDs (too long)`)
65
+ if (lowercaseOnly) {
66
+ id = id.toLowerCase()
67
+ }
68
+ return id.substring(0, len)
69
+ }
70
+
71
+ /**
72
+ * Returns a schema for an automatic ID with the specified params.
73
+ *
74
+ * Parameters mirror newId().
75
+ * @param {string} title title for the schema
76
+ *
77
+ * The returned schema has a newId() function on it which takes no params and
78
+ * generates random new IDs which conform to the schema.
79
+ */
80
+ function makeAutoIdSchema (len = 20, lowercaseOnly = true, title = undefined) {
81
+ const allowedChars = `${lowercaseOnly ? '' : 'A-Z'}a-z0-9`
82
+ let schema = S.str
83
+ .pattern(`[${allowedChars}]{${len}}`)
84
+ .min(len).max(len)
85
+ .desc(`a unique ID consisting of ${len} digits and letters
86
+ (${lowercaseOnly ? 'lowercase only' : 'uppercase and lowercase'})`)
87
+ if (title) {
88
+ schema = schema.title(title)
89
+ }
90
+ schema.newId = () => newId(len, lowercaseOnly)
91
+ return schema
92
+ }
93
+
41
94
  Key.firestoreDB = firestoreDB
42
95
  const toExport = {
43
96
  S,
@@ -45,6 +98,8 @@ export default function setup (firestoreDB) {
45
98
  UniqueKeyList,
46
99
  Context,
47
100
  firestoreDB,
101
+ makeAutoIdSchema,
102
+ newId,
48
103
 
49
104
  // Errors
50
105
  DeletedTwiceError,
@@ -56,7 +111,7 @@ export default function setup (firestoreDB) {
56
111
  TransactionFailedError,
57
112
  WriteAttemptedInReadOnlyTxError
58
113
  }
59
- if (Number(process.env.INDEBUGGER)) {
114
+ if (Number(process.env.FIRESTORE_EMULATOR_HOST)) {
60
115
  toExport.__private = {
61
116
  __Field,
62
117
  fields: [