diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml index 8c663e98..ad806bea 100644 --- a/.github/workflows/docs.yaml +++ b/.github/workflows/docs.yaml @@ -3,15 +3,22 @@ name: Check if Reference Docs need to be regenerated on: pull_request +# Least privilege. This workflow only regenerates docs and diffs them; it never +# pushes. +permissions: + contents: read + jobs: docs: runs-on: ubuntu-latest name: Build steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + persist-credentials: false - name: Setup node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: '24' cache: 'npm' diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 1d76cd68..d4158b35 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -13,15 +13,22 @@ on: types: - published +# Least privilege by default. No job writes to the repo through GITHUB_TOKEN; +# the publish job authenticates to npm with NODE_AUTH_TOKEN. +permissions: + contents: read + jobs: build: runs-on: ubuntu-latest name: Build steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + persist-credentials: false - name: Setup node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: '24' cache: 'npm' @@ -31,7 +38,7 @@ jobs: id: pack-dir run: ./build.sh - name: 'Upload Artifact' - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 with: name: reactfire-${{ github.run_id }} path: | @@ -49,9 +56,11 @@ jobs: name: Test Node.js ${{ matrix.node }} (Ubuntu) steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + persist-credentials: false - name: Setup node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: ${{ matrix.node }} check-latest: true @@ -59,7 +68,7 @@ jobs: - name: Install deps run: npm ci - name: Setup Java - uses: actions/setup-java@v4 + uses: actions/setup-java@c1e323688fd81a25caa38c78aa6df2d33d3e20d9 # v4.8.0 with: distribution: 'temurin' java-version: '21' @@ -67,12 +76,12 @@ jobs: run: npm install working-directory: ./functions - name: Firebase emulator cache - uses: actions/cache@v4 + uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: path: ~/.cache/firebase/emulators key: firebase_emulators - name: 'Download Artifacts' - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - name: Expand Artifact run: | chmod +x reactfire-${{ github.run_id }}/unpack.sh @@ -88,9 +97,11 @@ jobs: name: Type check (React ${{ matrix.react }}) steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0 + with: + persist-credentials: false - name: Setup node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: '24' cache: 'npm' @@ -109,12 +120,12 @@ jobs: if: ${{ github.ref == 'refs/heads/main' || github.event_name == 'release' }} steps: - name: Setup node - uses: actions/setup-node@v4 + uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0 with: node-version: '24' - registry-url: 'https://registry.npmjs.org' + registry-url: 'https://wombat-dressing-room.appspot.com' - name: 'Download Artifacts' - uses: actions/download-artifact@v4 + uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0 - name: Publish run: | cd ./reactfire-${{ github.run_id }}/ diff --git a/package-lock.json b/package-lock.json index 845fbc18..5e7c64cb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7506,9 +7506,9 @@ "dev": true }, "node_modules/fast-uri": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.4.tgz", - "integrity": "sha512-8JnbkQ4juDyvYs4mgFGQqg4yCYtFDtUtmp2QIQq11ZZe5CFQ5wcqm1rqDgAh/QdMySuBnPzMUiJUNZG5N/AiQw==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", + "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", "dev": true, "funding": [ { @@ -9327,18 +9327,23 @@ } }, "node_modules/install-artifact-from-github": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/install-artifact-from-github/-/install-artifact-from-github-1.6.0.tgz", - "integrity": "sha512-wKsuzN8fy8QK7iEUqyWTQmvZ1QFGPn1xyl3/1iIIDthDjS7Hn9HoPwHlNakZirWbCsbad0lZMkr6Xfbpe1pUzw==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/install-artifact-from-github/-/install-artifact-from-github-1.7.0.tgz", + "integrity": "sha512-qAb91yAKVF9rFY4rVP21ZtYUyCScxAFt9udwzVWNLBE1pQcdQeB2gd1HlNPcQNYCzCDvJ/QJQPuWQ6aTmSlU8g==", "dev": true, "license": "BSD-3-Clause", "optional": true, "bin": { + "hash-github-cache": "bin/hash-github-cache.js", "install-from-cache": "bin/install-from-cache.js", "save-to-github-cache": "bin/save-to-github-cache.js" }, "engines": { "node": ">=18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/uhop" } }, "node_modules/internal-slot": { @@ -9356,9 +9361,9 @@ } }, "node_modules/ip-address": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.2.0.tgz", - "integrity": "sha512-/+S6j4E9AHvW9SWMSEY9Xfy66O5PWvVEJ08O0y5JGyEKQpojb0K0GKpz/v5HJ/G0vi3D2sjGK78119oXZeE0qA==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.4.0.tgz", + "integrity": "sha512-oSK96Grm3aP6OrS263xVxbNDGVL7rzBtYdpGqlDG8iQdoenDoTs/nkki+DflYbAEE8Xl6o5YxhxlrKvI3nqKXQ==", "dev": true, "license": "MIT", "engines": { @@ -11690,9 +11695,9 @@ "optional": true }, "node_modules/nanoid": { - "version": "3.3.12", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz", - "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==", + "version": "3.3.17", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.17.tgz", + "integrity": "sha512-xQLf0A3HOMlgHq0n247/LRuAOYmB7dXJ/DvAxGvsSBij45XtBSmQycu+F8ODbHwns/XyFZagyL1+J0Offw1E0g==", "dev": true, "funding": [ { @@ -11858,9 +11863,9 @@ } }, "node_modules/node-gyp": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-13.0.0.tgz", - "integrity": "sha512-FYYyBDWdc+kzoyPd5PqHUgM9DGs1C/Z4jxBZAOnA2GRUVXPivKRREq5q+VVPXVr9aGVqGMaMqyFHbviy/yb7Hg==", + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-13.0.1.tgz", + "integrity": "sha512-piOr0S10qy5THB+q5BdqkoOx65XL/tjTMUAit3vciPNp+snTOBnGunWH1Rz7XZUxf2T9uFrfT/Ty4+aC3yPeyg==", "dev": true, "license": "MIT", "optional": true, @@ -11873,7 +11878,7 @@ "semver": "^7.3.5", "tar": "^7.5.4", "tinyglobby": "^0.2.12", - "undici": "^6.25.0", + "undici": "^8.4.1", "which": "^7.0.0" }, "bin": { @@ -12676,9 +12681,9 @@ } }, "node_modules/postcss": { - "version": "8.5.15", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.15.tgz", - "integrity": "sha512-FfR8sjd4em2T6fb3I2MwAJU7HWVMr9zba+enmQeeWFfCbm+UOC/0X4DS8XtpUTMwWMGbjKYP7xjfNekzyGmB3A==", + "version": "8.5.25", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.25.tgz", + "integrity": "sha512-DTPx3RWSSnWyzLxQnlH0rJP+EW5ekl16ZU4/psbIhA0e53kJfdgaN5vKM+xP7yJtXVu+nfdVFmlgFDEKAe4Pyw==", "dev": true, "funding": [ { @@ -12696,7 +12701,7 @@ ], "license": "MIT", "dependencies": { - "nanoid": "^3.3.12", + "nanoid": "^3.3.16", "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, @@ -13162,17 +13167,17 @@ } }, "node_modules/re2": { - "version": "1.25.0", - "resolved": "https://registry.npmjs.org/re2/-/re2-1.25.0.tgz", - "integrity": "sha512-mtxKjWS+VYIt2ijgt6ohEdwzNlGPom1whyaEKJD40cBc/wqkO1vJoOyK539Qb8Xa9m4GA6hiPGDIbW/d3egSRQ==", + "version": "1.26.1", + "resolved": "https://registry.npmjs.org/re2/-/re2-1.26.1.tgz", + "integrity": "sha512-oi79a4h6EO3PAwNsDMWgeCcsRGQEUa52DIgOiFTZGDEZocEXG9h+oXy0qZqndo47huUeJuVWSoOJIEhOupqOcg==", "dev": true, "hasInstallScript": true, "license": "BSD-3-Clause", "optional": true, "dependencies": { - "install-artifact-from-github": "^1.6.0", - "nan": "^2.27.0", - "node-gyp": "^13.0.0" + "install-artifact-from-github": "^1.7.0", + "nan": "^2.28.0", + "node-gyp": "^13.0.1" }, "engines": { "node": "^22.22.2 || ^24.15.0 || >=26.0.0" @@ -15433,14 +15438,14 @@ } }, "node_modules/undici": { - "version": "6.27.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-6.27.0.tgz", - "integrity": "sha512-YmfV3YnEDzXRC5lZ2jWtWWHKGUm1zIt8AhesR1tens+HTNv+YZlN/dp6G727LOvMJ8xjP9Be7Y2Sdr96LDm+pg==", + "version": "8.9.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-8.9.0.tgz", + "integrity": "sha512-aWZpUj7XoGonMClx4gdDRfgBjqeA+F473aDmROQQbM9n6PRfK/u1q/a0X4wMTgcHfT8H6fpbt98PFuDUwFg2YA==", "dev": true, "license": "MIT", "optional": true, "engines": { - "node": ">=18.17" + "node": ">=22.19.0" } }, "node_modules/undici-types": { diff --git a/src/SuspenseSubject.ts b/src/SuspenseSubject.ts index 0c52b9b5..5b7ef884 100644 --- a/src/SuspenseSubject.ts +++ b/src/SuspenseSubject.ts @@ -1,6 +1,6 @@ import { empty, Observable, Subject, Subscriber, Subscription } from 'rxjs'; import { catchError, shareReplay, tap } from 'rxjs/operators'; -import { ObservableStatus } from './useObservable'; +import { ObservableStatus } from './useObservable.js'; export class SuspenseSubject extends Subject { private _value: T | undefined; diff --git a/src/auth.tsx b/src/auth.tsx index 9fba1a46..6e74d6c5 100644 --- a/src/auth.tsx +++ b/src/auth.tsx @@ -1,9 +1,9 @@ import * as React from 'react'; import { user } from 'rxfire/auth'; -import { preloadObservable, ReactFireOptions, useAuth, useObservable, ObservableStatus, ReactFireError } from './'; +import { preloadObservable, ReactFireOptions, useAuth, useObservable, ObservableStatus, ReactFireError } from './index.js'; import { from, of, defer } from 'rxjs'; import { map, switchMap } from 'rxjs/operators'; -import { useSuspenseEnabledFromConfigAndContext } from './firebaseApp'; +import { useSuspenseEnabledFromConfigAndContext } from './firebaseApp.js'; import type { Auth, User, IdTokenResult } from 'firebase/auth'; type Claims = IdTokenResult['claims']; diff --git a/src/database.tsx b/src/database.tsx index 3cfa9224..5c5f998c 100644 --- a/src/database.tsx +++ b/src/database.tsx @@ -1,5 +1,5 @@ import { list, object, QueryChange, listVal, objectVal } from 'rxfire/database'; -import { ReactFireOptions, useObservable, checkIdField, ObservableStatus, ReactFireGlobals } from './'; +import { ReactFireOptions, useObservable, checkIdField, ObservableStatus, ReactFireGlobals } from './index.js'; import type { Query as DatabaseQuery, DatabaseReference } from 'firebase/database'; diff --git a/src/firestore.tsx b/src/firestore.tsx index d5efa8bd..ed504f97 100644 --- a/src/firestore.tsx +++ b/src/firestore.tsx @@ -1,6 +1,6 @@ import { collectionData, doc, docData, fromRef } from 'rxfire/firestore'; -import { ReactFireOptions, useObservable, checkIdField, ReactFireGlobals } from './'; -import { preloadObservable, ObservableStatus } from './useObservable'; +import { ReactFireOptions, useObservable, checkIdField, ReactFireGlobals } from './index.js'; +import { preloadObservable, ObservableStatus } from './useObservable.js'; import { first } from 'rxjs/operators'; import { Query as FirestoreQuery, QuerySnapshot, DocumentReference, queryEqual, DocumentData, DocumentSnapshot } from 'firebase/firestore'; diff --git a/src/functions.tsx b/src/functions.tsx index e9f1f34b..d30be15b 100644 --- a/src/functions.tsx +++ b/src/functions.tsx @@ -1,7 +1,7 @@ import { httpsCallable as rxHttpsCallable } from 'rxfire/functions'; import { defer } from 'rxjs'; -import { ReactFireOptions, useObservable, ObservableStatus } from './'; -import { useFunctions } from '.'; +import { ReactFireOptions, useObservable, ObservableStatus } from './index.js'; +import { useFunctions } from './index.js'; import type { HttpsCallableOptions } from 'firebase/functions'; diff --git a/src/index.ts b/src/index.ts index ab60a1fe..028a4a62 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -import { SuspenseSubject } from './SuspenseSubject'; +import { SuspenseSubject } from './SuspenseSubject.js'; import type { Query as FirestoreQuery } from 'firebase/firestore'; import type { Query as DatabaseQuery } from 'firebase/database'; @@ -48,13 +48,13 @@ export function checkIdField(options: ReactFireOptions) { return checkOptions(options, 'idField'); } -export * from './auth'; -export * from './database'; -export * from './firebaseApp'; -export * from './firestore'; -export * from './functions'; -export * from './performance'; -export * from './remote-config'; -export * from './storage'; -export * from './useObservable'; -export * from './sdk'; +export * from './auth.js'; +export * from './database.js'; +export * from './firebaseApp.js'; +export * from './firestore.js'; +export * from './functions.js'; +export * from './performance.js'; +export * from './remote-config.js'; +export * from './storage.js'; +export * from './useObservable.js'; +export * from './sdk.js'; diff --git a/src/remote-config.tsx b/src/remote-config.tsx index 97376fb8..83b398a0 100644 --- a/src/remote-config.tsx +++ b/src/remote-config.tsx @@ -1,5 +1,5 @@ -import { useRemoteConfig } from './'; -import { useObservable, ObservableStatus } from './useObservable'; +import { useRemoteConfig } from './index.js'; +import { useObservable, ObservableStatus } from './useObservable.js'; import { getValue, getString, getBoolean, getNumber, getAll, AllParameters } from 'rxfire/remote-config'; import { Observable } from 'rxjs'; diff --git a/src/sdk.tsx b/src/sdk.tsx index ee66ffff..c3238604 100644 --- a/src/sdk.tsx +++ b/src/sdk.tsx @@ -9,11 +9,11 @@ import type { Functions } from 'firebase/functions'; import type { FirebasePerformance } from 'firebase/performance'; import type { FirebaseStorage } from 'firebase/storage'; import type { RemoteConfig } from 'firebase/remote-config'; -import { useFirebaseApp } from './firebaseApp'; +import { useFirebaseApp } from './firebaseApp.js'; import { FirebaseApp } from 'firebase/app'; -import { ObservableStatus, useObservable } from './useObservable'; +import { ObservableStatus, useObservable } from './useObservable.js'; import { from } from 'rxjs'; -import { ReactFireOptions } from '.'; +import { ReactFireOptions } from './index.js'; export const AppCheckSdkContext = React.createContext(undefined); export const AuthSdkContext = React.createContext(undefined); diff --git a/src/storage.tsx b/src/storage.tsx index 92f27a51..6bb1ccb3 100644 --- a/src/storage.tsx +++ b/src/storage.tsx @@ -1,8 +1,8 @@ import * as React from 'react'; import { getDownloadURL, fromTask } from 'rxfire/storage'; import { defer } from 'rxjs'; -import { ReactFireOptions, useObservable, ObservableStatus, useStorage } from './'; -import { useSuspenseEnabledFromConfigAndContext } from './firebaseApp'; +import { ReactFireOptions, useObservable, ObservableStatus, useStorage } from './index.js'; +import { useSuspenseEnabledFromConfigAndContext } from './firebaseApp.js'; import { ref } from 'firebase/storage'; import type { UploadTask, UploadTaskSnapshot, StorageReference, FirebaseStorage } from 'firebase/storage'; diff --git a/src/useObservable.ts b/src/useObservable.ts index aae1dac8..6364c9bf 100644 --- a/src/useObservable.ts +++ b/src/useObservable.ts @@ -1,9 +1,9 @@ import * as React from 'react'; import { useSyncExternalStore } from 'use-sync-external-store/shim'; import { Observable } from 'rxjs'; -import { SuspenseSubject } from './SuspenseSubject'; -import { useSuspenseEnabledFromConfigAndContext } from './firebaseApp'; -import { ReactFireGlobals, ReactFireOptions } from './'; +import { SuspenseSubject } from './SuspenseSubject.js'; +import { useSuspenseEnabledFromConfigAndContext } from './firebaseApp.js'; +import { ReactFireGlobals, ReactFireOptions } from './index.js'; const DEFAULT_TIMEOUT = 30_000;