first commit

This commit is contained in:
2026-03-10 16:18:05 +00:00
commit 11f9c069b5
31635 changed files with 3187747 additions and 0 deletions

32
node_modules/metro-cache/package.json generated vendored Normal file
View File

@@ -0,0 +1,32 @@
{
"name": "metro-cache",
"version": "0.83.3",
"description": "🚇 Cache layers for Metro.",
"main": "src/index.js",
"exports": {
".": "./src/index.js",
"./package.json": "./package.json",
"./private/*": "./src/*.js"
},
"repository": {
"type": "git",
"url": "git@github.com:facebook/metro.git"
},
"scripts": {
"prepare-release": "test -d build && rm -rf src.real && mv src src.real && mv build src",
"cleanup-release": "test ! -e build && mv src build && mv src.real src"
},
"dependencies": {
"exponential-backoff": "^3.1.1",
"flow-enums-runtime": "^0.0.6",
"https-proxy-agent": "^7.0.5",
"metro-core": "0.83.3"
},
"devDependencies": {
"memfs": "^4.38.2"
},
"license": "MIT",
"engines": {
"node": ">=20.19.4"
}
}

25
node_modules/metro-cache/src/Cache.d.ts generated vendored Normal file
View File

@@ -0,0 +1,25 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @oncall react_native
*/
import type {CacheStore} from './types';
/**
* Main cache class. Receives an array of cache instances, and sequentially
* traverses them to return a previously stored value. It also ensures setting
* the value in all instances.
*
* All get/set operations are logged via Metro's logger.
*/
declare class Cache<T> {
constructor(stores: ReadonlyArray<CacheStore<T>>);
get(key: Buffer): Promise<null | undefined | T>;
set(key: Buffer, value: T): Promise<void>;
get isDisabled(): boolean;
}
export default Cache;

105
node_modules/metro-cache/src/Cache.js generated vendored Normal file
View File

@@ -0,0 +1,105 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.default = void 0;
var _metroCore = require("metro-core");
class Cache {
#stores;
#hits = new WeakMap();
constructor(stores) {
this.#stores = stores;
}
async get(key) {
const stores = this.#stores;
const length = stores.length;
for (let i = 0; i < length; i++) {
const store = stores[i];
const storeName = store.name ?? store.constructor.name;
const name = storeName + "::" + key.toString("hex");
let value = null;
const logStart = _metroCore.Logger.log(
_metroCore.Logger.createActionStartEntry({
action_name: "Cache get",
log_entry_label: name,
}),
);
try {
const valueOrPromise = store.get(key);
if (valueOrPromise && typeof valueOrPromise.then === "function") {
value = await valueOrPromise;
} else {
value = valueOrPromise;
}
} finally {
const hitOrMiss = value != null ? "hit" : "miss";
_metroCore.Logger.log({
..._metroCore.Logger.createActionEndEntry(logStart),
action_result: hitOrMiss,
});
_metroCore.Logger.log(
_metroCore.Logger.createEntry({
action_name: "Cache " + hitOrMiss,
log_entry_label: name,
}),
);
if (value != null) {
this.#hits.set(key, store);
return value;
}
}
}
return null;
}
async set(key, value) {
const stores = this.#stores;
const stop = this.#hits.get(key);
const length = stores.length;
const promises = [];
const writeErrors = [];
const storesWithErrors = new Set();
for (let i = 0; i < length && stores[i] !== stop; i++) {
const store = stores[i];
const storeName = store.name ?? store.constructor.name;
const name = storeName + "::" + key.toString("hex");
const logStart = _metroCore.Logger.log(
_metroCore.Logger.createActionStartEntry({
action_name: "Cache set",
log_entry_label: name,
}),
);
promises.push(
(async () => {
try {
await stores[i].set(key, value);
_metroCore.Logger.log(
_metroCore.Logger.createActionEndEntry(logStart),
);
} catch (e) {
_metroCore.Logger.log(
_metroCore.Logger.createActionEndEntry(logStart, e),
);
storesWithErrors.add(storeName);
writeErrors.push(
new Error(`Cache write failed for ${name}`, {
cause: e,
}),
);
}
})(),
);
}
await Promise.allSettled(promises);
if (writeErrors.length > 0) {
throw new AggregateError(
writeErrors,
`Cache write failed for store(s): ${Array.from(storesWithErrors).join(", ")}`,
);
}
}
get isDisabled() {
return this.#stores.length === 0;
}
}
exports.default = Cache;

136
node_modules/metro-cache/src/Cache.js.flow generated vendored Normal file
View File

