diff --git a/.prettierignore b/.prettierignore index ca9f916676d..8ef17af838c 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,5 @@ # This file is pre-built and need not be formatted packages/auth packages/firebase/firebase* -packages/firestore/scripts +packages/firestore/scripts/*.js dist diff --git a/common/api-review/firestore-exp.api.md b/common/api-review/firestore-exp.api.md new file mode 100644 index 00000000000..5cce2f4df22 --- /dev/null +++ b/common/api-review/firestore-exp.api.md @@ -0,0 +1,561 @@ +## API Report File for "@firebase/firestore-exp" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { DocumentData as DocumentData_2 } from '@firebase/firestore-types'; +import { FirebaseApp } from '@firebase/app-types'; +import { FirebaseAuthInternalName } from '@firebase/auth-interop-types'; +import { _FirebaseService } from '@firebase/app-types'; +import { LogLevelString as LogLevel } from '@firebase/logger'; +import { Provider } from '@firebase/component'; +import { SetOptions as SetOptions_2 } from '@firebase/firestore-types'; +import { SnapshotMetadata as SnapshotMetadata_2 } from '@firebase/firestore-types'; + +// @public +export function addDoc(reference: CollectionReference, data: T): Promise>; + +// @public +export function arrayRemove(...elements: unknown[]): FieldValue; + +// @public +export function arrayUnion(...elements: unknown[]): FieldValue; + +// @public +export class Bytes { + constructor(byteString: ByteString); + // Warning: (ae-forgotten-export) The symbol "ByteString" needs to be exported by the entry point index.d.ts + // + // (undocumented) + _byteString: ByteString; + static fromBase64String(base64: string): Bytes; + static fromUint8Array(array: Uint8Array): Bytes; + isEqual(other: Bytes): boolean; + toBase64(): string; + toString(): string; + toUint8Array(): Uint8Array; +} + +// @public +export const CACHE_SIZE_UNLIMITED = -1; + +// @public +export function clearIndexedDbPersistence(firestore: FirebaseFirestore): Promise; + +// Warning: (ae-forgotten-export) The symbol "FirebaseFirestore" needs to be exported by the entry point index.d.ts +// +// @public +export function collection(firestore: FirebaseFirestore_2, path: string, ...pathSegments: string[]): CollectionReference; + +// @public +export function collection(reference: CollectionReference, path: string, ...pathSegments: string[]): CollectionReference; + +// @public +export function collection(reference: DocumentReference, path: string, ...pathSegments: string[]): CollectionReference; + +// @public +export function collectionGroup(firestore: FirebaseFirestore_2, collectionId: string): Query; + +// @public +export class CollectionReference extends Query { + // Warning: (ae-forgotten-export) The symbol "FirestoreDataConverter" needs to be exported by the entry point index.d.ts + constructor(firestore: FirebaseFirestore_2, converter: FirestoreDataConverter_2 | null, _path: ResourcePath); + // (undocumented) + readonly firestore: FirebaseFirestore_2; + get id(): string; + get parent(): DocumentReference | null; + get path(): string; + // Warning: (ae-forgotten-export) The symbol "ResourcePath" needs to be exported by the entry point index.d.ts + // + // (undocumented) + readonly _path: ResourcePath; + // (undocumented) + readonly type = "collection"; + withConverter(converter: FirestoreDataConverter_2): CollectionReference; +} + +// @public +export function deleteDoc(reference: DocumentReference): Promise; + +// @public +export function deleteField(): FieldValue; + +// @public +export function disableNetwork(firestore: FirebaseFirestore): Promise; + +// @public +export function doc(firestore: FirebaseFirestore_2, path: string, ...pathSegments: string[]): DocumentReference; + +// @public +export function doc(reference: CollectionReference, path?: string, ...pathSegments: string[]): DocumentReference; + +// @public +export function doc(reference: DocumentReference, path: string, ...pathSegments: string[]): DocumentReference; + +// @public +export interface DocumentChange { + readonly doc: QueryDocumentSnapshot; + readonly newIndex: number; + readonly oldIndex: number; + readonly type: DocumentChangeType; +} + +// @public +export type DocumentChangeType = 'added' | 'removed' | 'modified'; + +// @public +export interface DocumentData { + // (undocumented) + [field: string]: any; +} + +// @public +export function documentId(): FieldPath; + +// Warning: (ae-forgotten-export) The symbol "_DocumentKeyReference" needs to be exported by the entry point index.d.ts +// +// @public +export class DocumentReference extends _DocumentKeyReference { + constructor(firestore: FirebaseFirestore_2, _converter: FirestoreDataConverter_2 | null, _path: ResourcePath); + readonly firestore: FirebaseFirestore_2; + get id(): string; + get parent(): CollectionReference; + get path(): string; + // (undocumented) + readonly _path: ResourcePath; + readonly type = "document"; + withConverter(converter: FirestoreDataConverter_2): DocumentReference; +} + +// Warning: (ae-forgotten-export) The symbol "DocumentSnapshot" needs to be exported by the entry point index.d.ts +// +// @public +export class DocumentSnapshot extends DocumentSnapshot_2 { + // Warning: (ae-forgotten-export) The symbol "DocumentKey" needs to be exported by the entry point index.d.ts + // Warning: (ae-forgotten-export) The symbol "Document" needs to be exported by the entry point index.d.ts + constructor(_firestore: FirebaseFirestore, key: DocumentKey, document: Document_2 | null, metadata: SnapshotMetadata, converter: FirestoreDataConverter | null); + data(options?: SnapshotOptions): T | undefined; + exists(): this is QueryDocumentSnapshot; + // (undocumented) + readonly _firestore: FirebaseFirestore; + get(fieldPath: string | FieldPath, options?: SnapshotOptions): any; + readonly metadata: SnapshotMetadata; +} + +// @public +export function enableIndexedDbPersistence(firestore: FirebaseFirestore, persistenceSettings?: PersistenceSettings): Promise; + +// @public +export function enableMultiTabIndexedDbPersistence(firestore: FirebaseFirestore): Promise; + +// @public +export function enableNetwork(firestore: FirebaseFirestore): Promise; + +// @public +export function endAt(snapshot: DocumentSnapshot_2): QueryConstraint; + +// @public +export function endAt(...fieldValues: unknown[]): QueryConstraint; + +// @public +export function endBefore(snapshot: DocumentSnapshot_2): QueryConstraint; + +// @public +export function endBefore(...fieldValues: unknown[]): QueryConstraint; + +// Warning: (ae-forgotten-export) The symbol "_BaseFieldPath" needs to be exported by the entry point index.d.ts +// +// @public +export class FieldPath extends _BaseFieldPath { + constructor(...fieldNames: string[]); + isEqual(other: FieldPath): boolean; +} + +// @public +export abstract class FieldValue { + constructor(_methodName: string); + // (undocumented) + abstract isEqual(other: FieldValue): boolean; + // (undocumented) + _methodName: string; + // Warning: (ae-forgotten-export) The symbol "ParseContext" needs to be exported by the entry point index.d.ts + // Warning: (ae-forgotten-export) The symbol "FieldTransform" needs to be exported by the entry point index.d.ts + // + // (undocumented) + abstract _toFieldTransform(context: ParseContext): FieldTransform | null; +} + +// @public +export class FirebaseFirestore extends FirebaseFirestore_2 implements _FirebaseService { + constructor(app: FirebaseApp, authProvider: Provider); + // (undocumented) + readonly _clientId: string; + // Warning: (ae-forgotten-export) The symbol "ComponentConfiguration" needs to be exported by the entry point index.d.ts + // + // (undocumented) + _getConfiguration(): Promise; + // (undocumented) + _getSettings(): Settings; + // (undocumented) + readonly _persistenceKey: string; + // Warning: (ae-forgotten-export) The symbol "AsyncQueue" needs to be exported by the entry point index.d.ts + // + // (undocumented) + readonly _queue: AsyncQueue; + // Warning: (ae-forgotten-export) The symbol "CredentialChangeListener" needs to be exported by the entry point index.d.ts + // + // (undocumented) + _setCredentialChangeListener(credentialListener: CredentialChangeListener): void; + // (undocumented) + protected _settings?: Settings; + // (undocumented) + _terminate(): Promise; + // (undocumented) + _verifyNotTerminated(): void; +} + +// @public +export interface FirestoreDataConverter extends FirestoreDataConverter_2 { + fromFirestore(snapshot: QueryDocumentSnapshot, options?: SnapshotOptions): T; + toFirestore(modelObject: T): DocumentData; + toFirestore(modelObject: Partial, options: SetOptions): DocumentData; +} + +// @public +export class FirestoreError extends Error { + constructor(code: FirestoreErrorCode, message: string); + // (undocumented) + readonly code: FirestoreErrorCode; + // (undocumented) + readonly message: string; + // (undocumented) + readonly name: string; + // (undocumented) + readonly stack?: string; +} + +// @public +export type FirestoreErrorCode = 'cancelled' | 'unknown' | 'invalid-argument' | 'deadline-exceeded' | 'not-found' | 'already-exists' | 'permission-denied' | 'resource-exhausted' | 'failed-precondition' | 'aborted' | 'out-of-range' | 'unimplemented' | 'internal' | 'unavailable' | 'data-loss' | 'unauthenticated'; + +// @public +export class GeoPoint { + constructor(latitude: number, longitude: number); + _compareTo(other: GeoPoint): number; + isEqual(other: GeoPoint): boolean; + get latitude(): number; + get longitude(): number; + // (undocumented) + toJSON(): { + latitude: number; + longitude: number; + }; +} + +// @public +export function getDoc(reference: DocumentReference): Promise>; + +// @public +export function getDocFromCache(reference: DocumentReference): Promise>; + +// @public +export function getDocFromServer(reference: DocumentReference): Promise>; + +// @public +export function getDocs(query: Query): Promise>; + +// @public +export function getDocsFromCache(query: Query): Promise>; + +// @public +export function getDocsFromServer(query: Query): Promise>; + +// @public +export function getFirestore(app: FirebaseApp): FirebaseFirestore; + +// @public +export function increment(n: number): FieldValue; + +// @public +export function initializeFirestore(app: FirebaseApp, settings: Settings): FirebaseFirestore; + +// @public +export function limit(limit: number): QueryConstraint; + +// @public +export function limitToLast(limit: number): QueryConstraint; + +export { LogLevel } + +// @public +export function onSnapshot(reference: DocumentReference, observer: { + next?: (snapshot: DocumentSnapshot) => void; + error?: (error: FirestoreError) => void; + complete?: () => void; +}): Unsubscribe; + +// @public +export function onSnapshot(reference: DocumentReference, options: SnapshotListenOptions, observer: { + next?: (snapshot: DocumentSnapshot) => void; + error?: (error: FirestoreError) => void; + complete?: () => void; +}): Unsubscribe; + +// @public +export function onSnapshot(reference: DocumentReference, onNext: (snapshot: DocumentSnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; + +// @public +export function onSnapshot(reference: DocumentReference, options: SnapshotListenOptions, onNext: (snapshot: DocumentSnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; + +// @public +export function onSnapshot(query: Query, observer: { + next?: (snapshot: QuerySnapshot) => void; + error?: (error: FirestoreError) => void; + complete?: () => void; +}): Unsubscribe; + +// @public +export function onSnapshot(query: Query, options: SnapshotListenOptions, observer: { + next?: (snapshot: QuerySnapshot) => void; + error?: (error: FirestoreError) => void; + complete?: () => void; +}): Unsubscribe; + +// @public +export function onSnapshot(query: Query, onNext: (snapshot: QuerySnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; + +// @public +export function onSnapshot(query: Query, options: SnapshotListenOptions, onNext: (snapshot: QuerySnapshot) => void, onError?: (error: FirestoreError) => void, onCompletion?: () => void): Unsubscribe; + +// @public +export function onSnapshotsInSync(firestore: FirebaseFirestore, observer: { + next?: (value: void) => void; + error?: (error: FirestoreError) => void; + complete?: () => void; +}): Unsubscribe; + +// @public +export function onSnapshotsInSync(firestore: FirebaseFirestore, onSync: () => void): Unsubscribe; + +// @public +export function orderBy(fieldPath: string | FieldPath, directionStr?: OrderByDirection): QueryConstraint; + +// @public +export type OrderByDirection = 'desc' | 'asc'; + +// @public (undocumented) +export interface PersistenceSettings { + // (undocumented) + forceOwnership?: boolean; +} + +// @public +export class Query { + constructor(firestore: FirebaseFirestore_2, _converter: FirestoreDataConverter_2 | null, _query: Query_2); + // (undocumented) + readonly _converter: FirestoreDataConverter_2 | null; + readonly firestore: FirebaseFirestore_2; + // Warning: (ae-forgotten-export) The symbol "Query" needs to be exported by the entry point index.d.ts + // + // (undocumented) + readonly _query: Query_2; + readonly type: 'query' | 'collection'; + withConverter(converter: FirestoreDataConverter_2): Query; +} + +// @public +export function query(query: Query, ...queryConstraints: QueryConstraint[]): Query; + +// @public +export abstract class QueryConstraint { + abstract _apply(query: Query): Query; + abstract readonly type: QueryConstraintType; +} + +// @public +export type QueryConstraintType = 'where' | 'orderBy' | 'limit' | 'limitToLast' | 'startAt' | 'startAfter' | 'endAt' | 'endBefore'; + +// @public +export class QueryDocumentSnapshot extends DocumentSnapshot { + // @override + data(options?: SnapshotOptions): T; +} + +// @public +export function queryEqual(left: Query, right: Query): boolean; + +// @public +export class QuerySnapshot { + constructor(_firestore: FirebaseFirestore, query: Query, _snapshot: ViewSnapshot); + docChanges(options?: SnapshotListenOptions): Array>; + get docs(): Array>; + get empty(): boolean; + // (undocumented) + readonly _firestore: FirebaseFirestore; + forEach(callback: (result: QueryDocumentSnapshot) => void, thisArg?: unknown): void; + readonly metadata: SnapshotMetadata; + readonly query: Query; + get size(): number; + // Warning: (ae-forgotten-export) The symbol "ViewSnapshot" needs to be exported by the entry point index.d.ts + // + // (undocumented) + readonly _snapshot: ViewSnapshot; +} + +// @public +export function refEqual(left: DocumentReference | CollectionReference, right: DocumentReference | CollectionReference): boolean; + +// @public +export function runTransaction(firestore: FirebaseFirestore, updateFunction: (transaction: Transaction) => Promise): Promise; + +// @public +export function serverTimestamp(): FieldValue; + +// @public +export function setDoc(reference: DocumentReference, data: T): Promise; + +// @public +export function setDoc(reference: DocumentReference, data: Partial, options: SetOptions): Promise; + +// @public +export function setLogLevel(logLevel: LogLevel): void; + +// @public +export type SetOptions = { + readonly merge?: boolean; +} | { + readonly mergeFields?: Array; +}; + +// Warning: (ae-forgotten-export) The symbol "Settings" needs to be exported by the entry point index.d.ts +// +// @public (undocumented) +export interface Settings extends Settings_2 { + // (undocumented) + cacheSizeBytes?: number; +} + +// @public +export function snapshotEqual(left: DocumentSnapshot | QuerySnapshot, right: DocumentSnapshot | QuerySnapshot): boolean; + +// @public +export interface SnapshotListenOptions { + readonly includeMetadataChanges?: boolean; +} + +// @public +export class SnapshotMetadata implements SnapshotMetadata_2 { + constructor(hasPendingWrites: boolean, fromCache: boolean); + readonly fromCache: boolean; + readonly hasPendingWrites: boolean; + isEqual(other: SnapshotMetadata_2): boolean; +} + +// @public +export interface SnapshotOptions { + readonly serverTimestamps?: 'estimate' | 'previous' | 'none'; +} + +// @public +export function startAfter(snapshot: DocumentSnapshot_2): QueryConstraint; + +// @public +export function startAfter(...fieldValues: unknown[]): QueryConstraint; + +// @public (undocumented) +export function startAfter(snapshot: DocumentSnapshot_2): QueryConstraint; + +// @public (undocumented) +export function startAfter(...fieldValues: unknown[]): QueryConstraint; + +// @public +export function startAt(snapshot: DocumentSnapshot_2): QueryConstraint; + +// @public +export function startAt(...fieldValues: unknown[]): QueryConstraint; + +// @public +export function terminate(firestore: FirebaseFirestore): Promise; + +// @public +export class Timestamp { + constructor(seconds: number, nanoseconds: number); + // (undocumented) + _compareTo(other: Timestamp): number; + static fromDate(date: Date): Timestamp; + static fromMillis(milliseconds: number): Timestamp; + isEqual(other: Timestamp): boolean; + // (undocumented) + readonly nanoseconds: number; + static now(): Timestamp; + // (undocumented) + readonly seconds: number; + toDate(): Date; + // (undocumented) + toJSON(): { + seconds: number; + nanoseconds: number; + }; + toMillis(): number; + // (undocumented) + toString(): string; + valueOf(): string; +} + +// Warning: (ae-forgotten-export) The symbol "Transaction" needs to be exported by the entry point index.d.ts +// +// @public +export class Transaction extends Transaction_2 { + // Warning: (ae-forgotten-export) The symbol "Transaction" needs to be exported by the entry point index.d.ts + constructor(_firestore: FirebaseFirestore, _transaction: Transaction_3); + // (undocumented) + protected readonly _firestore: FirebaseFirestore; + get(documentRef: DocumentReference): Promise>; +} + +// @public (undocumented) +export interface Unsubscribe { + // (undocumented) + (): void; +} + +// @public +export interface UpdateData { + // (undocumented) + [fieldPath: string]: any; +} + +// @public +export function updateDoc(reference: DocumentReference, data: UpdateData): Promise; + +// @public +export function updateDoc(reference: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): Promise; + +// @public +export function waitForPendingWrites(firestore: FirebaseFirestore): Promise; + +// @public +export function where(fieldPath: string | FieldPath, opStr: WhereFilterOp, value: unknown): QueryConstraint; + +// @public +export type WhereFilterOp = '<' | '<=' | '==' | '!=' | '>=' | '>' | 'array-contains' | 'in' | 'array-contains-any' | 'not-in'; + +// @public +export class WriteBatch { + // Warning: (ae-forgotten-export) The symbol "Mutation" needs to be exported by the entry point index.d.ts + constructor(_firestore: FirebaseFirestore_2, _commitHandler: (m: Mutation[]) => Promise); + commit(): Promise; + delete(documentRef: DocumentReference): WriteBatch; + set(documentRef: DocumentReference, data: T): WriteBatch; + set(documentRef: DocumentReference, data: Partial, options: SetOptions): WriteBatch; + update(documentRef: DocumentReference, data: UpdateData): WriteBatch; + update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): WriteBatch; + } + +// @public +export function writeBatch(firestore: FirebaseFirestore): WriteBatch; + + +// (No @packageDocumentation comment for this package) + +``` diff --git a/common/api-review/firestore-lite.api.md b/common/api-review/firestore-lite.api.md new file mode 100644 index 00000000000..1a94c147471 --- /dev/null +++ b/common/api-review/firestore-lite.api.md @@ -0,0 +1,444 @@ +## API Report File for "@firebase/firestore-lite" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +import { DocumentData as DocumentData_2 } from '@firebase/firestore-types'; +import { FirebaseApp } from '@firebase/app-types'; +import { FirebaseAuthInternalName } from '@firebase/auth-interop-types'; +import { _FirebaseService } from '@firebase/app-types'; +import { LogLevel } from '@firebase/logger'; +import { LogLevelString } from '@firebase/logger'; +import { Provider } from '@firebase/component'; +import { SetOptions as SetOptions_2 } from '@firebase/firestore-types'; + +// @public +export function addDoc(reference: CollectionReference, data: T): Promise>; + +// @public +export function arrayRemove(...elements: unknown[]): FieldValue; + +// @public +export function arrayUnion(...elements: unknown[]): FieldValue; + +// @public +export class Bytes { + constructor(byteString: ByteString); + // Warning: (ae-forgotten-export) The symbol "ByteString" needs to be exported by the entry point index.d.ts + // + // (undocumented) + _byteString: ByteString; + static fromBase64String(base64: string): Bytes; + static fromUint8Array(array: Uint8Array): Bytes; + isEqual(other: Bytes): boolean; + toBase64(): string; + toString(): string; + toUint8Array(): Uint8Array; +} + +// @public +export function collection(firestore: FirebaseFirestore, path: string, ...pathSegments: string[]): CollectionReference; + +// @public +export function collection(reference: CollectionReference, path: string, ...pathSegments: string[]): CollectionReference; + +// @public +export function collection(reference: DocumentReference, path: string, ...pathSegments: string[]): CollectionReference; + +// @public +export function collectionGroup(firestore: FirebaseFirestore, collectionId: string): Query; + +// @public +export class CollectionReference extends Query { + constructor(firestore: FirebaseFirestore, converter: FirestoreDataConverter | null, _path: ResourcePath); + // (undocumented) + readonly firestore: FirebaseFirestore; + get id(): string; + get parent(): DocumentReference | null; + get path(): string; + // Warning: (ae-forgotten-export) The symbol "ResourcePath" needs to be exported by the entry point index.d.ts + // + // (undocumented) + readonly _path: ResourcePath; + // (undocumented) + readonly type = "collection"; + withConverter(converter: FirestoreDataConverter): CollectionReference; +} + +// @public +export function deleteDoc(reference: DocumentReference): Promise; + +// @public +export function deleteField(): FieldValue; + +// @public +export function doc(firestore: FirebaseFirestore, path: string, ...pathSegments: string[]): DocumentReference; + +// @public +export function doc(reference: CollectionReference, path?: string, ...pathSegments: string[]): DocumentReference; + +// @public +export function doc(reference: DocumentReference, path: string, ...pathSegments: string[]): DocumentReference; + +// @public +export interface DocumentData { + // (undocumented) + [field: string]: any; +} + +// @public +export function documentId(): FieldPath; + +// Warning: (ae-forgotten-export) The symbol "_DocumentKeyReference" needs to be exported by the entry point index.d.ts +// +// @public +export class DocumentReference extends _DocumentKeyReference { + constructor(firestore: FirebaseFirestore, _converter: FirestoreDataConverter | null, _path: ResourcePath); + readonly firestore: FirebaseFirestore; + get id(): string; + get parent(): CollectionReference; + get path(): string; + // (undocumented) + readonly _path: ResourcePath; + readonly type = "document"; + withConverter(converter: FirestoreDataConverter): DocumentReference; +} + +// @public +export class DocumentSnapshot { + constructor(_firestore: FirebaseFirestore, _key: DocumentKey, _document: Document_2 | null, _converter: UntypedFirestoreDataConverter | null); + // Warning: (ae-forgotten-export) The symbol "UntypedFirestoreDataConverter" needs to be exported by the entry point index.d.ts + // + // (undocumented) + _converter: UntypedFirestoreDataConverter | null; + data(): T | undefined; + // Warning: (ae-forgotten-export) The symbol "Document" needs to be exported by the entry point index.d.ts + // + // (undocumented) + _document: Document_2 | null; + exists(): this is QueryDocumentSnapshot; + // (undocumented) + _firestore: FirebaseFirestore; + get(fieldPath: string | FieldPath): any; + get id(): string; + // Warning: (ae-forgotten-export) The symbol "DocumentKey" needs to be exported by the entry point index.d.ts + // + // (undocumented) + _key: DocumentKey; + get ref(): DocumentReference; +} + +// @public +export function endAt(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function endAt(...fieldValues: unknown[]): QueryConstraint; + +// @public +export function endBefore(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function endBefore(...fieldValues: unknown[]): QueryConstraint; + +// Warning: (ae-forgotten-export) The symbol "_BaseFieldPath" needs to be exported by the entry point index.d.ts +// +// @public +export class FieldPath extends _BaseFieldPath { + constructor(...fieldNames: string[]); + isEqual(other: FieldPath): boolean; +} + +// @public +export abstract class FieldValue { + constructor(_methodName: string); + // (undocumented) + abstract isEqual(other: FieldValue): boolean; + // (undocumented) + _methodName: string; + // Warning: (ae-forgotten-export) The symbol "ParseContext" needs to be exported by the entry point index.d.ts + // Warning: (ae-forgotten-export) The symbol "FieldTransform" needs to be exported by the entry point index.d.ts + // + // (undocumented) + abstract _toFieldTransform(context: ParseContext): FieldTransform | null; +} + +// @public +export class FirebaseFirestore implements _FirebaseService { + constructor(app: FirebaseApp, authProvider: Provider); + readonly app: FirebaseApp; + // (undocumented) + _configureClient(settings: Settings): void; + // Warning: (ae-forgotten-export) The symbol "CredentialsProvider" needs to be exported by the entry point index.d.ts + // + // (undocumented) + readonly _credentials: CredentialsProvider; + // Warning: (ae-forgotten-export) The symbol "DatabaseId" needs to be exported by the entry point index.d.ts + // + // (undocumented) + readonly _databaseId: DatabaseId; + // (undocumented) + _delete(): Promise; + // (undocumented) + _getSettings(): Settings; + // (undocumented) + get _initialized(): boolean; + // (undocumented) + readonly _persistenceKey: string; + // (undocumented) + protected _settings?: Settings; + protected _terminate(): Promise; + // (undocumented) + get _terminated(): boolean; + } + +// @public +export interface FirestoreDataConverter { + fromFirestore(snapshot: QueryDocumentSnapshot): T; + toFirestore(modelObject: T): DocumentData; + toFirestore(modelObject: Partial, options: SetOptions): DocumentData; +} + +// @public +export class FirestoreError extends Error { + constructor(code: FirestoreErrorCode, message: string); + // (undocumented) + readonly code: FirestoreErrorCode; + // (undocumented) + readonly message: string; + // (undocumented) + readonly name: string; + // (undocumented) + readonly stack?: string; +} + +// @public +export type FirestoreErrorCode = 'cancelled' | 'unknown' | 'invalid-argument' | 'deadline-exceeded' | 'not-found' | 'already-exists' | 'permission-denied' | 'resource-exhausted' | 'failed-precondition' | 'aborted' | 'out-of-range' | 'unimplemented' | 'internal' | 'unavailable' | 'data-loss' | 'unauthenticated'; + +// @public +export class GeoPoint { + constructor(latitude: number, longitude: number); + _compareTo(other: GeoPoint): number; + isEqual(other: GeoPoint): boolean; + get latitude(): number; + get longitude(): number; + // (undocumented) + toJSON(): { + latitude: number; + longitude: number; + }; +} + +// @public +export function getDoc(reference: DocumentReference): Promise>; + +// @public +export function getDocs(query: Query): Promise>; + +// @public +export function getFirestore(app: FirebaseApp): FirebaseFirestore; + +// @public +export function increment(n: number): FieldValue; + +// @public +export function initializeFirestore(app: FirebaseApp, settings: Settings): FirebaseFirestore; + +// @public +export function limit(limit: number): QueryConstraint; + +// @public +export function limitToLast(limit: number): QueryConstraint; + +export { LogLevel } + +export { LogLevelString } + +// @public +export function orderBy(fieldPath: string | FieldPath, directionStr?: OrderByDirection): QueryConstraint; + +// @public +export type OrderByDirection = 'desc' | 'asc'; + +// @public +export class Query { + constructor(firestore: FirebaseFirestore, _converter: FirestoreDataConverter | null, _query: Query_2); + // (undocumented) + readonly _converter: FirestoreDataConverter | null; + readonly firestore: FirebaseFirestore; + // Warning: (ae-forgotten-export) The symbol "Query" needs to be exported by the entry point index.d.ts + // + // (undocumented) + readonly _query: Query_2; + readonly type: 'query' | 'collection'; + withConverter(converter: FirestoreDataConverter): Query; +} + +// @public +export function query(query: Query, ...queryConstraints: QueryConstraint[]): Query; + +// @public +export abstract class QueryConstraint { + abstract _apply(query: Query): Query; + abstract readonly type: QueryConstraintType; +} + +// @public +export type QueryConstraintType = 'where' | 'orderBy' | 'limit' | 'limitToLast' | 'startAt' | 'startAfter' | 'endAt' | 'endBefore'; + +// @public +export class QueryDocumentSnapshot extends DocumentSnapshot { + // @override + data(): T; +} + +// @public +export function queryEqual(left: Query, right: Query): boolean; + +// @public +export class QuerySnapshot { + constructor(_query: Query, _docs: Array>); + get docs(): Array>; + // (undocumented) + readonly _docs: Array>; + get empty(): boolean; + forEach(callback: (result: QueryDocumentSnapshot) => void, thisArg?: unknown): void; + readonly query: Query; + get size(): number; +} + +// @public +export function refEqual(left: DocumentReference | CollectionReference, right: DocumentReference | CollectionReference): boolean; + +// @public +export function runTransaction(firestore: FirebaseFirestore, updateFunction: (transaction: Transaction) => Promise): Promise; + +// @public +export function serverTimestamp(): FieldValue; + +// @public +export function setDoc(reference: DocumentReference, data: T): Promise; + +// @public +export function setDoc(reference: DocumentReference, data: Partial, options: SetOptions): Promise; + +// @public +export function setLogLevel(logLevel: LogLevelString): void; + +// @public +export type SetOptions = { + readonly merge?: boolean; +} | { + readonly mergeFields?: Array; +}; + +// @public (undocumented) +export interface Settings { + // (undocumented) + host?: string; + // (undocumented) + ignoreUndefinedProperties?: boolean; + // (undocumented) + ssl?: boolean; +} + +// @public +export function snapshotEqual(left: DocumentSnapshot | QuerySnapshot, right: DocumentSnapshot | QuerySnapshot): boolean; + +// @public +export function startAfter(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function startAfter(...fieldValues: unknown[]): QueryConstraint; + +// @public (undocumented) +export function startAfter(snapshot: DocumentSnapshot): QueryConstraint; + +// @public (undocumented) +export function startAfter(...fieldValues: unknown[]): QueryConstraint; + +// @public +export function startAt(snapshot: DocumentSnapshot): QueryConstraint; + +// @public +export function startAt(...fieldValues: unknown[]): QueryConstraint; + +// @public +export function terminate(firestore: FirebaseFirestore): Promise; + +// @public +export class Timestamp { + constructor(seconds: number, nanoseconds: number); + // (undocumented) + _compareTo(other: Timestamp): number; + static fromDate(date: Date): Timestamp; + static fromMillis(milliseconds: number): Timestamp; + isEqual(other: Timestamp): boolean; + // (undocumented) + readonly nanoseconds: number; + static now(): Timestamp; + // (undocumented) + readonly seconds: number; + toDate(): Date; + // (undocumented) + toJSON(): { + seconds: number; + nanoseconds: number; + }; + toMillis(): number; + // (undocumented) + toString(): string; + valueOf(): string; +} + +// @public +export class Transaction { + // Warning: (ae-forgotten-export) The symbol "Transaction" needs to be exported by the entry point index.d.ts + constructor(_firestore: FirebaseFirestore, _transaction: Transaction_2); + delete(documentRef: DocumentReference): this; + // (undocumented) + protected readonly _firestore: FirebaseFirestore; + get(documentRef: DocumentReference): Promise>; + set(documentRef: DocumentReference, data: T): this; + set(documentRef: DocumentReference, data: Partial, options: SetOptions): this; + update(documentRef: DocumentReference, data: UpdateData): this; + update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): this; +} + +// @public +export interface UpdateData { + // (undocumented) + [fieldPath: string]: any; +} + +// @public +export function updateDoc(reference: DocumentReference, data: UpdateData): Promise; + +// @public +export function updateDoc(reference: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): Promise; + +// @public +export function where(fieldPath: string | FieldPath, opStr: WhereFilterOp, value: unknown): QueryConstraint; + +// @public +export type WhereFilterOp = '<' | '<=' | '==' | '!=' | '>=' | '>' | 'array-contains' | 'in' | 'array-contains-any' | 'not-in'; + +// @public +export class WriteBatch { + // Warning: (ae-forgotten-export) The symbol "Mutation" needs to be exported by the entry point index.d.ts + constructor(_firestore: FirebaseFirestore, _commitHandler: (m: Mutation[]) => Promise); + commit(): Promise; + delete(documentRef: DocumentReference): WriteBatch; + set(documentRef: DocumentReference, data: T): WriteBatch; + set(documentRef: DocumentReference, data: Partial, options: SetOptions): WriteBatch; + update(documentRef: DocumentReference, data: UpdateData): WriteBatch; + update(documentRef: DocumentReference, field: string | FieldPath, value: unknown, ...moreFieldsAndValues: unknown[]): WriteBatch; + } + +// @public +export function writeBatch(firestore: FirebaseFirestore): WriteBatch; + + +// (No @packageDocumentation comment for this package) + +``` diff --git a/package.json b/package.json index f4253bc80b9..333e2657ebf 100644 --- a/package.json +++ b/package.json @@ -140,6 +140,7 @@ "ora": "5.1.0", "prettier": "2.1.2", "protractor": "5.4.2", + "rollup-plugin-copy": "3.3.0", "rxjs": "6.6.3", "semver": "7.3.2", "simple-git": "2.22.0", diff --git a/packages/firestore/.eslintrc.js b/packages/firestore/.eslintrc.js index d570b10446d..502c45c314f 100644 --- a/packages/firestore/.eslintrc.js +++ b/packages/firestore/.eslintrc.js @@ -47,6 +47,15 @@ module.exports = { ] }, overrides: [ + { + files: ['**/*.d.ts'], + rules: { + 'camelcase': 'off', + 'import/no-duplicates': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-unused-vars': 'off' + } + }, { files: ['**/*.test.ts', '**/test/**/*.ts'], rules: { diff --git a/packages/firestore/exp-types/index.d.ts b/packages/firestore/exp-types/index.d.ts index 5c1bb7f2b68..7375a9f5dda 100644 --- a/packages/firestore/exp-types/index.d.ts +++ b/packages/firestore/exp-types/index.d.ts @@ -15,534 +15,6 @@ * limitations under the License. */ -import { FirebaseApp } from '@firebase/app-types-exp'; - -/* eslint-disable @typescript-eslint/no-explicit-any */ - -export interface DocumentData { - [field: string]: any; -} - -export interface UpdateData { - [fieldPath: string]: any; -} - -export const CACHE_SIZE_UNLIMITED: number; - -export interface Settings { - host?: string; - ssl?: boolean; - ignoreUndefinedProperties?: boolean; - cacheSizeBytes?: number; -} - -export interface PersistenceSettings { - forceOwnership?: boolean; -} - -export interface SnapshotListenOptions { - readonly includeMetadataChanges?: boolean; -} - -export interface SnapshotOptions { - readonly serverTimestamps?: 'estimate' | 'previous' | 'none'; -} - -export class SnapshotMetadata { - private constructor(); - - readonly hasPendingWrites: boolean; - readonly fromCache: boolean; - - isEqual(other: SnapshotMetadata): boolean; -} - -export type LogLevel = - | 'debug' - | 'error' - | 'silent' - | 'warn' - | 'info' - | 'verbose'; - -export function setLogLevel(logLevel: LogLevel): void; - -export interface FirestoreDataConverter { - toFirestore(modelObject: T): DocumentData; - toFirestore(modelObject: Partial, options: SetOptions): DocumentData; - fromFirestore( - snapshot: QueryDocumentSnapshot, - options?: SnapshotOptions - ): T; -} - -export class FirebaseFirestore { - private constructor(); - readonly app: FirebaseApp; -} - -export function initializeFirestore( - app: FirebaseApp, - settings: Settings -): FirebaseFirestore; -export function getFirestore(app: FirebaseApp): FirebaseFirestore; - -export function terminate(firestore: FirebaseFirestore): Promise; -export function writeBatch(firestore: FirebaseFirestore): WriteBatch; -export function runTransaction( - firestore: FirebaseFirestore, - updateFunction: (transaction: Transaction) => Promise -): Promise; -export function waitForPendingWrites( - firestore: FirebaseFirestore -): Promise; -export function enableNetwork(firestore: FirebaseFirestore): Promise; -export function disableNetwork(firestore: FirebaseFirestore): Promise; - -export function enableIndexedDbPersistence( - firestore: FirebaseFirestore, - persistenceSettings?: PersistenceSettings -): Promise; -export function enableMultiTabIndexedDbPersistence( - firestore: FirebaseFirestore -): Promise; -export function clearIndexedDbPersistence( - firestore: FirebaseFirestore -): Promise; - -export function collection( - firestore: FirebaseFirestore, - path: string, - ...pathComponents: string[] -): CollectionReference; -export function collection( - reference: CollectionReference, - path: string, - ...pathComponents: string[] -): CollectionReference; -export function collection( - reference: DocumentReference, - path: string, - ...pathComponents: string[] -): CollectionReference; -export function doc( - firestore: FirebaseFirestore, - path: string, - ...pathComponents: string[] -): DocumentReference; -export function doc( - reference: CollectionReference, - path?: string, - ...pathComponents: string[] -): DocumentReference; -export function doc( - reference: DocumentReference, - path: string, - ...pathComponents: string[] -): DocumentReference; -export function collectionGroup( - firestore: FirebaseFirestore, - collectionId: string -): Query; - -export class GeoPoint { - constructor(latitude: number, longitude: number); - - readonly latitude: number; - readonly longitude: number; - - isEqual(other: GeoPoint): boolean; -} - -export class Timestamp { - constructor(seconds: number, nanoseconds: number); - - static now(): Timestamp; - - static fromDate(date: Date): Timestamp; - - static fromMillis(milliseconds: number): Timestamp; - - readonly seconds: number; - readonly nanoseconds: number; - - toDate(): Date; - - toMillis(): number; - - isEqual(other: Timestamp): boolean; - - valueOf(): string; -} - -export class Bytes { - private constructor(); - - static fromBase64String(base64: string): Blob; - - static fromUint8Array(array: Uint8Array): Blob; - - toBase64(): string; - - toUint8Array(): Uint8Array; - - isEqual(other: Blob): boolean; -} - -export class Transaction { - private constructor(); - - get(documentRef: DocumentReference): Promise>; - - set(documentRef: DocumentReference, data: T): Transaction; - set( - documentRef: DocumentReference, - data: Partial, - options: SetOptions - ): Transaction; - - update(documentRef: DocumentReference, data: UpdateData): Transaction; - update( - documentRef: DocumentReference, - field: string | FieldPath, - value: any, - ...moreFieldsAndValues: any[] - ): Transaction; - - delete(documentRef: DocumentReference): Transaction; -} - -export class WriteBatch { - private constructor(); - - set(documentRef: DocumentReference, data: T): WriteBatch; - set( - documentRef: DocumentReference, - data: Partial, - options: SetOptions - ): WriteBatch; - - update(documentRef: DocumentReference, data: UpdateData): WriteBatch; - update( - documentRef: DocumentReference, - field: string | FieldPath, - value: any, - ...moreFieldsAndValues: any[] - ): WriteBatch; - - delete(documentRef: DocumentReference): WriteBatch; - - commit(): Promise; -} - -export type SetOptions = - | { - readonly merge?: boolean; - } - | { - readonly mergeFields?: Array; - }; - -export class DocumentReference { - private constructor(); - readonly type: 'document'; - readonly firestore: FirebaseFirestore; - readonly converter: FirestoreDataConverter | null; - readonly path: string; - readonly id: string; - - get parent(): CollectionReference; - - withConverter(converter: FirestoreDataConverter): DocumentReference; -} - -export class DocumentSnapshot { - protected constructor(); - - readonly ref: DocumentReference; - readonly id: string; - readonly metadata: SnapshotMetadata; - - exists(): this is QueryDocumentSnapshot; - - data(options?: SnapshotOptions): T | undefined; - - get(fieldPath: string | FieldPath, options?: SnapshotOptions): any; -} - -export class QueryDocumentSnapshot extends DocumentSnapshot< - T -> { - data(options?: SnapshotOptions): T; -} - -export type OrderByDirection = 'desc' | 'asc'; - -export type WhereFilterOp = - | '<' - | '<=' - | '==' - | '!=' - | '>=' - | '>' - | 'array-contains' - | 'in' - | 'array-contains-any' - | 'not-in'; - -export class Query { - protected constructor(); - readonly type: 'query' | 'collection'; - readonly firestore: FirebaseFirestore; - readonly converter: FirestoreDataConverter | null; - - withConverter(converter: FirestoreDataConverter): Query; -} - -export type QueryConstraintType = - | 'where' - | 'orderBy' - | 'limit' - | 'limitToLast' - | 'startAt' - | 'startAfter' - | 'endAt' - | 'endBefore'; - -export class QueryConstraint { - private constructor(); - readonly type: QueryConstraintType; -} - -export function query( - query: CollectionReference | Query, - ...constraints: QueryConstraint[] -): Query; - -export function where( - fieldPath: string | FieldPath, - opStr: WhereFilterOp, - value: any -): QueryConstraint; -export function orderBy( - fieldPath: string | FieldPath, - directionStr?: OrderByDirection -): QueryConstraint; -export function limit(limit: number): QueryConstraint; -export function limitToLast(limit: number): QueryConstraint; -export function startAt(snapshot: DocumentSnapshot): QueryConstraint; -export function startAt(...fieldValues: any[]): QueryConstraint; -export function startAfter(snapshot: DocumentSnapshot): QueryConstraint; -export function startAfter(...fieldValues: any[]): QueryConstraint; -export function endBefore(snapshot: DocumentSnapshot): QueryConstraint; -export function endBefore(...fieldValues: any[]): QueryConstraint; -export function endAt(snapshot: DocumentSnapshot): QueryConstraint; -export function endAt(...fieldValues: any[]): QueryConstraint; - -export class QuerySnapshot { - private constructor(); - readonly query: Query; - readonly docs: Array>; - readonly metadata: SnapshotMetadata; - readonly size: number; - readonly empty: boolean; - docChanges(options?: SnapshotListenOptions): Array>; - forEach( - callback: (result: QueryDocumentSnapshot) => void, - thisArg?: any - ): void; -} - -export type DocumentChangeType = 'added' | 'removed' | 'modified'; - -export interface DocumentChange { - readonly type: DocumentChangeType; - readonly doc: QueryDocumentSnapshot; - readonly oldIndex: number; - readonly newIndex: number; -} - -export class CollectionReference extends Query { - private constructor(); - readonly type: 'collection'; - readonly id: string; - readonly path: string; - - get parent(): DocumentReference | null; - - withConverter( - converter: FirestoreDataConverter - ): CollectionReference; -} - -export function getDoc( - reference: DocumentReference -): Promise>; -export function getDocFromCache( - reference: DocumentReference -): Promise>; -export function getDocFromServer( - reference: DocumentReference -): Promise>; -export function getDocs(query: Query): Promise>; -export function getDocsFromCache(query: Query): Promise>; -export function getDocsFromServer( - query: Query -): Promise>; - -export function addDoc( - reference: CollectionReference, - data: T -): Promise>; -export function setDoc( - reference: DocumentReference, - data: T -): Promise; -export function setDoc( - reference: DocumentReference, - data: Partial, - options: SetOptions -): Promise; -export function updateDoc( - reference: DocumentReference, - data: UpdateData -): Promise; -export function updateDoc( - reference: DocumentReference, - field: string | FieldPath, - value: any, - ...moreFieldsAndValues: any[] -): Promise; -export function deleteDoc(reference: DocumentReference): Promise; - -export function onSnapshot( - reference: DocumentReference, - observer: { - next?: (snapshot: DocumentSnapshot) => void; - error?: (error: FirestoreError) => void; - complete?: () => void; - } -): () => void; -export function onSnapshot( - reference: DocumentReference, - options: SnapshotListenOptions, - observer: { - next?: (snapshot: DocumentSnapshot) => void; - error?: (error: FirestoreError) => void; - complete?: () => void; - } -): () => void; -export function onSnapshot( - reference: DocumentReference, - onNext: (snapshot: DocumentSnapshot) => void, - onError?: (error: FirestoreError) => void, - onCompletion?: () => void -): () => void; -export function onSnapshot( - reference: DocumentReference, - options: SnapshotListenOptions, - onNext: (snapshot: DocumentSnapshot) => void, - onError?: (error: FirestoreError) => void, - onCompletion?: () => void -): () => void; -export function onSnapshot( - query: Query, - observer: { - next?: (snapshot: QuerySnapshot) => void; - error?: (error: FirestoreError) => void; - complete?: () => void; - } -): () => void; -export function onSnapshot( - query: Query, - options: SnapshotListenOptions, - observer: { - next?: (snapshot: QuerySnapshot) => void; - error?: (error: FirestoreError) => void; - complete?: () => void; - } -): () => void; -export function onSnapshot( - query: Query, - onNext: (snapshot: QuerySnapshot) => void, - onError?: (error: FirestoreError) => void, - onCompletion?: () => void -): () => void; -export function onSnapshot( - query: Query, - options: SnapshotListenOptions, - onNext: (snapshot: QuerySnapshot) => void, - onError?: (error: FirestoreError) => void, - onCompletion?: () => void -): () => void; -export function onSnapshotsInSync( - firestore: FirebaseFirestore, - observer: { - next?: (value: void) => void; - error?: (error: FirestoreError) => void; - complete?: () => void; - } -): () => void; -export function onSnapshotsInSync( - firestore: FirebaseFirestore, - onSync: () => void -): () => void; - -export class FieldValue { - private constructor(); - isEqual(other: FieldValue): boolean; -} - -export function serverTimestamp(): FieldValue; -export function deleteField(): FieldValue; -export function arrayUnion(...elements: any[]): FieldValue; -export function arrayRemove(...elements: any[]): FieldValue; -export function increment(n: number): FieldValue; - -export class FieldPath { - constructor(...fieldNames: string[]); - isEqual(other: FieldPath): boolean; -} - -export function documentId(): FieldPath; - -export function refEqual( - left: DocumentReference | CollectionReference, - right: DocumentReference | CollectionReference -): boolean; -export function queryEqual(left: Query, right: Query): boolean; -export function snapshotEqual( - left: DocumentSnapshot | QuerySnapshot, - right: DocumentSnapshot | QuerySnapshot -): boolean; - -export type FirestoreErrorCode = - | 'cancelled' - | 'unknown' - | 'invalid-argument' - | 'deadline-exceeded' - | 'not-found' - | 'already-exists' - | 'permission-denied' - | 'resource-exhausted' - | 'failed-precondition' - | 'aborted' - | 'out-of-range' - | 'unimplemented' - | 'internal' - | 'unavailable' - | 'data-loss' - | 'unauthenticated'; - -export interface FirestoreError { - code: FirestoreErrorCode; - message: string; - name: string; - stack?: string; -} - -declare module '@firebase/component' { - interface NameServiceMapping { - 'firestore-exp': FirebaseFirestore; - } +export declare class B extends A { + bData: K; } diff --git a/packages/firestore/exp/api-extractor.json b/packages/firestore/exp/api-extractor.json new file mode 100644 index 00000000000..a1ac0c29dd3 --- /dev/null +++ b/packages/firestore/exp/api-extractor.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../config/api-extractor.json", + "mainEntryPointFilePath": "../dist/exp/firestore/exp/index.d.ts", + "dtsRollup": { + "enabled": true, + "publicTrimmedFilePath": "../dist/exp/private.d.ts" + } +} diff --git a/packages/firestore/exp/index.ts b/packages/firestore/exp/index.ts index 5ac7079c8ee..d2b220ecc65 100644 --- a/packages/firestore/exp/index.ts +++ b/packages/firestore/exp/index.ts @@ -31,7 +31,9 @@ export { waitForPendingWrites, disableNetwork, enableNetwork, - terminate + terminate, + Settings, + PersistenceSettings } from './src/api/database'; export { @@ -68,9 +70,12 @@ export { QueryConstraintType, DocumentData, UpdateData, - OrderByDirection + OrderByDirection, + WhereFilterOp } from '../lite/src/api/reference'; +export { Unsubscribe } from '../src/api/observer'; + export { runTransaction, Transaction } from './src/api/transaction'; export { @@ -97,7 +102,7 @@ export { serverTimestamp } from '../lite/src/api/field_value'; -export { setLogLevel, LogLevel } from '../src/util/log'; +export { setLogLevel, LogLevelString as LogLevel } from '../src/util/log'; export { Bytes } from '../lite/src/api/bytes'; diff --git a/packages/firestore/exp/package.json b/packages/firestore/exp/package.json index ade9dc962bf..1d443e3781a 100644 --- a/packages/firestore/exp/package.json +++ b/packages/firestore/exp/package.json @@ -1,5 +1,5 @@ { - "name": "@firebase/firestore/exp", + "name": "@firebase/firestore-exp", "description": "A tree-shakeable version of the Firestore SDK", "main": "../dist/exp/index.node.umd.js", "main-esm": "../dist/exp/index.node.esm2017.js", diff --git a/packages/firestore/exp/src/api/database.ts b/packages/firestore/exp/src/api/database.ts index 7c5e957f64f..bb34b1388de 100644 --- a/packages/firestore/exp/src/api/database.ts +++ b/packages/firestore/exp/src/api/database.ts @@ -52,13 +52,22 @@ import { indexedDbClearPersistence, indexedDbStoragePrefix } from '../../../src/local/indexeddb_persistence'; -import { PersistenceSettings } from '../../../exp-types'; + +declare module '@firebase/component' { + interface NameServiceMapping { + 'firestore-exp': FirebaseFirestore; + } +} /** DOMException error code constants. */ const DOM_EXCEPTION_INVALID_STATE = 11; const DOM_EXCEPTION_ABORTED = 20; const DOM_EXCEPTION_QUOTA_EXCEEDED = 22; +export interface PersistenceSettings { + forceOwnership?: boolean; +} + export interface Settings extends LiteSettings { cacheSizeBytes?: number; } @@ -76,6 +85,7 @@ export class FirebaseFirestore _firestoreClient: FirestoreClient | undefined; + /** @hideconstructor */ constructor( databaseIdOrApp: DatabaseId | FirebaseApp, authProvider: Provider diff --git a/packages/firestore/exp/src/api/snapshot.ts b/packages/firestore/exp/src/api/snapshot.ts index ec42d8a6f5e..1640a624be1 100644 --- a/packages/firestore/exp/src/api/snapshot.ts +++ b/packages/firestore/exp/src/api/snapshot.ts @@ -20,6 +20,7 @@ import { Document } from '../../../src/model/document'; import { AbstractUserDataWriter } from '../../../src/api/user_data_writer'; import { DocumentSnapshot as LiteDocumentSnapshot, + FirestoreDataConverter as LiteFirestoreDataConverter, fieldPathFromArgument } from '../../../lite/src/api/snapshot'; import { FirebaseFirestore } from './database'; @@ -80,7 +81,8 @@ import { newQueryComparator } from '../../../src/core/query'; * } * ``` */ -export interface FirestoreDataConverter { +export interface FirestoreDataConverter + extends LiteFirestoreDataConverter { /** * Called by the Firestore SDK to convert a custom model object of type `T` * into a plain Javascript object (suitable for writing directly to the @@ -88,6 +90,13 @@ export interface FirestoreDataConverter { * `toFirestore()` must be defined with `Partial`. */ toFirestore(modelObject: T): DocumentData; + + /** + * Called by the Firestore SDK to convert a custom model object of type `T` + * into a plain Javascript object (suitable for writing directly to the + * Firestore database). Used with {@link setData()}, {@link WriteBatch#set()} + * and {@link Transaction#set()}} with `merge:true` or `mergeFields`. + */ toFirestore(modelObject: Partial, options: SetOptions): DocumentData; /** @@ -178,6 +187,7 @@ export class DocumentSnapshot extends LiteDocumentSnapshot< */ readonly metadata: SnapshotMetadata; + /** @hideconstructor protected */ constructor( readonly _firestore: FirebaseFirestore, userDataWriter: AbstractUserDataWriter, @@ -325,6 +335,7 @@ export class QuerySnapshot { private _cachedChanges?: Array>; private _cachedChangesIncludeMetadataChanges?: boolean; + /** @hideconstructor */ constructor( readonly _firestore: FirebaseFirestore, readonly _userDataWriter: AbstractUserDataWriter, diff --git a/packages/firestore/exp/src/api/transaction.ts b/packages/firestore/exp/src/api/transaction.ts index 3a3a2bf6a2a..bd76d6ad754 100644 --- a/packages/firestore/exp/src/api/transaction.ts +++ b/packages/firestore/exp/src/api/transaction.ts @@ -39,6 +39,7 @@ export class Transaction extends LiteTransaction { // This class implements the same logic as the Transaction API in the Lite SDK // but is subclassed in order to return its own DocumentSnapshot types. + /** @hideconstructor */ constructor( protected readonly _firestore: FirebaseFirestore, _transaction: InternalTransaction diff --git a/packages/firestore/externs.json b/packages/firestore/externs.json index 06e8519f3c6..1a7749da1a1 100644 --- a/packages/firestore/externs.json +++ b/packages/firestore/externs.json @@ -29,7 +29,7 @@ "packages/util/dist/src/crypt.d.ts", "packages/util/dist/src/environment.d.ts", "packages/firestore/src/protos/firestore_bundle_proto.ts", - "packages/firestore/src/protos/firestore_proto_api.d.ts", + "packages/firestore/src/protos/firestore_proto_api.ts", "packages/firestore/src/util/error.ts", "packages/firestore/src/local/indexeddb_schema.ts", "packages/firestore/src/local/shared_client_state_schema.ts" diff --git a/packages/firestore/lite-types/index.d.ts b/packages/firestore/lite-types/index.d.ts index 40806fa50d5..bec24bd21cf 100644 --- a/packages/firestore/lite-types/index.d.ts +++ b/packages/firestore/lite-types/index.d.ts @@ -1,255 +1,810 @@ +import { DocumentData as DocumentData_2 } from '@firebase/firestore-types'; +import { FirebaseApp } from '@firebase/app-types'; +import { FirebaseAuthInternalName } from '@firebase/auth-interop-types'; +import { _FirebaseService } from '@firebase/app-types'; +import { LogLevel } from '@firebase/logger'; +import { LogLevelString } from '@firebase/logger'; +import { Provider } from '@firebase/component'; +import { SetOptions as SetOptions_2 } from '@firebase/firestore-types'; /** - * @license - * Copyright 2020 Google LLC + * Add a new document to specified `CollectionReference` with the given data, + * assigning it a document ID automatically. * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * The result of this write will only be reflected in document reads that occur + * after the returned Promise resolves. If the client is offline, the + * write fails. If you would like to see local modifications or buffer writes + * until the client is online, use the full Firestore SDK. * - * http://www.apache.org/licenses/LICENSE-2.0 + * @param reference A reference to the collection to add this document to. + * @param data An Object containing the data for the new document. + * @return A Promise resolved with a `DocumentReference` pointing to the + * newly created document after it has been written to the backend. + */ +export declare function addDoc( + reference: CollectionReference, + data: T +): Promise>; +/** + * Returns a special value that can be used with {@link setDoc()} or {@link + * updateDoc()} that tells the server to remove the given elements from any + * array value that already exists on the server. All instances of each element + * specified will be removed from the array. If the field being modified is not + * already an array it will be overwritten with an empty array. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * @param elements The elements to remove from the array. + * @return The `FieldValue` sentinel for use in a call to `setDoc()` or + * `updateDoc()` */ - -import { FirebaseApp } from '@firebase/app-types-exp'; - -/* eslint-disable @typescript-eslint/no-explicit-any */ - -export interface DocumentData { - [field: string]: any; -} - -export interface UpdateData { - [fieldPath: string]: any; -} - -export interface Settings { - host?: string; - ssl?: boolean; - ignoreUndefinedProperties?: boolean; -} - -export type LogLevel = - | 'debug' - | 'error' - | 'silent' - | 'warn' - | 'info' - | 'verbose'; - -export function setLogLevel(logLevel: LogLevel): void; - -export interface FirestoreDataConverter { - toFirestore(modelObject: T): DocumentData; - toFirestore(modelObject: Partial, options: SetOptions): DocumentData; - fromFirestore(snapshot: QueryDocumentSnapshot): T; -} - -export class FirebaseFirestore { +export declare function arrayRemove(...elements: unknown[]): FieldValue; +/** + * Returns a special value that can be used with {@link setDoc()} or {@link + * updateDoc()} that tells the server to union the given elements with any array + * value that already exists on the server. Each specified element that doesn't + * already exist in the array will be added to the end. If the field being + * modified is not already an array it will be overwritten with an array + * containing exactly the specified elements. + * + * @param elements The elements to union into the array. + * @return The `FieldValue` sentinel for use in a call to `setDoc()` or + * `updateDoc()`. + */ +export declare function arrayUnion(...elements: unknown[]): FieldValue; +/** + * An immutable object representing an array of bytes. + */ +export declare class Bytes { private constructor(); - readonly app: FirebaseApp; + /** + * Creates a new `Bytes` object from the given Base64 string, converting it to + * bytes. + * + * @param base64 The Base64 string used to create the `Bytes` object. + */ + static fromBase64String(base64: string): Bytes; + /** + * Creates a new `Bytes` object from the given Uint8Array. + * + * @param array The Uint8Array used to create the `Bytes` object. + */ + static fromUint8Array(array: Uint8Array): Bytes; + /** + * Returns the underlying bytes as a Base64-encoded string. + * + * @return The Base64-encoded string created from the `Bytes` object. + */ + toBase64(): string; + /** + * Returns the underlying bytes in a new `Uint8Array`. + * + * @return The Uint8Array created from the `Bytes` object. + */ + toUint8Array(): Uint8Array; + /** + * Returns a string representation of the `Bytes` object. + * + * @return A string representation of the `Bytes` object. + */ + toString(): string; + /** + * Returns true if this `Bytes` object is equal to the provided one. + * + * @param other The `Bytes` object to compare against. + * @return true if this `Bytes` object is equal to the provided one. + */ + isEqual(other: Bytes): boolean; } - -export function initializeFirestore( - app: FirebaseApp, - settings: Settings -): FirebaseFirestore; -export function getFirestore(app: FirebaseApp): FirebaseFirestore; -export function terminate(firestore: FirebaseFirestore): Promise; -export function writeBatch(firestore: FirebaseFirestore): WriteBatch; -export function runTransaction( - firestore: FirebaseFirestore, - updateFunction: (transaction: Transaction) => Promise -): Promise; - -export function collection( +/** + * Gets a `CollectionReference` instance that refers to the collection at + * the specified absolute path. + * + * @param firestore A reference to the root Firestore instance. + * @param path A slash-separated path to a collection. + * @param pathSegments Additional path segments to apply relative to the first + * argument. + * @throws If the final path has an even number of segments and does not point + * to a collection. + * @return The `CollectionReference` instance. + */ +export declare function collection( firestore: FirebaseFirestore, path: string, - ...pathComponents: string[] + ...pathSegments: string[] ): CollectionReference; -export function collection( +/** + * Gets a `CollectionReference` instance that refers to a subcollection of + * `reference` at the the specified relative path. + * + * @param reference A reference to a collection. + * @param path A slash-separated path to a collection. + * @param pathSegments Additional path segments to apply relative to the first + * argument. + * @throws If the final path has an even number of segments and does not point + * to a collection. + * @return The `CollectionReference` instance. + */ +export declare function collection( reference: CollectionReference, path: string, - ...pathComponents: string[] + ...pathSegments: string[] ): CollectionReference; -export function collection( +/** + * Gets a `CollectionReference` instance that refers to a subcollection of + * `reference` at the the specified relative path. + * + * @param reference A reference to a Firestore document. + * @param path A slash-separated path to a collection. + * @param pathSegments Additional path segments that will be applied relative + * to the first argument. + * @throws If the final path has an even number of segments and does not point + * to a collection. + * @return The `CollectionReference` instance. + */ +export declare function collection( reference: DocumentReference, path: string, - ...pathComponents: string[] + ...pathSegments: string[] ): CollectionReference; -export function doc( +/** + * Creates and returns a new `Query` instance that includes all documents in the + * database that are contained in a collection or subcollection with the + * given `collectionId`. + * + * @param firestore A reference to the root Firestore instance. + * @param collectionId Identifies the collections to query over. Every + * collection or subcollection with this ID as the last segment of its path + * will be included. Cannot contain a slash. + * @return The created `Query`. + */ +export declare function collectionGroup( + firestore: FirebaseFirestore, + collectionId: string +): Query; +/** + * A `CollectionReference` object can be used for adding documents, getting + * document references, and querying for documents (using {@link query()}`). + */ +export declare class CollectionReference { + readonly firestore: FirebaseFirestore; + readonly type = 'collection'; + private constructor(); + /** The collection's identifier. */ + get id(): string; + /** + * A string representing the path of the referenced collection (relative + * to the root of the database). + */ + get path(): string; + /** + * A reference to the containing `DocumentReference` if this is a + * subcollection. If this isn't a subcollection, the reference is null. + */ + get parent(): DocumentReference | null; + /** + * Applies a custom data converter to this CollectionReference, allowing you + * to use your own custom model objects with Firestore. When you call {@link + * addDoc()} with the returned `CollectionReference` instance, the provided + * converter will convert between Firestore data and your custom type `U`. + * + * @param converter Converts objects to and from Firestore. + * @return A `CollectionReference` that uses the provided converter. + */ + withConverter( + converter: FirestoreDataConverter + ): CollectionReference; +} +/** + * Deletes the document referred to by the specified `DocumentReference`. + * + * The deletion will only be reflected in document reads that occur after the + * returned Promise resolves. If the client is offline, the + * delete fails. If you would like to see local modifications or buffer writes + * until the client is online, use the full Firestore SDK. + * + * @param reference A reference to the document to delete. + * @return A Promise resolved once the document has been successfully + * deleted from the backend. + */ +export declare function deleteDoc(reference: DocumentReference): Promise; +/** + * Returns a sentinel for use with {@link updateDoc()} or + * {@link setDoc `setDoc({}, { merge: true })`} to mark a field for deletion. + */ +export declare function deleteField(): FieldValue; +/** + * Gets a `DocumentReference` instance that refers to the document at the + * specified abosulute path. + * + * @param firestore A reference to the root Firestore instance. + * @param path A slash-separated path to a document. + * @param pathSegments Additional path segments that will be applied relative + * to the first argument. + * @throws If the final path has an odd number of segments and does not point to + * a document. + * @return The `DocumentReference` instance. + */ +export declare function doc( firestore: FirebaseFirestore, path: string, - ...pathComponents: string[] + ...pathSegments: string[] ): DocumentReference; -export function doc( +/** + * Gets a `DocumentReference` instance that refers to a document within + * `reference` at the specified relative path. If no path is specified, an + * automatically-generated unique ID will be used for the returned + * `DocumentReference`. + * + * @param reference A reference to a collection. + * @param path A slash-separated path to a document. Has to be omitted to use + * auto-genrated IDs. + * @param pathSegments Additional path segments that will be applied relative + * to the first argument. + * @throws If the final path has an odd number of segments and does not point to + * a document. + * @return The `DocumentReference` instance. + */ +export declare function doc( reference: CollectionReference, path?: string, - ...pathComponents: string[] + ...pathSegments: string[] ): DocumentReference; -export function doc( +/** + * Gets a `DocumentReference` instance that refers to a document within + * `reference` at the specified relative path. + * + * @param reference A reference to a Firestore document. + * @param path A slash-separated path to a document. + * @param pathSegments Additional path segments that will be applied relative + * to the first argument. + * @throws If the final path has an odd number of segments and does not point to + * a document. + * @return The `DocumentReference` instance. + */ +export declare function doc( reference: DocumentReference, path: string, - ...pathComponents: string[] + ...pathSegments: string[] ): DocumentReference; -export function collectionGroup( - firestore: FirebaseFirestore, - collectionId: string -): Query; - -export class GeoPoint { - constructor(latitude: number, longitude: number); - - readonly latitude: number; - readonly longitude: number; - - isEqual(other: GeoPoint): boolean; -} - -export class Timestamp { - constructor(seconds: number, nanoseconds: number); - - static now(): Timestamp; - - static fromDate(date: Date): Timestamp; - - static fromMillis(milliseconds: number): Timestamp; - - readonly seconds: number; - readonly nanoseconds: number; - - toDate(): Date; - - toMillis(): number; - - isEqual(other: Timestamp): boolean; - - valueOf(): string; -} - -export class Bytes { - private constructor(); - - static fromBase64String(base64: string): Blob; - - static fromUint8Array(array: Uint8Array): Blob; - - toBase64(): string; - - toUint8Array(): Uint8Array; - - isEqual(other: Blob): boolean; -} - -export class Transaction { - private constructor(); - - get(documentRef: DocumentReference): Promise>; - - set(documentRef: DocumentReference, data: T): Transaction; - set( - documentRef: DocumentReference, - data: Partial, - options: SetOptions - ): Transaction; - - update(documentRef: DocumentReference, data: UpdateData): Transaction; - update( - documentRef: DocumentReference, - field: string | FieldPath, - value: any, - ...moreFieldsAndValues: any[] - ): Transaction; - - delete(documentRef: DocumentReference): Transaction; -} - -export class WriteBatch { - private constructor(); - - set(documentRef: DocumentReference, data: T): WriteBatch; - set( - documentRef: DocumentReference, - data: Partial, - options: SetOptions - ): WriteBatch; - - update(documentRef: DocumentReference, data: UpdateData): WriteBatch; - update( - documentRef: DocumentReference, - field: string | FieldPath, - value: any, - ...moreFieldsAndValues: any[] - ): WriteBatch; - - delete(documentRef: DocumentReference): WriteBatch; - - commit(): Promise; +/** + * Document data (for use with {@link setDoc()}) consists of fields mapped to + * values. + */ +export declare interface DocumentData { + [field: string]: any; } - -export type SetOptions = - | { - readonly merge?: boolean; - } - | { - readonly mergeFields?: Array; - }; - -export class DocumentReference { - private constructor(); - readonly type: 'document'; +/** + * Returns a special sentinel `FieldPath` to refer to the ID of a document. + * It can be used in queries to sort or filter by the document ID. + */ +export declare function documentId(): FieldPath; +/** + * A `DocumentReference` refers to a document location in a Firestore database + * and can be used to write, read, or listen to the location. The document at + * the referenced location may or may not exist. + */ +export declare class DocumentReference { + /** The type of this Firestore reference. */ + readonly type = 'document'; + /** + * The {@link FirebaseFirestore} the document is in. + * This is useful for performing transactions, for example. + */ readonly firestore: FirebaseFirestore; - readonly converter: FirestoreDataConverter | null; - readonly path: string; - readonly id: string; - + private constructor(); + /** + * The document's identifier within its collection. + */ + get id(): string; + /** + * A string representing the path of the referenced document (relative + * to the root of the database). + */ + get path(): string; + /** + * The collection this `DocumentReference` belongs to. + */ get parent(): CollectionReference; - + /** + * Applies a custom data converter to this `DocumentReference`, allowing you + * to use your own custom model objects with Firestore. When you call {@link + * setDoc()}, {@link getDoc()}, etc. with the returned `DocumentReference` + * instance, the provided converter will convert between Firestore data and + * your custom type `U`. + * + * @param converter Converts objects to and from Firestore. + * @return A `DocumentReference` that uses the provided converter. + */ withConverter(converter: FirestoreDataConverter): DocumentReference; } - -export class DocumentSnapshot { - readonly ref: DocumentReference; - readonly id: string; +/** + * A `DocumentSnapshot` contains data read from a document in your Firestore + * database. The data can be extracted with `.data()` or `.get()` to + * get a specific field. + * + * For a `DocumentSnapshot` that points to a non-existing document, any data + * access will return 'undefined'. You can use the `exists()` method to + * explicitly verify a document's existence. + */ +export declare class DocumentSnapshot { + protected constructor(); + /** Property of the `DocumentSnapshot` that provides the document's ID. */ + get id(): string; + /** + * The `DocumentReference` for the document included in the `DocumentSnapshot`. + */ + get ref(): DocumentReference; + /** + * Signals whether or not the document at the snapshot's location exists. + * + * @return true if the document exists. + */ exists(): this is QueryDocumentSnapshot; + /** + * Retrieves all fields in the document as an `Object`. Returns `undefined` if + * the document doesn't exist. + * + * @return An `Object` containing all fields in the document or `undefined` + * if the document doesn't exist. + */ data(): T | undefined; + /** + * Retrieves the field specified by `fieldPath`. Returns `undefined` if the + * document or field doesn't exist. + * + * @param fieldPath The path (for example 'foo' or 'foo.bar') to a specific + * field. + * @return The data at the specified field location or undefined if no such + * field exists in the document. + */ get(fieldPath: string | FieldPath): any; } - -export class QueryDocumentSnapshot extends DocumentSnapshot< - T -> { - data(): T; +/** + * Creates a `QueryConstraint` that modifies the result set to end at the + * provided document (inclusive). The end position is relative to the order of + * the query. The document must contain all of the fields provided in the + * orderBy of the query. + * + * @param snapshot The snapshot of the document to end at. + * @return A `QueryConstraint` to pass to `query()` + */ +export declare function endAt( + snapshot: DocumentSnapshot +): QueryConstraint; +/** + * Creates a `QueryConstraint` that modifies the result set to end at the + * provided fields relative to the order of the query. The order of the field + * values must match the order of the order by clauses of the query. + * + * @param fieldValues The field values to end this query at, in order + * of the query's order by. + * @return A `QueryConstraint` to pass to `query()` + */ +export declare function endAt(...fieldValues: unknown[]): QueryConstraint; +/** + * Creates a `QueryConstraint` that modifies the result set to end before the + * provided document (exclusive). The end position is relative to the order of + * the query. The document must contain all of the fields provided in the + * orderBy of the query. + * + * @param snapshot The snapshot of the document to end before. + * @return A `QueryConstraint` to pass to `query()` + */ +export declare function endBefore( + snapshot: DocumentSnapshot +): QueryConstraint; +/** + * Creates a `QueryConstraint` that modifies the result set to end before the + * provided fields relative to the order of the query. The order of the field + * values must match the order of the order by clauses of the query. + * + * @param fieldValues The field values to end this query before, in order + * of the query's order by. + * @return A `QueryConstraint` to pass to `query()` + */ +export declare function endBefore(...fieldValues: unknown[]): QueryConstraint; +/** + * A `FieldPath` refers to a field in a document. The path may consist of a + * single field name (referring to a top-level field in the document), or a + * list of field names (referring to a nested field in the document). + * + * Create a `FieldPath` by providing field names. If more than one field + * name is provided, the path will point to a nested field in a document. + */ +export declare class FieldPath { + /** + * Creates a FieldPath from the provided field names. If more than one field + * name is provided, the path will point to a nested field in a document. + * + * @param fieldNames A list of field names. + */ + constructor(...fieldNames: string[]); + /** + * Returns true if this `FieldPath` is equal to the provided one. + * + * @param other The `FieldPath` to compare against. + * @return true if this `FieldPath` is equal to the provided one. + */ + isEqual(other: FieldPath): boolean; } - -export type OrderByDirection = 'desc' | 'asc'; - -export type WhereFilterOp = - | '<' - | '<=' - | '==' - | '!=' - | '>=' - | '>' - | 'array-contains' - | 'in' - | 'array-contains-any' - | 'not-in'; - -export class Query { - protected constructor(); +/** + * Sentinel values that can be used when writing document fields with `set()` + * or `update()`. + */ +export declare abstract class FieldValue { + /** + * @param _methodName The public API endpoint that returns this class. + */ + constructor(_methodName: string); + abstract isEqual(other: FieldValue): boolean; +} +/** + * The Cloud Firestore service interface. + * + * Do not call this constructor directly. Instead, use {@link getFirestore()}. + */ +export declare class FirebaseFirestore { + /** + * The {@link FirebaseApp app} associated with this `Firestore` service + * instance. + */ + readonly app: FirebaseApp; + private constructor(); +} +/** + * Converter used by `withConverter()` to transform user objects of type `T` + * into Firestore data. + * + * Using the converter allows you to specify generic type arguments when + * storing and retrieving objects from Firestore. + * + * @example + * ```typescript + * class Post { + * constructor(readonly title: string, readonly author: string) {} + * + * toString(): string { + * return this.title + ', by ' + this.author; + * } + * } + * + * const postConverter = { + * toFirestore(post: Post): firebase.firestore.DocumentData { + * return {title: post.title, author: post.author}; + * }, + * fromFirestore(snapshot: firebase.firestore.QueryDocumentSnapshot): Post { + * const data = snapshot.data(options)!; + * return new Post(data.title, data.author); + * } + * }; + * + * const postSnap = await firebase.firestore() + * .collection('posts') + * .withConverter(postConverter) + * .doc().get(); + * const post = postSnap.data(); + * if (post !== undefined) { + * post.title; // string + * post.toString(); // Should be defined + * post.someNonExistentProperty; // TS error + * } + * ``` + */ +export declare interface FirestoreDataConverter { + /** + * Called by the Firestore SDK to convert a custom model object of type `T` + * into a plain Javascript object (suitable for writing directly to the + * Firestore database). Used with {@link setData()}, {@link WriteBatch#set()} + * and {@link Transaction#set()}}. + */ + toFirestore(modelObject: T): DocumentData; + /** + * Called by the Firestore SDK to convert a custom model object of type `T` + * into a plain Javascript object (suitable for writing directly to the + * Firestore database). Used with {@link setData()}, {@link WriteBatch#set()} + * and {@link Transaction#set()}} with `merge:true` or `mergeFields`. + */ + toFirestore(modelObject: Partial, options: SetOptions): DocumentData; + /** + * Called by the Firestore SDK to convert Firestore data into an object of + * type T. You can access your data by calling: `snapshot.data()`. + * + * @param snapshot A `QueryDocumentSnapshot` containing your data and + * metadata. + */ + fromFirestore(snapshot: QueryDocumentSnapshot): T; +} +/** An error returned by a Firestore operation. */ +export declare class FirestoreError { + readonly code: FirestoreErrorCode; + readonly message: string; + readonly name: string; + readonly stack?: string; + private constructor(); +} +/** + * @license + * Copyright 2017 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * The set of Firestore status codes. The codes are the same at the ones + * exposed by gRPC here: + * https://github.com/grpc/grpc/blob/master/doc/statuscodes.md + * + * Possible values: + * - 'cancelled': The operation was cancelled (typically by the caller). + * - 'unknown': Unknown error or an error from a different error domain. + * - 'invalid-argument': Client specified an invalid argument. Note that this + * differs from 'failed-precondition'. 'invalid-argument' indicates + * arguments that are problematic regardless of the state of the system + * (e.g. an invalid field name). + * - 'deadline-exceeded': Deadline expired before operation could complete. + * For operations that change the state of the system, this error may be + * returned even if the operation has completed successfully. For example, + * a successful response from a server could have been delayed long enough + * for the deadline to expire. + * - 'not-found': Some requested document was not found. + * - 'already-exists': Some document that we attempted to create already + * exists. + * - 'permission-denied': The caller does not have permission to execute the + * specified operation. + * - 'resource-exhausted': Some resource has been exhausted, perhaps a + * per-user quota, or perhaps the entire file system is out of space. + * - 'failed-precondition': Operation was rejected because the system is not + * in a state required for the operation's execution. + * - 'aborted': The operation was aborted, typically due to a concurrency + * issue like transaction aborts, etc. + * - 'out-of-range': Operation was attempted past the valid range. + * - 'unimplemented': Operation is not implemented or not supported/enabled. + * - 'internal': Internal errors. Means some invariants expected by + * underlying system has been broken. If you see one of these errors, + * something is very broken. + * - 'unavailable': The service is currently unavailable. This is most likely + * a transient condition and may be corrected by retrying with a backoff. + * - 'data-loss': Unrecoverable data loss or corruption. + * - 'unauthenticated': The request does not have valid authentication + * credentials for the operation. + */ +export declare type FirestoreErrorCode = + | 'cancelled' + | 'unknown' + | 'invalid-argument' + | 'deadline-exceeded' + | 'not-found' + | 'already-exists' + | 'permission-denied' + | 'resource-exhausted' + | 'failed-precondition' + | 'aborted' + | 'out-of-range' + | 'unimplemented' + | 'internal' + | 'unavailable' + | 'data-loss' + | 'unauthenticated'; +/** + * @license + * Copyright 2017 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * An immutable object representing a geographic location in Firestore. The + * location is represented as latitude/longitude pair. + * + * Latitude values are in the range of [-90, 90]. + * Longitude values are in the range of [-180, 180]. + */ +export declare class GeoPoint { + /** + * Creates a new immutable `GeoPoint` object with the provided latitude and + * longitude values. + * @param latitude The latitude as number between -90 and 90. + * @param longitude The longitude as number between -180 and 180. + */ + constructor(latitude: number, longitude: number); + /** + * The latitude of this `GeoPoint` instance. + */ + get latitude(): number; + /** + * The longitude of this `GeoPoint` instance. + */ + get longitude(): number; + /** + * Returns true if this `GeoPoint` is equal to the provided one. + * + * @param other The `GeoPoint` to compare against. + * @return true if this `GeoPoint` is equal to the provided one. + */ + isEqual(other: GeoPoint): boolean; + toJSON(): { + latitude: number; + longitude: number; + }; +} +/** + * Reads the document referred to by the specified document reference. + * + * All documents are directly fetched from the server, even if the document was + * previously read or modified. Recent modifications are only reflected in the + * retrieved `DocumentSnapshot` if they have already been applied by the + * backend. If the client is offline, the read fails. If you like to use + * caching or see local modifications, please use the full Firestore SDK. + * + * @param reference The reference of the document to fetch. + * @return A Promise resolved with a `DocumentSnapshot` containing the current + * document contents. + */ +export declare function getDoc( + reference: DocumentReference +): Promise>; +/** + * Executes the query and returns the results as a {@link QuerySnapshot}. + * + * All queries are executed directly by the server, even if the the query was + * previously executed. Recent modifications are only reflected in the retrieved + * results if they have already been applied by the backend. If the client is + * offline, the operation fails. To see previously cached result and local + * modifications, use the full Firestore SDK. + * + * @param query The `Query` to execute. + * @return A Promise that will be resolved with the results of the query. + */ +export declare function getDocs(query: Query): Promise>; +/** + * Returns the existing instance of Firestore that is associated with the + * provided {@link FirebaseApp}. If no instance exists, initializes a new + * instance with default settings. + * + * @param app The {@link FirebaseApp} instance that the returned Firestore + * instance is associated with. + * @return The `Firestore` instance of the provided app. + */ +export declare function getFirestore(app: FirebaseApp): FirebaseFirestore; +/** + * Returns a special value that can be used with {@link setDoc()} or {@link + * updateDoc()} that tells the server to increment the field's current value by + * the given value. + * + * If either the operand or the current field value uses floating point + * precision, all arithmetic follows IEEE 754 semantics. If both values are + * integers, values outside of JavaScript's safe number range + * (`Number.MIN_SAFE_INTEGER` to `Number.MAX_SAFE_INTEGER`) are also subject to + * precision loss. Furthermore, once processed by the Firestore backend, all + * integer operations are capped between -2^63 and 2^63-1. + * + * If the current field value is not of type `number`, or if the field does not + * yet exist, the transformation sets the field to the given value. + * + * @param n The value to increment by. + * @return The `FieldValue` sentinel for use in a call to `setDoc()` or + * `updateDoc()` + */ +export declare function increment(n: number): FieldValue; +/** + * Initializes a new instance of Cloud Firestore with the provided settings. + * Can only be called before any other functions, including + * {@link getFirestore()}. If the custom settings are empty, this function is + * equivalent to calling {@link getFirestore()}. + * + * @param app The {@link FirebaseApp} with which the `Firestore` instance will be + * associated. + * @param settings A settings object to configure the `Firestore` instance. + * @return A newly initialized Firestore instance. + */ +export declare function initializeFirestore( + app: FirebaseApp, + settings: Settings +): FirebaseFirestore; +/** + * Creates a `QueryConstraint` that only returns the first matching documents. + * + * @param limit The maximum number of items to return. + * @return The created `Query`. + */ +export declare function limit(limit: number): QueryConstraint; +/** + * Creates a `QueryConstraint` that only returns the last matching documents. + * + * You must specify at least one `orderBy` clause for `limitToLast` queries, + * otherwise an exception will be thrown during execution. + * + * @param limit The maximum number of items to return. + * @return The created `Query`. + */ +export declare function limitToLast(limit: number): QueryConstraint; +export { LogLevel }; +export { LogLevelString }; +/** + * Creates a `QueryConstraint` that sorts the query result by the + * specified field, optionally in descending order instead of ascending. + * + * @param fieldPath The field to sort by. + * @param directionStr Optional direction to sort by ('asc' or 'desc'). If + * not specified, order will be ascending. + * @return The created `Query`. + */ +export declare function orderBy( + fieldPath: string | FieldPath, + directionStr?: OrderByDirection +): QueryConstraint; +/** + * The direction of a {@link orderBy()} clause is specified as 'desc' or 'asc' + * (descending or ascending). + */ +export declare type OrderByDirection = 'desc' | 'asc'; +/** + * A `Query` refers to a Query which you can read or listen to. You can also + * construct refined `Query` objects by adding filters and ordering. + */ +export declare class Query { + /** The type of this Firestore reference. */ readonly type: 'query' | 'collection'; + /** + * The `FirebaseFirestore` for the Firestore database (useful for performing + * transactions, etc.). + */ readonly firestore: FirebaseFirestore; - readonly converter: FirestoreDataConverter | null; - + protected constructor(); + /** + * Applies a custom data converter to this query, allowing you to use your own + * custom model objects with Firestore. When you call {@link getDocs()} with + * the returned query, the provided converter will convert between Firestore + * data and your custom type `U`. + * + * @param converter Converts objects to and from Firestore. + * @return A `Query` that uses the provided converter. + */ withConverter(converter: FirestoreDataConverter): Query; } - -export type QueryConstraintType = +/** + * Creates a new immutable instance of `query` that is extended to also include + * additional query constraints. + * + * @param query The query instance to use as a base for the new constraints. + * @param queryConstraints The list of `QueryConstraint`s to apply. + * @throws if any of the provided query constraints cannot be combined with the + * existing or new constraints. + */ +export declare function query( + query: Query, + ...queryConstraints: QueryConstraint[] +): Query; +/** + * A `QueryConstraint` is used to narrow the set of documents returned by a + * Firestore query. `QueryConstraint`s are created by invoking {@link where()}, + * {@link orderBy()}, {@link startAt()}, {@link startAfter()}, {@link + * endBefore()}, {@link endAt()}, {@link limit()} or {@link limitToLast()} and + * can then be passed to {@link query()} to create a new query instance that + * also contains this `QueryConstraint`. + */ +export declare abstract class QueryConstraint { + /** The type of this query constraints */ + abstract readonly type: QueryConstraintType; +} +/** Describes the different query constraints available in this SDK. */ +export declare type QueryConstraintType = | 'where' | 'orderBy' | 'limit' @@ -258,147 +813,631 @@ export type QueryConstraintType = | 'startAfter' | 'endAt' | 'endBefore'; - -export class QueryConstraint { - private constructor(); - readonly type: QueryConstraintType; +/** + * A `QueryDocumentSnapshot` contains data read from a document in your + * Firestore database as part of a query. The document is guaranteed to exist + * and its data can be extracted with `.data()` or `.get()` to get a + * specific field. + * + * A `QueryDocumentSnapshot` offers the same API surface as a + * `DocumentSnapshot`. Since query results contain only existing documents, the + * `exists` property will always be true and `data()` will never return + * 'undefined'. + */ +export declare class QueryDocumentSnapshot { + /** + * Retrieves all fields in the document as an `Object`. + * + * @override + * @return An `Object` containing all fields in the document. + */ + data(): T; } - -export function query( - query: CollectionReference | Query, - ...constraints: QueryConstraint[] -): Query; - -export function where( - fieldPath: string | FieldPath, - opStr: WhereFilterOp, - value: any -): QueryConstraint; -export function orderBy( - fieldPath: string | FieldPath, - directionStr?: OrderByDirection -): QueryConstraint; -export function limit(limit: number): QueryConstraint; -export function limitToLast(limit: number): QueryConstraint; -export function startAt(snapshot: DocumentSnapshot): QueryConstraint; -export function startAt(...fieldValues: any[]): QueryConstraint; -export function startAfter(snapshot: DocumentSnapshot): QueryConstraint; -export function startAfter(...fieldValues: any[]): QueryConstraint; -export function endBefore(snapshot: DocumentSnapshot): QueryConstraint; -export function endBefore(...fieldValues: any[]): QueryConstraint; -export function endAt(snapshot: DocumentSnapshot): QueryConstraint; -export function endAt(...fieldValues: any[]): QueryConstraint; - -export class QuerySnapshot { - private constructor(); +/** + * Returns true if the provided queries point to the same collection and apply + * the same constraints. + * + * @param left A `Query` to compare. + * @param right A Query` to compare. + * @return true if the references point to the same location in the same + * Firestore database. + */ +export declare function queryEqual(left: Query, right: Query): boolean; +/** + * A `QuerySnapshot` contains zero or more `DocumentSnapshot` objects + * representing the results of a query. The documents can be accessed as an + * array via the `docs` property or enumerated using the `forEach` method. The + * number of documents can be determined via the `empty` and `size` + * properties. + */ +export declare class QuerySnapshot { + /** + * The query on which you called {@link getDocs} in order to get this + * `QuerySnapshot`. + */ readonly query: Query; - readonly docs: Array>; - readonly size: number; - readonly empty: boolean; + private constructor(); + /** An array of all the documents in the `QuerySnapshot`. */ + get docs(): Array>; + /** The number of documents in the `QuerySnapshot`. */ + get size(): number; + /** True if there are no documents in the `QuerySnapshot`. */ + get empty(): boolean; + /** + * Enumerates all of the documents in the `QuerySnapshot`. + * + * @param callback A callback to be called with a `QueryDocumentSnapshot` for + * each document in the snapshot. + * @param thisArg The `this` binding for the callback. + */ forEach( callback: (result: QueryDocumentSnapshot) => void, - thisArg?: any + thisArg?: unknown ): void; } - -export class CollectionReference extends Query { - private constructor(); - readonly type: 'collection'; - readonly id: string; - readonly path: string; - - get parent(): DocumentReference | null; - - withConverter( - converter: FirestoreDataConverter - ): CollectionReference; -} - -export function getDoc( - reference: DocumentReference -): Promise>; -export function getDocs(query: Query): Promise>; - -export function addDoc( - reference: CollectionReference, - data: T -): Promise>; -export function setDoc( +/** + * Returns true if the provided references are equal. + * + * @param left A reference to compare. + * @param right A reference to compare. + * @return true if the references point to the same location in the same + * Firestore database. + */ +export declare function refEqual( + left: DocumentReference | CollectionReference, + right: DocumentReference | CollectionReference +): boolean; +/** + * Executes the given `updateFunction` and then attempts to commit the changes + * applied within the transaction. If any document read within the transaction + * has changed, Cloud Firestore retries the `updateFunction`. If it fails to + * commit after 5 attempts, the transaction fails. + * + * The maximum number of writes allowed in a single transaction is 500. + * + * @param firestore A reference to the Firestore database to run this + * transaction against. + * @param updateFunction The function to execute within the transaction context. + * @return If the transaction completed successfully or was explicitly aborted + * (the `updateFunction` returned a failed promise), the promise returned by the + * `updateFunction `is returned here. Otherwise, if the transaction failed, a + * rejected promise with the corresponding failure error is returned. + */ +export declare function runTransaction( + firestore: FirebaseFirestore, + updateFunction: (transaction: Transaction) => Promise +): Promise; +/** + * Returns a sentinel used with {@link setDoc()} or {@link updateDoc()} to + * include a server-generated timestamp in the written data. + */ +export declare function serverTimestamp(): FieldValue; +/** + * Writes to the document referred to by the specified `DocumentReference`. If + * the document does not yet exist, it will be created. + * + * The result of this write will only be reflected in document reads that occur + * after the returned Promise resolves. If the client is offline, the + * write fails. If you would like to see local modifications or buffer writes + * until the client is online, use the full Firestore SDK. + * + * @param reference A reference to the document to write. + * @param data A map of the fields and values for the document. + * @return A Promise resolved once the data has been successfully written + * to the backend. + */ +export declare function setDoc( reference: DocumentReference, data: T ): Promise; -export function setDoc( +/** + * Writes to the document referred to by the specified `DocumentReference`. If + * the document does not yet exist, it will be created. If you provide `merge` + * or `mergeFields`, the provided data can be merged into an existing document. + * + * The result of this write will only be reflected in document reads that occur + * after the returned Promise resolves. If the client is offline, the + * write fails. If you would like to see local modifications or buffer writes + * until the client is online, use the full Firestore SDK. + * + * @param reference A reference to the document to write. + * @param data A map of the fields and values for the document. + * @param options An object to configure the set behavior. + * @return A Promise resolved once the data has been successfully written + * to the backend. + */ +export declare function setDoc( reference: DocumentReference, data: Partial, options: SetOptions ): Promise; -export function updateDoc( +/** + * Sets the verbosity of Cloud Firestore logs (debug, error, or silent). + * + * @param logLevel + * The verbosity you set for activity and error logging. Can be any of + * the following values: + * + *
    + *
  • `debug` for the most verbose logging level, primarily for + * debugging.
  • + *
  • `error` to log errors only.
  • + *
  • `silent` to turn off logging.
  • + *
