create-expo-module 0.4.1 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/create-expo-module.js +18 -8
- package/build/create-expo-module.js.map +1 -1
- package/build/createExampleApp.js +2 -2
- package/build/createExampleApp.js.map +1 -1
- package/build/prompts.d.ts +2 -1
- package/build/prompts.js +22 -15
- package/build/prompts.js.map +1 -1
- package/package.json +2 -2
- package/src/create-expo-module.ts +18 -8
- package/src/createExampleApp.ts +3 -3
- package/src/prompts.ts +22 -16
|
@@ -13,7 +13,7 @@ const path_1 = __importDefault(require("path"));
|
|
|
13
13
|
const prompts_1 = __importDefault(require("prompts"));
|
|
14
14
|
const createExampleApp_1 = require("./createExampleApp");
|
|
15
15
|
const packageManager_1 = require("./packageManager");
|
|
16
|
-
const prompts_2 =
|
|
16
|
+
const prompts_2 = require("./prompts");
|
|
17
17
|
const resolvePackageManager_1 = require("./resolvePackageManager");
|
|
18
18
|
const utils_1 = require("./utils");
|
|
19
19
|
const packageJson = require('../package.json');
|
|
@@ -29,11 +29,12 @@ const IGNORES_PATHS = ['.DS_Store', 'build', 'node_modules', 'package.json'];
|
|
|
29
29
|
* @param command An object from `commander`.
|
|
30
30
|
*/
|
|
31
31
|
async function main(target, options) {
|
|
32
|
-
const
|
|
32
|
+
const slug = await askForPackageSlugAsync(target);
|
|
33
|
+
const targetDir = path_1.default.join(CWD, target || slug);
|
|
33
34
|
await fs_extra_1.default.ensureDir(targetDir);
|
|
34
35
|
await confirmTargetDirAsync(targetDir);
|
|
35
36
|
options.target = targetDir;
|
|
36
|
-
const data = await askForSubstitutionDataAsync(
|
|
37
|
+
const data = await askForSubstitutionDataAsync(slug);
|
|
37
38
|
// Make one line break between prompts and progress logs
|
|
38
39
|
console.log();
|
|
39
40
|
const packageManager = await (0, resolvePackageManager_1.resolvePackageManager)();
|
|
@@ -135,17 +136,26 @@ async function createModuleFromTemplate(templatePath, targetPath, data) {
|
|
|
135
136
|
await fs_extra_1.default.outputFile(toPath, renderedContent, { encoding: 'utf8' });
|
|
136
137
|
}
|
|
137
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Asks the user for the package slug (npm package name).
|
|
141
|
+
*/
|
|
142
|
+
async function askForPackageSlugAsync(customTargetPath) {
|
|
143
|
+
const { slug } = await (0, prompts_1.default)((0, prompts_2.getSlugPrompt)(customTargetPath), {
|
|
144
|
+
onCancel: () => process.exit(0),
|
|
145
|
+
});
|
|
146
|
+
return slug;
|
|
147
|
+
}
|
|
138
148
|
/**
|
|
139
149
|
* Asks the user for some data necessary to render the template.
|
|
140
150
|
* Some values may already be provided by command options, the prompt is skipped in that case.
|
|
141
151
|
*/
|
|
142
|
-
async function askForSubstitutionDataAsync(
|
|
143
|
-
const promptQueries = await (0, prompts_2.
|
|
152
|
+
async function askForSubstitutionDataAsync(slug) {
|
|
153
|
+
const promptQueries = await (0, prompts_2.getSubstitutionDataPrompts)(slug);
|
|
144
154
|
// Stop the process when the user cancels/exits the prompt.
|
|
145
155
|
const onCancel = () => {
|
|
146
156
|
process.exit(0);
|
|
147
157
|
};
|
|
148
|
-
const {
|
|
158
|
+
const { name, description, package: projectPackage, authorName, authorEmail, authorUrl, repo, } = await (0, prompts_1.default)(promptQueries, { onCancel });
|
|
149
159
|
return {
|
|
150
160
|
project: {
|
|
151
161
|
slug,
|
|
@@ -170,7 +180,7 @@ async function confirmTargetDirAsync(targetDir) {
|
|
|
170
180
|
const { shouldContinue } = await (0, prompts_1.default)({
|
|
171
181
|
type: 'confirm',
|
|
172
182
|
name: 'shouldContinue',
|
|
173
|
-
message: `The target directory ${chalk_1.default.magenta(targetDir)} is not empty
|
|
183
|
+
message: `The target directory ${chalk_1.default.magenta(targetDir)} is not empty, do you want to continue anyway?`,
|
|
174
184
|
initial: true,
|
|
175
185
|
}, {
|
|
176
186
|
onCancel: () => false,
|
|
@@ -184,7 +194,7 @@ program
|
|
|
184
194
|
.name(packageJson.name)
|
|
185
195
|
.version(packageJson.version)
|
|
186
196
|
.description(packageJson.description)
|
|
187
|
-
.arguments('[
|
|
197
|
+
.arguments('[path]')
|
|
188
198
|
.option('-s, --source <source_dir>', 'Local path to the template. By default it downloads `expo-module-template` from NPM.')
|
|
189
199
|
.option('--with-readme', 'Whether to include README.md file.', false)
|
|
190
200
|
.option('--with-changelog', 'Whether to include CHANGELOG.md file.', false)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-expo-module.js","sourceRoot":"","sources":["../src/create-expo-module.ts"],"names":[],"mappings":"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","sourcesContent":["import spawnAsync from '@expo/spawn-async';\nimport chalk from 'chalk';\nimport { Command } from 'commander';\nimport downloadTarball from 'download-tarball';\nimport ejs from 'ejs';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport prompts from 'prompts';\n\nimport { createExampleApp } from './createExampleApp';\nimport { installDependencies } from './packageManager';\nimport getPrompts from './prompts';\nimport { resolvePackageManager } from './resolvePackageManager';\nimport { CommandOptions, SubstitutionData } from './types';\nimport { newStep } from './utils';\n\nconst packageJson = require('../package.json');\n\n// `yarn run` may change the current working dir, then we should use `INIT_CWD` env.\nconst CWD = process.env.INIT_CWD || process.cwd();\n\n// Ignore some paths. Especially `package.json` as it is rendered\n// from `$package.json` file instead of the original one.\nconst IGNORES_PATHS = ['.DS_Store', 'build', 'node_modules', 'package.json'];\n\n/**\n * The main function of the command.\n *\n * @param target Path to the directory where to create the module. Defaults to current working dir.\n * @param command An object from `commander`.\n */\nasync function main(target: string | undefined, options: CommandOptions) {\n const targetDir = target ? path.join(CWD, target) : CWD;\n\n await fs.ensureDir(targetDir);\n await confirmTargetDirAsync(targetDir);\n\n options.target = targetDir;\n\n const data = await askForSubstitutionDataAsync(targetDir);\n\n // Make one line break between prompts and progress logs\n console.log();\n\n const packageManager = await resolvePackageManager();\n const packagePath = options.source\n ? path.join(CWD, options.source)\n : await downloadPackageAsync(targetDir);\n\n await newStep('Creating the module from template files', async (step) => {\n await createModuleFromTemplate(packagePath, targetDir, data);\n step.succeed('Created the module from template files');\n });\n\n await newStep('Installing module dependencies', async (step) => {\n await installDependencies(packageManager, targetDir);\n step.succeed('Installed module dependencies');\n });\n\n await newStep('Compiling TypeScript files', async (step) => {\n await spawnAsync(packageManager, ['run', 'build'], {\n cwd: targetDir,\n stdio: 'ignore',\n });\n step.succeed('Compiled TypeScript files');\n });\n\n if (!options.source) {\n // Files in the downloaded tarball are wrapped in `package` dir.\n // We should remove it after all.\n await fs.remove(packagePath);\n }\n if (!options.withReadme) {\n await fs.remove(path.join(targetDir, 'README.md'));\n }\n if (!options.withChangelog) {\n await fs.remove(path.join(targetDir, 'CHANGELOG.md'));\n }\n if (options.example) {\n // Create \"example\" folder\n await createExampleApp(data, targetDir, packageManager);\n }\n\n console.log();\n console.log('✅ Successfully created Expo module');\n}\n\n/**\n * Recursively scans for the files within the directory. Returned paths are relative to the `root` path.\n */\nasync function getFilesAsync(root: string, dir: string | null = null): Promise<string[]> {\n const files: string[] = [];\n const baseDir = dir ? path.join(root, dir) : root;\n\n for (const file of await fs.readdir(baseDir)) {\n const relativePath = dir ? path.join(dir, file) : file;\n\n if (IGNORES_PATHS.includes(relativePath) || IGNORES_PATHS.includes(file)) {\n continue;\n }\n\n const fullPath = path.join(baseDir, file);\n const stat = await fs.lstat(fullPath);\n\n if (stat.isDirectory()) {\n files.push(...(await getFilesAsync(root, relativePath)));\n } else {\n files.push(relativePath);\n }\n }\n return files;\n}\n\n/**\n * Asks NPM registry for the url to the tarball.\n */\nasync function getNpmTarballUrl(packageName: string, version: string = 'latest'): Promise<string> {\n const { stdout } = await spawnAsync('npm', ['view', `${packageName}@${version}`, 'dist.tarball']);\n return stdout.trim();\n}\n\n/**\n * Downloads the template from NPM registry.\n */\nasync function downloadPackageAsync(targetDir: string): Promise<string> {\n return await newStep('Downloading module template from npm', async (step) => {\n const tarballUrl = await getNpmTarballUrl('expo-module-template');\n\n await downloadTarball({\n url: tarballUrl,\n dir: targetDir,\n });\n\n step.succeed('Downloaded module template from npm');\n\n return path.join(targetDir, 'package');\n });\n}\n\n/**\n * Creates the module based on the `ejs` template (e.g. `expo-module-template` package).\n */\nasync function createModuleFromTemplate(\n templatePath: string,\n targetPath: string,\n data: SubstitutionData\n) {\n const files = await getFilesAsync(templatePath);\n\n // Iterate through all template files.\n for (const file of files) {\n const renderedRelativePath = ejs.render(file.replace(/^\\$/, ''), data, {\n openDelimiter: '{',\n closeDelimiter: '}',\n escape: (value: string) => value.replace('.', path.sep),\n });\n const fromPath = path.join(templatePath, file);\n const toPath = path.join(targetPath, renderedRelativePath);\n const template = await fs.readFile(fromPath, { encoding: 'utf8' });\n const renderedContent = ejs.render(template, data);\n\n await fs.outputFile(toPath, renderedContent, { encoding: 'utf8' });\n }\n}\n\n/**\n * Asks the user for some data necessary to render the template.\n * Some values may already be provided by command options, the prompt is skipped in that case.\n */\nasync function askForSubstitutionDataAsync(targetDir: string): Promise<SubstitutionData> {\n const promptQueries = await getPrompts(targetDir);\n\n // Stop the process when the user cancels/exits the prompt.\n const onCancel = () => {\n process.exit(0);\n };\n\n const {\n slug,\n name,\n description,\n package: projectPackage,\n authorName,\n authorEmail,\n authorUrl,\n repo,\n } = await prompts(promptQueries, { onCancel });\n\n return {\n project: {\n slug,\n name,\n version: '0.1.0',\n description,\n package: projectPackage,\n },\n author: `${authorName} <${authorEmail}> (${authorUrl})`,\n license: 'MIT',\n repo,\n };\n}\n\n/**\n * Checks whether the target directory is empty and if not, asks the user to confirm if he wants to continue.\n */\nasync function confirmTargetDirAsync(targetDir: string): Promise<void> {\n const files = await fs.readdir(targetDir);\n\n if (files.length === 0) {\n return;\n }\n const { shouldContinue } = await prompts(\n {\n type: 'confirm',\n name: 'shouldContinue',\n message: `The target directory ${chalk.magenta(\n targetDir\n )} is not empty.\\nDo you want to continue anyway?`,\n initial: true,\n },\n {\n onCancel: () => false,\n }\n );\n if (!shouldContinue) {\n process.exit(0);\n }\n}\n\nconst program = new Command();\n\nprogram\n .name(packageJson.name)\n .version(packageJson.version)\n .description(packageJson.description)\n .arguments('[target_dir]')\n .option(\n '-s, --source <source_dir>',\n 'Local path to the template. By default it downloads `expo-module-template` from NPM.'\n )\n .option('--with-readme', 'Whether to include README.md file.', false)\n .option('--with-changelog', 'Whether to include CHANGELOG.md file.', false)\n .option('--no-example', 'Whether to skip creating the example app.', false)\n .action(main);\n\nprogram.parse(process.argv);\n"]}
|
|
1
|
+
{"version":3,"file":"create-expo-module.js","sourceRoot":"","sources":["../src/create-expo-module.ts"],"names":[],"mappings":"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","sourcesContent":["import spawnAsync from '@expo/spawn-async';\nimport chalk from 'chalk';\nimport { Command } from 'commander';\nimport downloadTarball from 'download-tarball';\nimport ejs from 'ejs';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport prompts from 'prompts';\n\nimport { createExampleApp } from './createExampleApp';\nimport { installDependencies } from './packageManager';\nimport { getSlugPrompt, getSubstitutionDataPrompts } from './prompts';\nimport { resolvePackageManager } from './resolvePackageManager';\nimport { CommandOptions, SubstitutionData } from './types';\nimport { newStep } from './utils';\n\nconst packageJson = require('../package.json');\n\n// `yarn run` may change the current working dir, then we should use `INIT_CWD` env.\nconst CWD = process.env.INIT_CWD || process.cwd();\n\n// Ignore some paths. Especially `package.json` as it is rendered\n// from `$package.json` file instead of the original one.\nconst IGNORES_PATHS = ['.DS_Store', 'build', 'node_modules', 'package.json'];\n\n/**\n * The main function of the command.\n *\n * @param target Path to the directory where to create the module. Defaults to current working dir.\n * @param command An object from `commander`.\n */\nasync function main(target: string | undefined, options: CommandOptions) {\n const slug = await askForPackageSlugAsync(target);\n const targetDir = path.join(CWD, target || slug);\n\n await fs.ensureDir(targetDir);\n await confirmTargetDirAsync(targetDir);\n\n options.target = targetDir;\n\n const data = await askForSubstitutionDataAsync(slug);\n\n // Make one line break between prompts and progress logs\n console.log();\n\n const packageManager = await resolvePackageManager();\n const packagePath = options.source\n ? path.join(CWD, options.source)\n : await downloadPackageAsync(targetDir);\n\n await newStep('Creating the module from template files', async (step) => {\n await createModuleFromTemplate(packagePath, targetDir, data);\n step.succeed('Created the module from template files');\n });\n\n await newStep('Installing module dependencies', async (step) => {\n await installDependencies(packageManager, targetDir);\n step.succeed('Installed module dependencies');\n });\n\n await newStep('Compiling TypeScript files', async (step) => {\n await spawnAsync(packageManager, ['run', 'build'], {\n cwd: targetDir,\n stdio: 'ignore',\n });\n step.succeed('Compiled TypeScript files');\n });\n\n if (!options.source) {\n // Files in the downloaded tarball are wrapped in `package` dir.\n // We should remove it after all.\n await fs.remove(packagePath);\n }\n if (!options.withReadme) {\n await fs.remove(path.join(targetDir, 'README.md'));\n }\n if (!options.withChangelog) {\n await fs.remove(path.join(targetDir, 'CHANGELOG.md'));\n }\n if (options.example) {\n // Create \"example\" folder\n await createExampleApp(data, targetDir, packageManager);\n }\n\n console.log();\n console.log('✅ Successfully created Expo module');\n}\n\n/**\n * Recursively scans for the files within the directory. Returned paths are relative to the `root` path.\n */\nasync function getFilesAsync(root: string, dir: string | null = null): Promise<string[]> {\n const files: string[] = [];\n const baseDir = dir ? path.join(root, dir) : root;\n\n for (const file of await fs.readdir(baseDir)) {\n const relativePath = dir ? path.join(dir, file) : file;\n\n if (IGNORES_PATHS.includes(relativePath) || IGNORES_PATHS.includes(file)) {\n continue;\n }\n\n const fullPath = path.join(baseDir, file);\n const stat = await fs.lstat(fullPath);\n\n if (stat.isDirectory()) {\n files.push(...(await getFilesAsync(root, relativePath)));\n } else {\n files.push(relativePath);\n }\n }\n return files;\n}\n\n/**\n * Asks NPM registry for the url to the tarball.\n */\nasync function getNpmTarballUrl(packageName: string, version: string = 'latest'): Promise<string> {\n const { stdout } = await spawnAsync('npm', ['view', `${packageName}@${version}`, 'dist.tarball']);\n return stdout.trim();\n}\n\n/**\n * Downloads the template from NPM registry.\n */\nasync function downloadPackageAsync(targetDir: string): Promise<string> {\n return await newStep('Downloading module template from npm', async (step) => {\n const tarballUrl = await getNpmTarballUrl('expo-module-template');\n\n await downloadTarball({\n url: tarballUrl,\n dir: targetDir,\n });\n\n step.succeed('Downloaded module template from npm');\n\n return path.join(targetDir, 'package');\n });\n}\n\n/**\n * Creates the module based on the `ejs` template (e.g. `expo-module-template` package).\n */\nasync function createModuleFromTemplate(\n templatePath: string,\n targetPath: string,\n data: SubstitutionData\n) {\n const files = await getFilesAsync(templatePath);\n\n // Iterate through all template files.\n for (const file of files) {\n const renderedRelativePath = ejs.render(file.replace(/^\\$/, ''), data, {\n openDelimiter: '{',\n closeDelimiter: '}',\n escape: (value: string) => value.replace('.', path.sep),\n });\n const fromPath = path.join(templatePath, file);\n const toPath = path.join(targetPath, renderedRelativePath);\n const template = await fs.readFile(fromPath, { encoding: 'utf8' });\n const renderedContent = ejs.render(template, data);\n\n await fs.outputFile(toPath, renderedContent, { encoding: 'utf8' });\n }\n}\n\n/**\n * Asks the user for the package slug (npm package name).\n */\nasync function askForPackageSlugAsync(customTargetPath?: string): Promise<string> {\n const { slug } = await prompts(getSlugPrompt(customTargetPath), {\n onCancel: () => process.exit(0),\n });\n return slug;\n}\n\n/**\n * Asks the user for some data necessary to render the template.\n * Some values may already be provided by command options, the prompt is skipped in that case.\n */\nasync function askForSubstitutionDataAsync(slug: string): Promise<SubstitutionData> {\n const promptQueries = await getSubstitutionDataPrompts(slug);\n\n // Stop the process when the user cancels/exits the prompt.\n const onCancel = () => {\n process.exit(0);\n };\n\n const {\n name,\n description,\n package: projectPackage,\n authorName,\n authorEmail,\n authorUrl,\n repo,\n } = await prompts(promptQueries, { onCancel });\n\n return {\n project: {\n slug,\n name,\n version: '0.1.0',\n description,\n package: projectPackage,\n },\n author: `${authorName} <${authorEmail}> (${authorUrl})`,\n license: 'MIT',\n repo,\n };\n}\n\n/**\n * Checks whether the target directory is empty and if not, asks the user to confirm if he wants to continue.\n */\nasync function confirmTargetDirAsync(targetDir: string): Promise<void> {\n const files = await fs.readdir(targetDir);\n\n if (files.length === 0) {\n return;\n }\n const { shouldContinue } = await prompts(\n {\n type: 'confirm',\n name: 'shouldContinue',\n message: `The target directory ${chalk.magenta(\n targetDir\n )} is not empty, do you want to continue anyway?`,\n initial: true,\n },\n {\n onCancel: () => false,\n }\n );\n if (!shouldContinue) {\n process.exit(0);\n }\n}\n\nconst program = new Command();\n\nprogram\n .name(packageJson.name)\n .version(packageJson.version)\n .description(packageJson.description)\n .arguments('[path]')\n .option(\n '-s, --source <source_dir>',\n 'Local path to the template. By default it downloads `expo-module-template` from NPM.'\n )\n .option('--with-readme', 'Whether to include README.md file.', false)\n .option('--with-changelog', 'Whether to include CHANGELOG.md file.', false)\n .option('--no-example', 'Whether to skip creating the example app.', false)\n .action(main);\n\nprogram.parse(process.argv);\n"]}
|
|
@@ -26,9 +26,9 @@ async function createExampleApp(data, targetDir, packageManager) {
|
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
28
28
|
await (0, utils_1.newStep)('Initializing the example app', async (step) => {
|
|
29
|
-
await (0, spawn_async_1.default)('
|
|
29
|
+
await (0, spawn_async_1.default)(packageManager, ['create', 'expo-app', exampleProjectSlug, '--template', 'blank-typescript'], {
|
|
30
30
|
cwd: targetDir,
|
|
31
|
-
stdio:
|
|
31
|
+
stdio: 'ignore',
|
|
32
32
|
});
|
|
33
33
|
step.succeed('Initialized the example app');
|
|
34
34
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createExampleApp.js","sourceRoot":"","sources":["../src/createExampleApp.ts"],"names":[],"mappings":";;;;;;AAAA,oEAA2C;AAC3C,wDAA0B;AAC1B,gDAAwB;AAExB,qDAAuD;AAGvD,mCAAkC;AAElC,kFAAkF;AAClF,MAAM,sBAAsB,GAAG,CAAC,iBAAiB,EAAE,oBAAoB,CAAC,CAAC;AAEzE;;GAEG;AACI,KAAK,UAAU,gBAAgB,CACpC,IAAsB,EACtB,SAAiB,EACjB,cAAkC;IAElC,mCAAmC;IACnC,MAAM,kBAAkB,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,UAAU,CAAC;IAE1D,0EAA0E;IAC1E,MAAM,UAAU,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,kBAAkB,CAAC,CAAC;IAE5D,iCAAiC;IACjC,MAAM,aAAa,GAAG,cAAI,CAAC,IAAI,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IAEtD,IAAI,CAAC,CAAC,MAAM,kBAAE,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,EAAE;QACzC,wEAAwE;QACxE,OAAO;KACR;IAED,MAAM,IAAA,eAAO,EAAC,8BAA8B,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QAC3D,MAAM,IAAA,qBAAU,EACd,
|
|
1
|
+
{"version":3,"file":"createExampleApp.js","sourceRoot":"","sources":["../src/createExampleApp.ts"],"names":[],"mappings":"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","sourcesContent":["import spawnAsync from '@expo/spawn-async';\nimport fs from 'fs-extra';\nimport path from 'path';\n\nimport { installDependencies } from './packageManager';\nimport { PackageManagerName } from './resolvePackageManager';\nimport { SubstitutionData } from './types';\nimport { newStep } from './utils';\n\n// These dependencies will be removed from the example app (`expo init` adds them)\nconst DEPENDENCIES_TO_REMOVE = ['expo-status-bar', 'expo-splash-screen'];\n\n/**\n * Initializes a new Expo project as an example app.\n */\nexport async function createExampleApp(\n data: SubstitutionData,\n targetDir: string,\n packageManager: PackageManagerName\n): Promise<void> {\n // Package name for the example app\n const exampleProjectSlug = `${data.project.slug}-example`;\n\n // `expo init` creates a new folder with the same name as the project slug\n const appTmpPath = path.join(targetDir, exampleProjectSlug);\n\n // Path to the target example dir\n const appTargetPath = path.join(targetDir, 'example');\n\n if (!(await fs.pathExists(appTargetPath))) {\n // The template doesn't include the example app, so just skip this phase\n return;\n }\n\n await newStep('Initializing the example app', async (step) => {\n await spawnAsync(\n packageManager,\n ['create', 'expo-app', exampleProjectSlug, '--template', 'blank-typescript'],\n {\n cwd: targetDir,\n stdio: 'ignore',\n }\n );\n step.succeed('Initialized the example app');\n });\n\n await newStep('Configuring the example app', async (step) => {\n // \"example\" folder already exists and contains template files,\n // that should replace these created by `expo init`.\n await moveFiles(appTargetPath, appTmpPath);\n\n // Cleanup the \"example\" dir\n await fs.rmdir(appTargetPath);\n\n // Move the temporary example app to \"example\" dir\n await fs.rename(appTmpPath, appTargetPath);\n\n await addMissingAppConfigFields(appTargetPath, data);\n\n step.succeed('Configured the example app');\n });\n\n await prebuildExampleApp(appTargetPath);\n\n await modifyPackageJson(appTargetPath);\n\n await newStep('Installing dependencies in the example app', async (step) => {\n await installDependencies(packageManager, appTargetPath);\n await podInstall(appTargetPath);\n step.succeed('Installed dependencies in the example app');\n });\n}\n\n/**\n * Copies files from one directory to another.\n */\nasync function moveFiles(fromPath: string, toPath: string): Promise<void> {\n for (const file of await fs.readdir(fromPath)) {\n await fs.move(path.join(fromPath, file), path.join(toPath, file), {\n overwrite: true,\n });\n }\n}\n\n/**\n * Adds missing configuration that are required to run `expo prebuild`.\n */\nasync function addMissingAppConfigFields(appPath: string, data: SubstitutionData): Promise<void> {\n const appConfigPath = path.join(appPath, 'app.json');\n const appConfig = await fs.readJson(appConfigPath);\n const appId = `${data.project.package}.example`;\n\n // Android package name needs to be added to app.json\n if (!appConfig.expo.android) {\n appConfig.expo.android = {};\n }\n appConfig.expo.android.package = appId;\n\n // Specify iOS bundle identifier\n if (!appConfig.expo.ios) {\n appConfig.expo.ios = {};\n }\n appConfig.expo.ios.bundleIdentifier = appId;\n\n await fs.writeJson(appConfigPath, appConfig, {\n spaces: 2,\n });\n}\n\n/**\n * Applies necessary changes to **package.json** of the example app.\n * It means setting the autolinking config and removing unnecessary dependencies.\n */\nasync function modifyPackageJson(appPath: string): Promise<void> {\n const packageJsonPath = path.join(appPath, 'package.json');\n const packageJson = await fs.readJson(packageJsonPath);\n\n if (!packageJson.expo) {\n packageJson.expo = {};\n }\n\n // Set the native modules dir to the root folder,\n // so that the autolinking can detect and link the module.\n packageJson.expo.autolinking = {\n nativeModulesDir: '..',\n };\n\n // Remove unnecessary dependencies\n for (const dependencyToRemove of DEPENDENCIES_TO_REMOVE) {\n delete packageJson.dependencies[dependencyToRemove];\n }\n\n await fs.writeJson(packageJsonPath, packageJson, {\n spaces: 2,\n });\n}\n\n/**\n * Runs `expo prebuild` in the example app.\n */\nasync function prebuildExampleApp(exampleAppPath: string): Promise<void> {\n await newStep('Prebuilding the example app', async (step) => {\n await spawnAsync('expo', ['prebuild', '--no-install'], {\n cwd: exampleAppPath,\n stdio: ['ignore', 'ignore', 'pipe'],\n });\n step.succeed('Prebuilt the example app');\n });\n}\n\n/**\n * Runs `pod install` in the iOS project at the given path.\n */\nasync function podInstall(appPath: string): Promise<void> {\n await spawnAsync('pod', ['install'], {\n cwd: path.join(appPath, 'ios'),\n stdio: ['ignore', 'ignore', 'pipe'],\n });\n}\n"]}
|
package/build/prompts.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
1
|
import { PromptObject } from 'prompts';
|
|
2
|
-
export
|
|
2
|
+
export declare function getSlugPrompt(customTargetPath?: string | null): PromptObject<string>;
|
|
3
|
+
export declare function getSubstitutionDataPrompts(slug: string): Promise<PromptObject<string>[]>;
|
package/build/prompts.js
CHANGED
|
@@ -3,25 +3,32 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.getSubstitutionDataPrompts = exports.getSlugPrompt = void 0;
|
|
6
7
|
const path_1 = __importDefault(require("path"));
|
|
7
8
|
const validate_npm_package_name_1 = __importDefault(require("validate-npm-package-name"));
|
|
8
9
|
const utils_1 = require("./utils");
|
|
9
|
-
|
|
10
|
-
const targetBasename = path_1.default.basename(
|
|
10
|
+
function getSlugPrompt(customTargetPath) {
|
|
11
|
+
const targetBasename = customTargetPath && path_1.default.basename(customTargetPath);
|
|
12
|
+
const initial = targetBasename && (0, validate_npm_package_name_1.default)(targetBasename).validForNewPackages
|
|
13
|
+
? targetBasename
|
|
14
|
+
: 'my-module';
|
|
15
|
+
return {
|
|
16
|
+
type: 'text',
|
|
17
|
+
name: 'slug',
|
|
18
|
+
message: 'What is the name of the npm package?',
|
|
19
|
+
initial,
|
|
20
|
+
validate: (input) => (0, validate_npm_package_name_1.default)(input).validForNewPackages || 'Must be a valid npm package name',
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
exports.getSlugPrompt = getSlugPrompt;
|
|
24
|
+
async function getSubstitutionDataPrompts(slug) {
|
|
11
25
|
return [
|
|
12
|
-
{
|
|
13
|
-
type: 'text',
|
|
14
|
-
name: 'slug',
|
|
15
|
-
message: 'What is the name of the npm package?',
|
|
16
|
-
initial: (0, validate_npm_package_name_1.default)(targetBasename).validForNewPackages ? targetBasename : undefined,
|
|
17
|
-
validate: (input) => (0, validate_npm_package_name_1.default)(input).validForNewPackages || 'Must be a valid npm package name',
|
|
18
|
-
},
|
|
19
26
|
{
|
|
20
27
|
type: 'text',
|
|
21
28
|
name: 'name',
|
|
22
29
|
message: 'What is the native module name?',
|
|
23
|
-
initial: (
|
|
24
|
-
return
|
|
30
|
+
initial: () => {
|
|
31
|
+
return slug
|
|
25
32
|
.replace(/^@/, '')
|
|
26
33
|
.replace(/^./, (match) => match.toUpperCase())
|
|
27
34
|
.replace(/\W+(\w)/g, (_, p1) => p1.toUpperCase());
|
|
@@ -39,8 +46,8 @@ async function getPrompts(targetDir) {
|
|
|
39
46
|
type: 'text',
|
|
40
47
|
name: 'package',
|
|
41
48
|
message: 'What is the Android package name?',
|
|
42
|
-
initial: (
|
|
43
|
-
const namespace =
|
|
49
|
+
initial: () => {
|
|
50
|
+
const namespace = slug
|
|
44
51
|
.replace(/\W/g, '')
|
|
45
52
|
.replace(/^(expo|reactnative)/, '')
|
|
46
53
|
.toLowerCase();
|
|
@@ -71,10 +78,10 @@ async function getPrompts(targetDir) {
|
|
|
71
78
|
type: 'text',
|
|
72
79
|
name: 'repo',
|
|
73
80
|
message: 'What is the URL for the repository?',
|
|
74
|
-
initial: async (_, answers) => await (0, utils_1.guessRepoUrl)(answers.authorUrl,
|
|
81
|
+
initial: async (_, answers) => await (0, utils_1.guessRepoUrl)(answers.authorUrl, slug),
|
|
75
82
|
validate: (input) => /^https?:\/\//.test(input) || 'Must be a valid URL',
|
|
76
83
|
},
|
|
77
84
|
];
|
|
78
85
|
}
|
|
79
|
-
exports.
|
|
86
|
+
exports.getSubstitutionDataPrompts = getSubstitutionDataPrompts;
|
|
80
87
|
//# sourceMappingURL=prompts.js.map
|
package/build/prompts.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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","sourcesContent":["import path from 'path';\nimport { Answers, PromptObject } from 'prompts';\nimport validateNpmPackage from 'validate-npm-package-name';\n\nimport { findGitHubEmail, findGitHubProfileUrl, findMyName, guessRepoUrl } from './utils';\n\nexport function getSlugPrompt(customTargetPath?: string | null): PromptObject<string> {\n const targetBasename = customTargetPath && path.basename(customTargetPath);\n const initial =\n targetBasename && validateNpmPackage(targetBasename).validForNewPackages\n ? targetBasename\n : 'my-module';\n\n return {\n type: 'text',\n name: 'slug',\n message: 'What is the name of the npm package?',\n initial,\n validate: (input) =>\n validateNpmPackage(input).validForNewPackages || 'Must be a valid npm package name',\n };\n}\n\nexport async function getSubstitutionDataPrompts(slug: string): Promise<PromptObject<string>[]> {\n return [\n {\n type: 'text',\n name: 'name',\n message: 'What is the native module name?',\n initial: () => {\n return slug\n .replace(/^@/, '')\n .replace(/^./, (match) => match.toUpperCase())\n .replace(/\\W+(\\w)/g, (_, p1) => p1.toUpperCase());\n },\n validate: (input) => !!input || 'The native module name cannot be empty',\n },\n {\n type: 'text',\n name: 'description',\n message: 'How would you describe the module?',\n initial: 'My new module',\n validate: (input) => !!input || 'The description cannot be empty',\n },\n {\n type: 'text',\n name: 'package',\n message: 'What is the Android package name?',\n initial: () => {\n const namespace = slug\n .replace(/\\W/g, '')\n .replace(/^(expo|reactnative)/, '')\n .toLowerCase();\n return `expo.modules.${namespace}`;\n },\n validate: (input) => !!input || 'The Android package name cannot be empty',\n },\n {\n type: 'text',\n name: 'authorName',\n message: 'What is the name of the package author?',\n initial: await findMyName(),\n validate: (input) => !!input || 'Cannot be empty',\n },\n {\n type: 'text',\n name: 'authorEmail',\n message: 'What is the email address of the author?',\n initial: await findGitHubEmail(),\n },\n {\n type: 'text',\n name: 'authorUrl',\n message: \"What is the URL to the author's GitHub profile?\",\n initial: async (_, answers: Answers<string>) =>\n await findGitHubProfileUrl(answers.authorEmail),\n },\n {\n type: 'text',\n name: 'repo',\n message: 'What is the URL for the repository?',\n initial: async (_, answers: Answers<string>) => await guessRepoUrl(answers.authorUrl, slug),\n validate: (input) => /^https?:\\/\\//.test(input) || 'Must be a valid URL',\n },\n ];\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-expo-module",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "The script to create the Expo module",
|
|
5
5
|
"main": "build/create-expo-module.js",
|
|
6
6
|
"types": "build/create-expo-module.d.ts",
|
|
@@ -50,5 +50,5 @@
|
|
|
50
50
|
"@types/prompts": "^2.0.14",
|
|
51
51
|
"expo-module-scripts": "^2.0.0"
|
|
52
52
|
},
|
|
53
|
-
"gitHead": "
|
|
53
|
+
"gitHead": "1ba5fa454b86aef6f32c0f4ce0f34e4ea98e969f"
|
|
54
54
|
}
|
|
@@ -9,7 +9,7 @@ import prompts from 'prompts';
|
|
|
9
9
|
|
|
10
10
|
import { createExampleApp } from './createExampleApp';
|
|
11
11
|
import { installDependencies } from './packageManager';
|
|
12
|
-
import
|
|
12
|
+
import { getSlugPrompt, getSubstitutionDataPrompts } from './prompts';
|
|
13
13
|
import { resolvePackageManager } from './resolvePackageManager';
|
|
14
14
|
import { CommandOptions, SubstitutionData } from './types';
|
|
15
15
|
import { newStep } from './utils';
|
|
@@ -30,14 +30,15 @@ const IGNORES_PATHS = ['.DS_Store', 'build', 'node_modules', 'package.json'];
|
|
|
30
30
|
* @param command An object from `commander`.
|
|
31
31
|
*/
|
|
32
32
|
async function main(target: string | undefined, options: CommandOptions) {
|
|
33
|
-
const
|
|
33
|
+
const slug = await askForPackageSlugAsync(target);
|
|
34
|
+
const targetDir = path.join(CWD, target || slug);
|
|
34
35
|
|
|
35
36
|
await fs.ensureDir(targetDir);
|
|
36
37
|
await confirmTargetDirAsync(targetDir);
|
|
37
38
|
|
|
38
39
|
options.target = targetDir;
|
|
39
40
|
|
|
40
|
-
const data = await askForSubstitutionDataAsync(
|
|
41
|
+
const data = await askForSubstitutionDataAsync(slug);
|
|
41
42
|
|
|
42
43
|
// Make one line break between prompts and progress logs
|
|
43
44
|
console.log();
|
|
@@ -163,12 +164,22 @@ async function createModuleFromTemplate(
|
|
|
163
164
|
}
|
|
164
165
|
}
|
|
165
166
|
|
|
167
|
+
/**
|
|
168
|
+
* Asks the user for the package slug (npm package name).
|
|
169
|
+
*/
|
|
170
|
+
async function askForPackageSlugAsync(customTargetPath?: string): Promise<string> {
|
|
171
|
+
const { slug } = await prompts(getSlugPrompt(customTargetPath), {
|
|
172
|
+
onCancel: () => process.exit(0),
|
|
173
|
+
});
|
|
174
|
+
return slug;
|
|
175
|
+
}
|
|
176
|
+
|
|
166
177
|
/**
|
|
167
178
|
* Asks the user for some data necessary to render the template.
|
|
168
179
|
* Some values may already be provided by command options, the prompt is skipped in that case.
|
|
169
180
|
*/
|
|
170
|
-
async function askForSubstitutionDataAsync(
|
|
171
|
-
const promptQueries = await
|
|
181
|
+
async function askForSubstitutionDataAsync(slug: string): Promise<SubstitutionData> {
|
|
182
|
+
const promptQueries = await getSubstitutionDataPrompts(slug);
|
|
172
183
|
|
|
173
184
|
// Stop the process when the user cancels/exits the prompt.
|
|
174
185
|
const onCancel = () => {
|
|
@@ -176,7 +187,6 @@ async function askForSubstitutionDataAsync(targetDir: string): Promise<Substitut
|
|
|
176
187
|
};
|
|
177
188
|
|
|
178
189
|
const {
|
|
179
|
-
slug,
|
|
180
190
|
name,
|
|
181
191
|
description,
|
|
182
192
|
package: projectPackage,
|
|
@@ -215,7 +225,7 @@ async function confirmTargetDirAsync(targetDir: string): Promise<void> {
|
|
|
215
225
|
name: 'shouldContinue',
|
|
216
226
|
message: `The target directory ${chalk.magenta(
|
|
217
227
|
targetDir
|
|
218
|
-
)} is not empty
|
|
228
|
+
)} is not empty, do you want to continue anyway?`,
|
|
219
229
|
initial: true,
|
|
220
230
|
},
|
|
221
231
|
{
|
|
@@ -233,7 +243,7 @@ program
|
|
|
233
243
|
.name(packageJson.name)
|
|
234
244
|
.version(packageJson.version)
|
|
235
245
|
.description(packageJson.description)
|
|
236
|
-
.arguments('[
|
|
246
|
+
.arguments('[path]')
|
|
237
247
|
.option(
|
|
238
248
|
'-s, --source <source_dir>',
|
|
239
249
|
'Local path to the template. By default it downloads `expo-module-template` from NPM.'
|
package/src/createExampleApp.ts
CHANGED
|
@@ -34,11 +34,11 @@ export async function createExampleApp(
|
|
|
34
34
|
|
|
35
35
|
await newStep('Initializing the example app', async (step) => {
|
|
36
36
|
await spawnAsync(
|
|
37
|
-
|
|
38
|
-
['
|
|
37
|
+
packageManager,
|
|
38
|
+
['create', 'expo-app', exampleProjectSlug, '--template', 'blank-typescript'],
|
|
39
39
|
{
|
|
40
40
|
cwd: targetDir,
|
|
41
|
-
stdio:
|
|
41
|
+
stdio: 'ignore',
|
|
42
42
|
}
|
|
43
43
|
);
|
|
44
44
|
step.succeed('Initialized the example app');
|
package/src/prompts.ts
CHANGED
|
@@ -4,24 +4,31 @@ import validateNpmPackage from 'validate-npm-package-name';
|
|
|
4
4
|
|
|
5
5
|
import { findGitHubEmail, findGitHubProfileUrl, findMyName, guessRepoUrl } from './utils';
|
|
6
6
|
|
|
7
|
-
export
|
|
8
|
-
const targetBasename = path.basename(
|
|
7
|
+
export function getSlugPrompt(customTargetPath?: string | null): PromptObject<string> {
|
|
8
|
+
const targetBasename = customTargetPath && path.basename(customTargetPath);
|
|
9
|
+
const initial =
|
|
10
|
+
targetBasename && validateNpmPackage(targetBasename).validForNewPackages
|
|
11
|
+
? targetBasename
|
|
12
|
+
: 'my-module';
|
|
9
13
|
|
|
14
|
+
return {
|
|
15
|
+
type: 'text',
|
|
16
|
+
name: 'slug',
|
|
17
|
+
message: 'What is the name of the npm package?',
|
|
18
|
+
initial,
|
|
19
|
+
validate: (input) =>
|
|
20
|
+
validateNpmPackage(input).validForNewPackages || 'Must be a valid npm package name',
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export async function getSubstitutionDataPrompts(slug: string): Promise<PromptObject<string>[]> {
|
|
10
25
|
return [
|
|
11
|
-
{
|
|
12
|
-
type: 'text',
|
|
13
|
-
name: 'slug',
|
|
14
|
-
message: 'What is the name of the npm package?',
|
|
15
|
-
initial: validateNpmPackage(targetBasename).validForNewPackages ? targetBasename : undefined,
|
|
16
|
-
validate: (input) =>
|
|
17
|
-
validateNpmPackage(input).validForNewPackages || 'Must be a valid npm package name',
|
|
18
|
-
},
|
|
19
26
|
{
|
|
20
27
|
type: 'text',
|
|
21
28
|
name: 'name',
|
|
22
29
|
message: 'What is the native module name?',
|
|
23
|
-
initial: (
|
|
24
|
-
return
|
|
30
|
+
initial: () => {
|
|
31
|
+
return slug
|
|
25
32
|
.replace(/^@/, '')
|
|
26
33
|
.replace(/^./, (match) => match.toUpperCase())
|
|
27
34
|
.replace(/\W+(\w)/g, (_, p1) => p1.toUpperCase());
|
|
@@ -39,8 +46,8 @@ export default async function getPrompts(targetDir: string): Promise<PromptObjec
|
|
|
39
46
|
type: 'text',
|
|
40
47
|
name: 'package',
|
|
41
48
|
message: 'What is the Android package name?',
|
|
42
|
-
initial: (
|
|
43
|
-
const namespace =
|
|
49
|
+
initial: () => {
|
|
50
|
+
const namespace = slug
|
|
44
51
|
.replace(/\W/g, '')
|
|
45
52
|
.replace(/^(expo|reactnative)/, '')
|
|
46
53
|
.toLowerCase();
|
|
@@ -72,8 +79,7 @@ export default async function getPrompts(targetDir: string): Promise<PromptObjec
|
|
|
72
79
|
type: 'text',
|
|
73
80
|
name: 'repo',
|
|
74
81
|
message: 'What is the URL for the repository?',
|
|
75
|
-
initial: async (_, answers: Answers<string>) =>
|
|
76
|
-
await guessRepoUrl(answers.authorUrl, answers.slug),
|
|
82
|
+
initial: async (_, answers: Answers<string>) => await guessRepoUrl(answers.authorUrl, slug),
|
|
77
83
|
validate: (input) => /^https?:\/\//.test(input) || 'Must be a valid URL',
|
|
78
84
|
},
|
|
79
85
|
];
|