Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 12 additions & 12 deletions __tests__/types/DefaultMigrator.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,33 +3,33 @@
import { firestore } from 'firebase-admin';
import { expectError, expectType } from 'tsd';
import { DefaultMigrator, Traverser, createMigrator, createTraverser } from '../../src';
import { D, collectionRef } from './_helpers';
import { TestAppModelType, TestDbModelType, collectionRef } from './_helpers';

const defaultMigrator = createMigrator(collectionRef);

expectType<Traverser<D>>(defaultMigrator.traverser);
expectType<Traverser<TestAppModelType, TestDbModelType>>(defaultMigrator.traverser);

(() => {
const modifiedMigrator = defaultMigrator.withPredicate((doc) => {
expectType<firestore.QueryDocumentSnapshot<D>>(doc);
expectType<firestore.QueryDocumentSnapshot<TestAppModelType, TestDbModelType>>(doc);
return false;
});
expectType<DefaultMigrator<D>>(modifiedMigrator);
expectType<DefaultMigrator<TestAppModelType, TestDbModelType>>(modifiedMigrator);
})();

(() => {
const traverser = createTraverser(collectionRef);
const modifiedMigrator = defaultMigrator.withTraverser(traverser);
expectType<DefaultMigrator<D>>(modifiedMigrator);
expectType<DefaultMigrator<TestAppModelType, TestDbModelType>>(modifiedMigrator);
})();

defaultMigrator.onBeforeBatchStart((batchDocs, batchIndex) => {
expectType<firestore.QueryDocumentSnapshot<D>[]>(batchDocs);
expectType<firestore.QueryDocumentSnapshot<TestAppModelType, TestDbModelType>[]>(batchDocs);
expectType<number>(batchIndex);
});

defaultMigrator.onAfterBatchComplete((batchDocs, batchIndex) => {
expectType<firestore.QueryDocumentSnapshot<D>[]>(batchDocs);
expectType<firestore.QueryDocumentSnapshot<TestAppModelType, TestDbModelType>[]>(batchDocs);
expectType<number>(batchIndex);
});

Expand All @@ -52,17 +52,17 @@ defaultMigrator.set({ num: 0 }, { merge: true });

expectError(
defaultMigrator.setWithDerivedData((doc) => {
expectType<firestore.QueryDocumentSnapshot<D>>(doc);
expectType<firestore.QueryDocumentSnapshot<TestAppModelType, TestDbModelType>>(doc);
return { num: 0 };
})
);
defaultMigrator.setWithDerivedData((doc) => {
expectType<firestore.QueryDocumentSnapshot<D>>(doc);
expectType<firestore.QueryDocumentSnapshot<TestAppModelType, TestDbModelType>>(doc);
return { num: 0, text: '' };
});
defaultMigrator.setWithDerivedData(
(doc) => {
expectType<firestore.QueryDocumentSnapshot<D>>(doc);
expectType<firestore.QueryDocumentSnapshot<TestAppModelType, TestDbModelType>>(doc);
return { num: 0 };
},
{ merge: true }
Expand All @@ -78,14 +78,14 @@ defaultMigrator.update('anyField', 'anyValue');

expectError(
defaultMigrator.updateWithDerivedData((doc) => {
expectType<firestore.QueryDocumentSnapshot<D>>(doc);
expectType<firestore.QueryDocumentSnapshot<TestAppModelType, TestDbModelType>>(doc);
return { anyField: '' };
})
);

expectError(
defaultMigrator.updateWithDerivedData((doc) => {
expectType<firestore.QueryDocumentSnapshot<D>>(doc);
expectType<firestore.QueryDocumentSnapshot<TestAppModelType, TestDbModelType>>(doc);
return ['anyField', 'anyValue'];
})
);
Expand Down
16 changes: 8 additions & 8 deletions __tests__/types/Traverser.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ import {
TraversalResult,
Traverser,
} from '../../src';
import { collectionRef, D } from './_helpers';
import { collectionRef, TestAppModelType, TestDbModelType } from './_helpers';

const traverser = createTraverser(collectionRef);

// TODO: Ideally we want to expect a firestore.CollectionReference<D> here because
// TODO: Ideally we want to expect a firestore.CollectionReference<TestAppModelType, TestDbModelType> here because
// we initialized the traverser with a collection reference.
expectType<Traversable<D>>(traverser.traversable);
expectType<Traversable<TestAppModelType, TestDbModelType>>(traverser.traversable);

expectType<TraversalConfig>(traverser.traversalConfig);

Expand All @@ -27,21 +27,21 @@ expectType<TraversalConfig>(traverser.traversalConfig);
maxDocCount: 0,
maxConcurrentBatchCount: 0,
});
expectType<Traverser<D>>(modifiedTraverser);
expectType<Traverser<TestAppModelType, TestDbModelType>>(modifiedTraverser);
})();

