create-proto 0.1.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 (69) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +43 -0
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +104 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/copy-template.d.ts +8 -0
  8. package/dist/copy-template.d.ts.map +1 -0
  9. package/dist/copy-template.js +46 -0
  10. package/dist/copy-template.js.map +1 -0
  11. package/dist/detect-pm.d.ts +3 -0
  12. package/dist/detect-pm.d.ts.map +1 -0
  13. package/dist/detect-pm.js +12 -0
  14. package/dist/detect-pm.js.map +1 -0
  15. package/dist/index.d.ts +3 -0
  16. package/dist/index.d.ts.map +1 -0
  17. package/dist/index.js +7 -0
  18. package/dist/index.js.map +1 -0
  19. package/dist/install-deps.d.ts +16 -0
  20. package/dist/install-deps.d.ts.map +1 -0
  21. package/dist/install-deps.js +37 -0
  22. package/dist/install-deps.js.map +1 -0
  23. package/dist/messages.d.ts +17 -0
  24. package/dist/messages.d.ts.map +1 -0
  25. package/dist/messages.js +16 -0
  26. package/dist/messages.js.map +1 -0
  27. package/dist/render-qr.d.ts +2 -0
  28. package/dist/render-qr.d.ts.map +1 -0
  29. package/dist/render-qr.js +9 -0
  30. package/dist/render-qr.js.map +1 -0
  31. package/dist/validate-name.d.ts +9 -0
  32. package/dist/validate-name.d.ts.map +1 -0
  33. package/dist/validate-name.js +33 -0
  34. package/dist/validate-name.js.map +1 -0
  35. package/package.json +64 -0
  36. package/template/.proto/app/(proto)/[...screen].tsx +24 -0
  37. package/template/.proto/app/_layout.tsx +5 -0
  38. package/template/.proto/expo-config/app.json +17 -0
  39. package/template/CLAUDE.md +71 -0
  40. package/template/DESIGN.md +53 -0
  41. package/template/README.md +6 -0
  42. package/template/app/index.tsx +5 -0
  43. package/template/app.config.js +1 -0
  44. package/template/assets/.gitkeep +0 -0
  45. package/template/assets/icon.png +0 -0
  46. package/template/assets/splash.png +0 -0
  47. package/template/babel.config.js +7 -0
  48. package/template/components/proto/.gitkeep +0 -0
  49. package/template/components/proto/Button.tsx +61 -0
  50. package/template/components/proto/Card.tsx +63 -0
  51. package/template/components/proto/Divider.tsx +15 -0
  52. package/template/components/proto/Modal.tsx +43 -0
  53. package/template/components/proto/Row.tsx +28 -0
  54. package/template/components/proto/Screen.tsx +38 -0
  55. package/template/components/proto/Stack.tsx +17 -0
  56. package/template/components/proto/Text.tsx +37 -0
  57. package/template/components/proto/Toggle.tsx +40 -0
  58. package/template/components/proto/index.ts +11 -0
  59. package/template/components/proto/tokens/liquidGlass.ts +38 -0
  60. package/template/components/proto/tokens/materialYou.ts +38 -0
  61. package/template/components/proto/types.ts +55 -0
  62. package/template/components/proto/useTheme.ts +35 -0
  63. package/template/components/shared/.gitkeep +0 -0
  64. package/template/metro.config.js +5 -0
  65. package/template/package.json +35 -0
  66. package/template/pnpm-workspace.yaml +1 -0
  67. package/template/proto.config.js +6 -0
  68. package/template/screens/.gitkeep +0 -0
  69. package/template/screens/Home.tsx +60 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sherizan Sheikh
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OF OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # create-proto
2
+
3
+ Scaffold a new Proto prototype:
4
+
5
+ ```bash
6
+ npm create proto@latest myapp
7
+ ```
8
+
9
+ ## What Proto is
10
+
11
+ A prompt-native design environment. The iOS Simulator is the canvas. Claude Code CLI is the design tool. The designer describes what they want; native iOS UI appears in the Simulator, with Apple's real Liquid Glass on iOS 26+.
12
+
13
+ No canvas. No IDE. No engineering concepts.
14
+
15
+ ## What this command does
16
+
17
+ 1. Scaffolds the project: `DESIGN.md` (design system source-of-truth), `CLAUDE.md` (Claude Code instructions for Proto-aware generation), Proto component library, a starter Welcome screen
18
+ 2. Installs dependencies (Expo SDK 55, React Native, Reanimated 4, `@expo/ui`, `expo-glass-effect`)
19
+ 3. Auto-launches Metro and opens the iOS Simulator
20
+
21
+ Then in another terminal:
22
+
23
+ ```bash
24
+ cd myapp
25
+ claude
26
+ > add a liquid glass bottom tab bar with Home, Explore, Library, Profile tabs
27
+ ```
28
+
29
+ Claude reads `CLAUDE.md`, generates `app/_layout.tsx` using Apple's native `UITabBar` via `expo-router/unstable-native-tabs`, and the Simulator hot-reloads.
30
+
31
+ ## Requirements
32
+
33
+ - macOS with Xcode + iOS Simulator (Simulator is the canvas)
34
+ - Node.js 18+
35
+ - Claude Code installed (`npm i -g @anthropic-ai/claude-cli`)
36
+
37
+ ## Learn more
38
+
39
+ [github.com/sherizan/proto](https://github.com/sherizan/proto)
40
+
41
+ ## License
42
+
43
+ MIT
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ export declare function run(argv: string[]): Promise<void>;
2
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAcA,wBAAsB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA8DvD"}
package/dist/cli.js ADDED
@@ -0,0 +1,104 @@
1
+ import path from 'node:path';
2
+ import fs from 'node:fs';
3
+ import { spawn } from 'node:child_process';
4
+ import { fileURLToPath } from 'node:url';
5
+ import { createRequire } from 'node:module';
6
+ import { intro, outro, spinner, log } from '@clack/prompts';
7
+ import { messages } from './messages.js';
8
+ import { validateName } from './validate-name.js';
9
+ import { detectPm } from './detect-pm.js';
10
+ import { copyTemplate } from './copy-template.js';
11
+ import { installDeps } from './install-deps.js';
12
+ const DEFAULT_NAME = 'my-prototype';
13
+ export async function run(argv) {
14
+ intro(messages.header);
15
+ const rawName = argv[2] ?? DEFAULT_NAME;
16
+ if (argv[2] === undefined) {
17
+ log.info(messages.usingDefaultName(DEFAULT_NAME));
18
+ }
19
+ const validated = validateName(rawName);
20
+ if (!validated.ok) {
21
+ log.error(validated.reason);
22
+ process.exit(1);
23
+ }
24
+ const name = validated.sanitized;
25
+ const dest = path.resolve(process.cwd(), name);
26
+ if (fs.existsSync(dest)) {
27
+ log.error(messages.folderExists(name));
28
+ process.exit(1);
29
+ }
30
+ const here = path.dirname(fileURLToPath(import.meta.url));
31
+ const templateRoot = path.resolve(here, '../template');
32
+ const cleanupAndExit = () => {
33
+ if (fs.existsSync(dest)) {
34
+ fs.rmSync(dest, { recursive: true, force: true });
35
+ }
36
+ console.log('\n' + messages.cancelled);
37
+ process.exit(130);
38
+ };
39
+ process.on('SIGINT', cleanupAndExit);
40
+ const startMs = Date.now();
41
+ const s = spinner();
42
+ s.start(messages.settingUp(name));
43
+ try {
44
+ const today = new Date().toISOString().slice(0, 10);
45
+ await copyTemplate({
46
+ templateRoot,
47
+ destRoot: dest,
48
+ projectName: name,
49
+ substitutions: {
50
+ '{{APP_NAME}}': name,
51
+ '{{DATE}}': today,
52
+ },
53
+ });
54
+ const pm = detectPm(process.env.npm_config_user_agent);
55
+ await installDeps({ cwd: dest, pm });
56
+ const elapsed = Math.round((Date.now() - startMs) / 1000);
57
+ s.stop(messages.installed(elapsed));
58
+ }
59
+ catch (err) {
60
+ s.stop(err instanceof Error ? err.message : messages.installFailed);
61
+ if (fs.existsSync(dest)) {
62
+ log.info(messages.installFailedHint(name));
63
+ }
64
+ process.exit(1);
65
+ }
66
+ outro(messages.bootingProto);
67
+ await spawnProtoStart(dest, name);
68
+ }
69
+ async function spawnProtoStart(cwd, name) {
70
+ const protoCliBin = resolveProtoCli();
71
+ if (!protoCliBin) {
72
+ log.error(messages.protoCliNotFound(name));
73
+ return;
74
+ }
75
+ await new Promise((resolve) => {
76
+ const child = spawn(process.execPath, [protoCliBin, 'start'], {
77
+ cwd,
78
+ stdio: 'inherit',
79
+ });
80
+ child.on('exit', () => resolve());
81
+ child.on('error', () => {
82
+ log.error(messages.protoCliNotFound(name));
83
+ resolve();
84
+ });
85
+ });
86
+ }
87
+ function resolveProtoCli() {
88
+ // Workspace + post-publish: pnpm symlinks @sherizan/proto-cli at top-level node_modules
89
+ try {
90
+ const req = createRequire(import.meta.url);
91
+ return req.resolve('@sherizan/proto-cli/dist/index.js');
92
+ }
93
+ catch { }
94
+ // Monorepo dev fallback if the workspace symlink is missing
95
+ try {
96
+ const here = path.dirname(fileURLToPath(import.meta.url));
97
+ const sibling = path.resolve(here, '../../proto-cli/dist/index.js');
98
+ if (fs.existsSync(sibling))
99
+ return sibling;
100
+ }
101
+ catch { }
102
+ return null;
103
+ }
104
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,YAAY,GAAG,cAAc,CAAC;AAEpC,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,IAAc;IACtC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAEvB,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC;IACxC,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QAC1B,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC,CAAC;IACpD,CAAC;IACD,MAAM,SAAS,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,CAAC,SAAS,CAAC,EAAE,EAAE,CAAC;QAClB,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QAC5B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,MAAM,IAAI,GAAG,SAAS,CAAC,SAAS,CAAC;IAEjC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,IAAI,CAAC,CAAC;IAC/C,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACxB,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IAC1D,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;IAEvD,MAAM,cAAc,GAAG,GAAG,EAAE;QAC1B,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;QACvC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC,CAAC;IACF,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC;IAErC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC3B,MAAM,CAAC,GAAG,OAAO,EAAE,CAAC;IACpB,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IAElC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACpD,MAAM,YAAY,CAAC;YACjB,YAAY;YACZ,QAAQ,EAAE,IAAI;YACd,WAAW,EAAE,IAAI;YACjB,aAAa,EAAE;gBACb,cAAc,EAAE,IAAI;gBACpB,UAAU,EAAE,KAAK;aAClB;SACF,CAAC,CAAC;QAEH,MAAM,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACvD,MAAM,WAAW,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC;QACrC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QAC1D,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,CAAC,CAAC,IAAI,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;QACpE,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC;QAC7C,CAAC;QACD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;IAC7B,MAAM,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACpC,CAAC;AAED,KAAK,UAAU,eAAe,CAAC,GAAW,EAAE,IAAY;IACtD,MAAM,WAAW,GAAG,eAAe,EAAE,CAAC;IACtC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;QAC3C,OAAO;IACT,CAAC;IAED,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAClC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE;YAC5D,GAAG;YACH,KAAK,EAAE,SAAS;SACjB,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC;QAClC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACrB,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;YAC3C,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,eAAe;IACtB,wFAAwF;IACxF,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC3C,OAAO,GAAG,CAAC,OAAO,CAAC,mCAAmC,CAAC,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEV,4DAA4D;IAC5D,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,+BAA+B,CAAC,CAAC;QACpE,IAAI,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;YAAE,OAAO,OAAO,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC,CAAA,CAAC;IAEV,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,8 @@
1
+ export type CopyOptions = {
2
+ templateRoot: string;
3
+ destRoot: string;
4
+ projectName: string;
5
+ substitutions?: Record<string, string>;
6
+ };
7
+ export declare function copyTemplate(options: CopyOptions): Promise<void>;
8
+ //# sourceMappingURL=copy-template.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy-template.d.ts","sourceRoot":"","sources":["../src/copy-template.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,WAAW,GAAG;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC,CAAC;AAaF,wBAAsB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAItE"}
@@ -0,0 +1,46 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ const TEXT_EXTENSIONS = new Set([
4
+ '.ts',
5
+ '.tsx',
6
+ '.js',
7
+ '.jsx',
8
+ '.json',
9
+ '.md',
10
+ '.txt',
11
+ '.html',
12
+ ]);
13
+ export async function copyTemplate(options) {
14
+ const { templateRoot, destRoot, projectName, substitutions } = options;
15
+ const map = { '{{name}}': projectName, ...(substitutions ?? {}) };
16
+ await walk(templateRoot, destRoot, map);
17
+ }
18
+ async function walk(srcDir, destDir, substitutions) {
19
+ await fs.promises.mkdir(destDir, { recursive: true });
20
+ const entries = await fs.promises.readdir(srcDir, { withFileTypes: true });
21
+ for (const entry of entries) {
22
+ const srcPath = path.join(srcDir, entry.name);
23
+ const destPath = path.join(destDir, entry.name);
24
+ if (entry.isDirectory()) {
25
+ await walk(srcPath, destPath, substitutions);
26
+ continue;
27
+ }
28
+ const ext = path.extname(entry.name);
29
+ if (TEXT_EXTENSIONS.has(ext)) {
30
+ const text = await fs.promises.readFile(srcPath, 'utf8');
31
+ const replaced = applySubstitutions(text, substitutions);
32
+ await fs.promises.writeFile(destPath, replaced, 'utf8');
33
+ }
34
+ else {
35
+ await fs.promises.copyFile(srcPath, destPath);
36
+ }
37
+ }
38
+ }
39
+ function applySubstitutions(text, substitutions) {
40
+ let out = text;
41
+ for (const [key, value] of Object.entries(substitutions)) {
42
+ out = out.split(key).join(value);
43
+ }
44
+ return out;
45
+ }
46
+ //# sourceMappingURL=copy-template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"copy-template.js","sourceRoot":"","sources":["../src/copy-template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAS7B,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,KAAK;IACL,MAAM;IACN,KAAK;IACL,MAAM;IACN,OAAO;IACP,KAAK;IACL,MAAM;IACN,OAAO;CACR,CAAC,CAAC;AAEH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,OAAoB;IACrD,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC;IACvE,MAAM,GAAG,GAAG,EAAE,UAAU,EAAE,WAAW,EAAE,GAAG,CAAC,aAAa,IAAI,EAAE,CAAC,EAAE,CAAC;IAClE,MAAM,IAAI,CAAC,YAAY,EAAE,QAAQ,EAAE,GAAG,CAAC,CAAC;AAC1C,CAAC;AAED,KAAK,UAAU,IAAI,CACjB,MAAc,EACd,OAAe,EACf,aAAqC;IAErC,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3E,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,aAAa,CAAC,CAAC;YAC7C,SAAS;QACX,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACzD,MAAM,QAAQ,GAAG,kBAAkB,CAAC,IAAI,EAAE,aAAa,CAAC,CAAC;YACzD,MAAM,EAAE,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC1D,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAY,EAAE,aAAqC;IAC7E,IAAI,GAAG,GAAG,IAAI,CAAC;IACf,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;QACzD,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,3 @@
1
+ export type PackageManager = 'npm' | 'pnpm' | 'yarn';
2
+ export declare function detectPm(userAgent: string | undefined): PackageManager;
3
+ //# sourceMappingURL=detect-pm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-pm.d.ts","sourceRoot":"","sources":["../src/detect-pm.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG,KAAK,GAAG,MAAM,GAAG,MAAM,CAAC;AAErD,wBAAgB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,cAAc,CAMtE"}
@@ -0,0 +1,12 @@
1
+ export function detectPm(userAgent) {
2
+ if (!userAgent)
3
+ return 'npm';
4
+ if (userAgent.startsWith('pnpm/'))
5
+ return 'pnpm';
6
+ if (userAgent.startsWith('yarn/'))
7
+ return 'yarn';
8
+ if (userAgent.startsWith('npm/'))
9
+ return 'npm';
10
+ return 'npm';
11
+ }
12
+ //# sourceMappingURL=detect-pm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"detect-pm.js","sourceRoot":"","sources":["../src/detect-pm.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,QAAQ,CAAC,SAA6B;IACpD,IAAI,CAAC,SAAS;QAAE,OAAO,KAAK,CAAC;IAC7B,IAAI,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,MAAM,CAAC;IACjD,IAAI,SAAS,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,MAAM,CAAC;IACjD,IAAI,SAAS,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/C,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import { run } from './cli.js';
3
+ run(process.argv).catch((err) => {
4
+ console.error(err instanceof Error ? err.message : err);
5
+ process.exit(1);
6
+ });
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,MAAM,UAAU,CAAC;AAE/B,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC9B,OAAO,CAAC,KAAK,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;IACxD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
@@ -0,0 +1,16 @@
1
+ import type { PackageManager } from './detect-pm.js';
2
+ export type SpawnResult = {
3
+ code: number | null;
4
+ stderr: string;
5
+ };
6
+ export type SpawnFn = (cmd: string, args: string[], opts: {
7
+ cwd: string;
8
+ }) => Promise<SpawnResult>;
9
+ export type InstallOptions = {
10
+ cwd: string;
11
+ pm: PackageManager;
12
+ spawnFn?: SpawnFn;
13
+ };
14
+ export declare function installDeps(options: InstallOptions): Promise<void>;
15
+ export declare function translateInstallError(stderr: string): string;
16
+ //# sourceMappingURL=install-deps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-deps.d.ts","sourceRoot":"","sources":["../src/install-deps.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,MAAM,MAAM,WAAW,GAAG;IAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAClE,MAAM,MAAM,OAAO,GAAG,CACpB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,MAAM,EAAE,EACd,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,KAClB,OAAO,CAAC,WAAW,CAAC,CAAC;AAE1B,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,cAAc,CAAC;IACnB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF,wBAAsB,WAAW,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CAMxE;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAW5D"}
@@ -0,0 +1,37 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { messages } from './messages.js';
3
+ export async function installDeps(options) {
4
+ const fn = options.spawnFn ?? defaultSpawn;
5
+ const result = await fn(options.pm, ['install', '--silent'], { cwd: options.cwd });
6
+ if (result.code !== 0) {
7
+ throw new Error(translateInstallError(result.stderr));
8
+ }
9
+ }
10
+ export function translateInstallError(stderr) {
11
+ if (/ENOTFOUND|ETIMEDOUT|ECONNREFUSED|EAI_AGAIN/.test(stderr)) {
12
+ return messages.noNetwork;
13
+ }
14
+ if (/EACCES/.test(stderr)) {
15
+ return messages.noPermission;
16
+ }
17
+ if (/ENOSPC/.test(stderr)) {
18
+ return messages.noSpace;
19
+ }
20
+ return messages.installFailed;
21
+ }
22
+ function defaultSpawn(cmd, args, opts) {
23
+ return new Promise((resolve) => {
24
+ const child = spawn(cmd, args, { cwd: opts.cwd, stdio: ['ignore', 'ignore', 'pipe'] });
25
+ let stderr = '';
26
+ child.stderr?.on('data', (chunk) => {
27
+ stderr += chunk.toString();
28
+ });
29
+ child.on('exit', (code) => {
30
+ resolve({ code, stderr });
31
+ });
32
+ child.on('error', (err) => {
33
+ resolve({ code: 1, stderr: err.message });
34
+ });
35
+ });
36
+ }
37
+ //# sourceMappingURL=install-deps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install-deps.js","sourceRoot":"","sources":["../src/install-deps.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAgBzC,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,OAAuB;IACvD,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,IAAI,YAAY,CAAC;IAC3C,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACnF,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACtB,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IACxD,CAAC;AACH,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,MAAc;IAClD,IAAI,4CAA4C,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC9D,OAAO,QAAQ,CAAC,SAAS,CAAC;IAC5B,CAAC;IACD,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,OAAO,QAAQ,CAAC,YAAY,CAAC;IAC/B,CAAC;IACD,IAAI,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,OAAO,QAAQ,CAAC,OAAO,CAAC;IAC1B,CAAC;IACD,OAAO,QAAQ,CAAC,aAAa,CAAC;AAChC,CAAC;AAED,SAAS,YAAY,CAAC,GAAW,EAAE,IAAc,EAAE,IAAqB;IACtE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC;QACvF,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE;YACjC,MAAM,IAAI,KAAK,CAAC,QAAQ,EAAE,CAAC;QAC7B,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;YACxB,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;QAC5B,CAAC,CAAC,CAAC;QACH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YACxB,OAAO,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,17 @@
1
+ export declare const messages: {
2
+ header: string;
3
+ settingUp: (name: string) => string;
4
+ installed: (seconds: number) => string;
5
+ folderExists: (name: string) => string;
6
+ installFailedHint: (name: string) => string;
7
+ cancelled: string;
8
+ usingDefaultName: (name: string) => string;
9
+ bootingProto: string;
10
+ protoCliNotFound: (name: string) => string;
11
+ noNetwork: string;
12
+ noPermission: string;
13
+ noSpace: string;
14
+ installFailed: string;
15
+ };
16
+ export type Messages = typeof messages;
17
+ //# sourceMappingURL=messages.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.d.ts","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,QAAQ;;sBAED,MAAM;yBACH,MAAM;yBACN,MAAM;8BAED,MAAM;;6BAGP,MAAM;;6BAGN,MAAM;;;;;CAShC,CAAC;AAEF,MAAM,MAAM,QAAQ,GAAG,OAAO,QAAQ,CAAC"}
@@ -0,0 +1,16 @@
1
+ export const messages = {
2
+ header: 'Proto',
3
+ settingUp: (name) => `Setting up ${name}...`,
4
+ installed: (seconds) => `Installed in ${seconds}s`,
5
+ folderExists: (name) => `That folder already exists. Pick another name: npm create proto@latest <name> (currently: "${name}").`,
6
+ installFailedHint: (name) => `Couldn't install dependencies. Once your environment is ready: cd ${name} && pnpm install && proto start`,
7
+ cancelled: 'Cancelled. Folder removed.',
8
+ usingDefaultName: (name) => `Using name: ${name} (pass a name as the first argument to override).`,
9
+ bootingProto: 'Booting Proto...',
10
+ protoCliNotFound: (name) => `Couldn't find proto-cli. Run manually: cd ${name} && proto start`,
11
+ noNetwork: "Couldn't reach the package registry. Check your internet and try again.",
12
+ noPermission: "Don't have permission to write here. Try a different folder.",
13
+ noSpace: 'Out of disk space. Free some up and try again.',
14
+ installFailed: "Couldn't get things installed. Try again, or visit proto.run/help",
15
+ };
16
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,QAAQ,GAAG;IACtB,MAAM,EAAE,OAAO;IACf,SAAS,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,cAAc,IAAI,KAAK;IACpD,SAAS,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,gBAAgB,OAAO,GAAG;IAC1D,YAAY,EAAE,CAAC,IAAY,EAAE,EAAE,CAC7B,8FAA8F,IAAI,KAAK;IACzG,iBAAiB,EAAE,CAAC,IAAY,EAAE,EAAE,CAClC,qEAAqE,IAAI,iCAAiC;IAC5G,SAAS,EAAE,4BAA4B;IACvC,gBAAgB,EAAE,CAAC,IAAY,EAAE,EAAE,CACjC,eAAe,IAAI,mDAAmD;IACxE,YAAY,EAAE,kBAAkB;IAChC,gBAAgB,EAAE,CAAC,IAAY,EAAE,EAAE,CACjC,6CAA6C,IAAI,iBAAiB;IACpE,SAAS,EACP,yEAAyE;IAC3E,YAAY,EACV,8DAA8D;IAChE,OAAO,EAAE,gDAAgD;IACzD,aAAa,EACX,mEAAmE;CACtE,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function renderQr(url: string): string;
2
+ //# sourceMappingURL=render-qr.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-qr.d.ts","sourceRoot":"","sources":["../src/render-qr.ts"],"names":[],"mappings":"AAEA,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAM5C"}
@@ -0,0 +1,9 @@
1
+ import qrcode from 'qrcode-terminal';
2
+ export function renderQr(url) {
3
+ let output = '';
4
+ qrcode.generate(url, { small: true }, (rendered) => {
5
+ output = rendered;
6
+ });
7
+ return output;
8
+ }
9
+ //# sourceMappingURL=render-qr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render-qr.js","sourceRoot":"","sources":["../src/render-qr.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,iBAAiB,CAAC;AAErC,MAAM,UAAU,QAAQ,CAAC,GAAW;IAClC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,MAAM,CAAC,QAAQ,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,QAAQ,EAAE,EAAE;QACjD,MAAM,GAAG,QAAQ,CAAC;IACpB,CAAC,CAAC,CAAC;IACH,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,9 @@
1
+ export type NameValidation = {
2
+ ok: true;
3
+ sanitized: string;
4
+ } | {
5
+ ok: false;
6
+ reason: string;
7
+ };
8
+ export declare function validateName(input: string): NameValidation;
9
+ //# sourceMappingURL=validate-name.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-name.d.ts","sourceRoot":"","sources":["../src/validate-name.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,cAAc,GACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAIlC,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,cAAc,CA6B1D"}
@@ -0,0 +1,33 @@
1
+ import validate from 'validate-npm-package-name';
2
+ const RESERVED = new Set(['node_modules', '.proto', 'proto']);
3
+ export function validateName(input) {
4
+ const trimmed = input.trim();
5
+ if (!trimmed) {
6
+ return { ok: false, reason: 'Give your prototype a name.' };
7
+ }
8
+ if (/\s/.test(trimmed)) {
9
+ return {
10
+ ok: false,
11
+ reason: 'No spaces allowed. Try hyphens instead, like "my-app".',
12
+ };
13
+ }
14
+ const sanitized = trimmed.toLowerCase();
15
+ if (RESERVED.has(sanitized)) {
16
+ return { ok: false, reason: 'That name is reserved. Pick something else.' };
17
+ }
18
+ if (/^\d/.test(sanitized)) {
19
+ return {
20
+ ok: false,
21
+ reason: 'That name has characters that cause trouble. Use letters, numbers, and hyphens.',
22
+ };
23
+ }
24
+ const result = validate(sanitized);
25
+ if (!result.validForNewPackages) {
26
+ return {
27
+ ok: false,
28
+ reason: 'That name has characters that cause trouble. Use letters, numbers, and hyphens.',
29
+ };
30
+ }
31
+ return { ok: true, sanitized };
32
+ }
33
+ //# sourceMappingURL=validate-name.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate-name.js","sourceRoot":"","sources":["../src/validate-name.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,2BAA2B,CAAC;AAMjD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,cAAc,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC;AAE9D,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,6BAA6B,EAAE,CAAC;IAC9D,CAAC;IACD,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,wDAAwD;SACjE,CAAC;IACJ,CAAC;IACD,MAAM,SAAS,GAAG,OAAO,CAAC,WAAW,EAAE,CAAC;IACxC,IAAI,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QAC5B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,6CAA6C,EAAE,CAAC;IAC9E,CAAC;IACD,IAAI,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;QAC1B,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,iFAAiF;SAC1F,CAAC;IACJ,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IACnC,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAChC,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,iFAAiF;SAC1F,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;AACjC,CAAC"}
package/package.json ADDED
@@ -0,0 +1,64 @@
1
+ {
2
+ "name": "create-proto",
3
+ "version": "0.1.0",
4
+ "description": "Scaffold a new Proto prototype: `npm create proto@latest myapp`. Designer-first native iOS prototyping environment that pairs with Claude Code.",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "author": "Sherizan Sheikh",
8
+ "homepage": "https://github.com/sherizan/proto#readme",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/sherizan/proto.git",
12
+ "directory": "packages/create-proto"
13
+ },
14
+ "bugs": {
15
+ "url": "https://github.com/sherizan/proto/issues"
16
+ },
17
+ "keywords": [
18
+ "proto",
19
+ "expo",
20
+ "react-native",
21
+ "prototyping",
22
+ "design-tool",
23
+ "ios",
24
+ "simulator",
25
+ "scaffold",
26
+ "create"
27
+ ],
28
+ "bin": {
29
+ "create-proto": "./dist/index.js"
30
+ },
31
+ "files": [
32
+ "dist",
33
+ "template",
34
+ "README.md",
35
+ "LICENSE"
36
+ ],
37
+ "engines": {
38
+ "node": ">=18"
39
+ },
40
+ "publishConfig": {
41
+ "access": "public"
42
+ },
43
+ "dependencies": {
44
+ "@clack/prompts": "^0.7.0",
45
+ "@sherizan/proto-cli": "^0.1.0",
46
+ "fs-extra": "^11.2.0",
47
+ "qrcode-terminal": "^0.12.0",
48
+ "validate-npm-package-name": "^5.0.1"
49
+ },
50
+ "devDependencies": {
51
+ "@types/fs-extra": "^11.0.4",
52
+ "@types/node": "^20.12.0",
53
+ "@types/qrcode-terminal": "^0.12.2",
54
+ "@types/validate-npm-package-name": "^4.0.2",
55
+ "tsx": "^4.15.0"
56
+ },
57
+ "scripts": {
58
+ "build": "tsc -p tsconfig.json",
59
+ "typecheck": "tsc -p tsconfig.json --noEmit",
60
+ "test": "vitest run",
61
+ "sync-template": "tsx scripts/sync-template.ts",
62
+ "prebuild": "tsx scripts/sync-template.ts"
63
+ }
64
+ }
@@ -0,0 +1,24 @@
1
+ import { useLocalSearchParams } from 'expo-router';
2
+ import { Screen, Text } from '../../../components/proto';
3
+
4
+ export default function DynamicScreen() {
5
+ const params = useLocalSearchParams<{ screen?: string[] }>();
6
+ const name = params.screen?.[0] ?? 'Home';
7
+
8
+ let Component: React.ComponentType | null = null;
9
+ try {
10
+ Component = require(`../../../screens/${name}`).default;
11
+ } catch {
12
+ Component = null;
13
+ }
14
+
15
+ if (!Component) {
16
+ return (
17
+ <Screen title="Not found">
18
+ <Text size="body">No screen named "{name}" yet.</Text>
19
+ </Screen>
20
+ );
21
+ }
22
+
23
+ return <Component />;
24
+ }
@@ -0,0 +1,5 @@
1
+ import { Stack } from 'expo-router';
2
+
3
+ export default function Layout() {
4
+ return <Stack screenOptions={{ headerShown: false }} />;
5
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "expo": {
3
+ "name": "{{name}}",
4
+ "slug": "{{name}}",
5
+ "version": "0.0.0",
6
+ "orientation": "portrait",
7
+ "icon": "./assets/icon.png",
8
+ "splash": {
9
+ "image": "./assets/splash.png",
10
+ "resizeMode": "contain",
11
+ "backgroundColor": "#FFFFFF"
12
+ },
13
+ "scheme": "{{name}}",
14
+ "plugins": ["expo-router"],
15
+ "experiments": { "typedRoutes": true }
16
+ }
17
+ }