@@ -0,0 +1,136 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @format
* @oncall react_native
*/
import type {CacheStore} from './types';
import {Logger} from 'metro-core';
/**
* Main cache class. Receives an array of cache instances, and sequentially
* traverses them to return a previously stored value. It also ensures setting
* the value in all instances.
*
* All get/set operations are logged via Metro's logger.
*/
export default class Cache<T> {
+#stores: $ReadOnlyArray<CacheStore<T>>;
+#hits: WeakMap<Buffer, CacheStore<T>> = new WeakMap();
constructor(stores: $ReadOnlyArray<CacheStore<T>>) {
this.#stores = stores;
}
async get(key: Buffer): Promise<?T> {
const stores = this.#stores;
const length = stores.length;
for (let i = 0; i < length; i++) {
const store = stores[i];
const storeName = store.name ?? store.constructor.name;
const name = storeName + '::' + key.toString('hex');
let value = null;
const logStart = Logger.log(
Logger.createActionStartEntry({
action_name: 'Cache get',
log_entry_label: name,
}),
);
try {
const valueOrPromise = store.get(key);
// $FlowFixMe[method-unbinding] added when improving typing for this parameters
if (valueOrPromise && typeof valueOrPromise.then === 'function') {
value = await valueOrPromise;
} else {
value = valueOrPromise;
}
} finally {
const hitOrMiss = value != null ? 'hit' : 'miss';
Logger.log({
...Logger.createActionEndEntry(logStart),
action_result: hitOrMiss,
});
// Deprecated - will be removed () - use 'Cache get' and action_result
// (above) instead.
// TODO: T196506422
Logger.log(
Logger.createEntry({
action_name: 'Cache ' + hitOrMiss,
log_entry_label: name,
}),
);
if (value != null) {
this.#hits.set(key, store);
return value;
}
}
}
return null;
}
async set(key: Buffer, value: T): Promise<void> {
const stores = this.#stores;
const stop = this.#hits.get(key);
const length = stores.length;
const promises = [];
const writeErrors = [];
const storesWithErrors = new Set<string>();
for (let i = 0; i < length && stores[i] !== stop; i++) {
const store = stores[i];
const storeName = store.name ?? store.constructor.name;
const name = storeName + '::' + key.toString('hex');
const logStart = Logger.log(
Logger.createActionStartEntry({
action_name: 'Cache set',
log_entry_label: name,
}),
);
promises.push(
(async () => {
try {
await stores[i].set(key, value);
Logger.log(Logger.createActionEndEntry(logStart));
} catch (e) {
Logger.log(Logger.createActionEndEntry(logStart, e));
storesWithErrors.add(storeName);
writeErrors.push(
new Error(`Cache write failed for ${name}`, {cause: e}),
);
}
})(),
);
}
await Promise.allSettled(promises);
if (writeErrors.length > 0) {
throw new AggregateError(
writeErrors,
`Cache write failed for store(s): ${Array.from(storesWithErrors).join(', ')}`,
);
}
}
// Returns true if the current configuration disables the cache, such that
// writing to the cache is a no-op and reading from the cache will always
// return null.
get isDisabled(): boolean {
return this.#stores.length === 0;
}
}

46
node_modules/metro-cache/src/index.d.ts generated vendored Normal file
View File

@@ -0,0 +1,46 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @oncall react_native
*/
import Cache from './Cache';
import stableHash from './stableHash';
import AutoCleanFileStore from './stores/AutoCleanFileStore';
import FileStore from './stores/FileStore';
import HttpGetStore from './stores/HttpGetStore';
import HttpStore from './stores/HttpStore';
export type {Options as FileOptions} from './stores/FileStore';
export type {Options as HttpOptions} from './stores/HttpStore';
export type {CacheStore} from './types';
export {
AutoCleanFileStore,
Cache,
FileStore,
HttpGetStore,
HttpStore,
stableHash,
};
export interface MetroCache {
readonly AutoCleanFileStore: typeof AutoCleanFileStore;
readonly Cache: typeof Cache;
readonly FileStore: typeof FileStore;
readonly HttpGetStore: typeof HttpGetStore;
readonly HttpStore: typeof HttpStore;
readonly stableHash: typeof stableHash;
}
/**
* Backwards-compatibility with CommonJS consumers using interopRequireDefault.
* Do not add to this list.
*
* @deprecated Default import from 'metro-cache' is deprecated, use named exports.
*/
declare const $$EXPORT_DEFAULT_DECLARATION$$: MetroCache;
declare type $$EXPORT_DEFAULT_DECLARATION$$ =
typeof $$EXPORT_DEFAULT_DECLARATION$$;
export default $$EXPORT_DEFAULT_DECLARATION$$;

61
node_modules/metro-cache/src/index.js generated vendored Normal file
View File

@@ -0,0 +1,61 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
Object.defineProperty(exports, "AutoCleanFileStore", {
enumerable: true,
get: function () {
return _AutoCleanFileStore.default;
},
});
Object.defineProperty(exports, "Cache", {
enumerable: true,
get: function () {
return _Cache.default;
},
});
Object.defineProperty(exports, "FileStore", {
enumerable: true,
get: function () {
return _FileStore.default;
},
});
Object.defineProperty(exports, "HttpGetStore", {
enumerable: true,
get: function () {
return _HttpGetStore.default;
},
});
Object.defineProperty(exports, "HttpStore", {
enumerable: true,
get: function () {
return _HttpStore.default;
},
});
exports.default = void 0;
Object.defineProperty(exports, "stableHash", {
enumerable: true,
get: function () {
return _stableHash.default;
},
});
var _Cache = _interopRequireDefault(require("./Cache"));
var _stableHash = _interopRequireDefault(require("./stableHash"));
var _AutoCleanFileStore = _interopRequireDefault(
require("./stores/AutoCleanFileStore"),
);
var _FileStore = _interopRequireDefault(require("./stores/FileStore"));
var _HttpGetStore = _interopRequireDefault(require("./stores/HttpGetStore"));
var _HttpStore = _interopRequireDefault(require("./stores/HttpStore"));
function _interopRequireDefault(e) {
return e && e.__esModule ? e : { default: e };
}
var _default = (exports.default = {
AutoCleanFileStore: _AutoCleanFileStore.default,
Cache: _Cache.default,
FileStore: _FileStore.default,
HttpGetStore: _HttpGetStore.default,
HttpStore: _HttpStore.default,
stableHash: _stableHash.default,
});

54
node_modules/metro-cache/src/index.js.flow generated vendored Normal file
View File

@@ -0,0 +1,54 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
* @oncall react_native
*/
import Cache from './Cache';
import stableHash from './stableHash';
import AutoCleanFileStore from './stores/AutoCleanFileStore';
import FileStore from './stores/FileStore';
import HttpGetStore from './stores/HttpGetStore';
import HttpStore from './stores/HttpStore';
export type {Options as FileOptions} from './stores/FileStore';
export type {Options as HttpOptions} from './stores/HttpStore';
export type {CacheStore} from './types';
export {
AutoCleanFileStore,
Cache,
FileStore,
HttpGetStore,
HttpStore,
stableHash,
};
export interface MetroCache {
+AutoCleanFileStore: typeof AutoCleanFileStore;
+Cache: typeof Cache;
+FileStore: typeof FileStore;
+HttpGetStore: typeof HttpGetStore;
+HttpStore: typeof HttpStore;
+stableHash: typeof stableHash;
}
/**
* Backwards-compatibility with CommonJS consumers using interopRequireDefault.
* Do not add to this list.
*
* @deprecated Default import from 'metro-cache' is deprecated, use named exports.
*/
export default {
AutoCleanFileStore,
Cache,
FileStore,
HttpGetStore,
HttpStore,
stableHash,
} as MetroCache;

