Skip to content

Commit dc67bc2

Browse files
feat(deleteReferences): Specify primary key in source collection ref
1 parent 698fb5a commit dc67bc2

File tree

2 files changed

+39
-27
lines changed

2 files changed

+39
-27
lines changed

src/common.ts

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,30 @@ export function isConfig(arg: Rule | Config): arg is Config {
1818
return (arg as Config).config !== undefined;
1919
}
2020

21-
export function replaceReferenceWithFields(
21+
enum Key {
22+
Primary = '{(.*?)}',
23+
Foreign = '([$][^/]*|$)',
24+
}
25+
26+
function regexMatches(text: string, regex: Key): string[] {
27+
return text.match(new RegExp(regex, 'g')) || [];
28+
}
29+
30+
export function getPrimaryKey(ref: string): string {
31+
const keys = regexMatches(ref, Key.Primary);
32+
if (keys.length > 0) {
33+
const pk = keys.pop(); // Pop the last item in the matched array
34+
return pk.replace(/\{|\}/g, ''); // Remove { } from the primary key
35+
}
36+
throw new Error('integrify: Missing a primary key in the source');
37+
}
38+
39+
export function replaceReferencesWith(
2240
fields: FirebaseFirestore.DocumentData,
2341
targetCollection: string
2442
): { hasFields: boolean; targetCollection: string } {
25-
const pRegex = /([\$][^\/]*|$)/g;
26-
const matches = targetCollection.match(pRegex); // Using global flag always returns an empty string at the end
27-
matches.pop();
28-
43+
const matches = regexMatches(targetCollection, Key.Foreign);
44+
matches.pop(); // The foreign key regex always return '' at the end
2945
let hasFields = false;
3046
if (matches.length > 0 && fields) {
3147
hasFields = true;

src/rules/deleteReferences.ts

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Config, Rule, replaceReferenceWithFields } from '../common';
1+
import { Config, Rule, replaceReferencesWith, getPrimaryKey } from '../common';
22

33
export interface DeleteReferencesRule extends Rule {
44
source: {
@@ -31,11 +31,12 @@ export function integrifyDeleteReferences(
3131
);
3232

3333
return functions.firestore
34-
.document(`${rule.source.collection}/{masterId}`)
34+
.document(rule.source.collection)
3535
.onDelete((snap, context) => {
36-
const masterId = context.params.masterId;
36+
// Get the last {...} in the source collection
37+
const primaryKey = context.params[getPrimaryKey(rule.source.collection)];
3738
console.log(
38-
`integrify: Detected delete in [${rule.source.collection}], id [${masterId}]`
39+
`integrify: Detected delete in [${rule.source.collection}], id [${primaryKey}]`
3940
);
4041

4142
// Call "pre" hook if defined
@@ -53,26 +54,21 @@ export function integrifyDeleteReferences(
5354
target.isCollectionGroup ? 'group ' : ''
5455
}[${target.collection}] where foreign key [${
5556
target.foreignKey
56-
}] matches [${masterId}]`
57+
}] matches [${primaryKey}]`
5758
);
5859

59-
try {
60-
// Replace the context.params in the target collection
61-
const paramSwap = replaceReferenceWithFields(
62-
context.params,
63-
target.collection
64-
);
65-
target.collection = paramSwap.targetCollection;
60+
// Replace the context.params in the target collection
61+
const paramSwap = replaceReferencesWith(
62+
context.params,
63+
target.collection
64+
);
6665

67-
// Replace the snapshot fields in the target collection
68-
const fieldSwap = replaceReferenceWithFields(
69-
snap.data(),
70-
target.collection
71-
);
72-
target.collection = fieldSwap.targetCollection;
73-
} catch (error) {
74-
throw new Error(error);
75-
}
66+
// Replace the snapshot fields in the target collection
67+
const fieldSwap = replaceReferencesWith(
68+
snap.data(),
69+
paramSwap.targetCollection
70+
);
71+
target.collection = fieldSwap.targetCollection;
7672

7773
// Delete all docs in this target corresponding to deleted master doc
7874
let whereable = null;
@@ -84,7 +80,7 @@ export function integrifyDeleteReferences(
8480

8581
promises.push(
8682
whereable
87-
.where(target.foreignKey, '==', masterId)
83+
.where(target.foreignKey, '==', primaryKey)
8884
.get()
8985
.then(querySnap => {
9086
querySnap.forEach(doc => {

0 commit comments

Comments
 (0)