@exanderal/stackcraft 0.2.1 → 0.3.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.
Files changed (39) hide show
  1. package/dist/create/index.d.ts.map +1 -1
  2. package/dist/create/index.js +12 -0
  3. package/dist/create/index.js.map +1 -1
  4. package/dist/create/scaffold.d.ts.map +1 -1
  5. package/dist/create/scaffold.js +5 -0
  6. package/dist/create/scaffold.js.map +1 -1
  7. package/dist/create/scaffolders/__tests__/web-vite.test.js +1 -0
  8. package/dist/create/scaffolders/__tests__/web-vite.test.js.map +1 -1
  9. package/dist/create/scaffolders/mobile-expo.d.ts +3 -0
  10. package/dist/create/scaffolders/mobile-expo.d.ts.map +1 -0
  11. package/dist/create/scaffolders/mobile-expo.js +14 -0
  12. package/dist/create/scaffolders/mobile-expo.js.map +1 -0
  13. package/dist/create/scaffolders/wire-client.d.ts.map +1 -1
  14. package/dist/create/scaffolders/wire-client.js +14 -0
  15. package/dist/create/scaffolders/wire-client.js.map +1 -1
  16. package/dist/create/types.d.ts +2 -0
  17. package/dist/create/types.d.ts.map +1 -1
  18. package/package.json +1 -1
  19. package/templates/base/tools/generators/module/schema.json +2 -1
  20. package/templates/mobile-expo/app/(tabs)/_layout.tsx +31 -0
  21. package/templates/mobile-expo/app/(tabs)/index.tsx +23 -0
  22. package/templates/mobile-expo/app/+not-found.tsx +40 -0
  23. package/templates/mobile-expo/app/_layout.tsx +31 -0
  24. package/templates/mobile-expo/app.json +39 -0
  25. package/templates/mobile-expo/assets/images/adaptive-icon.png +0 -0
  26. package/templates/mobile-expo/assets/images/favicon.png +0 -0
  27. package/templates/mobile-expo/assets/images/icon.png +0 -0
  28. package/templates/mobile-expo/assets/images/splash-icon.png +0 -0
  29. package/templates/mobile-expo/components/ExternalLink.tsx +25 -0
  30. package/templates/mobile-expo/components/StyledText.tsx +5 -0
  31. package/templates/mobile-expo/components/Themed.tsx +45 -0
  32. package/templates/mobile-expo/components/useClientOnlyValue.ts +4 -0
  33. package/templates/mobile-expo/components/useClientOnlyValue.web.ts +12 -0
  34. package/templates/mobile-expo/components/useColorScheme.ts +1 -0
  35. package/templates/mobile-expo/components/useColorScheme.web.ts +8 -0
  36. package/templates/mobile-expo/constants/Colors.ts +19 -0
  37. package/templates/mobile-expo/package.json +37 -0
  38. package/templates/mobile-expo/project.json +17 -0
  39. package/templates/mobile-expo/tsconfig.json +20 -0
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/create/index.ts"],"names":[],"mappings":"AAKA,wBAAsB,MAAM,kBA4E3B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/create/index.ts"],"names":[],"mappings":"AAKA,wBAAsB,MAAM,kBAyF3B"}
@@ -34,6 +34,17 @@ export async function create() {
34
34
  cancel('Cancelled.');
35
35
  process.exit(0);
36
36
  }