12
node_modules/metro-cache/src/stableHash.d.ts generated vendored Normal file
View File

@@ -0,0 +1,12 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @oncall react_native
*/
declare function stableHash(value: unknown): Buffer;
export default stableHash;

19
node_modules/metro-cache/src/stableHash.js generated vendored Normal file
View File

@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.default = stableHash;
var _crypto = _interopRequireDefault(require("crypto"));
var _canonicalize = _interopRequireDefault(
require("metro-core/private/canonicalize"),
);
function _interopRequireDefault(e) {
return e && e.__esModule ? e : { default: e };
}
function stableHash(value) {
return _crypto.default
.createHash("md5")
.update(JSON.stringify(value, _canonicalize.default))
.digest("buffer");
}

25
node_modules/metro-cache/src/stableHash.js.flow generated vendored Normal file
View File

@@ -0,0 +1,25 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
* @oncall react_native
*/
import crypto from 'crypto';
import canonicalize from 'metro-core/private/canonicalize';
export default function stableHash(value: mixed): Buffer {
return (
crypto
.createHash('md5')
/* $FlowFixMe[incompatible-type](>=0.95.0 site=react_native_fb) This comment suppresses an
* error found when Flow v0.95 was deployed. To see the error, delete this
* comment and run Flow. */
.update(JSON.stringify(value, canonicalize))
.digest('buffer')
);
}

View File

@@ -0,0 +1,32 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @oncall react_native
*/
import type {Options} from './FileStore';
import FileStore from './FileStore';
type CleanOptions = Readonly<
Omit<Options, keyof {intervalMs?: number; cleanupThresholdMs?: number}> & {
intervalMs?: number;
cleanupThresholdMs?: number;
}
>;
/**
* A FileStore that, at a given interval, stats the content of the cache root
* and deletes any file last modified a set threshold in the past.
*
* @deprecated This is not efficiently implemented and may cause significant
* redundant I/O when caches are large. Prefer your own cleanup scripts, or a
* custom Metro cache that uses watches, hooks get/set, and/or implements LRU.
*/
declare class AutoCleanFileStore<T> extends FileStore<T> {
constructor(opts: CleanOptions);
}
export default AutoCleanFileStore;

View File

@@ -0,0 +1,63 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.default = void 0;
var _FileStore = _interopRequireDefault(require("./FileStore"));
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
function _interopRequireDefault(e) {
return e && e.__esModule ? e : { default: e };
}
class AutoCleanFileStore extends _FileStore.default {
#intervalMs;
#cleanupThresholdMs;
#root;
constructor(opts) {
super({
root: opts.root,
});
this.#root = opts.root;
this.#intervalMs = opts.intervalMs ?? 10 * 60 * 1000;
this.#cleanupThresholdMs =
opts.cleanupThresholdMs ?? 3 * 24 * 60 * 60 * 1000;
this.#scheduleCleanup();
}
#scheduleCleanup() {
setTimeout(() => this.#doCleanup(), this.#intervalMs);
}
#doCleanup() {
const dirents = _fs.default.readdirSync(this.#root, {
recursive: true,
withFileTypes: true,
});
let warned = false;
const minModifiedTime = Date.now() - this.#cleanupThresholdMs;
dirents
.filter((dirent) => dirent.isFile())
.forEach((dirent) => {
const absolutePath = _path.default.join(
dirent.parentPath,
dirent.name.toString(),
);
try {
if (_fs.default.statSync(absolutePath).mtimeMs < minModifiedTime) {
_fs.default.unlinkSync(absolutePath);
}
} catch (e) {
if (!warned) {
console.warn(
"Problem cleaning up cache for " +
absolutePath +
": " +
e.message,
);
warned = true;
}
}
});
this.#scheduleCleanup();
}
}
exports.default = AutoCleanFileStore;

View File

@@ -0,0 +1,86 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
* @oncall react_native
*/
import type {Options} from './FileStore';
import FileStore from './FileStore';
import fs from 'fs';
import path from 'path';
type CleanOptions = $ReadOnly<{
...Options,
intervalMs?: number,
cleanupThresholdMs?: number,
}>;
/**
* A FileStore that, at a given interval, stats the content of the cache root
* and deletes any file last modified a set threshold in the past.
*
* @deprecated This is not efficiently implemented and may cause significant
* redundant I/O when caches are large. Prefer your own cleanup scripts, or a
* custom Metro cache that uses watches, hooks get/set, and/or implements LRU.
*/
export default class AutoCleanFileStore<T> extends FileStore<T> {
+#intervalMs: number;
+#cleanupThresholdMs: number;
+#root: string;
constructor(opts: CleanOptions) {
super({root: opts.root});
this.#root = opts.root;
this.#intervalMs = opts.intervalMs ?? 10 * 60 * 1000; // 10 minutes
this.#cleanupThresholdMs =
opts.cleanupThresholdMs ?? 3 * 24 * 60 * 60 * 1000; // 3 days
this.#scheduleCleanup();
}
#scheduleCleanup() {
setTimeout(() => this.#doCleanup(), this.#intervalMs);
}
#doCleanup() {
const dirents = fs.readdirSync(this.#root, {
recursive: true,
withFileTypes: true,
});
let warned = false;
const minModifiedTime = Date.now() - this.#cleanupThresholdMs;
dirents
.filter(dirent => dirent.isFile())
.forEach(dirent => {
const absolutePath = path.join(
// $FlowFixMe[prop-missing] - dirent.parentPath added in Node 20.12
dirent.parentPath,
dirent.name.toString(),
);
try {
if (fs.statSync(absolutePath).mtimeMs < minModifiedTime) {
fs.unlinkSync(absolutePath);
}
} catch (e) {
if (!warned) {
console.warn(
'Problem cleaning up cache for ' +
absolutePath +
': ' +
e.message,
);
warned = true;
}
}
});
this.#scheduleCleanup();
}
}

