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.
- package/LICENSE +21 -0
- package/README.md +43 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +104 -0
- package/dist/cli.js.map +1 -0
- package/dist/copy-template.d.ts +8 -0
- package/dist/copy-template.d.ts.map +1 -0
- package/dist/copy-template.js +46 -0
- package/dist/copy-template.js.map +1 -0
- package/dist/detect-pm.d.ts +3 -0
- package/dist/detect-pm.d.ts.map +1 -0
- package/dist/detect-pm.js +12 -0
- package/dist/detect-pm.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/index.js.map +1 -0
- package/dist/install-deps.d.ts +16 -0
- package/dist/install-deps.d.ts.map +1 -0
- package/dist/install-deps.js +37 -0
- package/dist/install-deps.js.map +1 -0
- package/dist/messages.d.ts +17 -0
- package/dist/messages.d.ts.map +1 -0
- package/dist/messages.js +16 -0
- package/dist/messages.js.map +1 -0
- package/dist/render-qr.d.ts +2 -0
- package/dist/render-qr.d.ts.map +1 -0
- package/dist/render-qr.js +9 -0
- package/dist/render-qr.js.map +1 -0
- package/dist/validate-name.d.ts +9 -0
- package/dist/validate-name.d.ts.map +1 -0
- package/dist/validate-name.js +33 -0
- package/dist/validate-name.js.map +1 -0
- package/package.json +64 -0
- package/template/.proto/app/(proto)/[...screen].tsx +24 -0
- package/template/.proto/app/_layout.tsx +5 -0
- package/template/.proto/expo-config/app.json +17 -0
- package/template/CLAUDE.md +71 -0
- package/template/DESIGN.md +53 -0
- package/template/README.md +6 -0
- package/template/app/index.tsx +5 -0
- package/template/app.config.js +1 -0
- package/template/assets/.gitkeep +0 -0
- package/template/assets/icon.png +0 -0
- package/template/assets/splash.png +0 -0
- package/template/babel.config.js +7 -0
- package/template/components/proto/.gitkeep +0 -0
- package/template/components/proto/Button.tsx +61 -0
- package/template/components/proto/Card.tsx +63 -0
- package/template/components/proto/Divider.tsx +15 -0
- package/template/components/proto/Modal.tsx +43 -0
- package/template/components/proto/Row.tsx +28 -0
- package/template/components/proto/Screen.tsx +38 -0
- package/template/components/proto/Stack.tsx +17 -0
- package/template/components/proto/Text.tsx +37 -0
- package/template/components/proto/Toggle.tsx +40 -0
- package/template/components/proto/index.ts +11 -0
- package/template/components/proto/tokens/liquidGlass.ts +38 -0
- package/template/components/proto/tokens/materialYou.ts +38 -0
- package/template/components/proto/types.ts +55 -0
- package/template/components/proto/useTheme.ts +35 -0
- package/template/components/shared/.gitkeep +0 -0
- package/template/metro.config.js +5 -0
- package/template/package.json +35 -0
- package/template/pnpm-workspace.yaml +1 -0
- package/template/proto.config.js +6 -0
- package/template/screens/.gitkeep +0 -0
- 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 @@
|
|
|
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
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -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 @@
|
|
|
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"}
|
package/dist/index.d.ts
ADDED
|
@@ -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 @@
|
|
|
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"}
|
package/dist/messages.js
ADDED
|
@@ -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 @@
|
|
|
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 @@
|
|
|
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 @@
|
|
|
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,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
|
+
}
|