+ */ +export declare function setLogLevel(logLevel: LogLevelString): void; +/** + * An options object that configures the behavior of {@link setDoc()}, {@link + * WriteBatch#set()} and {@link Transaction#set()} calls. These calls can be + * configured to perform granular merges instead of overwriting the target + * documents in their entirety by providing a `SetOptions` with `merge: true`. + * + * @param merge Changes the behavior of a `setDoc()` call to only replace the + * values specified in its data argument. Fields omitted from the `setDoc()` + * call remain untouched. + * @param mergeFields Changes the behavior of `setDoc()` calls to only replace + * the specified field paths. Any field path that is not specified is ignored + * and remains untouched. + */ +export declare type SetOptions = + | { + readonly merge?: boolean; + } + | { + readonly mergeFields?: Array; + }; +export declare interface Settings { + host?: string; + ssl?: boolean; + ignoreUndefinedProperties?: boolean; +} +/** + * Returns true if the provided snapshots are equal. + * + * @param left A snapshot to compare. + * @param right A snapshot to compare. + * @return true if the snapshots are equal. + */ +export declare function snapshotEqual( + left: DocumentSnapshot | QuerySnapshot, + right: DocumentSnapshot | QuerySnapshot +): boolean; +/** + * Creates a `QueryConstraint` that modifies the result set to start after the + * provided document (exclusive). The starting position is relative to the order + * of the query. The document must contain all of the fields provided in the + * orderBy of the query. + * + * @param snapshot The snapshot of the document to start after. + * @return A `QueryConstraint` to pass to `query()` + */ +export declare function startAfter( + snapshot: DocumentSnapshot +): QueryConstraint; +/** + * Creates a `QueryConstraint` that modifies the result set to start after the + * provided fields relative to the order of the query. The order of the field + * values must match the order of the order by clauses of the query. + * + * @param fieldValues The field values to start this query after, in order + * of the query's order by. + * @return A `QueryConstraint` to pass to `query()` + */ +export declare function startAfter(...fieldValues: unknown[]): QueryConstraint; +export declare function startAfter( + snapshot: DocumentSnapshot +): QueryConstraint; +export declare function startAfter(...fieldValues: unknown[]): QueryConstraint; +/** + * Creates a `QueryConstraint` that modifies the result set to start at the + * provided document (inclusive). The starting position is relative to the order + * of the query. The document must contain all of the fields provided in the + * `orderBy` of this query. + * + * @param snapshot The snapshot of the document to start at. + * @return A `QueryConstraint` to pass to `query()`. + */ +export declare function startAt( + snapshot: DocumentSnapshot +): QueryConstraint; +/** + * Creates a `QueryConstraint` that modifies the result set to start at the + * provided fields relative to the order of the query. The order of the field + * values must match the order of the order by clauses of the query. + * + * @param fieldValues The field values to start this query at, in order + * of the query's order by. + * @return A `QueryConstraint` to pass to `query()`. + */ +export declare function startAt(...fieldValues: unknown[]): QueryConstraint; +/** + * Terminates the provided Firestore instance. + * + * After calling `terminate()` only the `clearIndexedDbPersistence()` functions + * may be used. Any other function will throw a `FirestoreError`. Termination + * does not cancel any pending writes, and any promises that are awaiting a + * response from the server will not be resolved. + * + * To restart after termination, create a new instance of FirebaseFirestore with + * {@link getFirestore()}. + * + * Note: Under normal circumstances, calling `terminate()` is not required. This + * function is useful only when you want to force this instance to release all of + * its resources or in combination with {@link clearIndexedDbPersistence()} to + * ensure that all local state is destroyed between test runs. + * + * @return A promise that is resolved when the instance has been successfully + * terminated. + */ +export declare function terminate(firestore: FirebaseFirestore): Promise; +/** + * @license + * Copyright 2017 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * A `Timestamp` represents a point in time independent of any time zone or + * calendar, represented as seconds and fractions of seconds at nanosecond + * resolution in UTC Epoch time. + * + * It is encoded using the Proleptic Gregorian Calendar which extends the + * Gregorian calendar backwards to year one. It is encoded assuming all minutes + * are 60 seconds long, i.e. leap seconds are "smeared" so that no leap second + * table is needed for interpretation. Range is from 0001-01-01T00:00:00Z to + * 9999-12-31T23:59:59.999999999Z. + * + * @see https://github.com/google/protobuf/blob/master/src/google/protobuf/timestamp.proto + */ +export declare class Timestamp { + readonly seconds: number; + readonly nanoseconds: number; + /** + * Creates a new timestamp with the current date, with millisecond precision. + * + * @return a new timestamp representing the current date. + */ + static now(): Timestamp; + /** + * Creates a new timestamp from the given date. + * + * @param date The date to initialize the `Timestamp` from. + * @return A new `Timestamp` representing the same point in time as the given + * date. + */ + static fromDate(date: Date): Timestamp; + /** + * Creates a new timestamp from the given number of milliseconds. + * + * @param milliseconds Number of milliseconds since Unix epoch + * 1970-01-01T00:00:00Z. + * @return A new `Timestamp` representing the same point in time as the given + * number of milliseconds. + */ + static fromMillis(milliseconds: number): Timestamp; + /** + * Creates a new timestamp. + * + * @param seconds The number of seconds of UTC time since Unix epoch + * 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to + * 9999-12-31T23:59:59Z inclusive. + * @param nanoseconds The non-negative fractions of a second at nanosecond + * resolution. Negative second values with fractions must still have + * non-negative nanoseconds values that count forward in time. Must be + * from 0 to 999,999,999 inclusive. + */ + constructor(seconds: number, nanoseconds: number); + /** + * Converts a `Timestamp` to a JavaScript `Date` object. This conversion causes + * a loss of precision since `Date` objects only support millisecond precision. + * + * @return JavaScript `Date` object representing the same point in time as + * this `Timestamp`, with millisecond precision. + */ + toDate(): Date; + /** + * Converts a `Timestamp` to a numeric timestamp (in milliseconds since + * epoch). This operation causes a loss of precision. + * + * @return The point in time corresponding to this timestamp, represented as + * the number of milliseconds since Unix epoch 1970-01-01T00:00:00Z. + */ + toMillis(): number; + /** + * Returns true if this `Timestamp` is equal to the provided one. + * + * @param other The `Timestamp` to compare against. + * @return true if this `Timestamp` is equal to the provided one. + */ + isEqual(other: Timestamp): boolean; + toString(): string; + toJSON(): { + seconds: number; + nanoseconds: number; + }; + /** + * Converts this object to a primitive string, which allows Timestamp objects to be compared + * using the `>`, `<=`, `>=` and `>` operators. + */ + valueOf(): string; +} +/** + * A reference to a transaction. + * + * The `Transaction` object passed to a transaction's `updateFunction` provides + * the methods to read and write data within the transaction context. See + * {@link runTransaction()}. + */ +export declare class Transaction { + private constructor(); + /** + * Reads the document referenced by the provided {@link DocumentReference}. + * + * @param documentRef A reference to the document to be read. + * @return A `DocumentSnapshot` with the read data. + */ + get(documentRef: DocumentReference): Promise>; + /** + * Writes to the document referred to by the provided {@link + * DocumentReference}. If the document does not exist yet, it will be created. + * + * @param documentRef A reference to the document to be set. + * @param data An object of the fields and values for the document.\ + * @return This `Transaction` instance. Used for chaining method calls. + */ + set(documentRef: DocumentReference, data: T): this; + /** + * Writes to the document referred to by the provided {@link + * DocumentReference}. If the document does not exist yet, it will be created. + * If you provide `merge` or `mergeFields`, the provided data can be merged + * into an existing document. + * + * @param documentRef A reference to the document to be set. + * @param data An object of the fields and values for the document. + * @param options An object to configure the set behavior. + * @return This `Transaction` instance. Used for chaining method calls. + */ + set( + documentRef: DocumentReference, + data: Partial, + options: SetOptions + ): this; + /** + * Updates fields in the document referred to by the provided {@link + * DocumentReference}. The update will fail if applied to a document that does + * not exist. + * + * @param documentRef A reference to the document to be updated. + * @param data An object containing the fields and values with which to + * update the document. Fields can contain dots to reference nested fields + * within the document. + * @return This `Transaction` instance. Used for chaining method calls. + */ + update(documentRef: DocumentReference, data: UpdateData): this; + /** + * Updates fields in the document referred to by the provided {@link + * DocumentReference}. The update will fail if applied to a document that does + * not exist. + * + * Nested fields can be updated by providing dot-separated field path + * strings or by providing `FieldPath` objects. + * + * @param documentRef A reference to the document to be updated. + * @param field The first field to update. + * @param value The first value. + * @param moreFieldsAndValues Additional key/value pairs. + * @return This `Transaction` instance. Used for chaining method calls. + */ + update( + documentRef: DocumentReference, + field: string | FieldPath, + value: unknown, + ...moreFieldsAndValues: unknown[] + ): this; + /** + * Deletes the document referred to by the provided {@link DocumentReference}. + * + * @param documentRef A reference to the document to be deleted. + * @return This `Transaction` instance. Used for chaining method calls. + */ + delete(documentRef: DocumentReference): this; +} +/** + * Update data (for use with {@link updateDoc()}) consists of field paths (e.g. + * 'foo' or 'foo.baz') mapped to values. Fields that contain dots reference + * nested fields within the document. + */ +export declare interface UpdateData { + [fieldPath: string]: any; +} +/** + * Updates fields in the document referred to by the specified + * `DocumentReference`. The update will fail if applied to a document that does + * not exist. + * + * The result of this update will only be reflected in document reads that occur + * after the returned Promise resolves. If the client is offline, the + * update fails. If you would like to see local modifications or buffer writes + * until the client is online, use the full Firestore SDK. + * + * @param reference A reference to the document to update. + * @param data An object containing the fields and values with which to + * update the document. Fields can contain dots to reference nested fields + * within the document. + * @return A Promise resolved once the data has been successfully written + * to the backend. + */ +export declare function updateDoc( reference: DocumentReference, data: UpdateData ): Promise; -export function updateDoc( +/** + * Updates fields in the document referred to by the specified + * `DocumentReference` The update will fail if applied to a document that does + * not exist. + * + * Nested fields can be updated by providing dot-separated field path + * strings or by providing `FieldPath` objects. + * + * The result of this update will only be reflected in document reads that occur + * after the returned Promise resolves. If the client is offline, the + * update fails. If you would like to see local modifications or buffer writes + * until the client is online, use the full Firestore SDK. + * + * @param reference A reference to the document to update. + * @param field The first field to update. + * @param value The first value. + * @param moreFieldsAndValues Additional key value pairs. + * @return A Promise resolved once the data has been successfully written + * to the backend. + */ +export declare function updateDoc( reference: DocumentReference, field: string | FieldPath, - value: any, - ...moreFieldsAndValues: any[] + value: unknown, + ...moreFieldsAndValues: unknown[] ): Promise; -export function deleteDoc(reference: DocumentReference): Promise; - -export class FieldValue { +/** + * Creates a `QueryConstraint` that enforces that documents must contain the + * specified field and that the value should satisfy the relation constraint + * provided. + * + * @param fieldPath The path to compare + * @param opStr The operation string (e.g "<", "<=", "==", ">", ">=", "!="). + * @param value The value for comparison + * @return The created `Query`. + */ +export declare function where( + fieldPath: string | FieldPath, + opStr: WhereFilterOp, + value: unknown +): QueryConstraint; +/** + * Filter conditions in a {@link where()} clause are specified using the + * strings '<', '<=', '==', '!=', '>=', '>', 'array-contains', 'in', + * 'array-contains-any', and 'not-in'. + */ +export declare type WhereFilterOp = + | '<' + | '<=' + | '==' + | '!=' + | '>=' + | '>' + | 'array-contains' + | 'in' + | 'array-contains-any' + | 'not-in'; +/** + * A write batch, used to perform multiple writes as a single atomic unit. + * + * A `WriteBatch` object can be acquired by calling {@link writeBatch()}. It + * provides methods for adding writes to the write batch. None of the writes + * will be committed (or visible locally) until {@link WriteBatch#commit()} is + * called. + */ +export declare class WriteBatch { private constructor(); - isEqual(other: FieldValue): boolean; -} - -export function serverTimestamp(): FieldValue; -export function deleteField(): FieldValue; -export function arrayUnion(...elements: any[]): FieldValue; -export function arrayRemove(...elements: any[]): FieldValue; -export function increment(n: number): FieldValue; - -export class FieldPath { - constructor(...fieldNames: string[]); - isEqual(other: FieldPath): boolean; -} - -export function documentId(): FieldPath; - -export function refEqual( - left: DocumentReference | CollectionReference, - right: DocumentReference | CollectionReference -): boolean; -export function queryEqual(left: Query, right: Query): boolean; -export function snapshotEqual( - left: DocumentSnapshot | QuerySnapshot, - right: DocumentSnapshot | QuerySnapshot -): boolean; - -export type FirestoreErrorCode = - | 'cancelled' - | 'unknown' - | 'invalid-argument' - | 'deadline-exceeded' - | 'not-found' - | 'already-exists' - | 'permission-denied' - | 'resource-exhausted' - | 'failed-precondition' - | 'aborted' - | 'out-of-range' - | 'unimplemented' - | 'internal' - | 'unavailable' - | 'data-loss' - | 'unauthenticated'; - -export interface FirestoreError { - code: FirestoreErrorCode; - message: string; - name: string; - stack?: string; -} - -declare module '@firebase/component' { - interface NameServiceMapping { - 'firestore/lite': FirebaseFirestore; - } + /** + * Writes to the document referred to by the provided {@link + * DocumentReference}. If the document does not exist yet, it will be created. + * + * @param documentRef A reference to the document to be set. + * @param data An object of the fields and values for the document. + * @return This `WriteBatch` instance. Used for chaining method calls. + */ + set(documentRef: DocumentReference, data: T): WriteBatch; + /** + * Writes to the document referred to by the provided {@link + * DocumentReference}. If the document does not exist yet, it will be created. + * If you provide `merge` or `mergeFields`, the provided data can be merged + * into an existing document. + * + * @param documentRef A reference to the document to be set. + * @param data An object of the fields and values for the document. + * @param options An object to configure the set behavior. + * @return This `WriteBatch` instance. Used for chaining method calls. + */ + set( + documentRef: DocumentReference, + data: Partial, + options: SetOptions + ): WriteBatch; + /** + * Updates fields in the document referred to by the provided {@link + * DocumentReference}. The update will fail if applied to a document that does + * not exist. + * + * @param documentRef A reference to the document to be updated. + * @param data An object containing the fields and values with which to + * update the document. Fields can contain dots to reference nested fields + * within the document. + * @return This `WriteBatch` instance. Used for chaining method calls. + */ + update(documentRef: DocumentReference, data: UpdateData): WriteBatch; + /** + * Updates fields in the document referred to by this {@link + * DocumentReference}. The update will fail if applied to a document that does + * not exist. + * + * Nested fields can be update by providing dot-separated field path strings + * or by providing `FieldPath` objects. + * + * @param documentRef A reference to the document to be updated. + * @param field The first field to update. + * @param value The first value. + * @param moreFieldsAndValues Additional key value pairs. + * @return This `WriteBatch` instance. Used for chaining method calls. + */ + update( + documentRef: DocumentReference, + field: string | FieldPath, + value: unknown, + ...moreFieldsAndValues: unknown[] + ): WriteBatch; + /** + * Deletes the document referred to by the provided {@link DocumentReference}. + * + * @param documentRef A reference to the document to be deleted. + * @return This `WriteBatch` instance. Used for chaining method calls. + */ + delete(documentRef: DocumentReference): WriteBatch; + /** + * Commits all of the writes in this write batch as a single atomic unit. + * + * The result of these writes will only be reflected in document reads that + * occur after the returned Promise resolves. If the client is offline, the + * write fails. If you would like to see local modifications or buffer writes + * until the client is online, use the full Firestore SDK. + * + * @return A Promise resolved once all of the writes in the batch have been + * successfully written to the backend as an atomic unit (note that it won't + * resolve while you're offline). + */ + commit(): Promise; } +/** + * Creates a write batch, used for performing multiple writes as a single + * atomic operation. The maximum number of writes allowed in a single WriteBatch + * is 500. + * + * The result of these writes will only be reflected in document reads that + * occur after the returned Promise resolves. If the client is offline, the + * write fails. If you would like to see local modifications or buffer writes + * until the client is online, use the full Firestore SDK. + * + * @return A `WriteBatch` that can be used to atomically execute multiple + * writes. + */ +export declare function writeBatch(firestore: FirebaseFirestore): WriteBatch; +export {}; diff --git a/packages/firestore/lite/api-extractor.json b/packages/firestore/lite/api-extractor.json new file mode 100644 index 00000000000..cbf2b23abc4 --- /dev/null +++ b/packages/firestore/lite/api-extractor.json @@ -0,0 +1,8 @@ +{ + "extends": "../../../config/api-extractor.json", + "mainEntryPointFilePath": "../dist/lite/firestore/lite/index.d.ts", + "dtsRollup": { + "enabled": true, + "publicTrimmedFilePath": "../dist/lite/private.d.ts" + } +} diff --git a/packages/firestore/lite/dependencies.json b/packages/firestore/lite/dependencies.json index a7511b2eb37..430bb72e771 100644 --- a/packages/firestore/lite/dependencies.json +++ b/packages/firestore/lite/dependencies.json @@ -3136,4 +3136,4 @@ }, "sizeInBytes": 56682 } -} \ No newline at end of file +} diff --git a/packages/firestore/lite/package.json b/packages/firestore/lite/package.json index ad92dc85bcf..052743182da 100644 --- a/packages/firestore/lite/package.json +++ b/packages/firestore/lite/package.json @@ -1,5 +1,5 @@ { - "name": "@firebase/firestore/lite", + "name": "@firebase/firestore-lite", "description": "A lite version of the Firestore SDK", "main": "../dist/lite/index.node.umd.js", "main-esm": "../dist/lite/index.node.esm2017.js", diff --git a/packages/firestore/lite/src/api/bytes.ts b/packages/firestore/lite/src/api/bytes.ts index 0c8dfe9b206..ffd8289bcbf 100644 --- a/packages/firestore/lite/src/api/bytes.ts +++ b/packages/firestore/lite/src/api/bytes.ts @@ -24,6 +24,7 @@ import { ByteString } from '../../../src/util/byte_string'; export class Bytes { _byteString: ByteString; + /** @hideconstructor */ constructor(byteString: ByteString) { this._byteString = byteString; } diff --git a/packages/firestore/lite/src/api/database.ts b/packages/firestore/lite/src/api/database.ts index eac53329fee..2fe82976373 100644 --- a/packages/firestore/lite/src/api/database.ts +++ b/packages/firestore/lite/src/api/database.ts @@ -165,6 +165,7 @@ export class FirebaseFirestore implements _FirebaseService { private _app?: FirebaseApp; + /** @hideconstructor */ constructor( databaseIdOrApp: DatabaseId | FirebaseApp, authProvider: Provider diff --git a/packages/firestore/lite/src/api/reference.ts b/packages/firestore/lite/src/api/reference.ts index 492ec8f29cc..1d21ddd03d8 100644 --- a/packages/firestore/lite/src/api/reference.ts +++ b/packages/firestore/lite/src/api/reference.ts @@ -147,6 +147,7 @@ export class DocumentReference { */ readonly firestore: FirebaseFirestore; + /** @hideconstructor */ constructor( firestore: FirebaseFirestore, readonly _converter: FirestoreDataConverter | null, @@ -215,6 +216,8 @@ export class Query { readonly firestore: FirebaseFirestore; // This is the lite version of the Query class in the main SDK. + + /** @hideconstructor protected */ constructor( firestore: FirebaseFirestore, readonly _converter: FirestoreDataConverter | null, @@ -393,8 +396,8 @@ export function orderBy( directionStr: OrderByDirection = 'asc' ): QueryConstraint { const direction = directionStr as Direction; - const path = fieldPathFromArgument('orderBy', fieldPath); - return new QueryOrderByConstraint(path, direction); + const field = fieldPathFromArgument('orderBy', fieldPath); + return new QueryOrderByConstraint(field, direction); } class QueryLimitConstraint extends QueryConstraint { @@ -512,6 +515,10 @@ export function startAfter( * @return A `QueryConstraint` to pass to `query()` */ export function startAfter(...fieldValues: unknown[]): QueryConstraint; +export function startAfter( + snapshot: DocumentSnapshot +): QueryConstraint; +export function startAfter(...fieldValues: unknown[]): QueryConstraint; export function startAfter( ...docOrFields: Array> ): QueryConstraint { @@ -1034,6 +1041,7 @@ export function validateHasExplicitOrderByForLimitToLast( export class CollectionReference extends Query { readonly type = 'collection'; + /** @hideconstructor */ constructor( readonly firestore: FirebaseFirestore, converter: FirestoreDataConverter | null, diff --git a/packages/firestore/lite/src/api/snapshot.ts b/packages/firestore/lite/src/api/snapshot.ts index 33eefea49b4..d7a5e403670 100644 --- a/packages/firestore/lite/src/api/snapshot.ts +++ b/packages/firestore/lite/src/api/snapshot.ts @@ -116,6 +116,7 @@ export class DocumentSnapshot { // - No support for SnapshotMetadata. // - No support for SnapshotOptions. + /** @hideconstructor protected */ constructor( public _firestore: FirebaseFirestore, public _userDataWriter: AbstractUserDataWriter, @@ -238,6 +239,7 @@ export class QuerySnapshot { */ readonly query: Query; + /** @hideconstructor */ constructor( _query: Query, readonly _docs: Array> diff --git a/packages/firestore/lite/src/api/transaction.ts b/packages/firestore/lite/src/api/transaction.ts index 1350986b3c9..21d79c76865 100644 --- a/packages/firestore/lite/src/api/transaction.ts +++ b/packages/firestore/lite/src/api/transaction.ts @@ -64,6 +64,7 @@ export class Transaction { private readonly _dataReader: UserDataReader; + /** @hideconstructor */ constructor( protected readonly _firestore: FirebaseFirestore, private readonly _transaction: InternalTransaction @@ -138,13 +139,13 @@ export class Transaction { ): this; set( documentRef: DocumentReference, - value: T, + data: T, options?: SetOptions ): this { const ref = validateReference(documentRef, this._firestore); const convertedValue = applyFirestoreDataConverter( ref._converter, - value, + data, options ); const parsed = parseSetData( @@ -194,7 +195,7 @@ export class Transaction { update( documentRef: DocumentReference, fieldOrUpdateData: string | FieldPath | UpdateData, - value?: unknown, + data?: unknown, ...moreFieldsAndValues: unknown[] ): this { const ref = validateReference(documentRef, this._firestore); @@ -215,7 +216,7 @@ export class Transaction { 'Transaction.update', ref._key, fieldOrUpdateData, - value, + data, moreFieldsAndValues ); } else { diff --git a/packages/firestore/lite/src/api/write_batch.ts b/packages/firestore/lite/src/api/write_batch.ts index 4e094b4dbcc..b492258cf20 100644 --- a/packages/firestore/lite/src/api/write_batch.ts +++ b/packages/firestore/lite/src/api/write_batch.ts @@ -56,6 +56,7 @@ export class WriteBatch { private _mutations = [] as Mutation[]; private _committed = false; + /** @hideconstructor */ constructor( private readonly _firestore: FirebaseFirestore, private readonly _commitHandler: (m: Mutation[]) => Promise @@ -93,7 +94,7 @@ export class WriteBatch { data: T, options?: SetOptions ): WriteBatch { - this.verifyNotCommitted(); + this._verifyNotCommitted(); const ref = validateReference(documentRef, this._firestore); const convertedValue = applyFirestoreDataConverter( @@ -150,10 +151,10 @@ export class WriteBatch { update( documentRef: DocumentReference, fieldOrUpdateData: string | FieldPath | UpdateData, - value?: unknown, + data?: unknown, ...moreFieldsAndValues: unknown[] ): WriteBatch { - this.verifyNotCommitted(); + this._verifyNotCommitted(); const ref = validateReference(documentRef, this._firestore); // For Compat types, we have to "extract" the underlying types before @@ -172,7 +173,7 @@ export class WriteBatch { 'WriteBatch.update', ref._key, fieldOrUpdateData, - value, + data, moreFieldsAndValues ); } else { @@ -197,7 +198,7 @@ export class WriteBatch { * @return This `WriteBatch` instance. Used for chaining method calls. */ delete(documentRef: DocumentReference): WriteBatch { - this.verifyNotCommitted(); + this._verifyNotCommitted(); const ref = validateReference(documentRef, this._firestore); this._mutations = this._mutations.concat( new DeleteMutation(ref._key, Precondition.none()) @@ -218,7 +219,7 @@ export class WriteBatch { * resolve while you're offline). */ commit(): Promise { - this.verifyNotCommitted(); + this._verifyNotCommitted(); this._committed = true; if (this._mutations.length > 0) { return this._commitHandler(this._mutations); @@ -227,7 +228,7 @@ export class WriteBatch { return Promise.resolve(); } - private verifyNotCommitted(): void { + private _verifyNotCommitted(): void { if (this._committed) { throw new FirestoreError( Code.FAILED_PRECONDITION, diff --git a/packages/firestore/package.json b/packages/firestore/package.json index 3e2bbb6c78d..356c6540940 100644 --- a/packages/firestore/package.json +++ b/packages/firestore/package.json @@ -7,14 +7,16 @@ "description": "The Cloud Firestore component of the Firebase JS SDK.", "author": "Firebase (https://firebase.google.com/)", "scripts": { + "api-report:exp": "(cd exp; api-extractor run --local --verbose) && TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node scripts/prune-dts.ts --input dist/exp/private.d.ts --output exp-types/index.d.ts", + "api-report:lite": "(cd lite; api-extractor run --local --verbose) && TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' ts-node scripts/prune-dts.ts --input dist/lite/private.d.ts --output lite-types/index.d.ts", "bundle": "rollup -c", "build": "run-p 'bundle rollup.config.browser.js' 'bundle rollup.config.browser.memory.js' 'bundle rollup.config.node.js' 'bundle rollup.config.node.memory.js' 'bundle rollup.config.rn.js' 'bundle rollup.config.rn.memory.js' build:lite build:exp", "build:scripts": "tsc -moduleResolution node --module commonjs scripts/*.ts && ls scripts/*.js | xargs -I % sh -c 'terser % -o %'", "build:release": "run-p 'bundle rollup.config.browser.js' 'bundle rollup.config.browser.memory.js' 'bundle rollup.config.node.js' 'bundle rollup.config.node.memory.js' 'bundle rollup.config.rn.js' 'bundle rollup.config.rn.memory.js'", "build:deps": "lerna run --scope @firebase/firestore --include-dependencies build", "build:console": "node tools/console.build.js", - "build:exp": "rollup -c rollup.config.exp.js", - "build:lite": "rollup -c rollup.config.lite.js", + "build:exp": "rollup -c rollup.config.exp.js && yarn api-report:exp", + "build:lite": "rollup -c rollup.config.lite.js && yarn api-report:lite", "build:exp:release": "yarn build:exp && yarn build:lite", "predev": "yarn prebuild", "dev": "rollup -c -w", diff --git a/packages/firestore/rollup.config.exp.js b/packages/firestore/rollup.config.exp.js index 0765ec38680..df71e6e8dac 100644 --- a/packages/firestore/rollup.config.exp.js +++ b/packages/firestore/rollup.config.exp.js @@ -22,7 +22,7 @@ import typescriptPlugin from 'rollup-plugin-typescript2'; import typescript from 'typescript'; import path from 'path'; import replace from 'rollup-plugin-replace'; -import copy from 'rollup-plugin-copy-assets'; +import copy from 'rollup-plugin-copy'; import { terser } from 'rollup-plugin-terser'; import { importPathTransformer } from '../../scripts/exp/ts-transform-import-path'; @@ -43,9 +43,13 @@ const nodePlugins = [ transformers: [util.removeAssertTransformer, importPathTransformer] }), json({ preferConst: true }), - // Needed as we also use the *.proto files copy({ - assets: ['./src/protos'] + targets: [ + { + src: 'src/protos', + dest: 'dist/exp/src' + } + ] }), replace({ 'process.env.FIRESTORE_PROTO_ROOT': JSON.stringify('../src/protos') diff --git a/packages/firestore/rollup.config.lite.js b/packages/firestore/rollup.config.lite.js index 4ad76e409c8..57a8712437d 100644 --- a/packages/firestore/rollup.config.lite.js +++ b/packages/firestore/rollup.config.lite.js @@ -22,6 +22,8 @@ import alias from '@rollup/plugin-alias'; import typescriptPlugin from 'rollup-plugin-typescript2'; import typescript from 'typescript'; import sourcemaps from 'rollup-plugin-sourcemaps'; +import copy from 'rollup-plugin-copy'; +import replace from 'rollup-plugin-replace'; import { terser } from 'rollup-plugin-terser'; import { importPathTransformer } from '../../scripts/exp/ts-transform-import-path'; @@ -41,7 +43,18 @@ const nodePlugins = [ abortOnError: false, transformers: [util.removeAssertTransformer, importPathTransformer] }), - json({ preferConst: true }) + json({ preferConst: true }), + copy({ + targets: [ + { + src: 'src/protos', + dest: 'dist/lite/src' + } + ] + }), + replace({ + 'process.env.FIRESTORE_PROTO_ROOT': JSON.stringify('src/protos') + }) ]; const browserPlugins = [ diff --git a/packages/firestore/scripts/build-bundle.ts b/packages/firestore/scripts/build-bundle.ts index c3071edcb9e..a87bf83bbb6 100644 --- a/packages/firestore/scripts/build-bundle.ts +++ b/packages/firestore/scripts/build-bundle.ts @@ -28,7 +28,7 @@ const argv = yargs.options({ input: { type: 'string', demandOption: true, - desc: 'The location of the index.ts file' + desc: 'The location of the index.d.ts file' }, output: { type: 'string', diff --git a/packages/firestore/scripts/prune-dts.ts b/packages/firestore/scripts/prune-dts.ts new file mode 100644 index 00000000000..8c2683e8919 --- /dev/null +++ b/packages/firestore/scripts/prune-dts.ts @@ -0,0 +1,381 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as yargs from 'yargs'; +import * as ts from 'typescript'; +import * as fs from 'fs'; + +/** + * Prunes a DTS file based on three main rules: + * - Top level types are only included if they are also exported. + * - Underscore-prefixed members of class and interface types are stripped. + * - Constructors are made private or protected if marked with + * `@hideconstructor`/`@hideconstructor protected`. + * + * This function is meant to operate on DTS files generated by API extractor + * and extracts out the API that is relevant for third-party SDK consumers. + * + * @param inputLocation The file path to the .d.ts produced by API explorer. + * @param outputLocation The output location for the pruned .d.ts file. + */ +export function pruneDts(inputLocation: string, outputLocation: string): void { + const compilerOptions = {}; + const host = ts.createCompilerHost(compilerOptions); + const program = ts.createProgram([inputLocation], compilerOptions, host); + const printer: ts.Printer = ts.createPrinter(); + const sourceFile = program.getSourceFile(inputLocation)!; + const result: ts.TransformationResult = ts.transform< + ts.SourceFile + >(sourceFile, [dropPrivateApiTransformer.bind(null, program, host)]); + const transformedSourceFile: ts.SourceFile = result.transformed[0]; + const content = printer.printFile(transformedSourceFile); + fs.writeFileSync(outputLocation, content); +} + +/** Determines whether the provided identifier should be hidden. */ +function hasPrivatePrefix(name: ts.Identifier): boolean { + // Identifiers that are prefixed with an underscore are not not included in + // the public API. + return name.escapedText.toString().startsWith('_'); +} + +/** Returns whether the modifier array includes `exported`. */ +function isExported(modifiers?: ts.ModifiersArray): boolean { + return !!modifiers?.find(m => m.kind === ts.SyntaxKind.ExportKeyword); +} + +/** + * Replaces an existing constructor implementation if the constructor is marked + * with the JSDod tag `@hideconstructor`. The replaced constructor can either + * have `private` visibility` or `proctected`. To generate a protected + * constructor, specify `@hideconstructor proctected`. + * + * Returns either the modified constructor or the existing constructor if no + * modification was needed. + */ +function maybeHideConstructor( + node: ts.ConstructorDeclaration +): ts.ConstructorDeclaration { + const hideConstructorTag = ts + .getJSDocTags(node) + ?.find(t => t.tagName.escapedText === 'hideconstructor'); + + if (hideConstructorTag) { + const modifier = ts.createModifier( + hideConstructorTag.comment === 'protected' + ? ts.SyntaxKind.ProtectedKeyword + : ts.SyntaxKind.PrivateKeyword + ); + return ts.createConstructor( + node.decorators, + [modifier], + /*parameters=*/ [], + /* body= */ undefined + ); + } else { + return node; + } +} + +/** + * Examines `extends` and `implements` clauses and removes or replaces them if + * they refer to a non-exported type. When an export is removed, all members + * from the removed class are merged into the provided class or interface + * declaration. + * + * @example + * Input: + * class Foo { + * foo: string; + * } + * export class Bar extends Foo {} + * + * Output: + * export class Bar { + * foo: string; + * } + */ +function prunePrivateImports< + T extends ts.InterfaceDeclaration | ts.ClassDeclaration +>( + program: ts.Program, + host: ts.CompilerHost, + sourceFile: ts.SourceFile, + node: T +): T { + const typeChecker = program.getTypeChecker(); + const currentType = typeChecker.getTypeAtLocation(node); + const currentName = currentType?.symbol?.name; + + // The list of heritage clauses after all private symbols are removed. + const prunedHeritageClauses: ts.HeritageClause[] = []; + // Additional members that are copied from the private symbols into the public + // symbols + const additionalMembers: ts.NamedDeclaration[] = []; + + for (const heritageClause of node.heritageClauses || []) { + const exportedTypes: ts.ExpressionWithTypeArguments[] = []; + for (const type of heritageClause.types) { + if (isExported(type.modifiers)) { + exportedTypes.push(type); + } else { + const exportedSymbol = extractExportedSymbol( + typeChecker, + sourceFile, + type.expression + ); + + if (exportedSymbol && exportedSymbol.name !== currentName) { + // If there is a public type that we can refer to, update the import + // statement to refer to the public type. + exportedTypes.push( + ts.updateExpressionWithTypeArguments( + type, + type.typeArguments, + ts.createIdentifier(exportedSymbol.name) + ) + ); + } + + // Hide the type we are inheriting from and merge its declarations + // into the current class. + const privateType = typeChecker.getTypeAtLocation(type); + additionalMembers.push( + ...convertPropertiesForEnclosingClass( + program, + host, + sourceFile, + privateType.getProperties(), + node + ) + ); + } + } + + if (exportedTypes.length > 0) { + prunedHeritageClauses.push( + ts.updateHeritageClause(heritageClause, exportedTypes) + ); + } + } + + if (ts.isClassDeclaration(node)) { + return ts.updateClassDeclaration( + node, + node.decorators, + node.modifiers, + node.name, + node.typeParameters, + prunedHeritageClauses, + [...node.members, ...(additionalMembers as ts.ClassElement[])] + ) as T; + } else if (ts.isInterfaceDeclaration(node)) { + return ts.updateInterfaceDeclaration( + node, + node.decorators, + node.modifiers, + node.name, + node.typeParameters, + prunedHeritageClauses, + [...node.members, ...(additionalMembers as ts.TypeElement[])] + ) as T; + } else { + throw new Error('Only classes or interfaces are supported'); + } +} + +/** + * Iterates the provided symbols and returns named declarations for these + * symbols if they are missing from `currentClass`. This allows us to merge + * class hierarchies for classes whose inherited types are not part of the + * public API. + * + * This method relies on a private API in TypeScript's `codefix` package. + */ +function convertPropertiesForEnclosingClass( + program: ts.Program, + host: ts.CompilerHost, + sourceFile: ts.SourceFile, + parentClassSymbols: ts.Symbol[], + currentClass: ts.ClassDeclaration | ts.InterfaceDeclaration +): ts.NamedDeclaration[] { + const newMembers: ts.NamedDeclaration[] = []; + // The `codefix` package is not public but it does exactly what we want. We + // can explore adding a slimmed down version of this package to our repository + // if this dependency should ever break. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (ts as any).codefix.createMissingMemberNodes( + currentClass, + parentClassSymbols, + sourceFile, + { program, host }, + /* userPreferences= */ {}, + /* importAdder= */ undefined, + (c: ts.ClassElement) => newMembers.push(c) + ); + return []; +} +/** + * Replaces input types of public APIs that consume non-exported types, which + * allows us to exclude private types from the pruned definitions. Returns the + * the name of the exported API or undefined if no type is found. + * + * @example + * Input: + * class PrivateFoo {} + * export class PublicFoo extends PrivateFoo {} + * export function doFoo(foo: PrivateFoo); + * + * Output: + * export class PublicFoo {} + * export function doFoo(foo: PublicFoo); + */ +function extractExportedSymbol( + typeChecker: ts.TypeChecker, + sourceFile: ts.SourceFile, + typeName: ts.Node +): ts.Symbol | undefined { + if (!ts.isIdentifier(typeName)) { + return undefined; + } + + const localSymbolName = typeName.escapedText; + const allExportedSymbols = typeChecker.getExportsOfModule( + typeChecker.getSymbolAtLocation(sourceFile)! + ); + const exportedSymbolsForLocalType: ts.Symbol[] = []; + + // Examine all exported types and check if they extend or implement the + // provided local type. If so, we can use the exported type in lieu of the + // private type. + for (const symbol of allExportedSymbols) { + // Short circuit if the local types is already part of the public types. + if (symbol.name === localSymbolName) { + return symbol; + } + + for (const declaration of symbol.declarations) { + if ( + ts.isClassDeclaration(declaration) || + ts.isInterfaceDeclaration(declaration) + ) { + for (const heritageClause of declaration.heritageClauses || []) { + for (const type of heritageClause.types || []) { + if (ts.isIdentifier(type.expression)) { + const subclassName = type.expression.escapedText; + if (subclassName === localSymbolName) { + exportedSymbolsForLocalType.push(symbol); + } + } + } + } + } + } + } + + return exportedSymbolsForLocalType[0]; +} + +function dropPrivateApiTransformer( + program: ts.Program, + host: ts.CompilerHost, + context: ts.TransformationContext +): ts.Transformer { + const typeChecker = program.getTypeChecker(); + + return (sourceFile: ts.SourceFile) => { + function visit(node: ts.Node): ts.Node { + if ( + ts.isInterfaceDeclaration(node) || + ts.isClassDeclaration(node) || + ts.isFunctionDeclaration(node) || + ts.isVariableStatement(node) || + ts.isTypeAliasDeclaration(node) || + ts.isModuleDeclaration(node) || + ts.isEnumDeclaration(node) + ) { + // Remove any types that are not exported. + if (!isExported(node.modifiers)) { + return ts.createToken(ts.SyntaxKind.WhitespaceTrivia); + } + } + + if (ts.isConstructorDeclaration(node)) { + // Replace internal constructors with private constructors. + return maybeHideConstructor(node); + } else if ( + ts.isClassDeclaration(node) || + ts.isInterfaceDeclaration(node) + ) { + // Remove any imports that reference internal APIs, while retaining + // their public members. + return prunePrivateImports(program, host, sourceFile, node); + } else if ( + ts.isPropertyDeclaration(node) || + ts.isMethodDeclaration(node) || + ts.isGetAccessor(node) + ) { + // Remove any class and interface members that are prefixed with + // underscores. + if (hasPrivatePrefix(node.name as ts.Identifier)) { + return ts.createToken(ts.SyntaxKind.WhitespaceTrivia); + } + } else if (ts.isTypeReferenceNode(node)) { + // For public types that refer internal types, find a public type that + // we can refer to instead. + const publicName = extractExportedSymbol( + typeChecker, + sourceFile, + node.typeName + ); + return publicName + ? ts.updateTypeReferenceNode( + node, + ts.createIdentifier(publicName.name), + node.typeArguments + ) + : node; + } + + return node; + } + + function visitNodeAndChildren(node: T): T { + return ts.visitEachChild( + visit(node), + childNode => visitNodeAndChildren(childNode), + context + ) as T; + } + return visitNodeAndChildren(sourceFile); + }; +} + +const argv = yargs.options({ + input: { + type: 'string', + desc: 'The location of the index.ts file' + }, + output: { + type: 'string', + desc: 'The location for the index.d.ts file' + } +}).argv; + +if (argv.input && argv.output) { + pruneDts(argv.input, argv.output); +} diff --git a/packages/firestore/src/api/database.ts b/packages/firestore/src/api/database.ts index af1d08008c5..53da3483c65 100644 --- a/packages/firestore/src/api/database.ts +++ b/packages/firestore/src/api/database.ts @@ -880,6 +880,7 @@ export class SnapshotMetadata implements PublicSnapshotMetadata { */ readonly fromCache: boolean; + /** @hideconstructor */ constructor(hasPendingWrites: boolean, fromCache: boolean) { this.hasPendingWrites = hasPendingWrites; this.fromCache = fromCache; diff --git a/packages/firestore/src/protos/firestore_proto_api.d.ts b/packages/firestore/src/protos/firestore_proto_api.ts similarity index 99% rename from packages/firestore/src/protos/firestore_proto_api.d.ts rename to packages/firestore/src/protos/firestore_proto_api.ts index 6a62a636024..1d4055c7614 100644 --- a/packages/firestore/src/protos/firestore_proto_api.d.ts +++ b/packages/firestore/src/protos/firestore_proto_api.ts @@ -696,7 +696,6 @@ export interface ProjectsDatabasesDocumentsWriteNamedParameters { $Xgafv?: ProjectsDatabasesDocumentsApiClient$Xgafv; } export abstract class ProjectsDatabasesDocumentsApiClient { - private constructor(); abstract batchGet( database: string, $requestBody: BatchGetDocumentsRequest, @@ -1121,7 +1120,6 @@ export interface ProjectsDatabasesIndexesListNamedParameters { pageToken?: string; } export abstract class ProjectsDatabasesIndexesApiClient { - private constructor(); abstract create( parent: string, $requestBody: Index, diff --git a/packages/firestore/src/util/error.ts b/packages/firestore/src/util/error.ts index c89f44282b4..f629cfd69b7 100644 --- a/packages/firestore/src/util/error.ts +++ b/packages/firestore/src/util/error.ts @@ -209,9 +209,10 @@ export const Code = { /** An error returned by a Firestore operation. */ export class FirestoreError extends Error { - name = 'FirebaseError'; - stack?: string; + readonly name: string = 'FirebaseError'; + readonly stack?: string; + /** @hideconstructor */ constructor(readonly code: FirestoreErrorCode, readonly message: string) { super(message); diff --git a/packages/firestore/src/util/log.ts b/packages/firestore/src/util/log.ts index 36520fc70a9..a932a1b22c3 100644 --- a/packages/firestore/src/util/log.ts +++ b/packages/firestore/src/util/log.ts @@ -42,7 +42,7 @@ export function getLogLevel(): LogLevel { *
  • `silent` to turn off logging.
  • * */ -export function setLogLevel(logLevel: LogLevelString | LogLevel): void { +export function setLogLevel(logLevel: LogLevelString): void { logClient.setLogLevel(logLevel); } diff --git a/packages/firestore/test/unit/scripts/node/prune_dts.test.ts b/packages/firestore/test/unit/scripts/node/prune_dts.test.ts new file mode 100644 index 00000000000..c2a9a75ca54 --- /dev/null +++ b/packages/firestore/test/unit/scripts/node/prune_dts.test.ts @@ -0,0 +1,56 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as os from 'os'; +import { expect } from 'chai'; +import * as fs from 'fs'; +import * as path from 'path'; +import { pruneDts } from '../../../../scripts/prune-dts'; + +function runScript(source: string): string { + const tmpDir = os.tmpdir(); + const inputFile = path.resolve(tmpDir, 'input.d.ts'); + const outputFile = path.resolve(tmpDir, 'output.d.ts'); + fs.writeFileSync(inputFile, source, 'utf-8'); + pruneDts(inputFile, outputFile); + return fs.readFileSync(outputFile, 'utf-8'); +} + +describe.only('Prune DTS', () => { + it('handles different generic types', async () => { + const input = ` +class A { + aData: T; +} + +export declare class B extends A { + bData: K; +} + +export {}`; + + const expectedOutput = ` +export declare class B { + aData: K; + bData: K; +} + `; + + const actualOutput = runScript(input); + expect(actualOutput).to.equal(expectedOutput); + }); +}); diff --git a/packages/firestore/test/unit/util/async_queue.test.ts b/packages/firestore/test/unit/util/async_queue.test.ts index 64725146e3f..1882d4877cd 100644 --- a/packages/firestore/test/unit/util/async_queue.test.ts +++ b/packages/firestore/test/unit/util/async_queue.test.ts @@ -20,7 +20,12 @@ import * as chaiAsPromised from 'chai-as-promised'; import { expect, use } from 'chai'; import { AsyncQueue, TimerId } from '../../../src/util/async_queue'; import { Code } from '../../../src/util/error'; -import { getLogLevel, LogLevel, setLogLevel } from '../../../src/util/log'; +import { + getLogLevel, + LogLevel, + LogLevelString, + setLogLevel +} from '../../../src/util/log'; import { Deferred, Rejecter, Resolver } from '../../../src/util/promise'; import { fail } from '../../../src/util/assert'; import { IndexedDbTransactionError } from '../../../src/local/simple_db'; @@ -83,7 +88,7 @@ describe('AsyncQueue', () => { // Disable logging for this test to avoid the assertion being logged const oldLogLevel = getLogLevel(); - setLogLevel(LogLevel.SILENT); + setLogLevel('silent'); // Schedule a failing operation and make sure it's handled correctly. const op1Promise = queue @@ -134,7 +139,7 @@ describe('AsyncQueue', () => { }).to.throw(/already failed:.*Simulated Error/); // Finally, restore log level. - setLogLevel(oldLogLevel); + setLogLevel((oldLogLevel as unknown) as LogLevelString); }); }); diff --git a/scripts/prune-dts/package.json b/scripts/prune-dts/package.json new file mode 100644 index 00000000000..d00956e8d34 --- /dev/null +++ b/scripts/prune-dts/package.json @@ -0,0 +1,33 @@ +{ + "name": "@firebase/prune-dts", + "version": "2.0.2", + "engines": { + "node": "^8.13.0 || >=10.10.0" + }, + "description": "A script to prune non-exported types from a d.t.s.", + "author": "Firebase (https://firebase.google.com/)", + "scripts": { + "test": "TS_NODE_COMPILER_OPTIONS='{\"module\":\"commonjs\"}' mocha --require ts-node/register --timeout 5000 *.test.ts" + }, + "license": "Apache-2.0", + "dependencies": {}, + "repository": { + "directory": "scripts/prune-dts", + "type": "git", + "url": "https://github.com/firebase/firebase-js-sdk.git" + }, + "bugs": { + "url": "https://github.com/firebase/firebase-js-sdk/issues" + }, + "nyc": { + "extension": [ + ".ts" + ], + "reportDir": "./coverage/node" + }, + "devDependencies": { + "@types/prettier": "2.1.5", + "mocha": "8.2.1", + "prettier": "2.1.2" + } +} diff --git a/scripts/prune-dts/prune-dts.test.ts b/scripts/prune-dts/prune-dts.test.ts new file mode 100644 index 00000000000..c63162cf0b4 --- /dev/null +++ b/scripts/prune-dts/prune-dts.test.ts @@ -0,0 +1,100 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as os from 'os'; +import * as fs from 'fs'; +import * as path from 'path'; +import { format, resolveConfig } from 'prettier'; +import { expect } from 'chai'; +import { describe, it } from 'mocha'; + +import { pruneDts } from './prune-dts'; + +const testCasesDir = path.resolve(__dirname, 'tests'); +const tmpDir = os.tmpdir(); + +const testDataFilter = /(.*).input.d.ts/; +const testCaseFilterRe = /.*/; + +function runScript(inputFile: string): string { + const outputFile = path.resolve(tmpDir, 'output.d.ts'); + pruneDts(inputFile, outputFile); + return outputFile; +} + +interface TestCase { + name: string; + inputFileName: string; + outputFileName: string; +} + +function getTestCases(): TestCase[] { + if ( + !fs.existsSync(testCasesDir) || + !fs.lstatSync(testCasesDir).isDirectory() + ) { + throw new Error(`${testCasesDir} folder does not exist`); + } + + return fs + .readdirSync(testCasesDir) + .filter((fileName: string) => testDataFilter.test(fileName)) + .filter((fileName: string) => testCaseFilterRe.test(fileName)) + .map((fileName: string) => { + const testCaseName = fileName.match(testDataFilter)![1]; + + const inputFileName = `${testCaseName}.input.d.ts`; + const outputFileName = `${testCaseName}.output.d.ts`; + + const name = testCaseName.replace(/-/g, ' '); + return { name, inputFileName, outputFileName }; + }); +} + +describe('Prune DTS', () => { + for (const testCase of getTestCases()) { + it(testCase.name, async () => { + const absoluteInputFile = path.resolve( + testCasesDir, + testCase.inputFileName + ); + const absoluteOutputFile = path.resolve( + testCasesDir, + testCase.outputFileName + ); + + const tmpFile = runScript(absoluteInputFile); + const prettierConfig = await resolveConfig(absoluteInputFile); + + const expectedDtsUnformatted = fs.readFileSync( + absoluteOutputFile, + 'utf-8' + ); + const expectedDts = format(expectedDtsUnformatted, { + filepath: absoluteOutputFile, + ...prettierConfig + }); + const actualDtsUnformatted = fs.readFileSync(tmpFile, 'utf-8'); + const actualDts = format(actualDtsUnformatted, { + filepath: tmpFile, + ...prettierConfig + }); + + expect(actualDts).to.equal(expectedDts); + }); + } +}); diff --git a/scripts/prune-dts/prune-dts.ts b/scripts/prune-dts/prune-dts.ts new file mode 100644 index 00000000000..49f1c0492f0 --- /dev/null +++ b/scripts/prune-dts/prune-dts.ts @@ -0,0 +1,381 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import * as yargs from 'yargs'; +import * as ts from 'typescript'; +import * as fs from 'fs'; + +/** + * Prunes a DTS file based on three main rules: + * - Top level types are only included if they are also exported. + * - Underscore-prefixed members of class and interface types are stripped. + * - Constructors are made private or protected if marked with + * `@hideconstructor`/`@hideconstructor protected`. + * + * This function is meant to operate on DTS files generated by API extractor + * and extracts out the API that is relevant for third-party SDK consumers. + * + * @param inputLocation The file path to the .d.ts produced by API explorer. + * @param outputLocation The output location for the pruned .d.ts file. + */ +export function pruneDts(inputLocation: string, outputLocation: string): void { + const compilerOptions = {}; + const host = ts.createCompilerHost(compilerOptions); + const program = ts.createProgram([inputLocation], compilerOptions, host); + const printer: ts.Printer = ts.createPrinter(); + const sourceFile = program.getSourceFile(inputLocation)!; + const result: ts.TransformationResult = ts.transform< + ts.SourceFile + >(sourceFile, [dropPrivateApiTransformer.bind(null, program, host)]); + const transformedSourceFile: ts.SourceFile = result.transformed[0]; + const content = printer.printFile(transformedSourceFile); + fs.writeFileSync(outputLocation, content); +} + +/** Determines whether the provided identifier should be hidden. */ +function hasPrivatePrefix(name: ts.Identifier): boolean { + // Identifiers that are prefixed with an underscore are not not included in + // the public API. + return name.escapedText.toString().startsWith('_'); +} + +/** Returns whether the modifier array includes `exported`. */ +function isExported(modifiers?: ts.ModifiersArray): boolean { + return !!modifiers?.find(m => m.kind === ts.SyntaxKind.ExportKeyword); +} + +/** + * Replaces an existing constructor implementation if the constructor is marked + * with the JSDod tag `@hideconstructor`. The replaced constructor can either + * have `private` visibility` or `proctected`. To generate a protected + * constructor, specify `@hideconstructor proctected`. + * + * Returns either the modified constructor or the existing constructor if no + * modification was needed. + */ +function maybeHideConstructor( + node: ts.ConstructorDeclaration +): ts.ConstructorDeclaration { + const hideConstructorTag = ts + .getJSDocTags(node) + ?.find(t => t.tagName.escapedText === 'hideconstructor'); + + if (hideConstructorTag) { + const modifier = ts.createModifier( + hideConstructorTag.comment === 'protected' + ? ts.SyntaxKind.ProtectedKeyword + : ts.SyntaxKind.PrivateKeyword + ); + return ts.createConstructor( + node.decorators, + [modifier], + /*parameters=*/ [], + /* body= */ undefined + ); + } else { + return node; + } +} + +/** + * Examines `extends` and `implements` clauses and removes or replaces them if + * they refer to a non-exported type. When an export is removed, all members + * from the removed class are merged into the provided class or interface + * declaration. + * + * @example + * Input: + * class Foo { + * foo: string; + * } + * export class Bar extends Foo {} + * + * Output: + * export class Bar { + * foo: string; + * } + */ +function prunePrivateImports< + T extends ts.InterfaceDeclaration | ts.ClassDeclaration +>( + program: ts.Program, + host: ts.CompilerHost, + sourceFile: ts.SourceFile, + node: T +): T { + const typeChecker = program.getTypeChecker(); + const currentType = typeChecker.getTypeAtLocation(node); + const currentName = currentType?.symbol?.name; + + // The list of heritage clauses after all private symbols are removed. + const prunedHeritageClauses: ts.HeritageClause[] = []; + // Additional members that are copied from the private symbols into the public + // symbols + const additionalMembers: ts.NamedDeclaration[] = []; + + for (const heritageClause of node.heritageClauses || []) { + const exportedTypes: ts.ExpressionWithTypeArguments[] = []; + for (const type of heritageClause.types) { + if (isExported(type.modifiers)) { + exportedTypes.push(type); + } else { + const exportedSymbol = extractExportedSymbol( + typeChecker, + sourceFile, + type.expression + ); + + if (exportedSymbol && exportedSymbol.name !== currentName) { + // If there is a public type that we can refer to, update the import + // statement to refer to the public type. + exportedTypes.push( + ts.updateExpressionWithTypeArguments( + type, + type.typeArguments, + ts.createIdentifier(exportedSymbol.name) + ) + ); + } + + // Hide the type we are inheriting from and merge its declarations + // into the current class. + const privateType = typeChecker.getTypeAtLocation(type); + additionalMembers.push( + ...convertPropertiesForEnclosingClass( + program, + host, + sourceFile, + privateType.getProperties(), + node + ) + ); + } + } + + if (exportedTypes.length > 0) { + prunedHeritageClauses.push( + ts.updateHeritageClause(heritageClause, exportedTypes) + ); + } + } + + if (ts.isClassDeclaration(node)) { + return ts.updateClassDeclaration( + node, + node.decorators, + node.modifiers, + node.name, + node.typeParameters, + prunedHeritageClauses, + [...node.members, ...(additionalMembers as ts.ClassElement[])] + ) as T; + } else if (ts.isInterfaceDeclaration(node)) { + return ts.updateInterfaceDeclaration( + node, + node.decorators, + node.modifiers, + node.name, + node.typeParameters, + prunedHeritageClauses, + [...node.members, ...(additionalMembers as ts.TypeElement[])] + ) as T; + } else { + throw new Error('Only classes or interfaces are supported'); + } +} + +/** + * Iterates the provided symbols and returns named declarations for these + * symbols if they are missing from `currentClass`. This allows us to merge + * class hierarchies for classes whose inherited types are not part of the + * public API. + * + * This method relies on a private API in TypeScript's `codefix` package. + */ +function convertPropertiesForEnclosingClass( + program: ts.Program, + host: ts.CompilerHost, + sourceFile: ts.SourceFile, + parentClassSymbols: ts.Symbol[], + currentClass: ts.ClassDeclaration | ts.InterfaceDeclaration +): ts.NamedDeclaration[] { + const newMembers: ts.NamedDeclaration[] = []; + // The `codefix` package is not public but it does exactly what we want. We + // can explore adding a slimmed down version of this package to our repository + // if this dependency should ever break. + // eslint-disable-next-line @typescript-eslint/no-explicit-any + (ts as any).codefix.createMissingMemberNodes( + currentClass, + parentClassSymbols, + sourceFile, + { program, host }, + /* userPreferences= */ {}, + /* importAdder= */ undefined, + (c: ts.ClassElement) => newMembers.push(c) + ); + return newMembers; +} +/** + * Replaces input types of public APIs that consume non-exported types, which + * allows us to exclude private types from the pruned definitions. Returns the + * the name of the exported API or undefined if no type is found. + * + * @example + * Input: + * class PrivateFoo {} + * export class PublicFoo extends PrivateFoo {} + * export function doFoo(foo: PrivateFoo); + * + * Output: + * export class PublicFoo {} + * export function doFoo(foo: PublicFoo); + */ +function extractExportedSymbol( + typeChecker: ts.TypeChecker, + sourceFile: ts.SourceFile, + typeName: ts.Node +): ts.Symbol | undefined { + if (!ts.isIdentifier(typeName)) { + return undefined; + } + + const localSymbolName = typeName.escapedText; + const allExportedSymbols = typeChecker.getExportsOfModule( + typeChecker.getSymbolAtLocation(sourceFile)! + ); + const exportedSymbolsForLocalType: ts.Symbol[] = []; + + // Examine all exported types and check if they extend or implement the + // provided local type. If so, we can use the exported type in lieu of the + // private type. + for (const symbol of allExportedSymbols) { + // Short circuit if the local types is already part of the public types. + if (symbol.name === localSymbolName) { + return symbol; + } + + for (const declaration of symbol.declarations) { + if ( + ts.isClassDeclaration(declaration) || + ts.isInterfaceDeclaration(declaration) + ) { + for (const heritageClause of declaration.heritageClauses || []) { + for (const type of heritageClause.types || []) { + if (ts.isIdentifier(type.expression)) { + const subclassName = type.expression.escapedText; + if (subclassName === localSymbolName) { + exportedSymbolsForLocalType.push(symbol); + } + } + } + } + } + } + } + + return exportedSymbolsForLocalType[0]; +} + +function dropPrivateApiTransformer( + program: ts.Program, + host: ts.CompilerHost, + context: ts.TransformationContext +): ts.Transformer { + const typeChecker = program.getTypeChecker(); + + return (sourceFile: ts.SourceFile) => { + function visit(node: ts.Node): ts.Node { + if ( + ts.isInterfaceDeclaration(node) || + ts.isClassDeclaration(node) || + ts.isFunctionDeclaration(node) || + ts.isVariableStatement(node) || + ts.isTypeAliasDeclaration(node) || + ts.isModuleDeclaration(node) || + ts.isEnumDeclaration(node) + ) { + // Remove any types that are not exported. + if (!isExported(node.modifiers)) { + return ts.createToken(ts.SyntaxKind.WhitespaceTrivia); + } + } + + if (ts.isConstructorDeclaration(node)) { + // Replace internal constructors with private constructors. + return maybeHideConstructor(node); + } else if ( + ts.isClassDeclaration(node) || + ts.isInterfaceDeclaration(node) + ) { + // Remove any imports that reference internal APIs, while retaining + // their public members. + return prunePrivateImports(program, host, sourceFile, node); + } else if ( + ts.isPropertyDeclaration(node) || + ts.isMethodDeclaration(node) || + ts.isGetAccessor(node) + ) { + // Remove any class and interface members that are prefixed with + // underscores. + if (hasPrivatePrefix(node.name as ts.Identifier)) { + return ts.createToken(ts.SyntaxKind.WhitespaceTrivia); + } + } else if (ts.isTypeReferenceNode(node)) { + // For public types that refer internal types, find a public type that + // we can refer to instead. + const publicName = extractExportedSymbol( + typeChecker, + sourceFile, + node.typeName + ); + return publicName + ? ts.updateTypeReferenceNode( + node, + ts.createIdentifier(publicName.name), + node.typeArguments + ) + : node; + } + + return node; + } + + function visitNodeAndChildren(node: T): T { + return ts.visitEachChild( + visit(node), + childNode => visitNodeAndChildren(childNode), + context + ) as T; + } + return visitNodeAndChildren(sourceFile); + }; +} + +const argv = yargs.options({ + input: { + type: 'string', + desc: 'The location of the index.ts file' + }, + output: { + type: 'string', + desc: 'The location for the index.d.ts file' + } +}).argv; + +if (argv.input && argv.output) { + pruneDts(argv.input, argv.output); +} diff --git a/scripts/prune-dts/tests/hide-constructor.input.d.ts b/scripts/prune-dts/tests/hide-constructor.input.d.ts new file mode 100644 index 00000000000..15aadcfee41 --- /dev/null +++ b/scripts/prune-dts/tests/hide-constructor.input.d.ts @@ -0,0 +1,23 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class Foo { + /** @hideconstructor */ + constructor(bar: string); +} + +export {}; diff --git a/packages/firestore/src/protos/firestore_proto_api.js b/scripts/prune-dts/tests/hide-constructor.output.d.ts similarity index 88% rename from packages/firestore/src/protos/firestore_proto_api.js rename to scripts/prune-dts/tests/hide-constructor.output.d.ts index 21c443f41e5..3e12ad2ce44 100644 --- a/packages/firestore/src/protos/firestore_proto_api.js +++ b/scripts/prune-dts/tests/hide-constructor.output.d.ts @@ -14,5 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -// This file exists to solve an unresolved import error during the build. +export class Foo { + private constructor(); +} +export {}; diff --git a/scripts/prune-dts/tests/inherits-non-exported-members.input.d.ts b/scripts/prune-dts/tests/inherits-non-exported-members.input.d.ts new file mode 100644 index 00000000000..3d9f6b4aa7a --- /dev/null +++ b/scripts/prune-dts/tests/inherits-non-exported-members.input.d.ts @@ -0,0 +1,24 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare class Bar { + bar: string; +} +export class Foo extends Bar { + foo: string; +} +export {}; diff --git a/scripts/prune-dts/tests/inherits-non-exported-members.output.d.ts b/scripts/prune-dts/tests/inherits-non-exported-members.output.d.ts new file mode 100644 index 00000000000..482bc1b3135 --- /dev/null +++ b/scripts/prune-dts/tests/inherits-non-exported-members.output.d.ts @@ -0,0 +1,21 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export class Foo { + foo: string; + bar: string; +} +export {}; diff --git a/scripts/prune-dts/tests/prunes-non-exported-types.input.d.ts b/scripts/prune-dts/tests/prunes-non-exported-types.input.d.ts new file mode 100644 index 00000000000..622c5ac677f --- /dev/null +++ b/scripts/prune-dts/tests/prunes-non-exported-types.input.d.ts @@ -0,0 +1,23 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export function foo(): void; +declare function bar(): void; +export class Foo {} +declare class Bar {} + +export {}; diff --git a/scripts/prune-dts/tests/prunes-non-exported-types.output.d.ts b/scripts/prune-dts/tests/prunes-non-exported-types.output.d.ts new file mode 100644 index 00000000000..83282530081 --- /dev/null +++ b/scripts/prune-dts/tests/prunes-non-exported-types.output.d.ts @@ -0,0 +1,19 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export function foo(): void; +export class Foo {} +export {}; diff --git a/scripts/prune-dts/tests/prunes-underscores.input.d.ts b/scripts/prune-dts/tests/prunes-underscores.input.d.ts new file mode 100644 index 00000000000..6b849e36bf5 --- /dev/null +++ b/scripts/prune-dts/tests/prunes-underscores.input.d.ts @@ -0,0 +1,26 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class Foo { + foo: string; + _bar: string; + _barMethod(): string; + get _barGetter(): string; + readonly _barProperty: string; +} + +export {}; diff --git a/scripts/prune-dts/tests/prunes-underscores.output.d.ts b/scripts/prune-dts/tests/prunes-underscores.output.d.ts new file mode 100644 index 00000000000..f389da3749e --- /dev/null +++ b/scripts/prune-dts/tests/prunes-underscores.output.d.ts @@ -0,0 +1,20 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export class Foo { + foo: string; +} +export {}; diff --git a/scripts/prune-dts/tests/references-public-types.input.d.ts b/scripts/prune-dts/tests/references-public-types.input.d.ts new file mode 100644 index 00000000000..c27589a2b8b --- /dev/null +++ b/scripts/prune-dts/tests/references-public-types.input.d.ts @@ -0,0 +1,28 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +declare class Bar {} +export class Foo extends Bar {} +export function foo(bar: Bar): Bar; +export class Foobar { + constructor(bar: Bar); + bar: Bar; + readonly barProperty: Bar; + get barGetter(): Bar; + barMethod(bar: Bar): Bar; +} +export {}; diff --git a/scripts/prune-dts/tests/references-public-types.output.d.ts b/scripts/prune-dts/tests/references-public-types.output.d.ts new file mode 100644 index 00000000000..d80fbf9d9b2 --- /dev/null +++ b/scripts/prune-dts/tests/references-public-types.output.d.ts @@ -0,0 +1,27 @@ +/** + * @license + * Copyright 2020 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +export class Foo {} +export function foo(bar: Foo): Foo; +export class Foobar { + constructor(bar: Foo); + bar: Foo; + readonly barProperty: Foo; + get barGetter(): Foo; + barMethod(bar: Foo): Foo; +} +export {}; diff --git a/scripts/prune-dts/yarn.lock b/scripts/prune-dts/yarn.lock new file mode 100644 index 00000000000..3e6d8487dd8 --- /dev/null +++ b/scripts/prune-dts/yarn.lock @@ -0,0 +1,644 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@types/prettier@2.1.5": + version "2.1.5" + resolved "https://registry.npmjs.org/@types/prettier/-/prettier-2.1.5.tgz#b6ab3bba29e16b821d84e09ecfaded462b816b00" + integrity sha512-UEyp8LwZ4Dg30kVU2Q3amHHyTn1jEdhCIE59ANed76GaT1Vp76DD3ZWSAxgCrw6wJ0TqeoBpqmfUHiUDPs//HQ== + +"@ungap/promise-all-settled@1.1.2": + version "1.1.2" + resolved "https://registry.npmjs.org/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" + integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== + +ansi-colors@4.1.1: + version "4.1.1" + resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" + integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== + +ansi-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" + integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= + +ansi-regex@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz#8b9f8f08cf1acb843756a839ca8c7e3168c51997" + integrity sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg== + +ansi-styles@^3.2.0: + version "3.2.1" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" + integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== + dependencies: + color-convert "^1.9.0" + +ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +anymatch@~3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz#c55ecf02185e2469259399310c173ce31233b142" + integrity sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +balanced-match@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= + +binary-extensions@^2.0.0: + version "2.1.0" + resolved "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz#30fa40c9e7fe07dbc895678cd287024dea241dd9" + integrity sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +braces@~3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +browser-stdout@1.3.1: + version "1.3.1" + resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +camelcase@^5.0.0: + version "5.3.1" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.0.0: + version "6.2.0" + resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.2.0.tgz#924af881c9d525ac9d87f40d964e5cea982a1809" + integrity sha512-c7wVvbw3f37nuobQNtgsgG9POC9qMbNuMQmTCqZv23b6MIz0fcYpBiOlv9gEN/hdLdnZTDQhg6e9Dq5M1vKvfg== + +chalk@^4.0.0: + version "4.1.0" + resolved "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz#4e14870a618d9e2edd97dd8345fd9d9dc315646a" + integrity sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +chokidar@3.4.3: + version "3.4.3" + resolved "https://registry.npmjs.org/chokidar/-/chokidar-3.4.3.tgz#c1df38231448e45ca4ac588e6c79573ba6a57d5b" + integrity sha512-DtM3g7juCXQxFVSNPNByEC2+NImtBuxQQvWlHunpJIS5Ocr0lG306cC7FCi7cEA0fzmybPUIl4txBIobk1gGOQ== + dependencies: + anymatch "~3.1.1" + braces "~3.0.2" + glob-parent "~5.1.0" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.5.0" + optionalDependencies: + fsevents "~2.1.2" + +cliui@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz#deefcfdb2e800784aa34f46fa08e06851c7bbbc5" + integrity sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA== + dependencies: + string-width "^3.1.0" + strip-ansi "^5.2.0" + wrap-ansi "^5.1.0" + +color-convert@^1.9.0: + version "1.9.3" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" + integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== + dependencies: + color-name "1.1.3" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= + +debug@4.2.0: + version "4.2.0" + resolved "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz#7f150f93920e94c58f5574c2fd01a3110effe7f1" + integrity sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg== + dependencies: + ms "2.1.2" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +diff@4.0.2: + version "4.0.2" + resolved "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +emoji-regex@^7.0.1: + version "7.0.3" + resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156" + integrity sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA== + +escape-string-regexp@4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +find-up@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz#49169f1d7993430646da61ecc5ae355c21c97b73" + integrity sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg== + dependencies: + locate-path "^3.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= + +fsevents@~2.1.2: + version "2.1.3" + resolved "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz#fb738703ae8d2f9fe900c33836ddebee8b97f23e" + integrity sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ== + +get-caller-file@^2.0.1: + version "2.0.5" + resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +glob-parent@~5.1.0: + version "5.1.1" + resolved "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz#b6c1ef417c4e5663ea498f1c45afac6916bbc229" + integrity sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ== + dependencies: + is-glob "^4.0.1" + +glob@7.1.6: + version "7.1.6" + resolved "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" + integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.0.4" + once "^1.3.0" + path-is-absolute "^1.0.0" + +growl@1.10.5: + version "1.10.5" + resolved "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz#f2735dc2283674fa67478b10181059355c369e5e" + integrity sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +he@1.2.0: + version "1.2.0" + resolved "https://registry.npmjs.org/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= + +is-fullwidth-code-point@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" + integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.1" + resolved "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz#7567dbe9f2f5e2467bc77ab83c4a29482407a5dc" + integrity sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg== + dependencies: + is-extglob "^2.1.1" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= + +js-yaml@3.14.0: + version "3.14.0" + resolved "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz#a7a34170f26a21bb162424d8adacb4113a69e482" + integrity sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +locate-path@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz#dbec3b3ab759758071b58fe59fc41871af21400e" + integrity sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A== + dependencies: + p-locate "^3.0.0" + path-exists "^3.0.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +log-symbols@4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/log-symbols/-/log-symbols-4.0.0.tgz#69b3cc46d20f448eccdb75ea1fa733d9e821c920" + integrity sha512-FN8JBzLx6CzeMrB0tg6pqlGU1wCrXW+ZXGH481kfsBqer0hToTIiHdjH4Mq8xJUbvATujKCvaREGWpGUionraA== + dependencies: + chalk "^4.0.0" + +minimatch@3.0.4, minimatch@^3.0.4: + version "3.0.4" + resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== + dependencies: + brace-expansion "^1.1.7" + +mocha@8.2.1: + version "8.2.1" + resolved "https://registry.npmjs.org/mocha/-/mocha-8.2.1.tgz#f2fa68817ed0e53343d989df65ccd358bc3a4b39" + integrity sha512-cuLBVfyFfFqbNR0uUKbDGXKGk+UDFe6aR4os78XIrMQpZl/nv7JYHcvP5MFIAb374b2zFXsdgEGwmzMtP0Xg8w== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.4.3" + debug "4.2.0" + diff "4.0.2" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.1.6" + growl "1.10.5" + he "1.2.0" + js-yaml "3.14.0" + log-symbols "4.0.0" + minimatch "3.0.4" + ms "2.1.2" + nanoid "3.1.12" + serialize-javascript "5.0.1" + strip-json-comments "3.1.1" + supports-color "7.2.0" + which "2.0.2" + wide-align "1.1.3" + workerpool "6.0.2" + yargs "13.3.2" + yargs-parser "13.1.2" + yargs-unparser "2.0.0" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +nanoid@3.1.12: + version "3.1.12" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.1.12.tgz#6f7736c62e8d39421601e4a0c77623a97ea69654" + integrity sha512-1qstj9z5+x491jfiC4Nelk+f8XBad7LN20PmyWINJEMRSf3wcAjAWysw1qaA8z6NSKe2sjq1hRSDpBH5paCb6A== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.npmjs.org/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= + dependencies: + wrappy "1" + +p-limit@^2.0.0: + version "2.3.0" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.0.2" + resolved "https://registry.npmjs.org/p-limit/-/p-limit-3.0.2.tgz#1664e010af3cadc681baafd3e2a437be7b0fb5fe" + integrity sha512-iwqZSOoWIW+Ew4kAGUlN16J4M7OB3ysMLSZtnhmqx7njIHFPlxWBX8xo3lVTyFVq6mI/lL9qt2IsN1sHwaxJkg== + dependencies: + p-try "^2.0.0" + +p-locate@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz#322d69a05c0264b25997d9f40cd8a891ab0064a4" + integrity sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ== + dependencies: + p-limit "^2.0.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +path-exists@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" + integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= + +picomatch@^2.0.4, picomatch@^2.2.1: + version "2.2.2" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz#21f333e9b6b8eaff02468f5146ea406d345f4dad" + integrity sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg== + +prettier@2.1.2: + version "2.1.2" + resolved "https://registry.npmjs.org/prettier/-/prettier-2.1.2.tgz#3050700dae2e4c8b67c4c3f666cdb8af405e1ce5" + integrity sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +readdirp@~3.5.0: + version "3.5.0" + resolved "https://registry.npmjs.org/readdirp/-/readdirp-3.5.0.tgz#9ba74c019b15d365278d2e91bb8c48d7b4d42c9e" + integrity sha512-cMhu7c/8rdhkHXWsY+osBhfSy0JikwpHK/5+imo+LpeasTF8ouErHrlYkwT0++njiyuDvc7OFY5T3ukvZ8qmFQ== + dependencies: + picomatch "^2.2.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +serialize-javascript@5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz#7886ec848049a462467a97d3d918ebb2aaf934f4" + integrity sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA== + dependencies: + randombytes "^2.1.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= + +"string-width@^1.0.2 || 2": + version "2.1.1" + resolved "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" + integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== + dependencies: + is-fullwidth-code-point "^2.0.0" + strip-ansi "^4.0.0" + +string-width@^3.0.0, string-width@^3.1.0: + version "3.1.0" + resolved "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz#22767be21b62af1081574306f69ac51b62203961" + integrity sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w== + dependencies: + emoji-regex "^7.0.1" + is-fullwidth-code-point "^2.0.0" + strip-ansi "^5.1.0" + +strip-ansi@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" + integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= + dependencies: + ansi-regex "^3.0.0" + +strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: + version "5.2.0" + resolved "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz#8c9a536feb6afc962bdfa5b104a5091c1ad9c0ae" + integrity sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA== + dependencies: + ansi-regex "^4.1.0" + +strip-json-comments@3.1.1: + version "3.1.1" + resolved "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +supports-color@7.2.0, supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +which-module@^2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz#d9ef07dce77b9902b8a3a8fa4b31c3e3f7e6e87a" + integrity sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= + +which@2.0.2: + version "2.0.2" + resolved "https://registry.npmjs.org/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +wide-align@1.1.3: + version "1.1.3" + resolved "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" + integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== + dependencies: + string-width "^1.0.2 || 2" + +workerpool@6.0.2: + version "6.0.2" + resolved "https://registry.npmjs.org/workerpool/-/workerpool-6.0.2.tgz#e241b43d8d033f1beb52c7851069456039d1d438" + integrity sha512-DSNyvOpFKrNusaaUwk+ej6cBj1bmhLcBfj80elGk+ZIo5JSkq+unB1dLKEOcNfJDZgjGICfhQ0Q5TbP0PvF4+Q== + +wrap-ansi@^5.1.0: + version "5.1.0" + resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz#1fd1f67235d5b6d0fee781056001bfb694c03b09" + integrity sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q== + dependencies: + ansi-styles "^3.2.0" + string-width "^3.0.0" + strip-ansi "^5.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= + +y18n@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz#95ef94f85ecc81d007c264e190a120f0a3c8566b" + integrity sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w== + +yargs-parser@13.1.2, yargs-parser@^13.1.2: + version "13.1.2" + resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz#130f09702ebaeef2650d54ce6e3e5706f7a4fb38" + integrity sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@13.3.2: + version "13.3.2" + resolved "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz#ad7ffefec1aa59565ac915f82dccb38a9c31a2dd" + integrity sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw== + dependencies: + cliui "^5.0.0" + find-up "^3.0.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^3.0.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^13.1.2" diff --git a/yarn.lock b/yarn.lock index a9574ccae6d..8a4c17a1f6d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5137,6 +5137,11 @@ color@3.0.x: color-convert "^1.9.1" color-string "^1.5.2" +colorette@^1.1.0: + version "1.2.1" + resolved "https://registry.npmjs.org/colorette/-/colorette-1.2.1.tgz#4d0b921325c14faf92633086a536db6e89564b1b" + integrity sha512-puCDz0CzydiSYOrnXpz/PKd69zRrribezjtE9yd4zvytoRc8+RY/KJPvtPFKZS3E3wP6neGyMe0vOTlHO5L3Pw== + colors@1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz#0433f44d809680fdeb60ed260f1b0c262e82a40b" @@ -8028,6 +8033,20 @@ globals@^9.18.0: resolved "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz#aa3896b3e69b487f17e31ed2143d69a8e30c2d8a" integrity sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ== +globby@10.0.1: + version "10.0.1" + resolved "https://registry.npmjs.org/globby/-/globby-10.0.1.tgz#4782c34cb75dd683351335c5829cc3420e606b22" + integrity sha512-sSs4inE1FB2YQiymcmTv6NWENryABjUNPeWhOvmn4SjtKybglsyPZxFB3U1/+L1bYi0rNZDqCLlHyLYDl1Pq5A== + dependencies: + "@types/glob" "^7.1.1" + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.0.3" + glob "^7.1.3" + ignore "^5.1.1" + merge2 "^1.2.3" + slash "^3.0.0" + globby@^10.0.1: version "10.0.2" resolved "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz#277593e745acaa4646c3ab411289ec47a0392543" @@ -9362,6 +9381,16 @@ is-plain-object@^2.0.1, is-plain-object@^2.0.3, is-plain-object@^2.0.4: dependencies: isobject "^3.0.1" +is-plain-object@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-3.0.1.tgz#662d92d24c0aa4302407b0d45d21f2251c85f85b" + integrity sha512-Xnpx182SBMrr/aBik8y+GuR4U1L9FqMSojwDQwPMmxyC6bvEqly9UBCxhauBF5vNh2gwWJNX6oDV7O+OM4z34g== + +is-plain-object@^4.0.0: + version "4.1.1" + resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-4.1.1.tgz#1a14d6452cbd50790edc7fdaa0aed5a40a35ebb5" + integrity sha512-5Aw8LLVsDlZsETVMhoMXzqsXwQqr/0vlnBYzIXJbYo2F4yYlhLHs+Ez7Bod7IIQKWkJbJfxrWD7pA1Dw1TKrwA== + is-plain-object@^5.0.0: version "5.0.0" resolved "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz#4427f50ab3429e9025ea7d52e9043a9ef4159344" @@ -13662,6 +13691,24 @@ rollup-plugin-copy-assets@1.1.0: dependencies: fs-extra "^5.0.0" +rollup-plugin-copy@3.3.0: + version "3.3.0" + resolved "https://registry.npmjs.org/rollup-plugin-copy/-/rollup-plugin-copy-3.3.0.tgz#5ba230047f86b9f703a29288f242948a5580e7b9" + integrity sha512-euDjCUSBXZa06nqnwCNADbkAcYDfzwowfZQkto9K/TFhiH+QG7I4PUsEMwM9tDgomGWJc//z7KLW8t+tZwxADA== + dependencies: + "@types/fs-extra" "^8.0.1" + colorette "^1.1.0" + fs-extra "^8.1.0" + globby "10.0.1" + is-plain-object "^3.0.0" + +rollup-plugin-json@4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz#a18da0a4b30bf5ca1ee76ddb1422afbb84ae2b9e" + integrity sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow== + dependencies: + rollup-pluginutils "^2.5.0" + rollup-plugin-license@2.2.0: version "2.2.0" resolved "https://registry.npmjs.org/rollup-plugin-license/-/rollup-plugin-license-2.2.0.tgz#0d19139bbe44dda500fbf15530af07c91949e348"