18
node_modules/metro-cache/src/stores/FileStore.d.ts generated vendored Normal file
View File

@@ -0,0 +1,18 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @oncall react_native
*/
export type Options = Readonly<{root: string}>;
declare class FileStore<T> {
constructor(options: Options);
get(key: Buffer): Promise<null | undefined | T>;
set(key: Buffer, value: T): Promise<void>;
clear(): void;
}
export default FileStore;

79
node_modules/metro-cache/src/stores/FileStore.js generated vendored Normal file
View File

@@ -0,0 +1,79 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.default = void 0;
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
function _interopRequireDefault(e) {
return e && e.__esModule ? e : { default: e };
}
const NULL_BYTE = 0x00;
const NULL_BYTE_BUFFER = Buffer.from([NULL_BYTE]);
class FileStore {
#root;
constructor(options) {
this.#root = options.root;
}
async get(key) {
try {
const data = await _fs.default.promises.readFile(this.#getFilePath(key));
if (data[0] === NULL_BYTE) {
return data.slice(1);
}
return JSON.parse(data.toString("utf8"));
} catch (err) {
if (err.code === "ENOENT" || err instanceof SyntaxError) {
return null;
}
throw err;
}
}
async set(key, value) {
const filePath = this.#getFilePath(key);
try {
await this.#set(filePath, value);
} catch (err) {
if (err.code === "ENOENT") {
_fs.default.mkdirSync(_path.default.dirname(filePath), {
recursive: true,
});
await this.#set(filePath, value);
} else {
throw err;
}
}
}
async #set(filePath, value) {
let content;
if (value instanceof Buffer) {
content = Buffer.concat([NULL_BYTE_BUFFER, value]);
} else {
content = JSON.stringify(value) ?? JSON.stringify(null);
}
await _fs.default.promises.writeFile(filePath, content);
}
clear() {
this.#removeDirs();
}
#getFilePath(key) {
return _path.default.join(
this.#root,
key.slice(0, 1).toString("hex"),
key.slice(1).toString("hex"),
);
}
#removeDirs() {
for (let i = 0; i < 256; i++) {
_fs.default.rmSync(
_path.default.join(this.#root, ("0" + i.toString(16)).slice(-2)),
{
force: true,
recursive: true,
},
);
}
}
}
exports.default = FileStore;

91
node_modules/metro-cache/src/stores/FileStore.js.flow generated vendored Normal file
View File

@@ -0,0 +1,91 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @format
* @oncall react_native
*/
import fs from 'fs';
import path from 'path';
const NULL_BYTE = 0x00;
const NULL_BYTE_BUFFER = Buffer.from([NULL_BYTE]);
export type Options = $ReadOnly<{
root: string,
}>;
export default class FileStore<T> {
+#root: string;
constructor(options: Options) {
this.#root = options.root;
}
async get(key: Buffer): Promise<?T> {
try {
const data = await fs.promises.readFile(this.#getFilePath(key));
if (data[0] === NULL_BYTE) {
return (data.slice(1): any);
}
return JSON.parse(data.toString('utf8'));
} catch (err) {
if (err.code === 'ENOENT' || err instanceof SyntaxError) {
return null;
}
throw err;
}
}
async set(key: Buffer, value: T): Promise<void> {
const filePath = this.#getFilePath(key);
try {
await this.#set(filePath, value);
} catch (err) {
if (err.code === 'ENOENT') {
fs.mkdirSync(path.dirname(filePath), {recursive: true});
await this.#set(filePath, value);
} else {
throw err;
}
}
}
async #set(filePath: string, value: T): Promise<void> {
let content;
if (value instanceof Buffer) {
content = Buffer.concat([NULL_BYTE_BUFFER, value]);
} else {
content = JSON.stringify(value) ?? JSON.stringify(null);
}
await fs.promises.writeFile(filePath, content);
}
clear() {
this.#removeDirs();
}
#getFilePath(key: Buffer): string {
return path.join(
this.#root,
key.slice(0, 1).toString('hex'),
key.slice(1).toString('hex'),
);
}
#removeDirs() {
for (let i = 0; i < 256; i++) {
fs.rmSync(path.join(this.#root, ('0' + i.toString(16)).slice(-2)), {
force: true,
recursive: true,
});
}
}
}

14
node_modules/metro-cache/src/stores/HttpError.d.ts generated vendored Normal file
View File

@@ -0,0 +1,14 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
declare class HttpError extends Error {
code: number;
constructor(message: string, code: number);
}
export default HttpError;

13
node_modules/metro-cache/src/stores/HttpError.js generated vendored Normal file
View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.default = void 0;
class HttpError extends Error {
constructor(message, code) {
super(message);
this.code = code;
}
}
exports.default = HttpError;

19
node_modules/metro-cache/src/stores/HttpError.js.flow generated vendored Normal file
View File

@@ -0,0 +1,19 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
export default class HttpError extends Error {
code: number;
constructor(message: string, code: number) {
super(message);
this.code = code;
}
}

20
node_modules/metro-cache/src/stores/HttpGetStore.d.ts generated vendored Normal file
View File

@@ -0,0 +1,20 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @oncall react_native
*/
import type {Options as HttpOptions} from './HttpStore';
import HttpStore from './HttpStore';
declare class HttpGetStore<T> extends HttpStore<T> {
constructor(options: HttpOptions);
get(key: Buffer): Promise<null | undefined | T>;
set(_key: Buffer, _value: T): Promise<void>;
}
export default HttpGetStore;

