@bedrockio/model 0.10.1 → 0.11.0
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/CHANGELOG.md +4 -0
- package/README.md +11 -0
- package/dist/cjs/clone.js +55 -0
- package/dist/cjs/schema.js +2 -0
- package/eslint.config.js +0 -1
- package/package.json +1 -1
- package/src/clone.js +55 -0
- package/src/schema.js +2 -0
- package/types/clone.d.ts +2 -0
- package/types/clone.d.ts.map +1 -0
- package/types/schema.d.ts.map +1 -1
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -23,6 +23,7 @@ Bedrock utilities for model creation.
|
|
|
23
23
|
- [Access Control](#access-control)
|
|
24
24
|
- [Assign](#assign)
|
|
25
25
|
- [Upsert](#upsert)
|
|
26
|
+
- [Clone](#clone)
|
|
26
27
|
- [Slugs](#slugs)
|
|
27
28
|
- [Testing](#testing)
|
|
28
29
|
- [Troubleshooting](#troubleshooting)
|
|
@@ -1667,6 +1668,16 @@ if (!shop) {
|
|
|
1667
1668
|
}
|
|
1668
1669
|
```
|
|
1669
1670
|
|
|
1671
|
+
### Clone
|
|
1672
|
+
|
|
1673
|
+
Adds a single `clone` method on documents. This is an async method mostly for
|
|
1674
|
+
testing that will immediately create a copy of the document. It makes up for
|
|
1675
|
+
some of the shortcomings of the Mongoose `$clone` method:
|
|
1676
|
+
|
|
1677
|
+
- A new `id` will be generated.
|
|
1678
|
+
- Populated and self-referencing documents are handled.
|
|
1679
|
+
- Unique fields will be augmented to not collide.
|
|
1680
|
+
|
|
1670
1681
|
### Slugs
|
|
1671
1682
|
|
|
1672
1683
|
A common requirement is to allow slugs on documents to serve as ids for human
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.applyClone = applyClone;
|
|
7
|
+
// This module attempts to fix Mongoose $clone
|
|
8
|
+
// which has a number of issues including:
|
|
9
|
+
// - Keeps the same _id making it impossible to use
|
|
10
|
+
// the clone separate to the original document.
|
|
11
|
+
// - Fails on circular references.
|
|
12
|
+
// - Clones other internals like __v.
|
|
13
|
+
// - Cannot deal with unique fields.
|
|
14
|
+
//
|
|
15
|
+
function applyClone(schema) {
|
|
16
|
+
schema.method('clone', async function clone() {
|
|
17
|
+
return await cloneDocument(this);
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
async function cloneDocument(doc) {
|
|
21
|
+
const Model = doc.constructor;
|
|
22
|
+
const clone = new Model();
|
|
23
|
+
for (let [key, typedef] of Object.entries(Model.schema.obj)) {
|
|
24
|
+
let value = doc.get(key);
|
|
25
|
+
const {
|
|
26
|
+
unique,
|
|
27
|
+
softUnique
|
|
28
|
+
} = typedef;
|
|
29
|
+
if (value && (unique || softUnique)) {
|
|
30
|
+
value = getUniqueValue(value);
|
|
31
|
+
}
|
|
32
|
+
clone.set(key, value);
|
|
33
|
+
}
|
|
34
|
+
await clone.save();
|
|
35
|
+
return clone;
|
|
36
|
+
}
|
|
37
|
+
let counter = 1;
|
|
38
|
+
function getUniqueValue(value) {
|
|
39
|
+
const type = typeof value;
|
|
40
|
+
if (type === 'string') {
|
|
41
|
+
return getUniqueString(value);
|
|
42
|
+
} else if (type === 'number') {
|
|
43
|
+
return value + getCounter();
|
|
44
|
+
} else {
|
|
45
|
+
throw new Error(`Unique behavior not defined for ${type}.`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
function getUniqueString(str) {
|
|
49
|
+
const split = str.split('@');
|
|
50
|
+
split[0] += getCounter();
|
|
51
|
+
return split.join('@');
|
|
52
|
+
}
|
|
53
|
+
function getCounter() {
|
|
54
|
+
return counter++;
|
|
55
|
+
}
|
package/dist/cjs/schema.js
CHANGED
|
@@ -11,6 +11,7 @@ var _utils = require("./utils");
|
|
|
11
11
|
var _serialization = require("./serialization");
|
|
12
12
|
var _slug = require("./slug");
|
|
13
13
|
var _cache = require("./cache");
|
|
14
|
+
var _clone = require("./clone");
|
|
14
15
|
var _search = require("./search");
|
|
15
16
|
var _assign = require("./assign");
|
|
16
17
|
var _upsert = require("./upsert");
|
|
@@ -56,6 +57,7 @@ function createSchema(definition, options = {}) {
|
|
|
56
57
|
(0, _deleteHooks.applyDeleteHooks)(schema, definition);
|
|
57
58
|
(0, _search.applySearch)(schema, definition);
|
|
58
59
|
(0, _cache.applyCache)(schema, definition);
|
|
60
|
+
(0, _clone.applyClone)(schema);
|
|
59
61
|
(0, _disallowed.applyDisallowed)(schema);
|
|
60
62
|
(0, _include.applyInclude)(schema);
|
|
61
63
|
(0, _hydrate.applyHydrate)(schema);
|
package/eslint.config.js
CHANGED
package/package.json
CHANGED
package/src/clone.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// This module attempts to fix Mongoose $clone
|
|
2
|
+
// which has a number of issues including:
|
|
3
|
+
// - Keeps the same _id making it impossible to use
|
|
4
|
+
// the clone separate to the original document.
|
|
5
|
+
// - Fails on circular references.
|
|
6
|
+
// - Clones other internals like __v.
|
|
7
|
+
// - Cannot deal with unique fields.
|
|
8
|
+
//
|
|
9
|
+
export function applyClone(schema) {
|
|
10
|
+
schema.method('clone', async function clone() {
|
|
11
|
+
return await cloneDocument(this);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async function cloneDocument(doc) {
|
|
16
|
+
const Model = doc.constructor;
|
|
17
|
+
const clone = new Model();
|
|
18
|
+
|
|
19
|
+
for (let [key, typedef] of Object.entries(Model.schema.obj)) {
|
|
20
|
+
let value = doc.get(key);
|
|
21
|
+
const { unique, softUnique } = typedef;
|
|
22
|
+
if (value && (unique || softUnique)) {
|
|
23
|
+
value = getUniqueValue(value);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
clone.set(key, value);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
await clone.save();
|
|
30
|
+
|
|
31
|
+
return clone;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let counter = 1;
|
|
35
|
+
|
|
36
|
+
function getUniqueValue(value) {
|
|
37
|
+
const type = typeof value;
|
|
38
|
+
if (type === 'string') {
|
|
39
|
+
return getUniqueString(value);
|
|
40
|
+
} else if (type === 'number') {
|
|
41
|
+
return value + getCounter();
|
|
42
|
+
} else {
|
|
43
|
+
throw new Error(`Unique behavior not defined for ${type}.`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function getUniqueString(str) {
|
|
48
|
+
const split = str.split('@');
|
|
49
|
+
split[0] += getCounter();
|
|
50
|
+
return split.join('@');
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function getCounter() {
|
|
54
|
+
return counter++;
|
|
55
|
+
}
|
package/src/schema.js
CHANGED
|
@@ -6,6 +6,7 @@ import { isSchemaTypedef } from './utils';
|
|
|
6
6
|
import { serializeOptions } from './serialization';
|
|
7
7
|
import { applySlug } from './slug';
|
|
8
8
|
import { applyCache } from './cache';
|
|
9
|
+
import { applyClone } from './clone';
|
|
9
10
|
import { applySearch } from './search';
|
|
10
11
|
import { applyAssign } from './assign';
|
|
11
12
|
import { applyUpsert } from './upsert';
|
|
@@ -60,6 +61,7 @@ export function createSchema(definition, options = {}) {
|
|
|
60
61
|
applyDeleteHooks(schema, definition);
|
|
61
62
|
applySearch(schema, definition);
|
|
62
63
|
applyCache(schema, definition);
|
|
64
|
+
applyClone(schema);
|
|
63
65
|
applyDisallowed(schema);
|
|
64
66
|
applyInclude(schema);
|
|
65
67
|
applyHydrate(schema);
|
package/types/clone.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"clone.d.ts","sourceRoot":"","sources":["../src/clone.js"],"names":[],"mappings":"AAQA,8CAIC"}
|
package/types/schema.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../src/schema.js"],"names":[],"mappings":"AAwBA;;;;;;;GAOG;AACH,yCAJW,MAAM,YACN,QAAQ,CAAC,aAAa;;;;;;;YA6CM,CAAC;WACtC,CAAF;mBAAqB,CAAC;;;;;;;;;;;;;;;;;;;;;SAiHV,CAAA;gBAA2B,CAAC;SAAW,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;aApHnD;AAED,iEAsBC;qBAhGoB,UAAU"}
|