codingpixel-expo-app 0.1.6 → 0.1.7

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/fonts.js CHANGED
@@ -54,8 +54,11 @@ export function generateUseFontsBlocks(primary, secondary) {
54
54
  fontPairs.push([`${secondary}-Regular`, `${secondary}-Regular.ttf`], [`${secondary}-Medium`, `${secondary}-Medium.ttf`], [`${secondary}-SemiBold`, `${secondary}-SemiBold.ttf`], [`${secondary}-Bold`, `${secondary}-Bold.ttf`]);
55
55
  }
56
56
  const importBlock = `import { useFonts } from "expo-font";`;
57
+ // From `src/app/_layout.tsx` to `src/assets/fonts/`:
58
+ // .. → src → ../assets/fonts/<file>
59
+ // (Was `../../assets/fonts/...` when assets lived at project root pre-Deviation #22.)
57
60
  const mapEntries = fontPairs
58
- .map(([key, file]) => ` "${key}": require("../../assets/fonts/${file}"),`)
61
+ .map(([key, file]) => ` "${key}": require("../assets/fonts/${file}"),`)
59
62
  .join("\n");
60
63
  const hookBlock = ` const [loaded] = useFonts({\n${mapEntries}\n });`;
61
64
  const guardBlock = ` if (!loaded) return null;`;
package/dist/index.js CHANGED
@@ -14,13 +14,13 @@ import path from "node:path";
14
14
  import { fileURLToPath } from "node:url";
15
15
  import { resolveTargetDir } from "./bootstrap.js";
16
16
  import { gatherAnswers, validateEnvVars } from "./prompts.js";
17
- import { cleanupBlankTemplate, runCreateExpoApp } from "./scaffold.js";
17
+ import { cleanupBlankTemplate, moveExpoIconsIntoSrcAssets, runCreateExpoApp, } from "./scaffold.js";
18
18
  import { applyBase, applyBottomSheet, applyImagePicker } from "./overlay.js";
19
- import { patchAppJson, patchAppJsonPlugins, patchConstants, patchExpoRouterEntry, patchLayout, patchPackageJsonScripts, patchTsconfig, } from "./patch.js";
19
+ import { patchAppJson, patchAppJsonAssetPaths, patchAppJsonPlugins, patchConstants, patchExpoRouterEntry, patchLayout, patchPackageJsonScripts, patchTsconfig, } from "./patch.js";
20
20
  import { patchBabel } from "./babel.js";
21
21
  import { buildLayoutReplacements } from "./fonts.js";
22
22
  import { ensureLockfile, installNativeDeps } from "./install.js";
23
- import { log } from "./util.js";
23
+ import { ensureDir, log } from "./util.js";
24
24
  import { readSDKNotes } from "./sdkNotes.js";
25
25
  import { SDK_PROBE_RESULTS } from "./sdkProbeResults.js";
26
26
  const __filename = fileURLToPath(import.meta.url);