51
node_modules/metro-cache/src/stores/HttpGetStore.js generated vendored Normal file
View File

@@ -0,0 +1,51 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.default = void 0;
var _HttpStore = _interopRequireDefault(require("./HttpStore"));
var _metroCore = require("metro-core");
function _interopRequireDefault(e) {
return e && e.__esModule ? e : { default: e };
}
class HttpGetStore extends _HttpStore.default {
#warned;
constructor(options) {
super(options);
this.#warned = false;
}
async get(key) {
try {
return await super.get(key);
} catch (err) {
if (
!(err instanceof _HttpStore.default.HttpError) &&
!(err instanceof _HttpStore.default.NetworkError)
) {
throw err;
}
this.#warn(err);
return null;
}
}
async set(_key, _value) {}
#warn(err) {
if (!this.#warned) {
process.emitWarning(
[
"Could not connect to the HTTP cache.",
"Original error: " + err.message,
].join(" "),
);
_metroCore.Logger.log(
_metroCore.Logger.createEntry({
action_name: "HttpGetStore:Warning",
log_entry_label: `${err.message} (${err.code})`,
}),
);
this.#warned = true;
}
}
}
exports.default = HttpGetStore;

View File

@@ -0,0 +1,65 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
* @oncall react_native
*/
import type HttpError from './HttpError';
import type {Options as HttpOptions} from './HttpStore';
import type NetworkError from './NetworkError';
import HttpStore from './HttpStore';
import {Logger} from 'metro-core';
export default class HttpGetStore<T> extends HttpStore<T> {
#warned: boolean;
constructor(options: HttpOptions) {
super(options);
this.#warned = false;
}
async get(key: Buffer): Promise<?T> {
try {
return await super.get(key);
} catch (err) {
if (
!(err instanceof HttpStore.HttpError) &&
!(err instanceof HttpStore.NetworkError)
) {
throw err;
}
this.#warn(err);
return null;
}
}
async set(_key: Buffer, _value: T): Promise<void> {}
#warn(err: HttpError | NetworkError) {
if (!this.#warned) {
process.emitWarning(
[
'Could not connect to the HTTP cache.',
'Original error: ' + err.message,
].join(' '),
);
Logger.log(
Logger.createEntry({
action_name: 'HttpGetStore:Warning',
log_entry_label: `${err.message} (${err.code})`,
}),
);
this.#warned = true;
}
}
}

48
node_modules/metro-cache/src/stores/HttpStore.d.ts generated vendored Normal file
View File

@@ -0,0 +1,48 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @oncall react_native
*/
import HttpError from './HttpError';
import NetworkError from './NetworkError';
export type Options =
| EndpointOptions
| {getOptions: EndpointOptions; setOptions: EndpointOptions};
type EndpointOptions = {
endpoint: string;
family?: 4 | 6;
timeout?: number;
key?: string | ReadonlyArray<string> | Buffer | ReadonlyArray<Buffer>;
cert?: string | ReadonlyArray<string> | Buffer | ReadonlyArray<Buffer>;
ca?: string | ReadonlyArray<string> | Buffer | ReadonlyArray<Buffer>;
params?: URLSearchParams;
headers?: {[$$Key$$: string]: string};
additionalSuccessStatuses?: ReadonlyArray<number>;
/**
* Whether to include additional debug information in error messages.
*/
debug?: boolean;
/**
* Retry configuration
*/
maxAttempts?: number;
retryNetworkErrors?: boolean;
retryStatuses?: ReadonlySet<number>;
socketPath?: string;
proxy?: string;
};
declare class HttpStore<T> {
static HttpError: typeof HttpError;
static NetworkError: typeof NetworkError;
constructor(options: Options);
get(key: Buffer): Promise<null | undefined | T>;
set(key: Buffer, value: T): Promise<void>;
clear(): void;
}
export default HttpStore;

295
node_modules/metro-cache/src/stores/HttpStore.js generated vendored Normal file
View File

@@ -0,0 +1,295 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.default = void 0;
var _HttpError = _interopRequireDefault(require("./HttpError"));
var _NetworkError = _interopRequireDefault(require("./NetworkError"));
var _exponentialBackoff = require("exponential-backoff");
var _http = _interopRequireDefault(require("http"));
var _https = _interopRequireDefault(require("https"));
var _httpsProxyAgent = require("https-proxy-agent");
var _zlib = _interopRequireDefault(require("zlib"));
function _interopRequireDefault(e) {
return e && e.__esModule ? e : { default: e };
}
const ZLIB_OPTIONS = {
level: 9,
};
const NULL_BYTE = 0x00;
const NULL_BYTE_BUFFER = Buffer.from([NULL_BYTE]);
class HttpStore {
static HttpError = _HttpError.default;
static NetworkError = _NetworkError.default;
#getEndpoint;
#setEndpoint;
constructor(options) {
this.#getEndpoint = this.#createEndpointConfig(
options.getOptions != null ? options.getOptions : options,
);
this.#setEndpoint = this.#createEndpointConfig(
options.setOptions != null ? options.setOptions : options,
);
}
#createEndpointConfig(options) {
const agentConfig = {
family: options.family,
keepAlive: true,
keepAliveMsecs: options.timeout || 5000,
maxSockets: 64,
maxFreeSockets: 64,
};
if (options.key != null) {
agentConfig.key = options.key;
}
if (options.cert != null) {
agentConfig.cert = options.cert;
}
if (options.ca != null) {
agentConfig.ca = options.ca;
}
if (options.socketPath != null) {
agentConfig.socketPath = options.socketPath;
}
const uri = new URL(options.endpoint);
const module = uri.protocol === "http:" ? _http.default : _https.default;
const agent =
options.proxy != null
? new _httpsProxyAgent.HttpsProxyAgent(options.proxy, agentConfig)
: new module.Agent(agentConfig);
if (!uri.hostname || !uri.pathname) {
throw new TypeError("Invalid endpoint: " + options.endpoint);
}
return {
agent,
headers: options.headers,
host: uri.hostname,
path: uri.pathname,
port: +uri.port,
params: new URLSearchParams(options.params),
timeout: options.timeout || 5000,
module: uri.protocol === "http:" ? _http.default : _https.default,
additionalSuccessStatuses: new Set(
options.additionalSuccessStatuses ?? [],
),
debug: options.debug ?? false,
maxAttempts: options.maxAttempts ?? 1,
retryStatuses: new Set(options.retryStatuses ?? []),
retryNetworkErrors: options.retryNetworkErrors ?? false,
};
}
get(key) {
return this.#withRetries(() => this.#getOnce(key), this.#getEndpoint);
}
#getOnce(key) {
return new Promise((resolve, reject) => {
let searchParamsString = this.#getEndpoint.params.toString();
if (searchParamsString != "") {
searchParamsString = "?" + searchParamsString;
}
const options = {
agent: this.#getEndpoint.agent,
headers: this.#getEndpoint.headers,
host: this.#getEndpoint.host,
method: "GET",
path: `${this.#getEndpoint.path}/${key.toString("hex")}${searchParamsString}`,
port: this.#getEndpoint.port,
timeout: this.#getEndpoint.timeout,
};
const req = this.#getEndpoint.module.request(options, (res) => {
const code = res.statusCode;
const data = [];
if (code === 404) {
res.resume();
resolve(null);
return;
} else if (
code !== 200 &&
!this.#getEndpoint.additionalSuccessStatuses.has(code)
) {
if (this.#getEndpoint.debug) {
res.on("data", (chunk) => {
data.push(chunk);
});
res.on("error", (err) => {
reject(
new _HttpError.default(
"Encountered network error (" +
err.message +
") while handling HTTP error: " +
code +
" " +
_http.default.STATUS_CODES[code],
code,
),
);
});
res.on("end", () => {
const buffer = Buffer.concat(data);
reject(
new _HttpError.default(
"HTTP error: " +
code +
" " +
_http.default.STATUS_CODES[code] +
"\n\n" +
buffer.toString(),
code,
),
);
});
} else {
res.resume();
reject(
new _HttpError.default(
"HTTP error: " + code + " " + _http.default.STATUS_CODES[code],
code,
),
);
}
return;
}
const gunzipped = res.pipe(_zlib.default.createGunzip());
gunzipped.on("data", (chunk) => {
data.push(chunk);
});
gunzipped.on("error", (err) => {
reject(err);
});
gunzipped.on("end", () => {
try {
const buffer = Buffer.concat(data);
if (buffer.length > 0 && buffer[0] === NULL_BYTE) {
resolve(buffer.slice(1));
} else {
resolve(JSON.parse(buffer.toString("utf8")));
}
} catch (err) {
reject(err);
}
});
res.on("error", (err) => gunzipped.emit("error", err));
});
req.on("error", (err) => {
reject(new _NetworkError.default(err.message, err.code));
});
req.on("timeout", () => {
req.destroy(new Error("Request timed out"));
});
req.end();
});
}
set(key, value) {
return this.#withRetries(
() => this.#setOnce(key, value),
this.#setEndpoint,
);
}
#setOnce(key, value) {
return new Promise((resolve, reject) => {
const gzip = _zlib.default.createGzip(ZLIB_OPTIONS);
let searchParamsString = this.#setEndpoint.params.toString();
if (searchParamsString != "") {
searchParamsString = "?" + searchParamsString;
}
const options = {
agent: this.#setEndpoint.agent,
headers: this.#setEndpoint.headers,
host: this.#setEndpoint.host,
method: "PUT",
path: `${this.#setEndpoint.path}/${key.toString("hex")}${searchParamsString}`,
port: this.#setEndpoint.port,
timeout: this.#setEndpoint.timeout,
};
const req = this.#setEndpoint.module.request(options, (res) => {
const code = res.statusCode;
if (
(code < 200 || code > 299) &&
!this.#setEndpoint.additionalSuccessStatuses.has(code)
) {
if (this.#setEndpoint.debug) {
const data = [];
res.on("data", (chunk) => {
data.push(chunk);
});
res.on("error", (err) => {
reject(
new _HttpError.default(
"Encountered network error (" +
err.message +
") while handling HTTP error: " +
code +
" " +
_http.default.STATUS_CODES[code],
code,
),
);
});
res.on("end", () => {
const buffer = Buffer.concat(data);
reject(
new _HttpError.default(
"HTTP error: " +
code +
" " +
_http.default.STATUS_CODES[code] +
"\n\n" +
buffer.toString(),
code,
),
);
});
} else {
res.resume();
reject(
new _HttpError.default(
"HTTP error: " + code + " " + _http.default.STATUS_CODES[code],
code,
),
);
}
return;
}
res.on("error", (err) => {
reject(err);
});
res.on("end", () => {
resolve();
});
res.resume();
});
req.on("timeout", () => {
req.destroy(new Error("Request timed out"));
});
gzip.pipe(req);
if (value instanceof Buffer) {
gzip.write(NULL_BYTE_BUFFER);
gzip.end(value);
} else {
gzip.end(JSON.stringify(value) || "null");
}
});
}
clear() {}
#withRetries(fn, endpoint) {
if (endpoint.maxAttempts === 1) {
return fn();
}
return (0, _exponentialBackoff.backOff)(fn, {
jitter: "full",
maxDelay: 30000,
numOfAttempts: this.#getEndpoint.maxAttempts || Number.POSITIVE_INFINITY,
retry: (e) => {
if (e instanceof _HttpError.default) {
return this.#getEndpoint.retryStatuses.has(e.code);
}
return (
e instanceof _NetworkError.default &&
this.#getEndpoint.retryNetworkErrors
);
},
});
}
}
exports.default = HttpStore;

