UNPKG

create-nitro-lib

Version:
320 lines (281 loc) 7.06 kB
import path from 'node:path'; import fs from 'fs-extra'; import { toPascalCase } from '../utils/string.js'; export async function createNitroConfig(packageDir, config) { const pascalName = toPascalCase(config.name); const nitroConfig = { $schema: 'https://nitro.margelo.com/nitro.schema.json', cxxNamespace: [pascalName.toLowerCase()], ios: { iosModuleName: pascalName, }, android: { androidNamespace: [pascalName.toLowerCase()], androidCxxLibName: pascalName, }, autolinking: { [pascalName]: { swift: `Hybrid${pascalName}`, kotlin: `Hybrid${pascalName}`, }, }, ignorePaths: ['**/node_modules'], }; await fs.writeJson(path.join(packageDir, 'nitro.json'), nitroConfig, { spaces: 2, }); } export async function createPackageConfigFiles(packageDir, config) { const tsconfigContent = { include: ['src'], compilerOptions: { composite: true, rootDir: 'src', allowUnreachableCode: false, allowUnusedLabels: false, esModuleInterop: true, forceConsistentCasingInFileNames: true, jsx: 'react-jsx', lib: ['esnext'], module: 'esnext', target: 'esnext', moduleResolution: 'node', noEmit: false, noFallthroughCasesInSwitch: true, noImplicitReturns: true, noImplicitUseStrict: false, noStrictGenericChecks: false, noUncheckedIndexedAccess: true, noUnusedLocals: true, noUnusedParameters: true, resolveJsonModule: true, skipLibCheck: true, strict: true, }, }; const reactNativeConfigContent = `// https://github.com/react-native-community/cli/blob/main/docs/dependencies.md module.exports = { dependency: { platforms: { /** * @type {import('@react-native-community/cli-types').IOSDependencyParams} */ ios: {}, /** * @type {import('@react-native-community/cli-types').AndroidDependencyParams} */ android: {}, }, }, } `; await fs.writeJson(path.join(packageDir, 'tsconfig.json'), tsconfigContent, { spaces: 2, }); await fs.writeFile(path.join(packageDir, 'react-native.config.js'), reactNativeConfigContent); } export async function createRootConfigFiles(projectDir, config) { const tsconfigContent = { compilerOptions: { target: 'ES2020', module: 'ESNext', moduleResolution: 'node', lib: ['ES2020'], declaration: true, outDir: './lib', rootDir: './src', strict: true, esModuleInterop: true, allowSyntheticDefaultImports: true, skipLibCheck: true, forceConsistentCasingInFileNames: true, resolveJsonModule: true, jsx: 'react-jsx', }, include: ['package/src/**/*'], exclude: [ 'node_modules', 'package/lib', 'package/android', 'package/ios', 'example', ], }; const biomeConfigContent = { $schema: 'https://biomejs.dev/schemas/1.9.4/schema.json', formatter: { enabled: true, formatWithErrors: false, indentStyle: 'space', indentWidth: 2, lineEnding: 'lf', lineWidth: 80, attributePosition: 'auto', }, organizeImports: { enabled: true, }, linter: { enabled: true, rules: { recommended: true, correctness: { useExhaustiveDependencies: 'warn', }, }, }, javascript: { formatter: { jsxQuoteStyle: 'double', quoteProperties: 'asNeeded', semicolons: 'asNeeded', arrowParentheses: 'asNeeded', bracketSpacing: true, bracketSameLine: false, quoteStyle: 'single', attributePosition: 'auto', lineWidth: 90, trailingCommas: 'all', }, }, files: { include: [ 'example/**/*.ts', 'example/**/*.tsx', 'packages/**/*.ts', 'packages/**/*.tsx', ], }, }; const gitignoreContent = `# OSX # .DS_Store # XDE .expo/ dist/ expo-env.d.ts # VSCode .vscode/ jsconfig.json # Xcode # build/ *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata *.xccheckout *.moved-aside DerivedData *.hmap *.ipa *.xcuserstate # Android/IJ # .classpath .cxx .gradle .idea .project .settings local.properties android.iml # Example # example/ios example/android # Native *.orig.* *.jks *.p8 *.p12 *.key *.mobileprovision # Ruby example/vendor/ # node.js # node_modules/ npm-debug.log yarn-debug.log yarn-error.log # BUCK buck-out/ \.buckd/ android/app/libs android/keystores/debug.keystore # Yarn .yarn/* !.yarn/patches !.yarn/plugins !.yarn/releases !.yarn/sdks !.yarn/versions # Expo .expo/ # generated by bob lib/ # typescript *.tsbuildinfo # Metro .metro-health-check* # debug npm-debug.* yarn-debug.* yarn-error.* `; const pascaleName = toPascalCase(config.name); const readmeContent = `# ${config.packageName} ${config.description} ## Installation \`\`\`sh npm install ${config.packageName} \`\`\` ## Usage \`\`\`javascript import { ${pascaleName}Spec } from '${config.packageName}'; import { NitroModules } from 'react-native-nitro-modules'; const ${pascaleName} = NitroModules.create<${pascaleName}Spec>('${pascaleName}'); const result = ${pascaleName}.hello('World'); console.log(result); \`\`\` ## API ### \`hello(name: string): string\` Returns a greeting message. ### \`add(a: number, b: number): number\` Adds two numbers and returns the result. ## Development This project uses a workspace structure with: - \`package/\` - The nitro module source code - \`example/\` - Example app demonstrating usage ### Setup \`\`\`sh npm install npm run build \`\`\` ### Running the example \`\`\`sh cd example npm run ios # or npm run android \`\`\` ## Contributing See the [contributing guide](CONTRIBUTING.md) to learn how to contribute to the repository. ## License MIT `; await fs.writeJson(path.join(projectDir, 'tsconfig.json'), tsconfigContent, { spaces: 2, }); await fs.writeJson(path.join(projectDir, 'biome.json'), biomeConfigContent, { spaces: 2, }); await fs.writeFile(path.join(projectDir, '.gitignore'), gitignoreContent); await fs.writeFile(path.join(projectDir, 'README.md'), readmeContent); }