UNPKG

@expo/fingerprint

Version:

A library to generate a fingerprint from a React Native project

236 lines (235 loc) 7.37 kB
/// <reference types="node" /> import type { IMinimatch } from 'minimatch'; import type { SourceSkips } from './sourcer/SourceSkips'; export type FingerprintSource = HashSource & { /** * Hash value of the `source`. * If the source is excluding by `Options.dirExcludes`, the value will be null. */ hash: string | null; /** * Debug info from the hashing process. Differs based on source type. Designed to be consumed by humans * as opposed to programmatically. */ debugInfo?: DebugInfo; }; export interface Fingerprint { /** * Sources and their hash values to generate a fingerprint */ sources: FingerprintSource[]; /** * The final hash value of the whole fingerprint */ hash: string; } export type FingerprintDiffItem = { /** * The operation type of the diff item. */ op: 'added'; /** * The added source. */ addedSource: FingerprintSource; } | { /** * The operation type of the diff item. */ op: 'removed'; /** * The removed source. */ removedSource: FingerprintSource; } | { /** * The operation type of the diff item. */ op: 'changed'; /** * The source before. */ beforeSource: FingerprintSource; /** * The source after. */ afterSource: FingerprintSource; }; export type Platform = 'android' | 'ios'; export interface Options { /** * Only get native files from the given platforms. Default is `['android', 'ios']`. */ platforms?: Platform[]; /** * I/O concurrent limit. Default is the number of CPU core. */ concurrentIoLimit?: number; /** * The algorithm passing to `crypto.createHash()`. Default is `'sha1'`. */ hashAlgorithm?: string; /** * Excludes directories from hashing. This supported pattern is as `glob()`. * Default is `['android/build', 'android/app/build', 'android/app/.cxx', 'ios/Pods']`. * @deprecated Use `ignorePaths` instead. */ dirExcludes?: string[]; /** * Ignore files and directories from hashing. This supported pattern is as `glob()`. * * Please note that the pattern matching is slightly different from gitignore. For example, we don't support partial matching where `build` does not match `android/build`. You should use `'**' + '/build'` instead. * @see [minimatch implementations](https://github.com/isaacs/minimatch#comparisons-to-other-fnmatchglob-implementations) for more reference. * * Besides this `ignorePaths`, fingerprint comes with implicit default ignorePaths defined in `Options.DEFAULT_IGNORE_PATHS`. * If you want to override the default ignorePaths, use `!` prefix. */ ignorePaths?: string[]; /** * Additional sources for hashing. */ extraSources?: HashSource[]; /** * Skips some sources from fingerprint. * @default DEFAULT_SOURCE_SKIPS */ sourceSkips?: SourceSkips; /** * Enable ReactImportsPatcher to transform imports from React of the form `#import "RCTBridge.h"` to `#import <React/RCTBridge.h>`. * This is useful when you want to have a stable fingerprint for Expo projects, * since expo-modules-autolinking will change the import style on iOS. * @default true for Expo SDK 51 and lower. */ enableReactImportsPatcher?: boolean; /** * Use the react-native core autolinking sources from expo-modules-autolinking rather than @react-native-community/cli. * @default true for Expo SDK 52 and higher. */ useRNCoreAutolinkingFromExpo?: boolean; /** * Whether running the functions should mute all console output. This is useful when fingerprinting is being done as * part of a CLI that outputs a fingerprint and outputting anything else pollutes the results. */ silent?: boolean; /** * Whether to include verbose debug info in source output. Useful for debugging. */ debug?: boolean; /** * A custom hook function to transform file content sources before hashing. */ fileHookTransform?: FileHookTransformFunction; } type SourceSkipsKeys = keyof typeof SourceSkips; /** * Supported options from fingerprint.config.js */ export type Config = Pick<Options, 'concurrentIoLimit' | 'hashAlgorithm' | 'ignorePaths' | 'extraSources' | 'enableReactImportsPatcher' | 'useRNCoreAutolinkingFromExpo' | 'debug' | 'fileHookTransform'> & { sourceSkips?: SourceSkips | SourceSkipsKeys[]; }; /** * Hook function to transform file content sources before hashing. */ export type FileHookTransformFunction = ( /** * Source from HashSourceFile or HashSourceContents. */ source: FileHookTransformSource, /** * The chunk of file content. * When the stream reaches the end, the chunk will be null. */ chunk: Buffer | string | null, /** * Indicates the end of the file. */ isEndOfFile: boolean, /** * The encoding of the chunk. */ encoding: BufferEncoding) => Buffer | string | null; /** * The `source` parameter for `FileHookTransformFunction`. */ export type FileHookTransformSource = { type: 'file'; filePath: string; } | { type: 'contents'; id: string; }; export type NormalizedOptions = Omit<Options, 'ignorePaths'> & { platforms: NonNullable<Options['platforms']>; concurrentIoLimit: NonNullable<Options['concurrentIoLimit']>; hashAlgorithm: NonNullable<Options['hashAlgorithm']>; sourceSkips: NonNullable<Options['sourceSkips']>; enableReactImportsPatcher: NonNullable<Options['enableReactImportsPatcher']>; ignorePathMatchObjects: IMinimatch[]; /** * A ignore pattern list specific for dir matching. It is built by `ignorePathMatchObjects` in runtime. */ ignoreDirMatchObjects: IMinimatch[]; }; export interface HashSourceFile { type: 'file'; filePath: string; /** * Reasons of this source coming from */ reasons: string[]; } export interface HashSourceDir { type: 'dir'; filePath: string; /** * Reasons of this source coming from */ reasons: string[]; } export interface HashSourceContents { type: 'contents'; id: string; contents: string | Buffer; /** * Reasons of this source coming from */ reasons: string[]; } export type HashSource = HashSourceFile | HashSourceDir | HashSourceContents; export interface DebugInfoFile { path: string; hash: string; /** Indicates whether the source is transformed by `fileHookTransform` */ isTransformed?: boolean; } export interface DebugInfoDir { path: string; hash: string; children: (DebugInfoFile | DebugInfoDir | undefined)[]; } export interface DebugInfoContents { hash: string; /** Indicates whether the source is transformed by `fileHookTransform` */ isTransformed?: boolean; } export type DebugInfo = DebugInfoFile | DebugInfoDir | DebugInfoContents; export interface HashResultFile { type: 'file'; id: string; hex: string; debugInfo?: DebugInfoFile; } export interface HashResultDir { type: 'dir'; id: string; hex: string; debugInfo?: DebugInfoDir; } export interface HashResultContents { type: 'contents'; id: string; hex: string; debugInfo?: DebugInfoContents; } export type HashResult = HashResultFile | HashResultDir | HashResultContents; export {};