create-react-native-library 0.44.3 → 0.45.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/lib/{utils → exampleApp}/addCodegenBuildScript.js +8 -2
- package/lib/exampleApp/addCodegenBuildScript.js.map +1 -0
- package/lib/exampleApp/dependencies.js +32 -0
- package/lib/exampleApp/dependencies.js.map +1 -0
- package/lib/{utils → exampleApp}/generateExampleApp.js +2 -2
- package/lib/exampleApp/generateExampleApp.js.map +1 -0
- package/lib/index.js +91 -624
- package/lib/index.js.map +1 -1
- package/lib/inform.js +91 -0
- package/lib/inform.js.map +1 -0
- package/lib/input.js +266 -0
- package/lib/input.js.map +1 -0
- package/lib/template.js +175 -0
- package/lib/template.js.map +1 -0
- package/lib/utils/assert.js +59 -0
- package/lib/utils/assert.js.map +1 -0
- package/lib/utils/initialCommit.js +34 -0
- package/lib/utils/initialCommit.js.map +1 -0
- package/lib/utils/promiseWithFallback.js +25 -0
- package/lib/utils/promiseWithFallback.js.map +1 -0
- package/package.json +2 -2
- package/templates/common/$package.json +2 -2
- package/templates/common/CONTRIBUTING.md +0 -25
- package/templates/common/babel.config.js +1 -3
- package/templates/common/tsconfig.json +1 -0
- package/templates/common-local/$package.json +1 -1
- package/templates/example-module-legacy/example/src/App.tsx +25 -0
- package/templates/example-module-new/example/src/App.tsx +20 -0
- package/templates/example-view/example/src/App.tsx +23 -0
- package/templates/js-library/src/index.tsx +2 -2
- package/templates/kotlin-library-new/android/src/main/java/com/{%- project.package_dir %}/{%- project.name %}Package.kt +2 -2
- package/templates/native-common/android/build.gradle +3 -19
- package/templates/objc-library/ios/{%- project.name %}.h +4 -4
- package/templates/objc-library/ios/{%- project.name %}.mm +1 -6
- package/templates/objc-view-new/ios/{%- project.name %}View.h +0 -3
- package/templates/objc-view-new/ios/{%- project.name %}View.mm +6 -6
- package/lib/utils/addCodegenBuildScript.js.map +0 -1
- package/lib/utils/generateExampleApp.js.map +0 -1
- package/templates/common-example/example/src/App.tsx +0 -57
- package/templates/kotlin-library-mixed/android/src/main/java/com/{%- project.package_dir %}/{%- project.name %}Module.kt +0 -24
- package/templates/kotlin-library-mixed/android/src/main/java/com/{%- project.package_dir %}/{%- project.name %}Package.kt +0 -35
- package/templates/kotlin-library-mixed/android/src/newarch/{%- project.name %}Spec.kt +0 -7
- package/templates/kotlin-library-mixed/android/src/oldarch/{%- project.name %}Spec.kt +0 -11
- package/templates/kotlin-view-mixed/android/src/main/java/com/{%- project.package_dir %}/{%- project.name %}Package.kt +0 -19
- package/templates/kotlin-view-mixed/android/src/main/java/com/{%- project.package_dir %}/{%- project.name %}View.kt +0 -15
- package/templates/kotlin-view-mixed/android/src/main/java/com/{%- project.package_dir %}/{%- project.name %}ViewManager.kt +0 -28
- package/templates/kotlin-view-mixed/android/src/newarch/{%- project.name %}ViewManagerSpec.kt +0 -21
- package/templates/kotlin-view-mixed/android/src/oldarch/{%- project.name %}ViewManagerSpec.kt +0 -9
- package/templates/native-library-mixed/react-native.config.js +0 -16
- package/templates/native-library-mixed/src/Native{%- project.name %}.ts +0 -8
- package/templates/native-library-mixed/src/index.tsx +0 -29
- package/templates/native-view-mixed/react-native.config.js +0 -16
- package/templates/native-view-mixed/src/index.tsx +0 -2
- package/templates/native-view-mixed/src/{%- project.name %}ViewNativeComponent.ts +0 -8
- package/templates/objc-view-mixed/ios/Utils.h +0 -8
- package/templates/objc-view-mixed/ios/Utils.m +0 -26
- package/templates/objc-view-mixed/ios/{%- project.name %}View.h +0 -17
- package/templates/objc-view-mixed/ios/{%- project.name %}View.mm +0 -60
- package/templates/objc-view-mixed/ios/{%- project.name %}ViewManager.mm +0 -23
- /package/templates/{common-example → example-common}/example/metro.config.js +0 -0
package/lib/template.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.applyTemplates = applyTemplates;
|
|
7
|
+
exports.generateTemplateConfiguration = generateTemplateConfiguration;
|
|
8
|
+
var _path = _interopRequireDefault(require("path"));
|
|
9
|
+
var _fsExtra = _interopRequireDefault(require("fs-extra"));
|
|
10
|
+
var _ejs = _interopRequireDefault(require("ejs"));
|
|
11
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
// Please think at least 5 times before introducing a new config key
|
|
13
|
+
// You can just reuse the existing ones most of the time
|
|
14
|
+
|
|
15
|
+
const BINARIES = [/(gradlew|\.(jar|keystore|png|jpg|gif))$/, /\$\.yarn(?![a-z])/];
|
|
16
|
+
const COMMON_FILES = _path.default.resolve(__dirname, '../templates/common');
|
|
17
|
+
const COMMON_LOCAL_FILES = _path.default.resolve(__dirname, '../templates/common-local');
|
|
18
|
+
const EXAMPLE_COMMON_FILES = _path.default.resolve(__dirname, '../templates/example-common');
|
|
19
|
+
const EXAMPLE_MODULE_LEGACY_FILES = _path.default.resolve(__dirname, '../templates/example-module-legacy');
|
|
20
|
+
const EXAMPLE_MODULE_NEW_FILES = _path.default.resolve(__dirname, '../templates/example-module-new');
|
|
21
|
+
const EXAMPLE_VIEW_FILES = _path.default.resolve(__dirname, '../templates/example-view');
|
|
22
|
+
const JS_FILES = _path.default.resolve(__dirname, '../templates/js-library');
|
|
23
|
+
const EXPO_FILES = _path.default.resolve(__dirname, '../templates/expo-library');
|
|
24
|
+
const CPP_FILES = _path.default.resolve(__dirname, '../templates/cpp-library');
|
|
25
|
+
const NATIVE_COMMON_FILES = _path.default.resolve(__dirname, '../templates/native-common');
|
|
26
|
+
const NATIVE_COMMON_EXAMPLE_FILES = _path.default.resolve(__dirname, '../templates/native-common-example');
|
|
27
|
+
const NATIVE_FILES = {
|
|
28
|
+
module_legacy: _path.default.resolve(__dirname, '../templates/native-library-legacy'),
|
|
29
|
+
module_new: _path.default.resolve(__dirname, '../templates/native-library-new'),
|
|
30
|
+
view_legacy: _path.default.resolve(__dirname, '../templates/native-view-legacy'),
|
|
31
|
+
view_new: _path.default.resolve(__dirname, '../templates/native-view-new')
|
|
32
|
+
};
|
|
33
|
+
const OBJC_FILES = {
|
|
34
|
+
module_common: _path.default.resolve(__dirname, '../templates/objc-library'),
|
|
35
|
+
view_legacy: _path.default.resolve(__dirname, '../templates/objc-view-legacy'),
|
|
36
|
+
view_new: _path.default.resolve(__dirname, '../templates/objc-view-new')
|
|
37
|
+
};
|
|
38
|
+
const KOTLIN_FILES = {
|
|
39
|
+
module_legacy: _path.default.resolve(__dirname, '../templates/kotlin-library-legacy'),
|
|
40
|
+
module_new: _path.default.resolve(__dirname, '../templates/kotlin-library-new'),
|
|
41
|
+
view_legacy: _path.default.resolve(__dirname, '../templates/kotlin-view-legacy'),
|
|
42
|
+
view_new: _path.default.resolve(__dirname, '../templates/kotlin-view-new')
|
|
43
|
+
};
|
|
44
|
+
const SWIFT_FILES = {
|
|
45
|
+
module_legacy: _path.default.resolve(__dirname, '../templates/swift-library-legacy'),
|
|
46
|
+
view_legacy: _path.default.resolve(__dirname, '../templates/swift-view-legacy')
|
|
47
|
+
};
|
|
48
|
+
function generateTemplateConfiguration({
|
|
49
|
+
bobVersion,
|
|
50
|
+
basename,
|
|
51
|
+
answers
|
|
52
|
+
}) {
|
|
53
|
+
const {
|
|
54
|
+
slug,
|
|
55
|
+
languages,
|
|
56
|
+
type
|
|
57
|
+
} = answers;
|
|
58
|
+
const arch = type === 'module-legacy' || type === 'view-legacy' ? 'legacy' : 'new';
|
|
59
|
+
const project = slug.replace(/^(react-native-|@[^/]+\/)/, '');
|
|
60
|
+
let namespace;
|
|
61
|
+
if (slug.startsWith('@') && slug.includes('/')) {
|
|
62
|
+
namespace = slug.split('/')[0]?.replace(/[^a-z0-9]/g, '').toLowerCase();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Create a package identifier with specified namespace when possible
|
|
66
|
+
const pack = `${namespace ? `${namespace}.` : ''}${project.replace(/[^a-z0-9]/g, '').toLowerCase()}`;
|
|
67
|
+
return {
|
|
68
|
+
bob: {
|
|
69
|
+
version: bobVersion
|
|
70
|
+
},
|
|
71
|
+
project: {
|
|
72
|
+
slug,
|
|
73
|
+
description: answers.description,
|
|
74
|
+
name: /^[A-Z]/.test(basename) && /^[a-z0-9]+$/i.test(basename) ?
|
|
75
|
+
// If the project name is already in PascalCase, use it as-is
|
|
76
|
+
basename :
|
|
77
|
+
// Otherwise, convert it to PascalCase and remove any non-alphanumeric characters
|
|
78
|
+
`${project.charAt(0).toUpperCase()}${project.replace(/[^a-z0-9](\w)/g, (_, $1) => $1.toUpperCase()).slice(1)}`,
|
|
79
|
+
package: pack,
|
|
80
|
+
package_dir: pack.replace(/\./g, '/'),
|
|
81
|
+
package_cpp: pack.replace(/\./g, '_'),
|
|
82
|
+
identifier: slug.replace(/[^a-z0-9]+/g, '-').replace(/^-/, ''),
|
|
83
|
+
native: languages !== 'js',
|
|
84
|
+
arch,
|
|
85
|
+
cpp: languages === 'cpp',
|
|
86
|
+
swift: languages === 'kotlin-swift',
|
|
87
|
+
view: answers.type.startsWith('view'),
|
|
88
|
+
module: answers.type.startsWith('module')
|
|
89
|
+
},
|
|
90
|
+
author: {
|
|
91
|
+
name: answers.authorName,
|
|
92
|
+
email: answers.authorEmail,
|
|
93
|
+
url: answers.authorUrl
|
|
94
|
+
},
|
|
95
|
+
repo: answers.repoUrl,
|
|
96
|
+
example: answers.example,
|
|
97
|
+
year: new Date().getFullYear()
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
async function applyTemplates(answers, config, folder) {
|
|
101
|
+
const {
|
|
102
|
+
local
|
|
103
|
+
} = answers;
|
|
104
|
+
if (local) {
|
|
105
|
+
await applyTemplate(config, COMMON_LOCAL_FILES, folder);
|
|
106
|
+
} else {
|
|
107
|
+
await applyTemplate(config, COMMON_FILES, folder);
|
|
108
|
+
if (config.example !== 'none') {
|
|
109
|
+
await applyTemplate(config, EXAMPLE_COMMON_FILES, folder);
|
|
110
|
+
if (config.project.view) {
|
|
111
|
+
await applyTemplate(config, EXAMPLE_VIEW_FILES, folder);
|
|
112
|
+
} else {
|
|
113
|
+
if (config.project.arch === 'legacy') {
|
|
114
|
+
await applyTemplate(config, EXAMPLE_MODULE_LEGACY_FILES, folder);
|
|
115
|
+
} else {
|
|
116
|
+
await applyTemplate(config, EXAMPLE_MODULE_NEW_FILES, folder);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (answers.languages === 'js') {
|
|
122
|
+
await applyTemplate(config, JS_FILES, folder);
|
|
123
|
+
await applyTemplate(config, EXPO_FILES, folder);
|
|
124
|
+
} else {
|
|
125
|
+
await applyTemplate(config, NATIVE_COMMON_FILES, folder);
|
|
126
|
+
if (config.example !== 'none') {
|
|
127
|
+
await applyTemplate(config, NATIVE_COMMON_EXAMPLE_FILES, folder);
|
|
128
|
+
}
|
|
129
|
+
if (config.project.module) {
|
|
130
|
+
await applyTemplate(config, NATIVE_FILES[`module_${config.project.arch}`], folder);
|
|
131
|
+
} else {
|
|
132
|
+
await applyTemplate(config, NATIVE_FILES[`view_${config.project.arch}`], folder);
|
|
133
|
+
}
|
|
134
|
+
if (config.project.swift) {
|
|
135
|
+
await applyTemplate(config, SWIFT_FILES[`module_legacy`], folder);
|
|
136
|
+
} else {
|
|
137
|
+
if (config.project.module) {
|
|
138
|
+
await applyTemplate(config, OBJC_FILES[`module_common`], folder);
|
|
139
|
+
} else {
|
|
140
|
+
await applyTemplate(config, OBJC_FILES[`view_${config.project.arch}`], folder);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
const templateType = `${config.project.module ? 'module' : 'view'}_${config.project.arch}`;
|
|
144
|
+
await applyTemplate(config, KOTLIN_FILES[templateType], folder);
|
|
145
|
+
if (config.project.cpp) {
|
|
146
|
+
await applyTemplate(config, CPP_FILES, folder);
|
|
147
|
+
await _fsExtra.default.remove(_path.default.join(folder, 'ios', `${config.project.name}.m`));
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* This copies the template files and renders them via ejs
|
|
154
|
+
*/
|
|
155
|
+
async function applyTemplate(config, source, destination) {
|
|
156
|
+
await _fsExtra.default.mkdirp(destination);
|
|
157
|
+
const files = await _fsExtra.default.readdir(source);
|
|
158
|
+
for (const f of files) {
|
|
159
|
+
const target = _path.default.join(destination, _ejs.default.render(f.replace(/^\$/, ''), config, {
|
|
160
|
+
openDelimiter: '{',
|
|
161
|
+
closeDelimiter: '}'
|
|
162
|
+
}));
|
|
163
|
+
const file = _path.default.join(source, f);
|
|
164
|
+
const stats = await _fsExtra.default.stat(file);
|
|
165
|
+
if (stats.isDirectory()) {
|
|
166
|
+
await applyTemplate(config, file, target);
|
|
167
|
+
} else if (!BINARIES.some(r => r.test(file))) {
|
|
168
|
+
const content = await _fsExtra.default.readFile(file, 'utf8');
|
|
169
|
+
await _fsExtra.default.writeFile(target, _ejs.default.render(content, config));
|
|
170
|
+
} else {
|
|
171
|
+
await _fsExtra.default.copyFile(file, target);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
//# sourceMappingURL=template.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template.js","names":["_path","_interopRequireDefault","require","_fsExtra","_ejs","e","__esModule","default","BINARIES","COMMON_FILES","path","resolve","__dirname","COMMON_LOCAL_FILES","EXAMPLE_COMMON_FILES","EXAMPLE_MODULE_LEGACY_FILES","EXAMPLE_MODULE_NEW_FILES","EXAMPLE_VIEW_FILES","JS_FILES","EXPO_FILES","CPP_FILES","NATIVE_COMMON_FILES","NATIVE_COMMON_EXAMPLE_FILES","NATIVE_FILES","module_legacy","module_new","view_legacy","view_new","OBJC_FILES","module_common","KOTLIN_FILES","SWIFT_FILES","generateTemplateConfiguration","bobVersion","basename","answers","slug","languages","type","arch","project","replace","namespace","startsWith","includes","split","toLowerCase","pack","bob","version","description","name","test","charAt","toUpperCase","_","$1","slice","package","package_dir","package_cpp","identifier","native","cpp","swift","view","module","author","authorName","email","authorEmail","url","authorUrl","repo","repoUrl","example","year","Date","getFullYear","applyTemplates","config","folder","local","applyTemplate","templateType","fs","remove","join","source","destination","mkdirp","files","readdir","f","target","ejs","render","openDelimiter","closeDelimiter","file","stats","stat","isDirectory","some","r","content","readFile","writeFile","copyFile"],"sources":["../src/template.ts"],"sourcesContent":["import path from 'path';\nimport fs from 'fs-extra';\nimport ejs from 'ejs';\nimport type { Answers, ExampleApp, SupportedArchitecture } from './input';\n\n// Please think at least 5 times before introducing a new config key\n// You can just reuse the existing ones most of the time\nexport type TemplateConfiguration = {\n bob: {\n version: string;\n };\n project: {\n slug: string;\n description: string;\n name: string;\n package: string;\n package_dir: string;\n package_cpp: string;\n identifier: string;\n native: boolean;\n arch: SupportedArchitecture;\n cpp: boolean;\n swift: boolean;\n view: boolean;\n module: boolean;\n };\n author: {\n name: string;\n email: string;\n url: string;\n };\n repo: string;\n example: ExampleApp;\n year: number;\n};\n\nconst BINARIES = [\n /(gradlew|\\.(jar|keystore|png|jpg|gif))$/,\n /\\$\\.yarn(?![a-z])/,\n];\n\nconst COMMON_FILES = path.resolve(__dirname, '../templates/common');\nconst COMMON_LOCAL_FILES = path.resolve(__dirname, '../templates/common-local');\nconst EXAMPLE_COMMON_FILES = path.resolve(\n __dirname,\n '../templates/example-common'\n);\nconst EXAMPLE_MODULE_LEGACY_FILES = path.resolve(\n __dirname,\n '../templates/example-module-legacy'\n);\nconst EXAMPLE_MODULE_NEW_FILES = path.resolve(\n __dirname,\n '../templates/example-module-new'\n);\nconst EXAMPLE_VIEW_FILES = path.resolve(__dirname, '../templates/example-view');\n\nconst JS_FILES = path.resolve(__dirname, '../templates/js-library');\nconst EXPO_FILES = path.resolve(__dirname, '../templates/expo-library');\nconst CPP_FILES = path.resolve(__dirname, '../templates/cpp-library');\nconst NATIVE_COMMON_FILES = path.resolve(\n __dirname,\n '../templates/native-common'\n);\nconst NATIVE_COMMON_EXAMPLE_FILES = path.resolve(\n __dirname,\n '../templates/native-common-example'\n);\n\nconst NATIVE_FILES = {\n module_legacy: path.resolve(__dirname, '../templates/native-library-legacy'),\n module_new: path.resolve(__dirname, '../templates/native-library-new'),\n view_legacy: path.resolve(__dirname, '../templates/native-view-legacy'),\n view_new: path.resolve(__dirname, '../templates/native-view-new'),\n} as const;\n\nconst OBJC_FILES = {\n module_common: path.resolve(__dirname, '../templates/objc-library'),\n view_legacy: path.resolve(__dirname, '../templates/objc-view-legacy'),\n view_new: path.resolve(__dirname, '../templates/objc-view-new'),\n} as const;\n\nconst KOTLIN_FILES = {\n module_legacy: path.resolve(__dirname, '../templates/kotlin-library-legacy'),\n module_new: path.resolve(__dirname, '../templates/kotlin-library-new'),\n view_legacy: path.resolve(__dirname, '../templates/kotlin-view-legacy'),\n view_new: path.resolve(__dirname, '../templates/kotlin-view-new'),\n} as const;\n\nconst SWIFT_FILES = {\n module_legacy: path.resolve(__dirname, '../templates/swift-library-legacy'),\n view_legacy: path.resolve(__dirname, '../templates/swift-view-legacy'),\n} as const;\n\nexport function generateTemplateConfiguration({\n bobVersion,\n basename,\n answers,\n}: {\n bobVersion: string;\n basename: string;\n answers: Required<Answers>;\n}): TemplateConfiguration {\n const { slug, languages, type } = answers;\n\n const arch =\n type === 'module-legacy' || type === 'view-legacy' ? 'legacy' : 'new';\n\n const project = slug.replace(/^(react-native-|@[^/]+\\/)/, '');\n let namespace: string | undefined;\n\n if (slug.startsWith('@') && slug.includes('/')) {\n namespace = slug\n .split('/')[0]\n ?.replace(/[^a-z0-9]/g, '')\n .toLowerCase();\n }\n\n // Create a package identifier with specified namespace when possible\n const pack = `${namespace ? `${namespace}.` : ''}${project\n .replace(/[^a-z0-9]/g, '')\n .toLowerCase()}`;\n\n return {\n bob: {\n version: bobVersion,\n },\n project: {\n slug,\n description: answers.description,\n name:\n /^[A-Z]/.test(basename) && /^[a-z0-9]+$/i.test(basename)\n ? // If the project name is already in PascalCase, use it as-is\n basename\n : // Otherwise, convert it to PascalCase and remove any non-alphanumeric characters\n `${project.charAt(0).toUpperCase()}${project\n .replace(/[^a-z0-9](\\w)/g, (_, $1) => $1.toUpperCase())\n .slice(1)}`,\n package: pack,\n package_dir: pack.replace(/\\./g, '/'),\n package_cpp: pack.replace(/\\./g, '_'),\n identifier: slug.replace(/[^a-z0-9]+/g, '-').replace(/^-/, ''),\n native: languages !== 'js',\n arch,\n cpp: languages === 'cpp',\n swift: languages === 'kotlin-swift',\n view: answers.type.startsWith('view'),\n module: answers.type.startsWith('module'),\n },\n author: {\n name: answers.authorName,\n email: answers.authorEmail,\n url: answers.authorUrl,\n },\n repo: answers.repoUrl,\n example: answers.example,\n year: new Date().getFullYear(),\n };\n}\n\nexport async function applyTemplates(\n answers: Answers,\n config: TemplateConfiguration,\n folder: string\n) {\n const { local } = answers;\n if (local) {\n await applyTemplate(config, COMMON_LOCAL_FILES, folder);\n } else {\n await applyTemplate(config, COMMON_FILES, folder);\n\n if (config.example !== 'none') {\n await applyTemplate(config, EXAMPLE_COMMON_FILES, folder);\n\n if (config.project.view) {\n await applyTemplate(config, EXAMPLE_VIEW_FILES, folder);\n } else {\n if (config.project.arch === 'legacy') {\n await applyTemplate(config, EXAMPLE_MODULE_LEGACY_FILES, folder);\n } else {\n await applyTemplate(config, EXAMPLE_MODULE_NEW_FILES, folder);\n }\n }\n }\n }\n\n if (answers.languages === 'js') {\n await applyTemplate(config, JS_FILES, folder);\n await applyTemplate(config, EXPO_FILES, folder);\n } else {\n await applyTemplate(config, NATIVE_COMMON_FILES, folder);\n\n if (config.example !== 'none') {\n await applyTemplate(config, NATIVE_COMMON_EXAMPLE_FILES, folder);\n }\n\n if (config.project.module) {\n await applyTemplate(\n config,\n NATIVE_FILES[`module_${config.project.arch}`],\n folder\n );\n } else {\n await applyTemplate(\n config,\n NATIVE_FILES[`view_${config.project.arch}`],\n folder\n );\n }\n\n if (config.project.swift) {\n await applyTemplate(config, SWIFT_FILES[`module_legacy`], folder);\n } else {\n if (config.project.module) {\n await applyTemplate(config, OBJC_FILES[`module_common`], folder);\n } else {\n await applyTemplate(\n config,\n OBJC_FILES[`view_${config.project.arch}`],\n folder\n );\n }\n }\n\n const templateType = `${config.project.module ? 'module' : 'view'}_${\n config.project.arch\n }` as const;\n\n await applyTemplate(config, KOTLIN_FILES[templateType], folder);\n\n if (config.project.cpp) {\n await applyTemplate(config, CPP_FILES, folder);\n await fs.remove(path.join(folder, 'ios', `${config.project.name}.m`));\n }\n }\n}\n\n/**\n * This copies the template files and renders them via ejs\n */\nasync function applyTemplate(\n config: TemplateConfiguration,\n source: string,\n destination: string\n) {\n await fs.mkdirp(destination);\n\n const files = await fs.readdir(source);\n\n for (const f of files) {\n const target = path.join(\n destination,\n ejs.render(f.replace(/^\\$/, ''), config, {\n openDelimiter: '{',\n closeDelimiter: '}',\n })\n );\n\n const file = path.join(source, f);\n const stats = await fs.stat(file);\n\n if (stats.isDirectory()) {\n await applyTemplate(config, file, target);\n } else if (!BINARIES.some((r) => r.test(file))) {\n const content = await fs.readFile(file, 'utf8');\n\n await fs.writeFile(target, ejs.render(content, config));\n } else {\n await fs.copyFile(file, target);\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.assertNpxExists = assertNpxExists;
|
|
7
|
+
exports.assertUserInput = assertUserInput;
|
|
8
|
+
var _kleur = _interopRequireDefault(require("kleur"));
|
|
9
|
+
var _spawn = require("./spawn");
|
|
10
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
+
async function assertNpxExists() {
|
|
12
|
+
try {
|
|
13
|
+
await (0, _spawn.spawn)('npx', ['--help']);
|
|
14
|
+
} catch (error) {
|
|
15
|
+
// @ts-expect-error: TS doesn't know about `code`
|
|
16
|
+
if (error != null && error.code === 'ENOENT') {
|
|
17
|
+
console.log(`Couldn't find ${_kleur.default.blue('npx')}! Please install it by running ${_kleur.default.blue('npm install -g npx')}`);
|
|
18
|
+
process.exit(1);
|
|
19
|
+
} else {
|
|
20
|
+
throw error;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Makes sure the answers are in expected form and ends the process with error if they are not
|
|
27
|
+
*/
|
|
28
|
+
function assertUserInput(questions, answers) {
|
|
29
|
+
for (const [key, value] of Object.entries(answers)) {
|
|
30
|
+
if (value == null) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
const question = questions.find(q => q.name === key);
|
|
34
|
+
if (question == null) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
let valid = question.validate ? question.validate(String(value)) : true;
|
|
38
|
+
|
|
39
|
+
// We also need to guard against invalid choices
|
|
40
|
+
// If we don't already have a validation message to provide a better error
|
|
41
|
+
if (typeof valid !== 'string' && 'choices' in question) {
|
|
42
|
+
const choices = typeof question.choices === 'function' ? question.choices(undefined,
|
|
43
|
+
// @ts-expect-error: it complains about optional values, but it should be fine
|
|
44
|
+
answers, question) : question.choices;
|
|
45
|
+
if (choices && !choices.some(choice => choice.value === value)) {
|
|
46
|
+
valid = `Supported values are - ${choices.map(c => _kleur.default.green(c.value))}`;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
if (valid !== true) {
|
|
50
|
+
let message = `Invalid value ${_kleur.default.red(String(value))} passed for ${_kleur.default.blue(key)}`;
|
|
51
|
+
if (typeof valid === 'string') {
|
|
52
|
+
message += `: ${valid}`;
|
|
53
|
+
}
|
|
54
|
+
console.log(message);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=assert.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assert.js","names":["_kleur","_interopRequireDefault","require","_spawn","e","__esModule","default","assertNpxExists","spawn","error","code","console","log","kleur","blue","process","exit","assertUserInput","questions","answers","key","value","Object","entries","question","find","q","name","valid","validate","String","choices","undefined","some","choice","map","c","green","message","red"],"sources":["../../src/utils/assert.ts"],"sourcesContent":["import kleur from 'kleur';\nimport { spawn } from './spawn';\nimport type { Answers, Args, Question } from '../input';\n\nexport async function assertNpxExists() {\n try {\n await spawn('npx', ['--help']);\n } catch (error) {\n // @ts-expect-error: TS doesn't know about `code`\n if (error != null && error.code === 'ENOENT') {\n console.log(\n `Couldn't find ${kleur.blue(\n 'npx'\n )}! Please install it by running ${kleur.blue('npm install -g npx')}`\n );\n\n process.exit(1);\n } else {\n throw error;\n }\n }\n}\n\n/**\n * Makes sure the answers are in expected form and ends the process with error if they are not\n */\nexport function assertUserInput(\n questions: Question[],\n answers: Answers | Args\n) {\n for (const [key, value] of Object.entries(answers)) {\n if (value == null) {\n continue;\n }\n\n const question = questions.find((q) => q.name === key);\n\n if (question == null) {\n continue;\n }\n\n let valid = question.validate ? question.validate(String(value)) : true;\n\n // We also need to guard against invalid choices\n // If we don't already have a validation message to provide a better error\n if (typeof valid !== 'string' && 'choices' in question) {\n const choices =\n typeof question.choices === 'function'\n ? question.choices(\n undefined,\n // @ts-expect-error: it complains about optional values, but it should be fine\n answers,\n question\n )\n : question.choices;\n\n if (choices && !choices.some((choice) => choice.value === value)) {\n valid = `Supported values are - ${choices.map((c) =>\n kleur.green(c.value)\n )}`;\n }\n }\n\n if (valid !== true) {\n let message = `Invalid value ${kleur.red(\n String(value)\n )} passed for ${kleur.blue(key)}`;\n\n if (typeof valid === 'string') {\n message += `: ${valid}`;\n }\n\n console.log(message);\n\n process.exit(1);\n }\n }\n}\n"],"mappings":";;;;;;;AAAA,IAAAA,MAAA,GAAAC,sBAAA,CAAAC,OAAA;AACA,IAAAC,MAAA,GAAAD,OAAA;AAAgC,SAAAD,uBAAAG,CAAA,WAAAA,CAAA,IAAAA,CAAA,CAAAC,UAAA,GAAAD,CAAA,KAAAE,OAAA,EAAAF,CAAA;AAGzB,eAAeG,eAAeA,CAAA,EAAG;EACtC,IAAI;IACF,MAAM,IAAAC,YAAK,EAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,CAAC;EAChC,CAAC,CAAC,OAAOC,KAAK,EAAE;IACd;IACA,IAAIA,KAAK,IAAI,IAAI,IAAIA,KAAK,CAACC,IAAI,KAAK,QAAQ,EAAE;MAC5CC,OAAO,CAACC,GAAG,CACT,iBAAiBC,cAAK,CAACC,IAAI,CACzB,KACF,CAAC,kCAAkCD,cAAK,CAACC,IAAI,CAAC,oBAAoB,CAAC,EACrE,CAAC;MAEDC,OAAO,CAACC,IAAI,CAAC,CAAC,CAAC;IACjB,CAAC,MAAM;MACL,MAAMP,KAAK;IACb;EACF;AACF;;AAEA;AACA;AACA;AACO,SAASQ,eAAeA,CAC7BC,SAAqB,EACrBC,OAAuB,EACvB;EACA,KAAK,MAAM,CAACC,GAAG,EAAEC,KAAK,CAAC,IAAIC,MAAM,CAACC,OAAO,CAACJ,OAAO,CAAC,EAAE;IAClD,IAAIE,KAAK,IAAI,IAAI,EAAE;MACjB;IACF;IAEA,MAAMG,QAAQ,GAAGN,SAAS,CAACO,IAAI,CAAEC,CAAC,IAAKA,CAAC,CAACC,IAAI,KAAKP,GAAG,CAAC;IAEtD,IAAII,QAAQ,IAAI,IAAI,EAAE;MACpB;IACF;IAEA,IAAII,KAAK,GAAGJ,QAAQ,CAACK,QAAQ,GAAGL,QAAQ,CAACK,QAAQ,CAACC,MAAM,CAACT,KAAK,CAAC,CAAC,GAAG,IAAI;;IAEvE;IACA;IACA,IAAI,OAAOO,KAAK,KAAK,QAAQ,IAAI,SAAS,IAAIJ,QAAQ,EAAE;MACtD,MAAMO,OAAO,GACX,OAAOP,QAAQ,CAACO,OAAO,KAAK,UAAU,GAClCP,QAAQ,CAACO,OAAO,CACdC,SAAS;MACT;MACAb,OAAO,EACPK,QACF,CAAC,GACDA,QAAQ,CAACO,OAAO;MAEtB,IAAIA,OAAO,IAAI,CAACA,OAAO,CAACE,IAAI,CAAEC,MAAM,IAAKA,MAAM,CAACb,KAAK,KAAKA,KAAK,CAAC,EAAE;QAChEO,KAAK,GAAG,0BAA0BG,OAAO,CAACI,GAAG,CAAEC,CAAC,IAC9CvB,cAAK,CAACwB,KAAK,CAACD,CAAC,CAACf,KAAK,CACrB,CAAC,EAAE;MACL;IACF;IAEA,IAAIO,KAAK,KAAK,IAAI,EAAE;MAClB,IAAIU,OAAO,GAAG,iBAAiBzB,cAAK,CAAC0B,GAAG,CACtCT,MAAM,CAACT,KAAK,CACd,CAAC,eAAeR,cAAK,CAACC,IAAI,CAACM,GAAG,CAAC,EAAE;MAEjC,IAAI,OAAOQ,KAAK,KAAK,QAAQ,EAAE;QAC7BU,OAAO,IAAI,KAAKV,KAAK,EAAE;MACzB;MAEAjB,OAAO,CAACC,GAAG,CAAC0B,OAAO,CAAC;MAEpBvB,OAAO,CAACC,IAAI,CAAC,CAAC,CAAC;IACjB;EACF;AACF","ignoreList":[]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.createInitialGitCommit = createInitialGitCommit;
|
|
7
|
+
var _spawn = require("./spawn");
|
|
8
|
+
async function createInitialGitCommit(folder) {
|
|
9
|
+
let isInGitRepo = false;
|
|
10
|
+
try {
|
|
11
|
+
isInGitRepo = (await (0, _spawn.spawn)('git', ['rev-parse', '--is-inside-work-tree'])) === 'true';
|
|
12
|
+
} catch (e) {
|
|
13
|
+
// Ignore error
|
|
14
|
+
}
|
|
15
|
+
if (!isInGitRepo) {
|
|
16
|
+
try {
|
|
17
|
+
await (0, _spawn.spawn)('git', ['init'], {
|
|
18
|
+
cwd: folder
|
|
19
|
+
});
|
|
20
|
+
await (0, _spawn.spawn)('git', ['branch', '-M', 'main'], {
|
|
21
|
+
cwd: folder
|
|
22
|
+
});
|
|
23
|
+
await (0, _spawn.spawn)('git', ['add', '.'], {
|
|
24
|
+
cwd: folder
|
|
25
|
+
});
|
|
26
|
+
await (0, _spawn.spawn)('git', ['commit', '-m', 'chore: initial commit'], {
|
|
27
|
+
cwd: folder
|
|
28
|
+
});
|
|
29
|
+
} catch (e) {
|
|
30
|
+
// Ignore error
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=initialCommit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"initialCommit.js","names":["_spawn","require","createInitialGitCommit","folder","isInGitRepo","spawn","e","cwd"],"sources":["../../src/utils/initialCommit.ts"],"sourcesContent":["import { spawn } from './spawn';\n\nexport async function createInitialGitCommit(folder: string) {\n let isInGitRepo = false;\n\n try {\n isInGitRepo =\n (await spawn('git', ['rev-parse', '--is-inside-work-tree'])) === 'true';\n } catch (e) {\n // Ignore error\n }\n\n if (!isInGitRepo) {\n try {\n await spawn('git', ['init'], { cwd: folder });\n await spawn('git', ['branch', '-M', 'main'], { cwd: folder });\n await spawn('git', ['add', '.'], { cwd: folder });\n await spawn('git', ['commit', '-m', 'chore: initial commit'], {\n cwd: folder,\n });\n } catch (e) {\n // Ignore error\n }\n }\n}\n"],"mappings":";;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAEO,eAAeC,sBAAsBA,CAACC,MAAc,EAAE;EAC3D,IAAIC,WAAW,GAAG,KAAK;EAEvB,IAAI;IACFA,WAAW,GACT,CAAC,MAAM,IAAAC,YAAK,EAAC,KAAK,EAAE,CAAC,WAAW,EAAE,uBAAuB,CAAC,CAAC,MAAM,MAAM;EAC3E,CAAC,CAAC,OAAOC,CAAC,EAAE;IACV;EAAA;EAGF,IAAI,CAACF,WAAW,EAAE;IAChB,IAAI;MACF,MAAM,IAAAC,YAAK,EAAC,KAAK,EAAE,CAAC,MAAM,CAAC,EAAE;QAAEE,GAAG,EAAEJ;MAAO,CAAC,CAAC;MAC7C,MAAM,IAAAE,YAAK,EAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,EAAE;QAAEE,GAAG,EAAEJ;MAAO,CAAC,CAAC;MAC7D,MAAM,IAAAE,YAAK,EAAC,KAAK,EAAE,CAAC,KAAK,EAAE,GAAG,CAAC,EAAE;QAAEE,GAAG,EAAEJ;MAAO,CAAC,CAAC;MACjD,MAAM,IAAAE,YAAK,EAAC,KAAK,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,uBAAuB,CAAC,EAAE;QAC5DE,GAAG,EAAEJ;MACP,CAAC,CAAC;IACJ,CAAC,CAAC,OAAOG,CAAC,EAAE;MACV;IAAA;EAEJ;AACF","ignoreList":[]}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.promiseWithFallback = promiseWithFallback;
|
|
7
|
+
exports.resolveBobVersionWithFallback = void 0;
|
|
8
|
+
var _spawn = require("./spawn");
|
|
9
|
+
function promiseWithFallback(promise, fallback, timeout) {
|
|
10
|
+
async function forceResolve() {
|
|
11
|
+
let result;
|
|
12
|
+
try {
|
|
13
|
+
result = await Promise.race([new Promise(resolve => {
|
|
14
|
+
setTimeout(() => resolve(fallback), timeout);
|
|
15
|
+
}), promise]);
|
|
16
|
+
} catch (e) {
|
|
17
|
+
result = fallback;
|
|
18
|
+
}
|
|
19
|
+
return result;
|
|
20
|
+
}
|
|
21
|
+
return forceResolve;
|
|
22
|
+
}
|
|
23
|
+
const resolveBobVersionWithFallback = fallback => promiseWithFallback((0, _spawn.spawn)('npm', ['view', 'react-native-builder-bob', 'dist-tags.latest']), fallback, 1000);
|
|
24
|
+
exports.resolveBobVersionWithFallback = resolveBobVersionWithFallback;
|
|
25
|
+
//# sourceMappingURL=promiseWithFallback.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"promiseWithFallback.js","names":["_spawn","require","promiseWithFallback","promise","fallback","timeout","forceResolve","result","Promise","race","resolve","setTimeout","e","resolveBobVersionWithFallback","spawn","exports"],"sources":["../../src/utils/promiseWithFallback.ts"],"sourcesContent":["import { spawn } from './spawn';\n\nexport function promiseWithFallback<T>(\n promise: Promise<T>,\n fallback: T,\n timeout: number\n): () => Promise<T> {\n async function forceResolve() {\n let result: T;\n\n try {\n result = await Promise.race([\n new Promise<T>((resolve) => {\n setTimeout(() => resolve(fallback), timeout);\n }),\n promise,\n ]);\n } catch (e) {\n result = fallback;\n }\n return result;\n }\n\n return forceResolve;\n}\n\nexport const resolveBobVersionWithFallback = (fallback: string) =>\n promiseWithFallback(\n spawn('npm', ['view', 'react-native-builder-bob', 'dist-tags.latest']),\n fallback,\n 1000\n );\n"],"mappings":";;;;;;;AAAA,IAAAA,MAAA,GAAAC,OAAA;AAEO,SAASC,mBAAmBA,CACjCC,OAAmB,EACnBC,QAAW,EACXC,OAAe,EACG;EAClB,eAAeC,YAAYA,CAAA,EAAG;IAC5B,IAAIC,MAAS;IAEb,IAAI;MACFA,MAAM,GAAG,MAAMC,OAAO,CAACC,IAAI,CAAC,CAC1B,IAAID,OAAO,CAAKE,OAAO,IAAK;QAC1BC,UAAU,CAAC,MAAMD,OAAO,CAACN,QAAQ,CAAC,EAAEC,OAAO,CAAC;MAC9C,CAAC,CAAC,EACFF,OAAO,CACR,CAAC;IACJ,CAAC,CAAC,OAAOS,CAAC,EAAE;MACVL,MAAM,GAAGH,QAAQ;IACnB;IACA,OAAOG,MAAM;EACf;EAEA,OAAOD,YAAY;AACrB;AAEO,MAAMO,6BAA6B,GAAIT,QAAgB,IAC5DF,mBAAmB,CACjB,IAAAY,YAAK,EAAC,KAAK,EAAE,CAAC,MAAM,EAAE,0BAA0B,EAAE,kBAAkB,CAAC,CAAC,EACtEV,QAAQ,EACR,IACF,CAAC;AAACW,OAAA,CAAAF,6BAAA,GAAAA,6BAAA","ignoreList":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-react-native-library",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.45.0",
|
|
4
4
|
"description": "CLI to scaffold React Native libraries",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"react-native",
|
|
@@ -65,5 +65,5 @@
|
|
|
65
65
|
"@types/validate-npm-package-name": "^3.0.3",
|
|
66
66
|
"@types/yargs": "^17.0.10"
|
|
67
67
|
},
|
|
68
|
-
"gitHead": "
|
|
68
|
+
"gitHead": "50bfbb8d45358ad97b336266d06e1a60228f56e7"
|
|
69
69
|
}
|
|
@@ -198,7 +198,7 @@
|
|
|
198
198
|
},
|
|
199
199
|
"codegenConfig": {
|
|
200
200
|
"name": "RN<%- project.name -%><%- project.view ? 'View': '' -%>Spec",
|
|
201
|
-
"type": "<%- project.view ? '
|
|
201
|
+
"type": "<%- project.view ? 'all': 'modules' -%>",
|
|
202
202
|
"jsSrcsDir": "src",
|
|
203
203
|
"outputDir": {
|
|
204
204
|
"ios": "ios/generated",
|
|
@@ -209,7 +209,7 @@
|
|
|
209
209
|
<% if (example === 'vanilla') { -%>
|
|
210
210
|
},
|
|
211
211
|
"includesGeneratedCode": true
|
|
212
|
-
<% } else { -%>
|
|
212
|
+
<% } else { -%>
|
|
213
213
|
}
|
|
214
214
|
<% } -%>
|
|
215
215
|
<% } -%>
|
|
@@ -49,31 +49,6 @@ To run the example app on iOS:
|
|
|
49
49
|
yarn example ios
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
-
<% if (project.arch === 'mixed') { -%>
|
|
53
|
-
By default, the example is configured to build with the old architecture. To run the example with the new architecture, you can do the following:
|
|
54
|
-
|
|
55
|
-
1. For Android, run:
|
|
56
|
-
|
|
57
|
-
```sh
|
|
58
|
-
ORG_GRADLE_PROJECT_newArchEnabled=true yarn example android
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
2. For iOS, run:
|
|
62
|
-
|
|
63
|
-
```sh
|
|
64
|
-
cd example/ios
|
|
65
|
-
RCT_NEW_ARCH_ENABLED=1 pod install
|
|
66
|
-
cd -
|
|
67
|
-
yarn example ios
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
If you are building for a different architecture than your previous build, make sure to remove the build folders first. You can run the following command to cleanup all build folders:
|
|
71
|
-
|
|
72
|
-
```sh
|
|
73
|
-
yarn clean
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
<% } -%>
|
|
77
52
|
<% if (project.arch !== 'legacy') { -%>
|
|
78
53
|
To confirm that the app is running with the new architecture, you can check the Metro logs for a message like this:
|
|
79
54
|
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
<% if (project.arch !== 'legacy') { -%>
|
|
7
7
|
"codegenConfig": {
|
|
8
8
|
"name": "RN<%- project.name -%><%- project.view ? 'View': '' -%>Spec",
|
|
9
|
-
"type": <%- project.view ? '"
|
|
9
|
+
"type": <%- project.view ? '"all"': '"modules"' %>,
|
|
10
10
|
"jsSrcsDir": "src"
|
|
11
11
|
},
|
|
12
12
|
<% } -%>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useState, useEffect } from 'react';
|
|
2
|
+
import { Text, View, StyleSheet } from 'react-native';
|
|
3
|
+
import { multiply } from '<%- project.slug -%>';
|
|
4
|
+
|
|
5
|
+
export default function App() {
|
|
6
|
+
const [result, setResult] = useState<number | undefined>();
|
|
7
|
+
|
|
8
|
+
useEffect(() => {
|
|
9
|
+
multiply(3, 7).then(setResult);
|
|
10
|
+
}, []);
|
|
11
|
+
|
|
12
|
+
return (
|
|
13
|
+
<View style={styles.container}>
|
|
14
|
+
<Text>Result: {result}</Text>
|
|
15
|
+
</View>
|
|
16
|
+
);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const styles = StyleSheet.create({
|
|
20
|
+
container: {
|
|
21
|
+
flex: 1,
|
|
22
|
+
alignItems: 'center',
|
|
23
|
+
justifyContent: 'center',
|
|
24
|
+
},
|
|
25
|
+
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Text, View, StyleSheet } from 'react-native';
|
|
2
|
+
import { multiply } from '<%- project.slug -%>';
|
|
3
|
+
|
|
4
|
+
const result = multiply(3, 7);
|
|
5
|
+
|
|
6
|
+
export default function App() {
|
|
7
|
+
return (
|
|
8
|
+
<View style={styles.container}>
|
|
9
|
+
<Text>Result: {result}</Text>
|
|
10
|
+
</View>
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const styles = StyleSheet.create({
|
|
15
|
+
container: {
|
|
16
|
+
flex: 1,
|
|
17
|
+
alignItems: 'center',
|
|
18
|
+
justifyContent: 'center',
|
|
19
|
+
},
|
|
20
|
+
});
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { View, StyleSheet } from 'react-native';
|
|
2
|
+
import { <%- project.name -%>View } from '<%- project.slug -%>';
|
|
3
|
+
|
|
4
|
+
export default function App() {
|
|
5
|
+
return (
|
|
6
|
+
<View style={styles.container}>
|
|
7
|
+
<<%- project.name -%>View color="#32a852" style={styles.box} />
|
|
8
|
+
</View>
|
|
9
|
+
);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const styles = StyleSheet.create({
|
|
13
|
+
container: {
|
|
14
|
+
flex: 1,
|
|
15
|
+
alignItems: 'center',
|
|
16
|
+
justifyContent: 'center',
|
|
17
|
+
},
|
|
18
|
+
box: {
|
|
19
|
+
width: 60,
|
|
20
|
+
height: 60,
|
|
21
|
+
marginVertical: 20,
|
|
22
|
+
},
|
|
23
|
+
});
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export function multiply(a: number, b: number):
|
|
2
|
-
return
|
|
1
|
+
export function multiply(a: number, b: number): number {
|
|
2
|
+
return a * b;
|
|
3
3
|
}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
package com.<%- project.package %>
|
|
2
2
|
|
|
3
|
-
import com.facebook.react.
|
|
3
|
+
import com.facebook.react.BaseReactPackage
|
|
4
4
|
import com.facebook.react.bridge.NativeModule
|
|
5
5
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
6
|
import com.facebook.react.module.model.ReactModuleInfo
|
|
7
7
|
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
8
8
|
import java.util.HashMap
|
|
9
9
|
|
|
10
|
-
class <%- project.name -%>Package :
|
|
10
|
+
class <%- project.name -%>Package : BaseReactPackage() {
|
|
11
11
|
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
|
|
12
12
|
return if (name == <%- project.name -%>Module.NAME) {
|
|
13
13
|
<%- project.name -%>Module(reactContext)
|
|
@@ -66,7 +66,7 @@ android {
|
|
|
66
66
|
defaultConfig {
|
|
67
67
|
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
|
|
68
68
|
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
|
|
69
|
-
<% if (project.arch === "new"
|
|
69
|
+
<% if (project.arch === "new") { -%>
|
|
70
70
|
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
|
|
71
71
|
<% } -%>
|
|
72
72
|
|
|
@@ -87,7 +87,7 @@ android {
|
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
<% } -%>
|
|
90
|
-
<% if (project.arch === "new"
|
|
90
|
+
<% if (project.arch === "new") { -%>
|
|
91
91
|
|
|
92
92
|
buildFeatures {
|
|
93
93
|
buildConfig true
|
|
@@ -120,22 +120,6 @@ android {
|
|
|
120
120
|
}
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
|
-
<% } else if (project.arch === "mixed") { -%>
|
|
124
|
-
|
|
125
|
-
sourceSets {
|
|
126
|
-
main {
|
|
127
|
-
if (isNewArchitectureEnabled()) {
|
|
128
|
-
java.srcDirs += [
|
|
129
|
-
"src/newarch",
|
|
130
|
-
// Codegen specs
|
|
131
|
-
"generated/java",
|
|
132
|
-
"generated/jni"
|
|
133
|
-
]
|
|
134
|
-
} else {
|
|
135
|
-
java.srcDirs += ["src/oldarch"]
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
123
|
<% } -%>
|
|
140
124
|
}
|
|
141
125
|
|
|
@@ -154,7 +138,7 @@ dependencies {
|
|
|
154
138
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
155
139
|
}
|
|
156
140
|
|
|
157
|
-
<% if (project.arch === "new"
|
|
141
|
+
<% if (project.arch === "new") { -%>
|
|
158
142
|
if (isNewArchitectureEnabled()) {
|
|
159
143
|
react {
|
|
160
144
|
jsRootDir = file("../src/")
|
|
@@ -4,14 +4,14 @@
|
|
|
4
4
|
#endif
|
|
5
5
|
<% } -%>
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
#import "RN<%- project.name -%>Spec.h"
|
|
7
|
+
<% if (project.arch === 'new') { -%>
|
|
8
|
+
#import "generated/RN<%- project.name -%>Spec/RN<%- project.name -%>Spec.h"
|
|
9
9
|
|
|
10
10
|
@interface <%- project.name -%> : NSObject <Native<%- project.name -%>Spec>
|
|
11
|
-
|
|
11
|
+
<% } else { -%>
|
|
12
12
|
#import <React/RCTBridgeModule.h>
|
|
13
13
|
|
|
14
14
|
@interface <%- project.name -%> : NSObject <RCTBridgeModule>
|
|
15
|
-
|
|
15
|
+
<% } -%>
|
|
16
16
|
|
|
17
17
|
@end
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
RCT_EXPORT_MODULE()
|
|
6
6
|
|
|
7
|
-
<% if (project.arch === 'legacy'
|
|
7
|
+
<% if (project.arch === 'legacy') { -%>
|
|
8
8
|
// Example method
|
|
9
9
|
// See // https://reactnative.dev/docs/native-modules-ios
|
|
10
10
|
RCT_EXPORT_METHOD(multiply:(double)a
|
|
@@ -22,9 +22,6 @@ RCT_EXPORT_METHOD(multiply:(double)a
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
<% } -%>
|
|
25
|
-
<% if (project.arch === 'new' || project.arch === 'mixed') { -%>
|
|
26
|
-
// Don't compile this code when we build for the old architecture.
|
|
27
|
-
#ifdef RCT_NEW_ARCH_ENABLED
|
|
28
25
|
<% if (project.arch === 'new') { -%>
|
|
29
26
|
- (NSNumber *)multiply:(double)a b:(double)b {
|
|
30
27
|
<% if (project.cpp) { -%>
|
|
@@ -36,13 +33,11 @@ RCT_EXPORT_METHOD(multiply:(double)a
|
|
|
36
33
|
return result;
|
|
37
34
|
}
|
|
38
35
|
|
|
39
|
-
<% } -%>
|
|
40
36
|
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
|
|
41
37
|
(const facebook::react::ObjCTurboModule::InitParams &)params
|
|
42
38
|
{
|
|
43
39
|
return std::make_shared<facebook::react::Native<%- project.name -%>SpecJSI>(params);
|
|
44
40
|
}
|
|
45
|
-
#endif
|
|
46
41
|
<% } -%>
|
|
47
42
|
|
|
48
43
|
@end
|