37
+ const mobile = await select({
38
+ message: 'Mobile',
39
+ options: [
40
+ { value: 'none', label: 'None' },
41
+ { value: 'expo', label: 'Expo', hint: 'React Native with Expo Router' },
42
+ ],
43
+ });
44
+ if (isCancel(mobile)) {
45
+ cancel('Cancelled.');
46
+ process.exit(0);
47
+ }
37
48
  const database = await select({
38
49
  message: 'Database',
39
50
  options: [
@@ -61,6 +72,7 @@ export async function create() {
61
72
  frontend: frontend,
62
73
  backend: backend,
63
74
  database: database,
75
+ mobile: mobile,
64
76
  packageManager: packageManager,
65
77
  targetDir: resolve(process.cwd(), projectName),
66
78
  };
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/create/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/create/index.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/create/scaffold.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,wBAAsB,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,iBAwBlF"}
1
+ {"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../src/create/scaffold.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAE/C,wBAAsB,QAAQ,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,iBA6BlF"}
@@ -2,6 +2,7 @@ import { execa } from 'execa';
2
2
  import { scaffoldNestjsGraphql } from './scaffolders/api-nestjs-graphql.js';
3
3
  import { scaffoldNestjsRest } from './scaffolders/api-nestjs-rest.js';
4
4
  import { scaffoldBase } from './scaffolders/base.js';
5
+ import { scaffoldExpo } from './scaffolders/mobile-expo.js';
5
6
  import { scaffoldNextjs } from './scaffolders/web-nextjs.js';
6
7
  import { scaffoldVite } from './scaffolders/web-vite.js';
7
8
  import { wireClientIntegration } from './scaffolders/wire-client.js';
@@ -23,6 +24,10 @@ export async function scaffold(config, onStep) {
23
24
  onStep('Adding Next.js app...');
24
25
  await scaffoldNextjs(config);
25
26
  }
27
+ if (config.mobile === 'expo') {
28
+ onStep('Adding Expo mobile app...');
29
+ await scaffoldExpo(config);
30
+ }
26
31
  onStep('Wiring client integration...');
27
32
  await wireClientIntegration(config);
28
33
  onStep('Installing dependencies...');
@@ -1 +1 @@
1
- {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/create/scaffold.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAC7B,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAA;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AAGpE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAqB,EAAE,MAA6B;IACjF,MAAM,CAAC,uBAAuB,CAAC,CAAA;IAC/B,MAAM,YAAY,CAAC,MAAM,CAAC,CAAA;IAE1B,MAAM,CAAC,mBAAmB,CAAC,CAAA;IAC3B,IAAI,MAAM,CAAC,OAAO,KAAK,gBAAgB,EAAE,CAAC;QACxC,MAAM,qBAAqB,CAAC,MAAM,CAAC,CAAA;IACrC,CAAC;SAAM,CAAC;QACN,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAA;IAClC,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;QAC/B,MAAM,CAAC,4BAA4B,CAAC,CAAA;QACpC,MAAM,YAAY,CAAC,MAAM,CAAC,CAAA;IAC5B,CAAC;SAAM,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACxC,MAAM,CAAC,uBAAuB,CAAC,CAAA;QAC/B,MAAM,cAAc,CAAC,MAAM,CAAC,CAAA;IAC9B,CAAC;IAED,MAAM,CAAC,8BAA8B,CAAC,CAAA;IACtC,MAAM,qBAAqB,CAAC,MAAM,CAAC,CAAA;IAEnC,MAAM,CAAC,4BAA4B,CAAC,CAAA;IACpC,MAAM,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAA;AAC5E,CAAC"}
1
+ {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../../src/create/scaffold.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAC7B,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAA;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAA;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAA;AAGpE,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,MAAqB,EAAE,MAA6B;IACjF,MAAM,CAAC,uBAAuB,CAAC,CAAA;IAC/B,MAAM,YAAY,CAAC,MAAM,CAAC,CAAA;IAE1B,MAAM,CAAC,mBAAmB,CAAC,CAAA;IAC3B,IAAI,MAAM,CAAC,OAAO,KAAK,gBAAgB,EAAE,CAAC;QACxC,MAAM,qBAAqB,CAAC,MAAM,CAAC,CAAA;IACrC,CAAC;SAAM,CAAC;QACN,MAAM,kBAAkB,CAAC,MAAM,CAAC,CAAA;IAClC,CAAC;IAED,IAAI,MAAM,CAAC,QAAQ,KAAK,MAAM,EAAE,CAAC;QAC/B,MAAM,CAAC,4BAA4B,CAAC,CAAA;QACpC,MAAM,YAAY,CAAC,MAAM,CAAC,CAAA;IAC5B,CAAC;SAAM,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACxC,MAAM,CAAC,uBAAuB,CAAC,CAAA;QAC/B,MAAM,cAAc,CAAC,MAAM,CAAC,CAAA;IAC9B,CAAC;IAED,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QAC7B,MAAM,CAAC,2BAA2B,CAAC,CAAA;QACnC,MAAM,YAAY,CAAC,MAAM,CAAC,CAAA;IAC5B,CAAC;IAED,MAAM,CAAC,8BAA8B,CAAC,CAAA;IACtC,MAAM,qBAAqB,CAAC,MAAM,CAAC,CAAA;IAEnC,MAAM,CAAC,4BAA4B,CAAC,CAAA;IACpC,MAAM,KAAK,CAAC,MAAM,CAAC,cAAc,EAAE,CAAC,SAAS,CAAC,EAAE,EAAE,GAAG,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAA;AAC5E,CAAC"}
@@ -11,6 +11,7 @@ const CONFIG = {
11
11
  frontend: 'vite',
12
12
  backend: 'nestjs-rest',
13
13
  database: 'postgres',
14
+ mobile: 'none',
14
15
  packageManager: 'pnpm',
15
16
  targetDir: '/tmp/my-app',
16
17
  };
@@ -1 +1 @@
1
- {"version":3,"file":"web-vite.test.js","sourceRoot":"","sources":["../../../../src/create/scaffolders/__tests__/web-vite.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAE5D,EAAE,CAAC,IAAI,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,CAAC;IACjC,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;IAC3C,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;IACxC,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC;IACtC,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC;IACvC,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;CAChD,CAAC,CAAC,CAAA;AAEH,MAAM,MAAM,GAAG;IACb,WAAW,EAAE,QAAQ;IACrB,QAAQ,EAAE,MAAe;IACzB,OAAO,EAAE,aAAsB;IAC/B,QAAQ,EAAE,UAAmB;IAC7B,cAAc,EAAE,MAAe;IAC/B,SAAS,EAAE,aAAa;CACzB,CAAA;AAED,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC,CAAA;IAEnC,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAA;QAClD,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAA;QAEvD,MAAM,YAAY,CAAC,MAAM,CAAC,CAAA;QAE1B,MAAM,CAAC,KAAK,CAAC,CAAC,oBAAoB,CAChC,MAAM,CAAC,gBAAgB,CAAC,UAAU,CAAC,EACnC,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAA;QAC/C,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAA;QAEvD,MAAM,YAAY,CAAC,MAAM,CAAC,CAAA;QAE1B,MAAM,CAAC,EAAE,CAAC,CAAC,oBAAoB,CAC7B,MAAM,CAAC,gBAAgB,CAAC,UAAU,CAAC,EACnC,MAAM,CAAC,gBAAgB,CAAC,UAAU,CAAC,EACnC,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
1
+ {"version":3,"file":"web-vite.test.js","sourceRoot":"","sources":["../../../../src/create/scaffolders/__tests__/web-vite.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAE5D,EAAE,CAAC,IAAI,CAAC,kBAAkB,EAAE,GAAG,EAAE,CAAC,CAAC;IACjC,KAAK,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;IAC3C,EAAE,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;IACxC,OAAO,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC;IACtC,QAAQ,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,EAAE,CAAC;IACvC,SAAS,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC;CAChD,CAAC,CAAC,CAAA;AAEH,MAAM,MAAM,GAAG;IACb,WAAW,EAAE,QAAQ;IACrB,QAAQ,EAAE,MAAe;IACzB,OAAO,EAAE,aAAsB;IAC/B,QAAQ,EAAE,UAAmB;IAC7B,MAAM,EAAE,MAAe;IACvB,cAAc,EAAE,MAAe;IAC/B,SAAS,EAAE,aAAa;CACzB,CAAA;AAED,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC5B,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC,CAAA;IAEnC,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAA;QAClD,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAA;QAEvD,MAAM,YAAY,CAAC,MAAM,CAAC,CAAA;QAE1B,MAAM,CAAC,KAAK,CAAC,CAAC,oBAAoB,CAChC,MAAM,CAAC,gBAAgB,CAAC,UAAU,CAAC,EACnC,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAA;IACH,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,EAAE,EAAE,EAAE,GAAG,MAAM,MAAM,CAAC,kBAAkB,CAAC,CAAA;QAC/C,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAA;QAEvD,MAAM,YAAY,CAAC,MAAM,CAAC,CAAA;QAE1B,MAAM,CAAC,EAAE,CAAC,CAAC,oBAAoB,CAC7B,MAAM,CAAC,gBAAgB,CAAC,UAAU,CAAC,EACnC,MAAM,CAAC,gBAAgB,CAAC,UAAU,CAAC,EACnC,EAAE,SAAS,EAAE,IAAI,EAAE,CACpB,CAAA;IACH,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,3 @@
1
+ import type { ProjectConfig } from '../types.js';
2
+ export declare function scaffoldExpo(config: ProjectConfig): Promise<void>;
3
+ //# sourceMappingURL=mobile-expo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mobile-expo.d.ts","sourceRoot":"","sources":["../../../src/create/scaffolders/mobile-expo.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAMhD,wBAAsB,YAAY,CAAC,MAAM,EAAE,aAAa,iBAOvD"}
@@ -0,0 +1,14 @@
1
+ import { mkdir } from 'node:fs/promises';
2
+ import { dirname, join } from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import { copyTemplate } from './utils/copy.js';
5
+ const __dirname = dirname(fileURLToPath(import.meta.url));
6
+ const TEMPLATES_DIR = join(__dirname, '..', '..', '..', 'templates');
7
+ export async function scaffoldExpo(config) {
8
+ const appDir = join(config.targetDir, 'apps', 'mobile');
9
+ await mkdir(appDir, { recursive: true });
10
+ await copyTemplate(join(TEMPLATES_DIR, 'mobile-expo'), appDir, {
11
+ projectName: config.projectName,
12
+ });
13
+ }
14
+ //# sourceMappingURL=mobile-expo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mobile-expo.js","sourceRoot":"","sources":["../../../src/create/scaffolders/mobile-expo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AACxC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AAExC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAE9C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AACzD,MAAM,aAAa,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,WAAW,CAAC,CAAA;AAEpE,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,MAAqB;IACtD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAA;IACvD,MAAM,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAExC,MAAM,YAAY,CAAC,IAAI,CAAC,aAAa,EAAE,aAAa,CAAC,EAAE,MAAM,EAAE;QAC7D,WAAW,EAAE,MAAM,CAAC,WAAW;KAChC,CAAC,CAAA;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"wire-client.d.ts","sourceRoot":"","sources":["../../../src/create/scaffolders/wire-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,aAAa,iBAehE"}
1
+ {"version":3,"file":"wire-client.d.ts","sourceRoot":"","sources":["../../../src/create/scaffolders/wire-client.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD,wBAAsB,qBAAqB,CAAC,MAAM,EAAE,aAAa,iBAmBhE"}
@@ -14,6 +14,20 @@ export async function wireClientIntegration(config) {
14
14
  else {
15
15
  await writeFile(webPkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
16
16
  }
17
+ if (config.mobile === 'expo') {
18
+ await wireMobileTypes(config);
19
+ }
20
+ }
21
+ async function wireMobileTypes(config) {
22
+ const mobileDir = join(config.targetDir, 'apps', 'mobile');
23
+ const mobilePkgPath = join(mobileDir, 'package.json');
24
+ const pkg = JSON.parse(await readFile(mobilePkgPath, 'utf-8'));
25
+ pkg.dependencies['@local/types'] = 'workspace:*';
26
+ if (config.backend === 'nestjs-graphql') {
27
+ pkg.dependencies['@apollo/client'] = '^3.13.0';
28
+ pkg.dependencies['graphql'] = '^16.0.0';
29
+ }
30
+ await writeFile(mobilePkgPath, JSON.stringify(pkg, null, 2) + '\n', 'utf-8');
17
31
  }
18
32
  async function setupApolloClient(config, webDir) {
19
33
  await mkdir(join(webDir, 'src', 'lib'), { recursive: true });
@@ -1 +1 @@
1
- {"version":3,"file":"wire-client.js","sourceRoot":"","sources":["../../../src/create/scaffolders/wire-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"wire-client.js","sourceRoot":"","sources":["../../../src/create/scaffolders/wire-client.ts"],"names":[],"mappings":"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"}
@@ -2,11 +2,13 @@ export type PackageManager = 'pnpm' | 'npm';
2
2
  export type Frontend = 'vite' | 'nextjs';
3
3
  export type Backend = 'nestjs-rest' | 'nestjs-graphql';
4
4
  export type Database = 'postgres' | 'mysql';
5
+ export type Mobile = 'expo' | 'none';
5
6
  export interface ProjectConfig {
6
7
  projectName: string;
7
8
  frontend: Frontend;
8
9
  backend: Backend;
9
10
  database: Database;
11
+ mobile: Mobile;
10
12
  packageManager: PackageManager;
11
13
  targetDir: string;
12
14
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/create/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,CAAA;AAC3C,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAA;AACxC,MAAM,MAAM,OAAO,GAAG,aAAa,GAAG,gBAAgB,CAAA;AACtD,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAA;AAE3C,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,QAAQ,CAAA;IAClB,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,QAAQ,CAAA;IAClB,cAAc,EAAE,cAAc,CAAA;IAC9B,SAAS,EAAE,MAAM,CAAA;CAClB"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/create/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,KAAK,CAAA;AAC3C,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAA;AACxC,MAAM,MAAM,OAAO,GAAG,aAAa,GAAG,gBAAgB,CAAA;AACtD,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,OAAO,CAAA;AAC3C,MAAM,MAAM,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;AAEpC,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,QAAQ,CAAA;IAClB,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,QAAQ,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,cAAc,EAAE,cAAc,CAAA;IAC9B,SAAS,EAAE,MAAM,CAAA;CAClB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@exanderal/stackcraft",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "description": "Opinionated full-stack project scaffolding CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -16,7 +16,8 @@
16
16
  "graphql": {
17
17
  "type": "boolean",
18
18
  "description": "Add @ObjectType() to the model (required for GraphQL resolvers)",
19
- "default": false
19
+ "default": false,
20
+ "x-prompt": "Add @ObjectType() to the model? (required for GraphQL resolvers)"
20
21
  }
21
22
  },
22
23
  "required": ["name"]
@@ -0,0 +1,31 @@
1
+ import FontAwesome from '@expo/vector-icons/FontAwesome';
2
+ import { Tabs } from 'expo-router';
3
+
4
+ import Colors from '@/constants/Colors';
5
+ import { useColorScheme } from '@/components/useColorScheme';
6
+
7
+ function TabBarIcon(props: {
8
+ name: React.ComponentProps<typeof FontAwesome>['name'];
9
+ color: string;
10
+ }) {
11
+ return <FontAwesome size={28} style={{ marginBottom: -3 }} {...props} />;
12
+ }
13
+
14
+ export default function TabLayout() {
15
+ const colorScheme = useColorScheme();
16
+
17
+ return (
18
+ <Tabs
19
+ screenOptions={{
20
+ tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
21
+ }}>
22
+ <Tabs.Screen
23
+ name="index"
24
+ options={{
25
+ title: 'Home',
26
+ tabBarIcon: ({ color }) => <TabBarIcon name="home" color={color} />,
27
+ }}
28
+ />
29
+ </Tabs>
30
+ );
31
+ }
@@ -0,0 +1,23 @@
1
+ import { StyleSheet } from 'react-native';
2
+
3
+ import { Text, View } from '@/components/Themed';
4
+
5
+ export default function HomeScreen() {
6
+ return (
7
+ <View style={styles.container}>
8
+ <Text style={styles.title}>Home</Text>
9
+ </View>
10
+ );
11
+ }
12
+
13
+ const styles = StyleSheet.create({
14
+ container: {
15
+ flex: 1,
16
+ alignItems: 'center',
17
+ justifyContent: 'center',
18
+ },
19
+ title: {
20
+ fontSize: 20,
21
+ fontWeight: 'bold',
22
+ },
23
+ });
@@ -0,0 +1,40 @@
1
+ import { Link, Stack } from 'expo-router';
2
+ import { StyleSheet } from 'react-native';
3
+
4
+ import { Text, View } from '@/components/Themed';
5
+
6
+ export default function NotFoundScreen() {
7
+ return (
8
+ <>
9
+ <Stack.Screen options={{ title: 'Oops!' }} />
10
+ <View style={styles.container}>
11
+ <Text style={styles.title}>This screen doesn't exist.</Text>
12
+
13
+ <Link href="/" style={styles.link}>
14
+ <Text style={styles.linkText}>Go to home screen!</Text>
15
+ </Link>
16
+ </View>
17
+ </>
18
+ );
19
+ }
20
+
21
+ const styles = StyleSheet.create({
22
+ container: {
23
+ flex: 1,
24
+ alignItems: 'center',
25
+ justifyContent: 'center',
26
+ padding: 20,
27
+ },
28
+ title: {
29
+ fontSize: 20,
30
+ fontWeight: 'bold',
31
+ },
32
+ link: {
33
+ marginTop: 15,
34
+ paddingVertical: 15,
35
+ },
36
+ linkText: {
37
+ fontSize: 14,
38
+ color: '#2e78b7',
39
+ },
40
+ });
@@ -0,0 +1,31 @@
1
+ import { DarkTheme, DefaultTheme, ThemeProvider } from '@react-navigation/native';
2
+ import { Stack } from 'expo-router';
3
+ import * as SplashScreen from 'expo-splash-screen';
4
+ import { useEffect } from 'react';
5
+ import 'react-native-reanimated';
6
+
7
+ import { useColorScheme } from '@/components/useColorScheme';
8
+
9
+ export { ErrorBoundary } from 'expo-router';
10
+
11
+ export const unstable_settings = {
12
+ initialRouteName: '(tabs)',
13
+ };
14
+
15
+ SplashScreen.preventAutoHideAsync();
16
+
17
+ export default function RootLayout() {
18
+ const colorScheme = useColorScheme();
19
+
20
+ useEffect(() => {
21
+ SplashScreen.hideAsync();
22
+ }, []);
23
+
24
+ return (
25
+ <ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
26
+ <Stack>
27
+ <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
28
+ </Stack>
29
+ </ThemeProvider>
30
+ );
31
+ }
@@ -0,0 +1,39 @@
1
+ {
2
+ "expo": {
3
+ "name": "{{projectName}}",
4
+ "slug": "{{projectName}}",
5
+ "version": "1.0.0",
6
+ "orientation": "portrait",
7
+ "icon": "./assets/images/icon.png",
8
+ "scheme": "{{projectName}}",
9
+ "userInterfaceStyle": "automatic",
10
+ "newArchEnabled": true,
11
+ "splash": {
12
+ "image": "./assets/images/splash-icon.png",
13
+ "resizeMode": "contain",
14
+ "backgroundColor": "#ffffff"
15
+ },
16
+ "ios": {
17
+ "supportsTablet": true
18
+ },
19
+ "android": {
20
+ "adaptiveIcon": {
21
+ "foregroundImage": "./assets/images/adaptive-icon.png",
22
+ "backgroundColor": "#ffffff"
23
+ },
24
+ "edgeToEdgeEnabled": true,
25
+ "predictiveBackGestureEnabled": false
26
+ },
27
+ "web": {
28
+ "bundler": "metro",
29
+ "output": "static",
30
+ "favicon": "./assets/images/favicon.png"
31
+ },
32
+ "plugins": [
33
+ "expo-router"
34
+ ],
35
+ "experiments": {
36
+ "typedRoutes": true
37
+ }
38
+ }
39
+ }
@@ -0,0 +1,25 @@
1
+ import { Link } from 'expo-router';
2
+ import * as WebBrowser from 'expo-web-browser';
3
+ import React from 'react';
4
+ import { Platform } from 'react-native';
5
+
6
+ export function ExternalLink(
7
+ props: Omit<React.ComponentProps<typeof Link>, 'href'> & { href: string }
8
+ ) {
9
+ return (
10
+ <Link
11
+ target="_blank"
12
+ {...props}
13
+ // @ts-expect-error: External URLs are not typed.
14
+ href={props.href}
15
+ onPress={(e) => {
16
+ if (Platform.OS !== 'web') {
17
+ // Prevent the default behavior of linking to the default browser on native.
18
+ e.preventDefault();
19
+ // Open the link in an in-app browser.
20
+ WebBrowser.openBrowserAsync(props.href as string);
21
+ }
22
+ }}
23
+ />
24
+ );
25
+ }
@@ -0,0 +1,5 @@
1
+ import { Text, TextProps } from './Themed';
2
+
3
+ export function MonoText(props: TextProps) {
4
+ return <Text {...props} style={[props.style, { fontFamily: 'SpaceMono' }]} />;
5
+ }
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Learn more about Light and Dark modes:
3
+ * https://docs.expo.io/guides/color-schemes/
4
+ */
5
+
6
+ import { Text as DefaultText, View as DefaultView } from 'react-native';
7
+
8
+ import Colors from '@/constants/Colors';
9
+ import { useColorScheme } from './useColorScheme';
10
+
11
+ type ThemeProps = {
12
+ lightColor?: string;
13
+ darkColor?: string;
14
+ };
15
+
16
+ export type TextProps = ThemeProps & DefaultText['props'];
17
+ export type ViewProps = ThemeProps & DefaultView['props'];
18
+
19
+ export function useThemeColor(
20
+ props: { light?: string; dark?: string },
21
+ colorName: keyof typeof Colors.light & keyof typeof Colors.dark
22
+ ) {
23
+ const theme = useColorScheme() ?? 'light';
24
+ const colorFromProps = props[theme];
25
+
26
+ if (colorFromProps) {
27
+ return colorFromProps;
28
+ } else {
29
+ return Colors[theme][colorName];
30
+ }
31
+ }
32
+
33
+ export function Text(props: TextProps) {
34
+ const { style, lightColor, darkColor, ...otherProps } = props;
35
+ const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text');
36
+
37
+ return <DefaultText style={[{ color }, style]} {...otherProps} />;
38
+ }
39
+
40
+ export function View(props: ViewProps) {
41
+ const { style, lightColor, darkColor, ...otherProps } = props;
42
+ const backgroundColor = useThemeColor({ light: lightColor, dark: darkColor }, 'background');
43
+
44
+ return <DefaultView style={[{ backgroundColor }, style]} {...otherProps} />;
45
+ }
@@ -0,0 +1,4 @@
1
+ // This function is web-only as native doesn't currently support server (or build-time) rendering.
2
+ export function useClientOnlyValue<S, C>(server: S, client: C): S | C {
3
+ return client;
4
+ }
@@ -0,0 +1,12 @@
1
+ import React from 'react';
2
+
3
+ // `useEffect` is not invoked during server rendering, meaning
4
+ // we can use this to determine if we're on the server or not.
5
+ export function useClientOnlyValue<S, C>(server: S, client: C): S | C {
6
+ const [value, setValue] = React.useState<S | C>(server);
7
+ React.useEffect(() => {
8
+ setValue(client);
9
+ }, [client]);
10
+
11
+ return value;
12
+ }
@@ -0,0 +1 @@
1
+ export { useColorScheme } from 'react-native';
@@ -0,0 +1,8 @@
1
+ // NOTE: The default React Native styling doesn't support server rendering.
2
+ // Server rendered styles should not change between the first render of the HTML
3
+ // and the first render on the client. Typically, web developers will use CSS media queries
4
+ // to render different styles on the client and server, these aren't directly supported in React Native
5
+ // but can be achieved using a styling library like Nativewind.
6
+ export function useColorScheme() {
7
+ return 'light';
8
+ }
@@ -0,0 +1,19 @@
1
+ const tintColorLight = '#2f95dc';
2
+ const tintColorDark = '#fff';
3
+
4
+ export default {
5
+ light: {
6
+ text: '#000',
7
+ background: '#fff',
8
+ tint: tintColorLight,
9
+ tabIconDefault: '#ccc',
10
+ tabIconSelected: tintColorLight,
11
+ },
12
+ dark: {
13
+ text: '#fff',
14
+ background: '#000',
15
+ tint: tintColorDark,
16
+ tabIconDefault: '#ccc',
17
+ tabIconSelected: tintColorDark,
18
+ },
19
+ };
@@ -0,0 +1,37 @@
1
+ {
2
+ "name": "{{projectName}}-mobile",
3
+ "main": "expo-router/entry",
4
+ "version": "1.0.0",
5
+ "scripts": {
6
+ "dev": "expo start",
7
+ "android": "expo start --android",
8
+ "ios": "expo start --ios",
9
+ "web": "expo start --web",
10
+ "build": "expo export"
11
+ },
12
+ "dependencies": {
13
+ "@expo/vector-icons": "^15.0.3",
14
+ "@react-navigation/native": "^7.1.8",
15
+ "expo": "~54.0.33",
16
+ "expo-constants": "~18.0.13",
17
+ "expo-font": "~14.0.11",
18
+ "expo-linking": "~8.0.11",
19
+ "expo-router": "~6.0.23",
20
+ "expo-splash-screen": "~31.0.13",
21
+ "expo-status-bar": "~3.0.9",
22
+ "expo-web-browser": "~15.0.10",
23
+ "react": "19.1.0",
24
+ "react-dom": "19.1.0",
25
+ "react-native": "0.81.5",
26
+ "react-native-worklets": "0.5.1",
27
+ "react-native-reanimated": "~4.1.1",
28
+ "react-native-safe-area-context": "~5.6.0",
29
+ "react-native-screens": "~4.16.0",
30
+ "react-native-web": "~0.21.0"
31
+ },
32
+ "devDependencies": {
33
+ "@types/react": "~19.1.0",
34
+ "typescript": "~5.9.2"
35
+ },
36
+ "private": true
37
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "name": "mobile",
3
+ "targets": {
4
+ "dev": {
5
+ "executor": "nx:run-commands",
6
+ "options": { "command": "pnpm run dev", "cwd": "{projectRoot}" }
7
+ },
8
+ "build": {
9
+ "executor": "nx:run-commands",
10
+ "options": { "command": "pnpm run build", "cwd": "{projectRoot}" }
11
+ },
12
+ "lint": {
13
+ "executor": "nx:run-commands",
14
+ "options": { "command": "pnpm run lint", "cwd": "{projectRoot}" }
15
+ }
16
+ }
17
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "extends": "expo/tsconfig.base",
3
+ "compilerOptions": {
4
+ "strict": true,
5
+ "paths": {
6
+ "@/*": [
7
+ "./*"
8
+ ],
9
+ "@local/types/*": [
10
+ "../../packages/types/src/*"
11
+ ]
12
+ }
13
+ },
14
+ "include": [
15
+ "**/*.ts",
16
+ "**/*.tsx",
17
+ ".expo/types/**/*.ts",
18
+ "expo-env.d.ts"
19
+ ]
20
+ }