Initial commit

This commit is contained in:
2026-06-29 15:47:16 +02:00
commit b9d2db7ac9
7 changed files with 280 additions and 0 deletions
+133
View File
@@ -0,0 +1,133 @@
import { Command, program } from 'commander';
import { exec } from 'child_process';
import { promisify } from 'util';
import fs from 'fs';
const execAsync = promisify(exec);
program.name('Expo kit').description('Expo framework for multiple plugins').version('1.0.0');
program
.command('new')
.argument('<name>', 'Project name')
.option('--reactnavigation', 'Adds reactnavigation to project')
.option('--nativewind', 'Adds nativewind to project')
.option('--i18next', 'Adds i18next to project')
.action(createProject);
async function createProject(name: string, ...args: any[]) {
const dir = `${__dirname}/${name}`;
const options: {
reactnavigation: boolean;
nativewind: boolean;
i18next: boolean;
} = args[0];
console.log('📦 Installing starter template...');
await execAsync(
`git clone https://git.justzoe101.nl/Expo-Starter-Kit/Template.git ${dir} --depth 1`
);
combineAppJson(dir, {
appJson: {
expo: {
name,
slug: name.toLowerCase(),
},
},
});
await execAsync('npm i', {
cwd: dir,
});
console.log('✅ Starter template installed!\r\n');
if (options.reactnavigation) {
console.log('📦 Installing reactnavigation dependencies...');
const plugin = require(`${dir}/plugins/reactnavigation/plugin.json`);
await _installDependencies(dir, plugin);
console.log('✅ Reactnavigation installed!\r\n');
}
if (options.nativewind) {
console.log('📦 Installing nativewind dependencies...');
const plugin = require(`${dir}/plugins/nativewind/plugin.json`);
await _installDependencies(dir, plugin);
console.log('✅ Nativewind installed!\r\n');
}
if (options.i18next) {
console.log('📦 Installing i18next dependencies...');
const plugin = require(`${dir}/plugins/i18next/plugin.json`);
await _installDependencies(dir, plugin);
combineAppJson(dir, plugin);
console.log('✅ I18next installed!\r\n');
}
}
async function _installDependencies(dir: string, plugin: Plugin) {
const keys = Object.keys(plugin);
if (keys.includes('dependencies')) {
let dependencies: any = Object.entries(plugin.dependencies!);
dependencies = dependencies.flatMap((d: any[]) => `${d[0]}@${d[1]}`).join(' ');
await execAsync(`npm i ${dependencies}`, {
cwd: dir,
});
}
if (keys.includes('devDependencies')) {
let dependencies: any = Object.entries(plugin.devDependencies!);
dependencies = dependencies.flatMap((d: any[]) => `${d[0]}@${d[1]}`).join(' ');
await execAsync(`npm i ${dependencies} --save-dev`, {
cwd: dir,
});
}
if (keys.includes('expoDependencies')) {
let dependencies: any = plugin.expoDependencies!.join(' ');
await execAsync(`npx expo install ${dependencies}`, {
cwd: dir,
});
}
}
function combineAppJson(dir: string, plugin: Plugin) {
fs.writeFileSync(
`${dir}/app.json`,
JSON.stringify(deepMerge(require(`${dir}/app.json`), plugin.appJson), null, 4),
'utf8'
);
}
function deepMerge(target: any, source: any) {
if (Array.isArray(target) && Array.isArray(source)) {
return source; // or target.concat(source) if that's what you want
}
if (target && source && typeof target === 'object' && typeof source === 'object') {
const result = { ...target };
for (const key of Object.keys(source)) {
result[key] = key in target ? deepMerge(target[key], source[key]) : source[key];
}
return result;
}
return source;
}
type Plugin = {
dependencies?: Record<string, string>;
devDependencies?: Record<string, string>;
expoDependencies?: string[];
appJson?: object;
};
program.parse();