newcandies 0.1.1 → 0.1.3
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/dist/index.js +129 -58
- package/package.json +1 -1
- package/templates/default/assets/fonts/SpaceMono-Regular.ttf +0 -0
- package/templates/default/assets/images/adaptive-icon.png +0 -0
- package/templates/default/assets/images/favicon.png +0 -0
- package/templates/default/assets/images/icon.png +0 -0
- package/templates/default/assets/images/splash-icon.png +0 -0
package/dist/index.js
CHANGED
|
@@ -14,6 +14,9 @@ var TEMPLATE_MAP = {
|
|
|
14
14
|
},
|
|
15
15
|
"boilerplate/supersimplenotes": {
|
|
16
16
|
extraDeps: ["@react-native-community/netinfo"]
|
|
17
|
+
},
|
|
18
|
+
"app-brief/react-query/sproutsy": {
|
|
19
|
+
extraDeps: ["@tanstack/react-query"]
|
|
17
20
|
}
|
|
18
21
|
};
|
|
19
22
|
var TEMPLATES = {
|
|
@@ -32,7 +35,7 @@ var TEMPLATES = {
|
|
|
32
35
|
"mini-app-brief": { categories: [{ value: "forms", label: "forms", variants: [{ value: "lite", label: "lite" }] }] },
|
|
33
36
|
"default": [{ value: "default", label: "Default (Expo Router + Uniwind)" }]
|
|
34
37
|
};
|
|
35
|
-
var program = new Command().name("newcandies").option("-t, --type <type>").option("--template <name>").option("--category <name>").option("--variant <name>").option("-
|
|
38
|
+
var program = new Command().name("newcandies").option("-t, --type <type>").option("--template <name>").option("--category <name>").option("--variant <name>").option("-y, --yes").option("--pm <pm>", "npm|pnpm|yarn|bun").option("--no-install").parse(process.argv);
|
|
36
39
|
var opts = program.opts();
|
|
37
40
|
async function main() {
|
|
38
41
|
console.clear();
|
|
@@ -75,17 +78,6 @@ async function main() {
|
|
|
75
78
|
const cat = cats.find((c) => c.value === results.category);
|
|
76
79
|
return p.select({ message: "Pick variant", options: cat.variants });
|
|
77
80
|
},
|
|
78
|
-
navigator: async () => {
|
|
79
|
-
if (opts.navigator) return opts.navigator;
|
|
80
|
-
return p.select({
|
|
81
|
-
message: "Navigator",
|
|
82
|
-
options: [
|
|
83
|
-
{ value: "stack", label: "Stack" },
|
|
84
|
-
{ value: "tabs", label: "Tabs" }
|
|
85
|
-
],
|
|
86
|
-
initialValue: "tabs"
|
|
87
|
-
});
|
|
88
|
-
},
|
|
89
81
|
install: async () => {
|
|
90
82
|
if (opts.yes !== void 0) return !!opts.yes;
|
|
91
83
|
if (opts.install === false) return false;
|
|
@@ -112,7 +104,8 @@ async function main() {
|
|
|
112
104
|
const s = p.spinner();
|
|
113
105
|
s.start("Scaffolding");
|
|
114
106
|
await fs.ensureDir(dest);
|
|
115
|
-
|
|
107
|
+
const withQuery = project.type === "app-brief" && project.category === "react-query" && project.variant === "sproutsy";
|
|
108
|
+
await writeBaseline({ dest, name: project.name, withQuery });
|
|
116
109
|
await applyTemplateOverlay({ dest, type: project.type, template: project.template, category: project.category, variant: project.variant });
|
|
117
110
|
s.stop("Files ready");
|
|
118
111
|
const extraDeps = resolveExtraDeps({ type: project.type, template: project.template, category: project.category, variant: project.variant });
|
|
@@ -134,7 +127,35 @@ function TEMPLATESafe(type) {
|
|
|
134
127
|
if (Array.isArray(t)) return t;
|
|
135
128
|
return [{ value: "default", label: "Default (Expo Router + Uniwind)" }];
|
|
136
129
|
}
|
|
137
|
-
async function writeBaseline({ dest, name,
|
|
130
|
+
async function writeBaseline({ dest, name, withQuery }) {
|
|
131
|
+
const baseDeps = {
|
|
132
|
+
// Expo core + platform libs
|
|
133
|
+
expo: "latest",
|
|
134
|
+
"expo-constants": "~18.0.10",
|
|
135
|
+
"expo-font": "~14.0.9",
|
|
136
|
+
"expo-linking": "~8.0.8",
|
|
137
|
+
"expo-router": "~6.0.14",
|
|
138
|
+
"expo-splash-screen": "~31.0.10",
|
|
139
|
+
"expo-status-bar": "~3.0.8",
|
|
140
|
+
"expo-web-browser": "~15.0.9",
|
|
141
|
+
// React ecosystem
|
|
142
|
+
react: "19.1.0",
|
|
143
|
+
"react-dom": "19.1.0",
|
|
144
|
+
"react-native": "0.81.5",
|
|
145
|
+
"react-native-web": "~0.21.0",
|
|
146
|
+
// RN libs
|
|
147
|
+
"react-native-reanimated": "~4.1.1",
|
|
148
|
+
"react-native-gesture-handler": "latest",
|
|
149
|
+
"react-native-safe-area-context": "~5.6.0",
|
|
150
|
+
"react-native-screens": "~4.16.0",
|
|
151
|
+
"react-native-worklets": "0.5.1",
|
|
152
|
+
// Styling
|
|
153
|
+
tailwindcss: "^4.1.16",
|
|
154
|
+
uniwind: "^1.0.0"
|
|
155
|
+
};
|
|
156
|
+
if (withQuery) {
|
|
157
|
+
baseDeps["@tanstack/react-query"] = "latest";
|
|
158
|
+
}
|
|
138
159
|
const pkg = {
|
|
139
160
|
name,
|
|
140
161
|
version: "0.0.0",
|
|
@@ -144,16 +165,54 @@ async function writeBaseline({ dest, name, navigator }) {
|
|
|
144
165
|
start: "expo start",
|
|
145
166
|
android: "expo run:android",
|
|
146
167
|
ios: "expo run:ios"
|
|
168
|
+
},
|
|
169
|
+
dependencies: baseDeps,
|
|
170
|
+
devDependencies: {
|
|
171
|
+
"@types/react": "~19.1.0",
|
|
172
|
+
typescript: "~5.9.2"
|
|
147
173
|
}
|
|
148
174
|
};
|
|
149
175
|
await fs.writeJSON(path.join(dest, "package.json"), pkg, { spaces: 2 });
|
|
176
|
+
const slug = String(name).toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
|
|
177
|
+
const pkgNameSegment = slug.replace(/-/g, "") || "app";
|
|
178
|
+
const bundleId = `com.example.${pkgNameSegment}`;
|
|
150
179
|
const appJson = {
|
|
151
180
|
expo: {
|
|
152
181
|
name,
|
|
153
|
-
slug
|
|
154
|
-
|
|
182
|
+
slug,
|
|
183
|
+
version: "1.0.0",
|
|
184
|
+
orientation: "portrait",
|
|
185
|
+
icon: "./assets/images/icon.png",
|
|
186
|
+
scheme: slug,
|
|
187
|
+
userInterfaceStyle: "automatic",
|
|
188
|
+
newArchEnabled: true,
|
|
189
|
+
splash: {
|
|
190
|
+
image: "./assets/images/splash-icon.png",
|
|
191
|
+
resizeMode: "contain",
|
|
192
|
+
backgroundColor: "#ffffff"
|
|
193
|
+
},
|
|
194
|
+
ios: {
|
|
195
|
+
supportsTablet: true,
|
|
196
|
+
bundleIdentifier: bundleId
|
|
197
|
+
},
|
|
198
|
+
android: {
|
|
199
|
+
adaptiveIcon: {
|
|
200
|
+
foregroundImage: "./assets/images/adaptive-icon.png",
|
|
201
|
+
backgroundColor: "#ffffff"
|
|
202
|
+
},
|
|
203
|
+
edgeToEdgeEnabled: true,
|
|
204
|
+
predictiveBackGestureEnabled: false,
|
|
205
|
+
package: bundleId
|
|
206
|
+
},
|
|
207
|
+
web: {
|
|
208
|
+
bundler: "metro",
|
|
209
|
+
output: "static",
|
|
210
|
+
favicon: "./assets/images/favicon.png"
|
|
211
|
+
},
|
|
155
212
|
plugins: ["expo-router"],
|
|
156
|
-
experiments: {
|
|
213
|
+
experiments: {
|
|
214
|
+
typedRoutes: true
|
|
215
|
+
}
|
|
157
216
|
}
|
|
158
217
|
};
|
|
159
218
|
await fs.writeJSON(path.join(dest, "app.json"), appJson, { spaces: 2 });
|
|
@@ -193,6 +252,16 @@ module.exports = withUniwindConfig(config, {
|
|
|
193
252
|
await fs.writeJSON(path.join(dest, "tsconfig.json"), tsconfig, { spaces: 2 });
|
|
194
253
|
const appDir = path.join(dest, "app");
|
|
195
254
|
await fs.ensureDir(appDir);
|
|
255
|
+
const easJson = {
|
|
256
|
+
cli: { version: ">= 7.0.0" },
|
|
257
|
+
build: {
|
|
258
|
+
development: { developmentClient: true, distribution: "internal" },
|
|
259
|
+
preview: { distribution: "internal" },
|
|
260
|
+
production: {}
|
|
261
|
+
},
|
|
262
|
+
submit: { production: {} }
|
|
263
|
+
};
|
|
264
|
+
await fs.writeJSON(path.join(dest, "eas.json"), easJson, { spaces: 2 });
|
|
196
265
|
const globalCss = `@import 'tailwindcss';
|
|
197
266
|
@import 'uniwind';
|
|
198
267
|
|
|
@@ -212,25 +281,56 @@ module.exports = withUniwindConfig(config, {
|
|
|
212
281
|
}
|
|
213
282
|
`;
|
|
214
283
|
await fs.writeFile(path.join(appDir, "global.css"), globalCss);
|
|
215
|
-
|
|
216
|
-
const
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
import '../global.css';
|
|
220
|
-
import { Tabs } from 'expo-router';
|
|
284
|
+
{
|
|
285
|
+
const rootLayout = withQuery ? `import 'react-native-gesture-handler';
|
|
286
|
+
import './global.css';
|
|
287
|
+
import { Slot } from 'expo-router';
|
|
221
288
|
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
222
289
|
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
|
290
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
223
291
|
|
|
224
|
-
const
|
|
292
|
+
const queryClient = new QueryClient();
|
|
293
|
+
|
|
294
|
+
const RootLayout = () => {
|
|
295
|
+
return (
|
|
296
|
+
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
297
|
+
<SafeAreaProvider>
|
|
298
|
+
<QueryClientProvider client={queryClient}>
|
|
299
|
+
<Slot />
|
|
300
|
+
</QueryClientProvider>
|
|
301
|
+
</SafeAreaProvider>
|
|
302
|
+
</GestureHandlerRootView>
|
|
303
|
+
);
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
export default RootLayout;
|
|
307
|
+
` : `import 'react-native-gesture-handler';
|
|
308
|
+
import './global.css';
|
|
309
|
+
import { Slot } from 'expo-router';
|
|
310
|
+
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
311
|
+
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
|
312
|
+
|
|
313
|
+
const RootLayout = () => {
|
|
225
314
|
return (
|
|
226
315
|
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
227
316
|
<SafeAreaProvider>
|
|
228
|
-
<
|
|
317
|
+
<Slot />
|
|
229
318
|
</SafeAreaProvider>
|
|
230
319
|
</GestureHandlerRootView>
|
|
231
320
|
);
|
|
232
321
|
};
|
|
233
322
|
|
|
323
|
+
export default RootLayout;
|
|
324
|
+
`;
|
|
325
|
+
await fs.writeFile(path.join(appDir, "_layout.tsx"), rootLayout);
|
|
326
|
+
const tabsDir = path.join(appDir, "(tabs)");
|
|
327
|
+
await fs.ensureDir(tabsDir);
|
|
328
|
+
const layout = `import { Tabs } from 'expo-router';
|
|
329
|
+
|
|
330
|
+
const TabsLayout = () => {
|
|
331
|
+
return <Tabs screenOptions={{ headerShown: false }} />;
|
|
332
|
+
};
|
|
333
|
+
|
|
234
334
|
export default TabsLayout;
|
|
235
335
|
`;
|
|
236
336
|
await fs.writeFile(path.join(tabsDir, "_layout.tsx"), layout);
|
|
@@ -256,43 +356,14 @@ const Settings = () => (
|
|
|
256
356
|
export default Settings;
|
|
257
357
|
`;
|
|
258
358
|
await fs.writeFile(path.join(tabsDir, "settings.tsx"), settings);
|
|
259
|
-
} else {
|
|
260
|
-
const layout = `import 'react-native-gesture-handler';
|
|
261
|
-
import './global.css';
|
|
262
|
-
import { Stack } from 'expo-router';
|
|
263
|
-
import { GestureHandlerRootView } from 'react-native-gesture-handler';
|
|
264
|
-
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
|
265
|
-
|
|
266
|
-
const RootLayout = () => {
|
|
267
|
-
return (
|
|
268
|
-
<GestureHandlerRootView style={{ flex: 1 }}>
|
|
269
|
-
<SafeAreaProvider>
|
|
270
|
-
<Stack screenOptions={{ headerShown: false }} />
|
|
271
|
-
</SafeAreaProvider>
|
|
272
|
-
</GestureHandlerRootView>
|
|
273
|
-
);
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
export default RootLayout;
|
|
277
|
-
`;
|
|
278
|
-
await fs.writeFile(path.join(appDir, "_layout.tsx"), layout);
|
|
279
|
-
const index = `import { View, Text } from 'react-native';
|
|
280
|
-
|
|
281
|
-
const Home = () => {
|
|
282
|
-
return (
|
|
283
|
-
<View className="flex-1 items-center justify-center bg-background">
|
|
284
|
-
<Text className="text-foreground text-xl">Hello from Stack + Uniwind + Router</Text>
|
|
285
|
-
</View>
|
|
286
|
-
);
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
export default Home;
|
|
290
|
-
`;
|
|
291
|
-
await fs.writeFile(path.join(appDir, "index.tsx"), index);
|
|
292
359
|
}
|
|
293
360
|
}
|
|
294
361
|
async function applyTemplateOverlay({ dest, type, template, category, variant }) {
|
|
295
362
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
363
|
+
const defaultSrc = path.join(__dirname, "..", "templates", "default");
|
|
364
|
+
if (await fs.pathExists(defaultSrc)) {
|
|
365
|
+
await fs.copy(defaultSrc, dest, { overwrite: false, errorOnExist: false });
|
|
366
|
+
}
|
|
296
367
|
let src = null;
|
|
297
368
|
if (type === "app-brief" || type === "mini-app-brief") {
|
|
298
369
|
if (category && variant) {
|
package/package.json
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|