create-expo-cljs-app
Version:
Create a react native application with Expo and Shadow-CLJS!
135 lines (115 loc) • 4.21 kB
text/typescript
import glob from 'fast-glob';
import fs from 'fs-extra';
import path from 'path';
import { ModuleDescriptor, PackageRevision, SearchOptions } from '../types';
async function findPodspecFile(revision: PackageRevision): Promise<string | undefined> {
if (revision.config?.iosPodspecPath()) {
return revision.config.iosPodspecPath();
}
const [podspecFile] = await glob('*/*.podspec', {
cwd: revision.path,
ignore: ['**/node_modules/**'],
});
return podspecFile;
}
/**
* Resolves module search result with additional details required for iOS platform.
*/
export async function resolveModuleAsync(
packageName: string,
revision: PackageRevision,
options: SearchOptions
): Promise<ModuleDescriptor | null> {
const podspecFile = await findPodspecFile(revision);
if (!podspecFile) {
return null;
}
const podName = path.basename(podspecFile, path.extname(podspecFile));
const podspecDir = path.dirname(path.join(revision.path, podspecFile));
return {
podName,
podspecDir,
flags: options.flags,
modulesClassNames: revision.config?.iosModulesClassNames(),
appDelegateSubscribers: revision.config?.iosAppDelegateSubscribers(),
reactDelegateHandlers: revision.config?.iosReactDelegateHandlers(),
};
}
/**
* Generates Swift file that contains all autolinked Swift packages.
*/
export async function generatePackageListAsync(
modules: ModuleDescriptor[],
targetPath: string
): Promise<void> {
const className = path.basename(targetPath, path.extname(targetPath));
const generatedFileContent = await generatePackageListFileContentAsync(modules, className);
await fs.outputFile(targetPath, generatedFileContent);
}
/**
* Generates the string to put into the generated package list.
*/
async function generatePackageListFileContentAsync(
modules: ModuleDescriptor[],
className: string
): Promise<string> {
const modulesToImport = modules.filter(
(module) =>
module.modulesClassNames.length ||
module.appDelegateSubscribers.length ||
module.reactDelegateHandlers.length
);
const pods = modulesToImport.map((module) => module.podName);
const modulesClassNames = []
.concat(...modulesToImport.map((module) => module.modulesClassNames))
.filter(Boolean);
const appDelegateSubscribers = []
.concat(...modulesToImport.map((module) => module.appDelegateSubscribers))
.filter(Boolean);
const reactDelegateHandlerModules = modulesToImport.filter(
(module) => !!module.reactDelegateHandlers.length
);
return `/**
* Automatically generated by expo-modules-autolinking.
*
* This autogenerated class provides a list of classes of native Expo modules,
* but only these that are written in Swift and use the new API for creating Expo modules.
*/
import ExpoModulesCore
${pods.map((podName) => `import ${podName}\n`).join('')}
@objc(${className})
public class ${className}: ModulesProvider {
public override func getModuleClasses() -> [AnyModule.Type] {
return ${formatArrayOfClassNames(modulesClassNames)}
}
public override func getAppDelegateSubscribers() -> [ExpoAppDelegateSubscriber.Type] {
return ${formatArrayOfClassNames(appDelegateSubscribers)}
}
public override func getReactDelegateHandlers() -> [ExpoReactDelegateHandlerTupleType] {
return ${formatArrayOfReactDelegateHandler(reactDelegateHandlerModules)}
}
}
`;
}
/**
* Formats an array of class names to Swift's array containing these classes.
*/
function formatArrayOfClassNames(classNames: string[]): string {
const indent = ' ';
return `[${classNames.map((className) => `\n${indent.repeat(3)}${className}.self`).join(',')}
${indent.repeat(2)}]`;
}
/**
* Formats an array of modules to Swift's array containing ReactDelegateHandlers
*/
export function formatArrayOfReactDelegateHandler(modules: ModuleDescriptor[]): string {
const values: string[] = [];
for (const module of modules) {
for (const handler of module.reactDelegateHandlers) {
values.push(`(packageName: "${module.packageName}", handler: ${handler}.self)`);
}
}
const indent = ' ';
return `[${values.map((value) => `\n${indent.repeat(3)}${value}`).join(',')}
${indent.repeat(2)}]`;
}