410
node_modules/metro-cache/src/stores/HttpStore.js.flow generated vendored Normal file
View File

@@ -0,0 +1,410 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow
* @format
* @oncall react_native
*/
import type {HttpsProxyAgentOptions} from 'https-proxy-agent';
import HttpError from './HttpError';
import NetworkError from './NetworkError';
import {backOff} from 'exponential-backoff';
import http from 'http';
import https from 'https';
import {HttpsProxyAgent} from 'https-proxy-agent';
import zlib from 'zlib';
export type Options =
| EndpointOptions // Uses the same options for both reads and writes
| {getOptions: EndpointOptions, setOptions: EndpointOptions}; // Uses different options for reads and writes
type EndpointOptions = {
endpoint: string,
family?: 4 | 6,
timeout?: number,
key?: string | $ReadOnlyArray<string> | Buffer | $ReadOnlyArray<Buffer>,
cert?: string | $ReadOnlyArray<string> | Buffer | $ReadOnlyArray<Buffer>,
ca?: string | $ReadOnlyArray<string> | Buffer | $ReadOnlyArray<Buffer>,
params?: URLSearchParams,
headers?: {[string]: string},
additionalSuccessStatuses?: $ReadOnlyArray<number>,
/**
* Whether to include additional debug information in error messages.
*/
debug?: boolean,
/**
* Retry configuration
*/
maxAttempts?: number,
retryNetworkErrors?: boolean,
retryStatuses?: $ReadOnlySet<number>,
socketPath?: string,
proxy?: string,
};
type Endpoint = {
module: typeof http | typeof https,
host: string,
path: string,
port: number,
agent: http$Agent<tls$TLSSocket> | http$Agent<net$Socket>,
params: URLSearchParams,
headers?: {[string]: string},
timeout: number,
additionalSuccessStatuses: $ReadOnlySet<number>,
debug: boolean,
/**
* Retry configuration
*/
maxAttempts: number,
retryNetworkErrors: boolean,
retryStatuses: $ReadOnlySet<number>,
};
const ZLIB_OPTIONS: zlib$options = {
level: 9,
};
const NULL_BYTE = 0x00;
const NULL_BYTE_BUFFER = Buffer.from([NULL_BYTE]);
export default class HttpStore<T> {
static HttpError: typeof HttpError = HttpError;
static NetworkError: typeof NetworkError = NetworkError;
#getEndpoint: Endpoint;
#setEndpoint: Endpoint;
constructor(options: Options) {
this.#getEndpoint = this.#createEndpointConfig(
options.getOptions != null ? options.getOptions : options,
);
this.#setEndpoint = this.#createEndpointConfig(
options.setOptions != null ? options.setOptions : options,
);
}
#createEndpointConfig(options: EndpointOptions): Endpoint {
const agentConfig: http$agentOptions & HttpsProxyAgentOptions = {
family: options.family,
keepAlive: true,
keepAliveMsecs: options.timeout || 5000,
maxSockets: 64,
maxFreeSockets: 64,
};
if (options.key != null) {
// $FlowFixMe[incompatible-use] `key` is missing in the Flow definition
agentConfig.key = options.key;
}
if (options.cert != null) {
// $FlowFixMe[incompatible-use] `cert` is missing in the Flow definition
agentConfig.cert = options.cert;
}
if (options.ca != null) {
// $FlowFixMe[incompatible-use] `ca` is missing in the Flow definition
agentConfig.ca = options.ca;
}
if (options.socketPath != null) {
// $FlowFixMe[incompatible-use] `socketPath` is missing in the Flow definition
agentConfig.socketPath = options.socketPath;
}
const uri = new URL(options.endpoint);
const module = uri.protocol === 'http:' ? http : https;
const agent =
options.proxy != null
? new HttpsProxyAgent(options.proxy, agentConfig)
: new module.Agent(agentConfig);
if (!uri.hostname || !uri.pathname) {
throw new TypeError('Invalid endpoint: ' + options.endpoint);
}
return {
agent,
headers: options.headers,
host: uri.hostname,
path: uri.pathname,
port: +uri.port,
params: new URLSearchParams(options.params),
timeout: options.timeout || 5000,
module: uri.protocol === 'http:' ? http : https,
additionalSuccessStatuses: new Set(
options.additionalSuccessStatuses ?? [],
),
debug: options.debug ?? false,
maxAttempts: options.maxAttempts ?? 1,
retryStatuses: new Set(options.retryStatuses ?? []),
retryNetworkErrors: options.retryNetworkErrors ?? false,
};
}
get(key: Buffer): Promise<?T> {
return this.#withRetries(() => this.#getOnce(key), this.#getEndpoint);
}
#getOnce(key: Buffer): Promise<?T> {
return new Promise((resolve, reject) => {
let searchParamsString = this.#getEndpoint.params.toString();
if (searchParamsString != '') {
searchParamsString = '?' + searchParamsString;
}
const options = {
agent: this.#getEndpoint.agent,
headers: this.#getEndpoint.headers,
host: this.#getEndpoint.host,
method: 'GET',
path: `${this.#getEndpoint.path}/${key.toString(
'hex',
)}${searchParamsString}`,
port: this.#getEndpoint.port,
timeout: this.#getEndpoint.timeout,
};
// $FlowFixMe[incompatible-type]
/* $FlowFixMe[missing-local-annot](>=0.101.0 site=react_native_fb) This comment suppresses an
* error found when Flow v0.101 was deployed. To see the error, delete
* this comment and run Flow. */
const req = this.#getEndpoint.module.request(options, res => {
const code = res.statusCode;
const data = [];
if (code === 404) {
res.resume();
resolve(null);
return;
} else if (
code !== 200 &&
!this.#getEndpoint.additionalSuccessStatuses.has(code)
) {
if (this.#getEndpoint.debug) {
res.on('data', chunk => {
data.push(chunk);
});
res.on('error', err => {
reject(
new HttpError(
'Encountered network error (' +
err.message +
') while handling HTTP error: ' +
code +
' ' +
http.STATUS_CODES[code],
code,
),
);
});
res.on('end', () => {
const buffer = Buffer.concat(data);
reject(
new HttpError(
'HTTP error: ' +
code +
' ' +
http.STATUS_CODES[code] +
'\n\n' +
buffer.toString(),
code,
),
);
});
} else {
res.resume();
reject(
new HttpError(
'HTTP error: ' + code + ' ' + http.STATUS_CODES[code],
code,
),
);
}
return;
}
const gunzipped = res.pipe(zlib.createGunzip());
gunzipped.on('data', chunk => {
data.push(chunk);
});
gunzipped.on('error', err => {
reject(err);
});
gunzipped.on('end', () => {
try {
const buffer = Buffer.concat(data);
if (buffer.length > 0 && buffer[0] === NULL_BYTE) {
resolve((buffer.slice(1): any));
} else {
resolve(JSON.parse(buffer.toString('utf8')));
}
} catch (err) {
reject(err);
}
});
res.on('error', err => gunzipped.emit('error', err));
});
req.on('error', err => {
reject(new NetworkError(err.message, err.code));
});
req.on('timeout', () => {
req.destroy(new Error('Request timed out'));
});
req.end();
});
}
set(key: Buffer, value: T): Promise<void> {
return this.#withRetries(
() => this.#setOnce(key, value),
this.#setEndpoint,
);
}
#setOnce(key: Buffer, value: T): Promise<void> {
return new Promise((resolve, reject) => {
const gzip = zlib.createGzip(ZLIB_OPTIONS);
let searchParamsString = this.#setEndpoint.params.toString();
if (searchParamsString != '') {
searchParamsString = '?' + searchParamsString;
}
const options = {
agent: this.#setEndpoint.agent,
headers: this.#setEndpoint.headers,
host: this.#setEndpoint.host,
method: 'PUT',
path: `${this.#setEndpoint.path}/${key.toString(
'hex',
)}${searchParamsString}`,
port: this.#setEndpoint.port,
timeout: this.#setEndpoint.timeout,
};
// $FlowFixMe[incompatible-type]
/* $FlowFixMe[missing-local-annot](>=0.101.0 site=react_native_fb) This comment suppresses an
* error found when Flow v0.101 was deployed. To see the error, delete
* this comment and run Flow. */
const req = this.#setEndpoint.module.request(options, res => {
const code = res.statusCode;
if (
(code < 200 || code > 299) &&
!this.#setEndpoint.additionalSuccessStatuses.has(code)
) {
if (this.#setEndpoint.debug) {
const data = [];
res.on('data', chunk => {
data.push(chunk);
});
res.on('error', err => {
reject(
new HttpError(
'Encountered network error (' +
err.message +
') while handling HTTP error: ' +
code +
' ' +
http.STATUS_CODES[code],
code,
),
);
});
res.on('end', () => {
const buffer = Buffer.concat(data);
reject(
new HttpError(
'HTTP error: ' +
code +
' ' +
http.STATUS_CODES[code] +
'\n\n' +
buffer.toString(),
code,
),
);
});
} else {
res.resume();
reject(
new HttpError(
'HTTP error: ' + code + ' ' + http.STATUS_CODES[code],
code,
),
);
}
return;
}
res.on('error', err => {
reject(err);
});
res.on('end', () => {
resolve();
});
// Consume all the data from the response without processing it.
res.resume();
});
req.on('timeout', () => {
req.destroy(new Error('Request timed out'));
});
gzip.pipe(req);
if (value instanceof Buffer) {
gzip.write(NULL_BYTE_BUFFER);
gzip.end(value);
} else {
gzip.end(JSON.stringify(value) || 'null');
}
});
}
clear() {
// Not implemented.
}
#withRetries<R>(fn: () => Promise<R>, endpoint: Endpoint): Promise<R> {
if (endpoint.maxAttempts === 1) {
return fn();
}
return backOff(fn, {
jitter: 'full',
maxDelay: 30000,
numOfAttempts: this.#getEndpoint.maxAttempts || Number.POSITIVE_INFINITY,
retry: (e: Error) => {
if (e instanceof HttpError) {
return this.#getEndpoint.retryStatuses.has(e.code);
}
return (
e instanceof NetworkError && this.#getEndpoint.retryNetworkErrors
);
},
});
}
}

