@travetto/model-firestore 8.0.0-alpha.22 → 8.0.0-alpha.24
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/package.json +1 -1
- package/src/config.ts +3 -4
- package/support/cli.firestore_indexes.ts +93 -0
package/package.json
CHANGED
package/src/config.ts
CHANGED
|
@@ -6,13 +6,12 @@ import { PostConstruct } from '@travetto/di';
|
|
|
6
6
|
@Schema()
|
|
7
7
|
class FirestoreModelConfigCredentials {
|
|
8
8
|
client_email: string;
|
|
9
|
-
project_id: string;
|
|
10
9
|
private_key: string;
|
|
11
10
|
}
|
|
12
11
|
|
|
13
12
|
@Config('model.firestore')
|
|
14
13
|
export class FirestoreModelConfig {
|
|
15
|
-
|
|
14
|
+
databaseId?: string;
|
|
16
15
|
credentialsFile?: string;
|
|
17
16
|
emulator?: string;
|
|
18
17
|
projectId?: string;
|
|
@@ -22,8 +21,8 @@ export class FirestoreModelConfig {
|
|
|
22
21
|
|
|
23
22
|
@PostConstruct()
|
|
24
23
|
async finalizeConfig(): Promise<void> {
|
|
25
|
-
if (!this.
|
|
26
|
-
this.projectId
|
|
24
|
+
if (!this.projectId && !Runtime.production) {
|
|
25
|
+
this.projectId = 'trv-local-dev';
|
|
27
26
|
this.emulator ??= 'localhost:7000'; // From docker
|
|
28
27
|
}
|
|
29
28
|
if (this.emulator) {
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
|
|
4
|
+
import { type CliCommandShape, CliCommand, CliModuleFlag } from '@travetto/cli';
|
|
5
|
+
import { JSONUtil, Env } from '@travetto/runtime';
|
|
6
|
+
import { Registry } from '@travetto/registry';
|
|
7
|
+
import { DependencyRegistryIndex } from '@travetto/di';
|
|
8
|
+
import { ModelRegistryIndex } from '@travetto/model';
|
|
9
|
+
import { isModelIndexedIndex } from '@travetto/model-indexed';
|
|
10
|
+
|
|
11
|
+
import { FirestoreModelConfig } from '../src/config.ts';
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Generate the Firestore composite indexes JSON for all registered models.
|
|
15
|
+
*
|
|
16
|
+
* The resulting JSON can be written to stdout or to a file path for use in
|
|
17
|
+
* firebase-cli deployments.
|
|
18
|
+
*/
|
|
19
|
+
@CliCommand()
|
|
20
|
+
export class FirestoreIndexesCommand implements CliCommandShape {
|
|
21
|
+
|
|
22
|
+
/** Output file */
|
|
23
|
+
output?: string;
|
|
24
|
+
|
|
25
|
+
@CliModuleFlag({ short: 'm' })
|
|
26
|
+
module: string;
|
|
27
|
+
|
|
28
|
+
finalize(): void {
|
|
29
|
+
Env.DEBUG.set(false);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async main(): Promise<void> {
|
|
33
|
+
await Registry.init();
|
|
34
|
+
|
|
35
|
+
const config = await DependencyRegistryIndex.getInstance(FirestoreModelConfig);
|
|
36
|
+
|
|
37
|
+
const indexesList: unknown[] = [];
|
|
38
|
+
|
|
39
|
+
for (const cls of ModelRegistryIndex.getClasses()) {
|
|
40
|
+
let collectionGroup = ModelRegistryIndex.getStoreName(cls);
|
|
41
|
+
if (config.namespace) {
|
|
42
|
+
collectionGroup = `${config.namespace}_${collectionGroup}`;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const indices = ModelRegistryIndex.getIndices(cls);
|
|
46
|
+
for (const idx of indices) {
|
|
47
|
+
if (isModelIndexedIndex(idx)) {
|
|
48
|
+
const fieldsCount = (idx.keyTemplate?.length ?? 0) + (idx.sortTemplate?.length ?? 0);
|
|
49
|
+
// Only create composite indexes if we have at least 2 fields
|
|
50
|
+
if (fieldsCount >= 2) {
|
|
51
|
+
const fields: { fieldPath: string, order: 'ASCENDING' | 'DESCENDING' }[] = [];
|
|
52
|
+
|
|
53
|
+
// Add key fields first
|
|
54
|
+
for (const part of idx.keyTemplate) {
|
|
55
|
+
fields.push({
|
|
56
|
+
fieldPath: part.path.join('.'),
|
|
57
|
+
order: 'ASCENDING'
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Add sort fields second
|
|
62
|
+
for (const part of idx.sortTemplate) {
|
|
63
|
+
fields.push({
|
|
64
|
+
fieldPath: part.path.join('.'),
|
|
65
|
+
order: part.value === 1 ? 'ASCENDING' : 'DESCENDING'
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
indexesList.push({
|
|
70
|
+
collectionGroup,
|
|
71
|
+
queryScope: 'COLLECTION',
|
|
72
|
+
fields
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const outputData = {
|
|
80
|
+
indexes: indexesList,
|
|
81
|
+
fieldOverrides: []
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const text = JSONUtil.toUTF8Pretty(outputData);
|
|
85
|
+
|
|
86
|
+
if (this.output === '-' || !this.output) {
|
|
87
|
+
console.log!(text);
|
|
88
|
+
} else {
|
|
89
|
+
await fs.mkdir(path.dirname(this.output), { recursive: true });
|
|
90
|
+
await fs.writeFile(this.output, text, 'utf8');
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|