@@ -49,6 +49,7 @@ async function main() {
49
49
  log.info(`App name: ${target.name}`);
50
50
  await runCreateExpoApp(target.dir, target.name);
51
51
  cleanupBlankTemplate(target.dir);
52
+ moveExpoIconsIntoSrcAssets(target.dir);
52
53
  const answers = await gatherAnswers();
53
54
  log.info(`Answers: primaryFont="${answers.primaryFont}" secondaryFont="${answers.secondaryFont}" ` +
54
55
  `bottomSheet=${answers.bottomSheet} imagePicker=${answers.imagePicker} pm=${answers.packageManager}`);
@@ -56,6 +57,18 @@ async function main() {
56
57
  const templatesRoot = resolveTemplatesRoot();
57
58
  log.step("Overlaying templates/base/ …");
58
59
  applyBase(target.dir, templatesRoot);
60
+ // Ensure empty dirs that npm strips from the tarball still exist in the
61
+ // generated app (Deviation #22 + extension). All four are intentionally
62
+ // empty placeholders apps fill as features grow / they drop fonts/images.
63
+ // No `.gitkeep` is shipped — `ensureDir` creates the bare directory.
64
+ for (const rel of [
65
+ "src/features",
66
+ "src/core/hooks",
67
+ "src/assets/fonts",
68
+ "src/assets/images",
69
+ ]) {
70
+ ensureDir(path.join(target.dir, rel));
71
+ }
59
72
  if (answers.bottomSheet) {
60
73
  log.step("Overlaying templates/bottom-sheet/ …");
61
74
  applyBottomSheet(target.dir, templatesRoot);
@@ -67,6 +80,7 @@ async function main() {
67
80
  // ---- Patches ----
68
81
  log.step("Patching app.json + expo-router entry …");
69
82
  patchAppJson(target.dir, target.name, answers);
83
+ patchAppJsonAssetPaths(target.dir);
70
84
  patchExpoRouterEntry(target.dir);
71
85
  patchAppJsonPlugins(target.dir, answers);
72
86
  log.step("Splicing constants + layout sentinels …");
@@ -105,7 +119,7 @@ async function main() {
105
119
  "@components": "./src/ui/components",
106
120
  "@icons": "./src/ui/iconComponents",
107
121
  "@features": "./src/features",
108
- "@assets": "./assets",
122
+ "@assets": "./src/assets",
109
123
  },
110
124
  });
111
125
  // ---- Install + verify ----
package/dist/patch.js CHANGED
@@ -84,6 +84,41 @@ export function patchAppJson(target, name, _answers) {
84
84
  }
85
85
  writeJson(p, json);
86
86
  }
87
+ /**
88
+ * Rewrite `app.json` asset paths from create-expo-app's `./assets/<file>`
89
+ * defaults to `./src/assets/<file>` (Deviation #22 — unified asset layout).
90
+ *
91
+ * Pairs with `moveExpoIconsIntoSrcAssets` in scaffold.ts (which moves the
92
+ * actual PNG files). Idempotent: only rewrites paths that start with `./assets/`,
93
+ * so re-running on an already-patched app.json is a no-op.
94
+ */
95
+ export function patchAppJsonAssetPaths(target) {
96
+ const p = path.join(target, "app.json");
97
+ if (!fileExists(p))
98
+ return;
99
+ const json = readJson(p);
100
+ json.expo ??= {};
101
+ const rewrite = (value) => {
102
+ if (!value)
103
+ return value;
104
+ if (value.startsWith("./assets/")) {
105
+ return value.replace(/^\.\/assets\//, "./src/assets/");
106
+ }
107
+ return value;
108
+ };
109
+ if (json.expo.icon)
110
+ json.expo.icon = rewrite(json.expo.icon);
111
+ if (json.expo.splash?.image) {
112
+ json.expo.splash.image = rewrite(json.expo.splash.image);
113
+ }
114
+ if (json.expo.android?.adaptiveIcon?.foregroundImage) {
115
+ json.expo.android.adaptiveIcon.foregroundImage = rewrite(json.expo.android.adaptiveIcon.foregroundImage);
116
+ }
117
+ if (json.expo.web?.favicon) {
118
+ json.expo.web.favicon = rewrite(json.expo.web.favicon);
119
+ }
120
+ writeJson(p, json);
121
+ }
87
122
  /**
88
123
  * Phase 5 step 5 — add image-picker plugin entry conditionally. Idempotent via
89
124
  * `nameOf` equality (user-customized options object preserved).
@@ -214,7 +249,7 @@ const SPEC_PATHS = {
214
249
  "@components/*": ["src/ui/components/*"],
215
250
  "@icons/*": ["src/ui/iconComponents/*"],
216
251
  "@features/*": ["src/features/*"],
217
- "@assets": ["assets"],
252
+ "@assets": ["src/assets"],
218
253
  };
219
254
  /**
220
255
  * Phase 7 step 3 — patch tsconfig:
package/dist/scaffold.js CHANGED
@@ -53,3 +53,46 @@ export function cleanupBlankTemplate(target) {
53
53
  }
54
54
  }
55
55
  }
56
+ /**
57
+ * Move create-expo-app's root `assets/*.png` icons (icon, splash-icon,
58
+ * adaptive-icon, favicon) into `src/assets/` so the project has a single
59
+ * unified assets layout. Caller updates `app.json` paths separately (see
60
+ * `patchAppJsonAssetPaths` in patch.ts).
61
+ *
62
+ * Idempotent — if the source file is missing (already moved or never existed),
63
+ * skip it without erroring.
64
+ */
65
+ export function moveExpoIconsIntoSrcAssets(target) {
66
+ const rootAssets = path.join(target, "assets");
67
+ const srcAssets = path.join(target, "src", "assets");
68
+ if (!fs.existsSync(rootAssets))
69
+ return;
70
+ fs.mkdirSync(srcAssets, { recursive: true });
71
+ const movableFiles = [
72
+ "icon.png",
73
+ "splash-icon.png",
74
+ "adaptive-icon.png",
75
+ "favicon.png",
76
+ ];
77
+ let moved = 0;
78
+ for (const file of movableFiles) {
79
+ const from = path.join(rootAssets, file);
80
+ const to = path.join(srcAssets, file);
81
+ if (fileExists(from) && !fileExists(to)) {
82
+ fs.renameSync(from, to);
83
+ moved++;
84
+ }
85
+ }
86
+ // If root `assets/` is now empty (only icons lived there), remove it.
87
+ try {
88
+ const remaining = fs.readdirSync(rootAssets);
89
+ if (remaining.length === 0)
90
+ fs.rmdirSync(rootAssets);
91
+ }
92
+ catch {
93
+ // Not empty (user-added content) → leave alone.
94
+ }
95
+ if (moved > 0) {
96
+ log.step(`Moved ${moved} icon file(s) from assets/ to src/assets/.`);
97
+ }
98
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codingpixel-expo-app",
3
- "version": "0.1.6",
3
+ "version": "0.1.7",
4
4
  "description": "Opinionated Expo app scaffolder mirroring MyRoster conventions.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -0,0 +1 @@
1
+ export const Images = {};
@@ -1,54 +1,10 @@
1
1
  export const enum Colors {
2
2
  PRIMARY = "#2E5A88",
3
- PRIMARY_1 = "#436B94",
4
- PRIMARY_2 = "#587BA0",
5
- PRIMARY_3 = "#829CB8",
6
- PRIMARY_4 = "#97ADC4",
7
- PRIMARY_5 = "#ABBDCF",
8
- PRIMARY_6 = "#C1CEDC",
9
- PRIMARY_7 = "#D5DEE7",
10
- PRIMARY_8 = "#EBEFF4",
11
3
 
12
4
  SECONDARY = "#2D85B7",
13
- SECONDARY_1 = "#4292BF",
14
- SECONDARY_2 = "#579DC5",
15
- SECONDARY_3 = "#6CAACD",
16
- SECONDARY_4 = "#81B6D4",
17
- SECONDARY_5 = "#96C2DB",
18
- SECONDARY_6 = "#ABCEE2",
19
- SECONDARY_7 = "#C0DBEA",
20
- SECONDARY_8 = "#D5E7F1",
21
- SECONDARY_9 = "#EAF3F8",
22
-
23
- SUCCESS = "#22BB33",
24
- SUCCESS_10_PERCENT = "#E9F9EB",
25
- INFO = "#246BFD",
26
- WARNING = "#BF6A02",
27
- WARNING_10_PERCENT = "#FEF7EE",
28
- ERROR = "#BB2124",
29
- ERROR_10_PERCENT = "#F9E9EA",
30
- DISABLED = "#AAAAAA",
31
- DISABLED_BUTTON = "#693EC9",
32
- NOTIFICATION = "#F75555",
33
-
34
- PURPLE_TEN_PERCENT = "#F0ECFA",
35
- PURPLE = "#693EC9",
36
-
37
- GRAY_10 = "#303030",
38
- GRAY_9 = "#3C3D3D",
39
- GRAY_8 = "#444546",
40
- GRAY_7 = "#4E4F50",
41
- GRAY_6 = "#5B5D5F",
42
- GRAY_5 = "#86888A",
43
- GRAY_4 = "#AEB0B2",
44
- GRAY_3 = "#D0D1D1",
45
- GRAY_2 = "#E6E7E7",
46
- GRAY_1 = "#F5F6F6",
47
5
 
48
6
  WHITE = "#FFFFFF",
49
- BORDER = "#D1D0D0",
50
7
  BLACK = "#1A1A1A",
51
8
 
52
9
  TRANSPARENT = "transparent",
53
- BG_COLOR = "#FDFDFD",
54
10
  }
File without changes
File without changes
@@ -1,8 +0,0 @@
1
- // Asset registry shim. Apps add real exports as they bundle .png / .ttf etc.
2
- // Example:
3
- // import notification from "./images/notification.png";
4
- // export const Images = { notification };
5
- //
6
- // `@assets` resolves here via tsconfig path mapping.
7
- export const Images = {} as Record<string, number>;
8
- export {};