14
node_modules/metro-cache/src/stores/NetworkError.d.ts generated vendored Normal file
View File

@@ -0,0 +1,14 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
declare class NetworkError extends Error {
code: string;
constructor(message: string, code: string);
}
export default NetworkError;

13
node_modules/metro-cache/src/stores/NetworkError.js generated vendored Normal file
View File

@@ -0,0 +1,13 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true,
});
exports.default = void 0;
class NetworkError extends Error {
constructor(message, code) {
super(message);
this.code = code;
}
}
exports.default = NetworkError;

View File

@@ -0,0 +1,19 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
*/
export default class NetworkError extends Error {
code: string;
constructor(message: string, code: string) {
super(message);
this.code = code;
}
}

16
node_modules/metro-cache/src/types.d.ts generated vendored Normal file
View File

@@ -0,0 +1,16 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @oncall react_native
*/
export interface CacheStore<T> {
name?: string;
get(key: Buffer): (null | undefined | T) | Promise<null | undefined | T>;
set(key: Buffer, value: T): void | Promise<void>;
clear(): void | Promise<void>;
}

1
node_modules/metro-cache/src/types.js generated vendored Normal file
View File

@@ -0,0 +1 @@
"use strict";

17
node_modules/metro-cache/src/types.js.flow generated vendored Normal file
View File

@@ -0,0 +1,17 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
* @oncall react_native
*/
export interface CacheStore<T> {
name?: string;
get(key: Buffer): ?T | Promise<?T>;
set(key: Buffer, value: T): void | Promise<void>;
clear(): void | Promise<void>;
}