(() => {
const modifiedTraverser = traverser.withExitEarlyPredicate((batchDocs, batchIndex) => {
expectType<firestore.QueryDocumentSnapshot<D>[]>(batchDocs);
expectType<firestore.QueryDocumentSnapshot<TestAppModelType, TestDbModelType>[]>(batchDocs);
expectType<number>(batchIndex);
return false;
});
expectType<Traverser<D>>(modifiedTraverser);
expectType<Traverser<TestAppModelType, TestDbModelType>>(modifiedTraverser);
})();

(async () => {
const traversalResult1 = await traverser.traverseEach(async (doc, docIndex, batchIndex) => {
expectType<firestore.QueryDocumentSnapshot<D>>(doc);
expectType<firestore.QueryDocumentSnapshot<TestAppModelType, TestDbModelType>>(doc);
expectType<number>(docIndex);
expectType<number>(batchIndex);
});
Expand All @@ -50,7 +50,7 @@ expectType<TraversalConfig>(traverser.traversalConfig);

(async () => {
const traversalResult2 = await traverser.traverse(async (batchDocs, batchIndex) => {
expectType<firestore.QueryDocumentSnapshot<D>[]>(batchDocs);
expectType<firestore.QueryDocumentSnapshot<TestAppModelType, TestDbModelType>[]>(batchDocs);
expectType<number>(batchIndex);
});
expectType<TraversalResult>(traversalResult2);
Expand Down
12 changes: 10 additions & 2 deletions __tests__/types/_helpers.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
import { firestore } from 'firebase-admin';

export type D = {
export type TestAppModelType = {
text: string;
num: number;
};

export const collectionRef = firestore().collection('projects') as firestore.CollectionReference<D>;
export type TestDbModelType = {
text: string;
num: number;
};

export const collectionRef = firestore().collection('projects') as firestore.CollectionReference<
TestAppModelType,
TestDbModelType
>;
6 changes: 3 additions & 3 deletions __tests__/types/createBatchMigrator.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

import { expectType } from 'tsd';
import { createBatchMigrator, createTraverser, BatchMigrator } from '../../src';
import { collectionRef, D } from './_helpers';
import { collectionRef, TestAppModelType, TestDbModelType } from './_helpers';

// Signature 1

const traverser = createTraverser(collectionRef);
const batchMigrator = createBatchMigrator(traverser);
expectType<BatchMigrator<D>>(batchMigrator);
expectType<BatchMigrator<TestAppModelType, TestDbModelType>>(batchMigrator);

// Signature 2

Expand All @@ -17,4 +17,4 @@ const batchMigrator2 = createBatchMigrator(collectionRef, {
sleepTimeBetweenBatches: 0,
maxDocCount: 0,
});
expectType<BatchMigrator<D>>(batchMigrator2);
expectType<BatchMigrator<TestAppModelType, TestDbModelType>>(batchMigrator2);
6 changes: 3 additions & 3 deletions __tests__/types/createMigrator.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

import { expectType } from 'tsd';
import { createMigrator, createTraverser, DefaultMigrator } from '../../src';
import { collectionRef, D } from './_helpers';
import { collectionRef, TestAppModelType, TestDbModelType } from './_helpers';

// Signature 1

const traverser = createTraverser(collectionRef);
const defaultMigrator = createMigrator(traverser);
expectType<DefaultMigrator<D>>(defaultMigrator);
expectType<DefaultMigrator<TestAppModelType, TestDbModelType>>(defaultMigrator);

// Signature 2

Expand All @@ -18,4 +18,4 @@ const defaultMigrator2 = createMigrator(collectionRef, {
maxDocCount: 0,
maxConcurrentBatchCount: 0,
});
expectType<DefaultMigrator<D>>(defaultMigrator2);
expectType<DefaultMigrator<TestAppModelType, TestDbModelType>>(defaultMigrator2);
4 changes: 2 additions & 2 deletions __tests__/types/createTraverser.test-d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { expectType } from 'tsd';
import { createTraverser, Traverser } from '../../src';
import { collectionRef, D } from './_helpers';
import { collectionRef, TestAppModelType, TestDbModelType } from './_helpers';

const traverser = createTraverser(collectionRef, {
batchSize: 0,
Expand All @@ -11,4 +11,4 @@ const traverser = createTraverser(collectionRef, {
maxConcurrentBatchCount: 0,
});

expectType<Traverser<D>>(traverser);
expectType<Traverser<TestAppModelType, TestDbModelType>>(traverser);
31 changes: 23 additions & 8 deletions __tests__/utils/collectionPopulator.ts
Original file line number Diff line number Diff line change
@@ -1,23 +1,38 @@
import type { firestore } from 'firebase-admin';

interface CollectionPopulatorBuilder<D> {
withData(dataOrGetData: D | (() => D)): CollectionPopulator<D>;
interface CollectionPopulatorBuilder<
AppModelType = firestore.DocumentData,
DbModelType extends firestore.DocumentData = firestore.DocumentData
> {
withData(
dataOrGetData: AppModelType | (() => AppModelType)
): CollectionPopulator<AppModelType, DbModelType>;
}

interface CollectionPopulator<D> {
populate(opts: { count: number }): Promise<firestore.DocumentReference<D>[]>;
interface CollectionPopulator<
AppModelType = firestore.DocumentData,
DbModelType extends firestore.DocumentData = firestore.DocumentData
> {
populate(opts: {
count: number;
}): Promise<firestore.DocumentReference<AppModelType, DbModelType>[]>;
}

export function collectionPopulator<D>(
collectionRef: firestore.CollectionReference<D>
): CollectionPopulatorBuilder<D> {
export function collectionPopulator<
AppModelType = firestore.DocumentData,
DbModelType extends firestore.DocumentData = firestore.DocumentData
>(
collectionRef: firestore.CollectionReference<AppModelType, DbModelType>
): CollectionPopulatorBuilder<AppModelType, DbModelType> {
return {
withData: (dataOrGetData) => {
return {
populate: async ({ count: docCount }) => {
const promises = new Array(docCount).fill(null).map(async () => {
const data =
typeof dataOrGetData === 'function' ? (dataOrGetData as () => D)() : dataOrGetData;
typeof dataOrGetData === 'function'
? (dataOrGetData as () => AppModelType)()
: dataOrGetData;
return await collectionRef.add(data);
});

Expand Down
34 changes: 23 additions & 11 deletions src/api/createBatchMigrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,10 @@ import { createTraverser } from './createTraverser';
* @returns A new {@link BatchMigrator} object.
* @throws {@link InvalidConfigError} Thrown if the traversal config of the specified traverser is not compatible with this migrator.
*/
export function createBatchMigrator<D = firestore.DocumentData>(
traverser: Traverser<D>
): BatchMigrator<D>;
export function createBatchMigrator<
AppModelType = firestore.DocumentData,
DbModelType extends firestore.DocumentData = firestore.DocumentData
>(traverser: Traverser<AppModelType, DbModelType>): BatchMigrator<AppModelType, DbModelType>;

/**
* Creates a migrator that facilitates database migrations. The migrator creates a default traverser that
Expand All @@ -38,17 +39,28 @@ export function createBatchMigrator<D = firestore.DocumentData>(
* @returns A new {@link BatchMigrator} object.
* @throws {@link InvalidConfigError} Thrown if the specified `traversalConfig` is invalid or incompatible with this migrator.
*/
export function createBatchMigrator<D = firestore.DocumentData>(
traversable: Traversable<D>,
export function createBatchMigrator<
AppModelType = firestore.DocumentData,
DbModelType extends firestore.DocumentData = firestore.DocumentData
>(
traversable: Traversable<AppModelType, DbModelType>,
traversalConfig?: Partial<TraversalConfig>
): BatchMigrator<D>;
): BatchMigrator<AppModelType, DbModelType>;

export function createBatchMigrator<D = firestore.DocumentData>(
traversableOrTraverser: Traverser<D> | Traversable<D>,
export function createBatchMigrator<
AppModelType = firestore.DocumentData,
DbModelType extends firestore.DocumentData = firestore.DocumentData
>(
traversableOrTraverser:
| Traverser<AppModelType, DbModelType>
| Traversable<AppModelType, DbModelType>,
traversalConfig?: Partial<TraversalConfig>
): BatchMigrator<D> {
): BatchMigrator<AppModelType, DbModelType> {
const traverser = isTraverser(traversableOrTraverser)
? (traversableOrTraverser as Traverser<D>)
: createTraverser(traversableOrTraverser as Traversable<D>, traversalConfig);
? (traversableOrTraverser as Traverser<AppModelType, DbModelType>)
: createTraverser(
traversableOrTraverser as Traversable<AppModelType, DbModelType>,
traversalConfig
);
return new BasicBatchMigratorImpl(traverser);
}
34 changes: 23 additions & 11 deletions src/api/createMigrator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import { createTraverser } from './createTraverser';
* @param traverser - The traverser object that this migrator will use when traversing the collection and writing to documents.
* @returns A new {@link DefaultMigrator} object.
*/
export function createMigrator<D = firestore.DocumentData>(
traverser: Traverser<D>
): DefaultMigrator<D>;
export function createMigrator<
AppModelType = firestore.DocumentData,
DbModelType extends firestore.DocumentData = firestore.DocumentData
>(traverser: Traverser<AppModelType, DbModelType>): DefaultMigrator<AppModelType, DbModelType>;

/**
* Creates a migrator that facilitates database migrations. The migrator creates a default traverser that
Expand All @@ -27,17 +28,28 @@ export function createMigrator<D = firestore.DocumentData>(
* @returns A new {@link DefaultMigrator} object.
* @throws {@link InvalidConfigError} Thrown if the specified `traversalConfig` is invalid.
*/
export function createMigrator<D = firestore.DocumentData>(
traversable: Traversable<D>,
export function createMigrator<
AppModelType = firestore.DocumentData,
DbModelType extends firestore.DocumentData = firestore.DocumentData
>(
traversable: Traversable<AppModelType, DbModelType>,
traversalConfig?: Partial<TraversalConfig>
): DefaultMigrator<D>;
): DefaultMigrator<AppModelType, DbModelType>;

export function createMigrator<D = firestore.DocumentData>(
traversableOrTraverser: Traverser<D> | Traversable<D>,
export function createMigrator<
AppModelType = firestore.DocumentData,
DbModelType extends firestore.DocumentData = firestore.DocumentData
>(
traversableOrTraverser:
| Traverser<AppModelType, DbModelType>
| Traversable<AppModelType, DbModelType>,
traversalConfig?: Partial<TraversalConfig>
): DefaultMigrator<D> {
): DefaultMigrator<AppModelType, DbModelType> {
const traverser = isTraverser(traversableOrTraverser)
? (traversableOrTraverser as Traverser<D>)
: createTraverser(traversableOrTraverser as Traversable<D>, traversalConfig);
? (traversableOrTraverser as Traverser<AppModelType, DbModelType>)
: createTraverser(
traversableOrTraverser as Traversable<AppModelType, DbModelType>,
traversalConfig
);
return new BasicDefaultMigratorImpl(traverser);
}
9 changes: 6 additions & 3 deletions src/api/createTraverser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,12 @@ import type { Traversable, TraversalConfig, Traverser } from './interfaces';
* @returns A new {@link Traverser} object.
* @throws {@link InvalidConfigError} Thrown if the specified `config` is invalid.
*/
export function createTraverser<D = firestore.DocumentData>(
traversable: Traversable<D>,
export function createTraverser<
AppModelType = firestore.DocumentData,
DbModelType extends firestore.DocumentData = firestore.DocumentData
>(
traversable: Traversable<AppModelType, DbModelType>,
config?: Partial<TraversalConfig>
): Traverser<D> {
): Traverser<AppModelType, DbModelType> {
return new PromiseQueueBasedTraverserImpl(traversable, [], config);
}
7 changes: 5 additions & 2 deletions src/api/interfaces/BatchCallback.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import type { firestore } from 'firebase-admin';
/**
* A function that takes batch doc snapshots and the 0-based batch index as its arguments.
*/
export type BatchCallback<D = firestore.DocumentData> = (
batchDocs: firestore.QueryDocumentSnapshot<D>[],
export type BatchCallback<
AppModelType = firestore.DocumentData,
DbModelType extends firestore.DocumentData = firestore.DocumentData
> = (
batchDocs: firestore.QueryDocumentSnapshot<AppModelType, DbModelType>[],
batchIndex: number
) => void | Promise<void>;
Loading