refactor+chore: metro & misc. (#29)
* Refactored `lib/metro` and added types + cleaned up `tsconfig.json` + minor changes to `build.mjs` and `package.json` * Made requested changes + added eslint rule to restrict top-level await * Exclude `transform-async-to-generator` from `env` (async/await is es7)
This commit is contained in:
parent
fe586035e3
commit
6162dfd08b
10 changed files with 264 additions and 141 deletions
|
|
@ -9,6 +9,10 @@
|
|||
"import-alias"
|
||||
],
|
||||
"rules": {
|
||||
"no-restricted-syntax": [ "error", {
|
||||
"selector": "AwaitExpression:not(:function *)",
|
||||
"message": "Hermes does not support top-level await, and SWC cannot transform it."
|
||||
} ],
|
||||
"quotes": [ "error", "double", { "avoidEscape": true } ],
|
||||
"jsx-quotes": [ "error", "prefer-double" ],
|
||||
"no-mixed-spaces-and-tabs": "error",
|
||||
|
|
@ -72,4 +76,4 @@
|
|||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
25
build.mjs
25
build.mjs
|
|
@ -6,6 +6,7 @@ import { readFile } from "fs/promises";
|
|||
import { createServer } from "http";
|
||||
import { argv } from "process";
|
||||
|
||||
// @ts-ignore
|
||||
const isFlag = (s, l) => argv.slice(2).some(c => c === `-${s}` || c === `--${l}`);
|
||||
|
||||
const isRelease = isFlag("r", "release");
|
||||
|
|
@ -16,7 +17,7 @@ const commitHash = execSync("git rev-parse --short HEAD").toString().trim();
|
|||
|
||||
try {
|
||||
const ctx = await esbuild.context({
|
||||
entryPoints: ["src/entry.js"],
|
||||
entryPoints: ["./src/entry.js"],
|
||||
bundle: true,
|
||||
minify: isRelease,
|
||||
format: "iife",
|
||||
|
|
@ -33,13 +34,6 @@ try {
|
|||
},
|
||||
loader: { ".png": "dataurl" },
|
||||
legalComments: "none",
|
||||
alias: {
|
||||
"@lib/*": "src/lib/*",
|
||||
"@core/*": "src/core/*",
|
||||
"@metro/*": "src/lib/metro/*",
|
||||
"@ui/*": "src/lib/ui/*",
|
||||
"@types": "src/utils/types.ts",
|
||||
},
|
||||
plugins: [
|
||||
{
|
||||
name: "runtimeGlobalAlias",
|
||||
|
|
@ -55,6 +49,7 @@ try {
|
|||
namespace: "glob-" + key, path: args.path
|
||||
}));
|
||||
build.onLoad({ filter, namespace: "glob-" + key }, () => ({
|
||||
// @ts-ignore
|
||||
contents: `Object.defineProperty(module, 'exports', { get: () => ${globalMap[key]} })`,
|
||||
resolveDir: "src",
|
||||
}));
|
||||
|
|
@ -99,16 +94,22 @@ try {
|
|||
}
|
||||
},
|
||||
},
|
||||
// https://github.com/facebook/hermes/blob/3815fec63d1a6667ca3195160d6e12fee6a0d8d5/doc/Features.md
|
||||
// https://github.com/facebook/hermes/issues/696#issuecomment-1396235791
|
||||
env: {
|
||||
targets: "defaults",
|
||||
targets: "fully supports es6",
|
||||
include: [
|
||||
"transform-classes",
|
||||
"transform-arrow-functions",
|
||||
"transform-block-scoping",
|
||||
"transform-class-properties"
|
||||
"transform-classes"
|
||||
],
|
||||
exclude: [
|
||||
"transform-parameters"
|
||||
"transform-async-to-generator",
|
||||
"transform-exponentiation-operator",
|
||||
"transform-named-capturing-groups-regex",
|
||||
"transform-nullish-coalescing-operator",
|
||||
"transform-object-rest-spread",
|
||||
"transform-optional-chaining"
|
||||
]
|
||||
},
|
||||
});
|
||||
|
|
|
|||
18
package.json
18
package.json
|
|
@ -21,16 +21,17 @@
|
|||
"license": "BSD-3-Clause",
|
||||
"devDependencies": {
|
||||
"@react-native-clipboard/clipboard": "1.10.0",
|
||||
"@swc/core": "^1.4.6",
|
||||
"@types/chroma-js": "^2.4.4",
|
||||
"@types/lodash": "^4.14.202",
|
||||
"@swc/core": "^1.4.17",
|
||||
"@swc/helpers": "^0.5.11",
|
||||
"@types/chroma-js": "~2.4.0",
|
||||
"@types/lodash": "~4.17.0",
|
||||
"@types/node": "^20.11.25",
|
||||
"@types/react": "18.2.60",
|
||||
"@types/react-native": "0.72.3",
|
||||
"@types/react": "~18.2.0",
|
||||
"@types/react-native": "~0.72.0",
|
||||
"@typescript-eslint/eslint-plugin": "^7.1.1",
|
||||
"@typescript-eslint/parser": "^7.1.1",
|
||||
"@typescript-eslint/typescript-estree": "^7.1.1",
|
||||
"esbuild": "^0.17.19",
|
||||
"esbuild": "^0.20.2",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-plugin-import-alias": "^1.2.0",
|
||||
"eslint-plugin-react": "^7.34.0",
|
||||
|
|
@ -39,11 +40,10 @@
|
|||
"intl-messageformat": "^10.5.11",
|
||||
"moment": "2.22.2",
|
||||
"type-fest": "^4.12.0",
|
||||
"typescript": "^5.4.2",
|
||||
"typescript": "^5.4.5",
|
||||
"typescript-transform-paths": "^3.4.7"
|
||||
},
|
||||
"dependencies": {
|
||||
"@swc/helpers": "0.5.0",
|
||||
"fuzzysort": "^2.0.4",
|
||||
"spitroast": "^1.4.4"
|
||||
},
|
||||
|
|
@ -55,4 +55,4 @@
|
|||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,81 +1,67 @@
|
|||
import { instead } from "@lib/api/patcher";
|
||||
import type { Metro } from "@metro/types";
|
||||
import { metroRequire, modules } from "@metro/utils";
|
||||
|
||||
export type MetroModules = { [id: string]: any; };
|
||||
export type PropIntellisense<P extends string | symbol> = Record<P, any> & Record<PropertyKey, any>;
|
||||
export type PropsFinder = <T extends string | symbol>(...props: T[]) => PropIntellisense<T>;
|
||||
export type PropsFinderAll = <T extends string | symbol>(...props: T[]) => PropIntellisense<T>[];
|
||||
export type PropIntellisense<P extends PropertyKey> = Record<P, any> & Record<PropertyKey, any>;
|
||||
export type PropsFinder = <T extends PropertyKey>(...props: T[]) => PropIntellisense<T>;
|
||||
export type PropsFinderAll = <T extends PropertyKey>(...props: T[]) => PropIntellisense<T>[];
|
||||
|
||||
interface MetroRequire {
|
||||
(moduleId: string): any;
|
||||
importDefault(moduleId: string): any;
|
||||
importAll(moduleId: string): any;
|
||||
/** Makes the module associated with the specified ID non-enumberable. */
|
||||
function blacklistModule(id: Metro.ModuleID) {
|
||||
Object.defineProperty(modules, id, { enumerable: false });
|
||||
}
|
||||
|
||||
// Metro global vars
|
||||
declare var __r: MetroRequire;
|
||||
declare var modules: MetroModules;
|
||||
|
||||
// Function to blacklist a module, preventing it from being searched again
|
||||
const blacklist = (id: string) => Object.defineProperty(window.modules, id, {
|
||||
value: window.modules[id],
|
||||
enumerable: false,
|
||||
configurable: true,
|
||||
writable: true
|
||||
});
|
||||
|
||||
const functionToString = Function.prototype.toString;
|
||||
|
||||
for (const id in window.modules) {
|
||||
const moduleDefinition = window.modules[id];
|
||||
for (const id in modules) {
|
||||
const metroModule = modules[id];
|
||||
|
||||
if (moduleDefinition.factory) {
|
||||
instead("factory", moduleDefinition, (args, orig) => {
|
||||
if (metroModule!.factory) {
|
||||
instead("factory", metroModule, ((args: Parameters<Metro.FactoryFn>, origFunc: Metro.FactoryFn) => {
|
||||
const { 1: metroRequire, 4: moduleObject } = args;
|
||||
|
||||
args[2 /* metroImportDefault */] = (id: string) => {
|
||||
const exp = metroRequire(id);
|
||||
return exp && exp.__esModule ? exp.default : exp;
|
||||
args[2 /* metroImportDefault */] = id => {
|
||||
const exps = metroRequire(id);
|
||||
return exps && exps.__esModule ? exps.default : exps;
|
||||
};
|
||||
|
||||
args[3 /* metroImportAll */] = (id: string) => {
|
||||
const exp = metroRequire(id);
|
||||
if (exp && exp.__esModule) return exp;
|
||||
args[3 /* metroImportAll */] = id => {
|
||||
const exps = metroRequire(id);
|
||||
if (exps && exps.__esModule) return exps;
|
||||
|
||||
const importAll: Record<string, any> = {};
|
||||
if (exp) Object.assign(importAll, exp);
|
||||
return importAll.default = exp, importAll;
|
||||
if (exps) Object.assign(importAll, exps);
|
||||
importAll.default = exps;
|
||||
return importAll;
|
||||
};
|
||||
|
||||
orig(...args);
|
||||
origFunc(...args);
|
||||
if (moduleObject.exports) onModuleRequire(moduleObject.exports);
|
||||
});
|
||||
}) as any); // If only spitroast had better types
|
||||
}
|
||||
}
|
||||
|
||||
// Blacklist any "bad-actor" modules, e.g. the dreaded null proxy, the window itself, or undefined modules
|
||||
for (const id in window.modules) {
|
||||
const module = requireModule(id);
|
||||
for (const id in modules) {
|
||||
const moduleExports = requireModule(id);
|
||||
|
||||
if (!module || module === window || module["Revenge EOL when?"] === null) {
|
||||
blacklist(id);
|
||||
continue;
|
||||
}
|
||||
if (!moduleExports || moduleExports === window || moduleExports["Revenge EOL when?"] === null)
|
||||
blacklistModule(id);
|
||||
}
|
||||
|
||||
let patchedInspectSource = false;
|
||||
|
||||
function onModuleRequire(exports: any) {
|
||||
function onModuleRequire(moduleExports: any) {
|
||||
// Temporary
|
||||
exports.initSentry &&= () => { };
|
||||
if (exports.default?.track && exports.default.trackMaker) {
|
||||
exports.default.track = () => Promise.resolve();
|
||||
}
|
||||
moduleExports.initSentry &&= () => undefined;
|
||||
if (moduleExports.default?.track && moduleExports.default.trackMaker)
|
||||
moduleExports.default.track = () => Promise.resolve();
|
||||
|
||||
// There are modules registering the same native component
|
||||
if (exports?.default?.name === "requireNativeComponent") {
|
||||
instead("default", exports, (args, orig) => {
|
||||
if (moduleExports?.default?.name === "requireNativeComponent") {
|
||||
instead("default", moduleExports, (args, origFunc) => {
|
||||
try {
|
||||
return orig(...args);
|
||||
return origFunc(...args);
|
||||
} catch {
|
||||
return args[0];
|
||||
}
|
||||
|
|
@ -83,9 +69,9 @@ function onModuleRequire(exports: any) {
|
|||
}
|
||||
|
||||
// Hook DeveloperExperimentStore
|
||||
if (exports?.default?.constructor?.displayName === "DeveloperExperimentStore") {
|
||||
exports.default = new Proxy(exports.default, {
|
||||
get: (target, property, receiver) => {
|
||||
if (moduleExports?.default?.constructor?.displayName === "DeveloperExperimentStore") {
|
||||
moduleExports.default = new Proxy(moduleExports.default, {
|
||||
get(target, property, receiver) {
|
||||
if (property === "isDeveloper") {
|
||||
// Hopefully won't explode accessing it here :3
|
||||
const { settings } = require("@lib/settings");
|
||||
|
|
@ -99,66 +85,90 @@ function onModuleRequire(exports: any) {
|
|||
|
||||
// Funny infinity recursion caused by a race condition
|
||||
if (!patchedInspectSource && window["__core-js_shared__"]) {
|
||||
const inspect = (f: Function) => typeof f === "function" && functionToString.apply(f, []);
|
||||
const inspect = (f: unknown) => typeof f === "function" && functionToString.apply(f, []);
|
||||
window["__core-js_shared__"].inspectSource = inspect;
|
||||
patchedInspectSource = true;
|
||||
}
|
||||
}
|
||||
|
||||
function requireModule(id: string) {
|
||||
if (modules[id].isInitialized) return __r(id);
|
||||
const noopHandler = () => undefined;
|
||||
|
||||
function requireModule(id: Metro.ModuleID) {
|
||||
if (modules[id]!.isInitialized) return metroRequire(id);
|
||||
|
||||
// Disable Internal Metro error reporting logic
|
||||
const originalHandler = window.ErrorUtils.getGlobalHandler();
|
||||
window.ErrorUtils.setGlobalHandler(null);
|
||||
const originalHandler = ErrorUtils.getGlobalHandler();
|
||||
ErrorUtils.setGlobalHandler(noopHandler);
|
||||
|
||||
let moduleExports;
|
||||
try {
|
||||
var exports = __r(id); // metroRequire(id);
|
||||
moduleExports = metroRequire(id);
|
||||
} catch {
|
||||
var exports = undefined;
|
||||
moduleExports = undefined;
|
||||
}
|
||||
|
||||
// Done initializing! Now, revert our hacks
|
||||
window.ErrorUtils.setGlobalHandler(originalHandler);
|
||||
ErrorUtils.setGlobalHandler(originalHandler);
|
||||
|
||||
return exports;
|
||||
return moduleExports;
|
||||
}
|
||||
|
||||
function* getModules() {
|
||||
yield require("./polyfills/redesign");
|
||||
function* getModuleExports() {
|
||||
yield require("@metro/polyfills/redesign");
|
||||
|
||||
for (const id in modules) {
|
||||
yield requireModule(id);
|
||||
}
|
||||
}
|
||||
|
||||
// Function to filter through modules
|
||||
const filterModules = (modules: MetroModules, single = false) => (filter: (m: any) => boolean) => {
|
||||
const found = [];
|
||||
type ExportsFilter = (moduleExports: any) => unknown;
|
||||
|
||||
for (const exports of getModules()) {
|
||||
if (exports.default && exports.__esModule && filter(exports.default)) {
|
||||
if (single) return exports.default;
|
||||
found.push(exports.default);
|
||||
}
|
||||
function testExports(moduleExports: any, filter: ExportsFilter) {
|
||||
if (moduleExports.default && moduleExports.__esModule && filter(moduleExports.default))
|
||||
return moduleExports.default;
|
||||
if (filter(moduleExports))
|
||||
return moduleExports;
|
||||
}
|
||||
|
||||
if (filter(exports)) {
|
||||
if (single) return exports;
|
||||
else found.push(exports);
|
||||
}
|
||||
/**
|
||||
* Returns the exports of the first module where filter returns truthy, and undefined otherwise.
|
||||
* @param filter find calls filter once for each enumerable module's exports until it finds one where filter returns a thruthy value.
|
||||
*/
|
||||
export function find(filter: ExportsFilter) {
|
||||
for (const moduleExports of getModuleExports()) {
|
||||
const testedExports = testExports(moduleExports, filter);
|
||||
if (testedExports !== undefined)
|
||||
return testedExports;
|
||||
}
|
||||
}
|
||||
|
||||
if (!single) return found;
|
||||
};
|
||||
/**
|
||||
* Returns the exports of all modules where filter returns truthy.
|
||||
* @param filter findAll calls filter once for each enumerable module's exports, adding the exports to the returned array when filter returns a thruthy value.
|
||||
*/
|
||||
export function findAll(filter: ExportsFilter) {
|
||||
const foundExports: any[] = [];
|
||||
for (const moduleExports of getModuleExports()) {
|
||||
const testedExports = testExports(moduleExports, filter);
|
||||
if (testedExports !== undefined)
|
||||
foundExports.push(testedExports);
|
||||
}
|
||||
return foundExports;
|
||||
}
|
||||
|
||||
export const find = filterModules(modules, true);
|
||||
export const findAll = filterModules(modules);
|
||||
|
||||
const propsFilter = (props: (string | symbol)[]) => (m: any) => props.every(p => m[p] !== undefined);
|
||||
const nameFilter = (name: string, defaultExp: boolean) => (defaultExp ? (m: any) => m?.name === name : (m: any) => m?.default?.name === name);
|
||||
const dNameFilter = (displayName: string, defaultExp: boolean) => (defaultExp ? (m: any) => m?.displayName === displayName : (m: any) => m?.default?.displayName === displayName);
|
||||
const tNameFilter = (typeName: string, defaultExp: boolean) => (defaultExp ? (m: any) => m?.type?.name === typeName : (m: any) => m?.default?.type?.name === typeName);
|
||||
const storeFilter = (name: string) => (m: any) => m.getName && m.getName.length === 0 && m.getName() === name;
|
||||
const propsFilter = (props: PropertyKey[]) =>
|
||||
(exps: any) => props.every(p => exps[p] !== undefined);
|
||||
const nameFilter = (name: string, defaultExp: boolean) => defaultExp
|
||||
? (exps: any) => exps?.name === name
|
||||
: (exps: any) => exps?.default?.name === name;
|
||||
const dNameFilter = (displayName: string, defaultExp: boolean) => defaultExp
|
||||
? (exps: any) => exps?.displayName === displayName
|
||||
: (exps: any) => exps?.default?.displayName === displayName;
|
||||
const tNameFilter = (typeName: string, defaultExp: boolean) => defaultExp
|
||||
? (exps: any) => exps?.type?.name === typeName
|
||||
: (exps: any) => exps?.default?.type?.name === typeName;
|
||||
const storeFilter = (name: string) =>
|
||||
(exps: any) => exps.getName && exps.getName.length === 0 && exps.getName() === name;
|
||||
|
||||
export const findByProps: PropsFinder = (...props) => find(propsFilter(props));
|
||||
export const findByPropsAll: PropsFinderAll = (...props) => findAll(propsFilter(props));
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
export * as common from "./common";
|
||||
export * from "./utils";
|
||||
export {
|
||||
find,
|
||||
findAll,
|
||||
|
|
@ -10,6 +10,7 @@ export {
|
|||
findByPropsAll,
|
||||
findByStoreName,
|
||||
findByTypeName,
|
||||
findByTypeNameAll,
|
||||
findByTypeNameAll
|
||||
} from "./filters";
|
||||
export * as filters from "./filters";
|
||||
export * as common from "./common";
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import "@metro/index";
|
||||
import { metroRequire, modules } from "@metro";
|
||||
|
||||
import { LiteralUnion } from "type-fest";
|
||||
|
||||
|
|
@ -103,25 +103,23 @@ type Keys = LiteralUnion<typeof redesignProps extends Set<infer U> ? U : string,
|
|||
const redesignPropSource = {} as Record<Keys, any>;
|
||||
const redesignModule = {} as Record<Keys, any>;
|
||||
|
||||
for (const id in window.modules) {
|
||||
const exports = window.__r(id);
|
||||
polyfillRedesignModule(exports);
|
||||
for (const id in modules) {
|
||||
const moduleExports = metroRequire(id);
|
||||
polyfillRedesignModule(moduleExports);
|
||||
}
|
||||
|
||||
function polyfillRedesignModule(exports: any) {
|
||||
function polyfillRedesignModule(moduleExports: any) {
|
||||
const propMap = new Map<string, string | null>();
|
||||
|
||||
for (const prop of redesignProps) {
|
||||
if (exports?.[prop]) {
|
||||
if (moduleExports?.[prop])
|
||||
propMap.set(prop, null);
|
||||
}
|
||||
else if (exports?.default?.[prop]) {
|
||||
else if (moduleExports?.default?.[prop])
|
||||
propMap.set(prop, "default");
|
||||
}
|
||||
}
|
||||
|
||||
for (const [prop, defaultKey] of propMap) {
|
||||
const exportsForProp = defaultKey ? exports[defaultKey] : exports;
|
||||
const exportsForProp = defaultKey ? moduleExports[defaultKey] : moduleExports;
|
||||
|
||||
if (redesignModule[prop]) {
|
||||
if (Object.keys(exportsForProp).length < Object.keys(redesignPropSource[prop]).length) {
|
||||
|
|
|
|||
|
|
@ -1,3 +1,96 @@
|
|||
import type { Nullish } from "@types";
|
||||
|
||||
/** @see {@link https://github.com/facebook/metro/blob/c2d7539dfc10aacb2f99fcc2f268a3b53e867a90/packages/metro-runtime/src/polyfills/require.js} */
|
||||
export namespace Metro {
|
||||
export interface DependencyMap {
|
||||
readonly [indexer: number]: ModuleID;
|
||||
readonly paths?: Readonly<Record<ModuleID, string>> | undefined;
|
||||
}
|
||||
|
||||
export type InverseDependencyMap = Record<ModuleID, ModuleID[]>;
|
||||
|
||||
export type FactoryFn = (
|
||||
global: object,
|
||||
require: RequireFn,
|
||||
metroImportDefault: RequireFn,
|
||||
metroImportAll: RequireFn,
|
||||
moduleObject: {
|
||||
exports: any;
|
||||
},
|
||||
exports: any,
|
||||
dependencyMap: DependencyMap | Nullish,
|
||||
) => void;
|
||||
|
||||
export interface HotModuleReloadingData {
|
||||
_acceptCallback: (() => void) | Nullish;
|
||||
_disposeCallback: (() => void) | Nullish;
|
||||
_didAccept: boolean;
|
||||
accept: (callback?: (() => void) | undefined) => void;
|
||||
dispose: (callback?: (() => void) | undefined) => void;
|
||||
}
|
||||
|
||||
export type ModuleID = string | number;
|
||||
|
||||
export interface Module {
|
||||
id?: ModuleID | undefined;
|
||||
exports: any;
|
||||
hot?: HotModuleReloadingData | undefined;
|
||||
}
|
||||
|
||||
export interface ModuleDefinition {
|
||||
dependencyMap: DependencyMap | Nullish;
|
||||
error?: any;
|
||||
factory: FactoryFn | undefined;
|
||||
hasError: boolean;
|
||||
hot?: HotModuleReloadingData | undefined;
|
||||
importedAll: any;
|
||||
importedDefault: any;
|
||||
isInitialized: boolean;
|
||||
path?: string | undefined;
|
||||
publicModule: Module;
|
||||
verboseName?: string | undefined;
|
||||
}
|
||||
|
||||
export type ModuleList = Record<ModuleID, ModuleDefinition | Nullish>;
|
||||
|
||||
export type RequireFn = (id: ModuleID) => any;
|
||||
|
||||
export type DefineFn = (
|
||||
factory: FactoryFn,
|
||||
moduleId: ModuleID,
|
||||
dependencyMap?: DependencyMap | undefined,
|
||||
verboseName?: string | undefined,
|
||||
inverseDependencies?: InverseDependencyMap | undefined
|
||||
) => void;
|
||||
|
||||
export type ModuleDefiner = (moduleId: ModuleID) => void;
|
||||
|
||||
export type ClearFn = () => ModuleList;
|
||||
|
||||
export type RegisterSegmentFn = (
|
||||
segmentId: number,
|
||||
moduleDefiner: ModuleDefiner,
|
||||
moduleIds: Readonly<ModuleID[]> | Nullish
|
||||
) => void;
|
||||
|
||||
export interface Require extends RequireFn {
|
||||
importDefault: RequireFn;
|
||||
importAll: RequireFn;
|
||||
/** @throws {Error} */
|
||||
context: () => never;
|
||||
/** @throws {Error} */
|
||||
resolveWeak: () => never;
|
||||
unpackModuleId: (moduleId: ModuleID) => {
|
||||
localId: number;
|
||||
segmentId: number;
|
||||
};
|
||||
packModuleId: (value: {
|
||||
localId: number;
|
||||
segmentId: number;
|
||||
}) => ModuleID;
|
||||
}
|
||||
}
|
||||
|
||||
export interface Dispatcher {
|
||||
_actionHandlers: unknown;
|
||||
_interceptors?: ((payload: any) => void | boolean)[];
|
||||
|
|
@ -16,4 +109,3 @@ export interface Dispatcher {
|
|||
unsubscribe(actionType: string, callback: (payload: any) => void): void;
|
||||
wait(cb: () => void): void;
|
||||
}
|
||||
|
||||
|
|
|
|||
11
src/lib/metro/utils.ts
Normal file
11
src/lib/metro/utils.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
import type { Metro } from "@metro/types";
|
||||
|
||||
export const modules: Metro.ModuleList = window.modules;
|
||||
|
||||
export const metroRequire: Metro.Require = window.__r;
|
||||
|
||||
export const define: Metro.DefineFn = window.__d;
|
||||
|
||||
export const clear: Metro.ClearFn = window.__c;
|
||||
|
||||
export const registerSegment: Metro.RegisterSegmentFn = window.__registerSegment;
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
import { LiteralUnion } from "type-fest";
|
||||
|
||||
export type Nullish = null | undefined;
|
||||
|
||||
export type OptionalKeys<T extends Array<string>> = LiteralUnion<T[number], string>;
|
||||
|
||||
export interface Author {
|
||||
|
|
|
|||
|
|
@ -1,31 +1,35 @@
|
|||
{
|
||||
"include": ["src"],
|
||||
"exclude": ["node_modules"],
|
||||
"exclude": ["dist"],
|
||||
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"sourceMap": true,
|
||||
"module": "ESNext",
|
||||
"target": "ESNext",
|
||||
"declaration": true,
|
||||
"emitDeclarationOnly": true,
|
||||
"moduleResolution": "node",
|
||||
"esModuleInterop": true,
|
||||
"jsx": "react",
|
||||
"strict": true,
|
||||
"stripInternal": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
|
||||
"paths": {
|
||||
"@lib/*": ["src/lib/*"],
|
||||
"@core/*": ["src/core/*"],
|
||||
"@metro/*": ["src/lib/metro/*"],
|
||||
"@ui/*": ["src/lib/ui/*"],
|
||||
"@types": ["src/lib/utils/types.ts"],
|
||||
"bunny-build": ["src/modules.d.ts"]
|
||||
"@core/*": ["./src/core/*"],
|
||||
"@lib": ["./src/lib"],
|
||||
"@lib/*": ["./src/lib/*"],
|
||||
"@metro": ["./src/lib/metro"],
|
||||
"@metro/*": ["./src/lib/metro/*"],
|
||||
"@ui": ["./src/lib/ui"],
|
||||
"@ui/*": ["./src/lib/ui/*"],
|
||||
"@types": ["./src/lib/utils/types.ts"],
|
||||
"bunny-build": ["./src/modules.d.ts"]
|
||||
},
|
||||
|
||||
"module": "esnext",
|
||||
"moduleResolution": "bundler",
|
||||
"resolveJsonModule": true,
|
||||
|
||||
"noEmit": true,
|
||||
|
||||
"allowJs": true,
|
||||
"checkJs": true,
|
||||
|
||||
"plugins": [
|
||||
{ "transform": "typescript-transform-paths", "afterDeclarations": true }
|
||||
]
|
||||
],
|
||||
|
||||
"jsx": "react",
|
||||
"target": "esnext"
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue