create-idia-app 0.2.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/README.md +104 -0
- package/dist/index.js +412 -0
- package/dist/index.js.map +1 -0
- package/package.json +33 -0
- package/template/.cursor/rules/idia-ui-ds-brain.mdc +32 -0
- package/template/.cursor/rules/idia-ui-forms.mdc +34 -0
- package/template/.cursor/rules/idia-ui-overlays.mdc +23 -0
- package/template/.idia/brain/AGENTS.md +37 -0
- package/template/.idia/brain/ai/agents/retrieval-cheatsheet.md +209 -0
- package/template/.idia/brain/ai/skills/components/button/SKILL.md +32 -0
- package/template/.idia/brain/ai/skills/ds-brain-action-hierarchy/SKILL.md +46 -0
- package/template/.idia/brain/ai/skills/ds-brain-forms/SKILL.md +67 -0
- package/template/.idia/brain/ai/skills/ds-brain-index/SKILL.md +76 -0
- package/template/.idia/brain/ai/skills/ds-brain-overlays/SKILL.md +30 -0
- package/template/.idia/brain/ai/skills/ds-brain-retrieval/SKILL.md +54 -0
- package/template/.idia/brain/registry/ai-index.generated.json +833 -0
- package/template/.idia/brain/registry/component-registry.generated.json +2947 -0
- package/template/.idia/manifest.json +17 -0
- package/template/.storybook/main.ts +9 -0
- package/template/.storybook/preview.tsx +20 -0
- package/template/AGENTS.md +11 -0
- package/template/App.tsx +24 -0
- package/template/README.md +75 -0
- package/template/app.json +13 -0
- package/template/babel.config.js +25 -0
- package/template/global.css +32 -0
- package/template/index.ts +8 -0
- package/template/metro.config.js +19 -0
- package/template/package.json +85 -0
- package/template/public/fonts/Inter.ttf +0 -0
- package/template/public/fonts/NunitoSans.woff2 +0 -0
- package/template/src/config/env.ts +4 -0
- package/template/src/config/versions.ts +7 -0
- package/template/src/navigation/RootNavigator.tsx +27 -0
- package/template/src/navigation/linking.ts +13 -0
- package/template/src/navigation/types.ts +10 -0
- package/template/src/providers/AppProviders.tsx +47 -0
- package/template/src/screens/Home/HomeScreen.tsx +12 -0
- package/template/src/screens/Welcome/WelcomeScreen.tsx +115 -0
- package/template/src/stories/Button.stories.tsx +31 -0
- package/template/storybook-static/assets/Button.stories-CfapbH7U.js +196 -0
- package/template/storybook-static/assets/Color-F6OSRLHC-CFwL-RM_.js +1 -0
- package/template/storybook-static/assets/DocsRenderer-CFRXHY34-AADCayzw.js +729 -0
- package/template/storybook-static/assets/_commonjsHelpers-Cpj98o6Y.js +1 -0
- package/template/storybook-static/assets/axe-d-K7rF9D.js +30 -0
- package/template/storybook-static/assets/chunk-XP5HYGXS-BHXC9YeQ.js +1 -0
- package/template/storybook-static/assets/client-DGEjZp2f.js +25 -0
- package/template/storybook-static/assets/entry-preview-Dc5wkB2s.js +2 -0
- package/template/storybook-static/assets/entry-preview-docs-BaxqCxyK.js +46 -0
- package/template/storybook-static/assets/iframe-Bl15XKnQ.js +211 -0
- package/template/storybook-static/assets/index-Bhelpi4i.js +11 -0
- package/template/storybook-static/assets/index-C_pJYAGD.js +1 -0
- package/template/storybook-static/assets/index-D5Inswos.js +1 -0
- package/template/storybook-static/assets/index-NGyRR_en.js +9 -0
- package/template/storybook-static/assets/index-zmTGQa7e.js +9 -0
- package/template/storybook-static/assets/jsx-runtime-BjG_zV1W.js +9 -0
- package/template/storybook-static/assets/preview-BNUqaTig.js +1 -0
- package/template/storybook-static/assets/preview-Cfo7ZnTc.js +2 -0
- package/template/storybook-static/assets/preview-CrKLV1aL.css +1 -0
- package/template/storybook-static/assets/preview-DkVJIpDn.js +2 -0
- package/template/storybook-static/assets/preview-DrRsTNnS.js +17 -0
- package/template/storybook-static/assets/react-18-Bfhi6ooJ.js +1 -0
- package/template/storybook-static/assets/react-FmFgRqLi.js +1 -0
- package/template/storybook-static/assets/react-native-gesture-handler-BzS7UzhZ.js +52 -0
- package/template/storybook-static/assets/test-utils-X4YdDMST.js +9 -0
- package/template/storybook-static/favicon.svg +1 -0
- package/template/storybook-static/fonts/Inter.ttf +0 -0
- package/template/storybook-static/fonts/NunitoSans.woff2 +0 -0
- package/template/storybook-static/iframe.html +668 -0
- package/template/storybook-static/index.html +145 -0
- package/template/storybook-static/index.json +1 -0
- package/template/storybook-static/nunito-sans-bold-italic.woff2 +0 -0
- package/template/storybook-static/nunito-sans-bold.woff2 +0 -0
- package/template/storybook-static/nunito-sans-italic.woff2 +0 -0
- package/template/storybook-static/nunito-sans-regular.woff2 +0 -0
- package/template/storybook-static/project.json +1 -0
- package/template/storybook-static/sb-addons/a11y-2/manager-bundle.js +3 -0
- package/template/storybook-static/sb-addons/links-1/manager-bundle.js +3 -0
- package/template/storybook-static/sb-addons/storybook-core-core-server-presets-0/common-manager-bundle.js +3 -0
- package/template/storybook-static/sb-common-assets/favicon.svg +1 -0
- package/template/storybook-static/sb-common-assets/nunito-sans-bold-italic.woff2 +0 -0
- package/template/storybook-static/sb-common-assets/nunito-sans-bold.woff2 +0 -0
- package/template/storybook-static/sb-common-assets/nunito-sans-italic.woff2 +0 -0
- package/template/storybook-static/sb-common-assets/nunito-sans-regular.woff2 +0 -0
- package/template/storybook-static/sb-manager/globals-module-info.js +1052 -0
- package/template/storybook-static/sb-manager/globals-runtime.js +41775 -0
- package/template/storybook-static/sb-manager/globals.js +48 -0
- package/template/storybook-static/sb-manager/runtime.js +12048 -0
- package/template/tamagui.config.ts +18 -0
- package/template/tsconfig.json +11 -0
package/README.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# create-idia-app
|
|
2
|
+
|
|
3
|
+
Scaffold an Expo + React Navigation consumer app with `@idia-ui/core` and `@idia-ui/theme`.
|
|
4
|
+
|
|
5
|
+
**Track C Phase 2a** — local monorepo build only; not published to npm until Phase 5.
|
|
6
|
+
|
|
7
|
+
## Build
|
|
8
|
+
|
|
9
|
+
From repo root:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pnpm --filter create-idia-app build
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
`prebuild` copies `templates/consumer-app/` into `packages/create-idia-app/template/`. Refresh the source template first when the sandbox changes:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
node scripts/sync-consumer-template.mjs
|
|
19
|
+
pnpm --filter create-idia-app build
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Local usage
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
node packages/create-idia-app/dist/index.js my-app
|
|
26
|
+
# or
|
|
27
|
+
pnpm --filter create-idia-app exec create-idia-app my-app
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### Flags
|
|
31
|
+
|
|
32
|
+
| Flag | Behavior |
|
|
33
|
+
|------|----------|
|
|
34
|
+
| `--pm <pnpm\|npm\|yarn>` | Override package manager |
|
|
35
|
+
| `--skip-install` | Skip install + doctor |
|
|
36
|
+
| `--force` | Overwrite existing directory |
|
|
37
|
+
| `--no-git` | Skip `git init` |
|
|
38
|
+
| `--with-storybook` | Warn only — Phase 3 |
|
|
39
|
+
| `--with-brain` | Warn only — Phase 4 |
|
|
40
|
+
|
|
41
|
+
## E2E outside monorepo (pre–Phase 5)
|
|
42
|
+
|
|
43
|
+
`@idia-ui/*` is **not** on public npm at `0.2.0` yet. External e2e uses packed tarballs + `file:` overrides (same procedure as Phase 0.5 / 1a).
|
|
44
|
+
|
|
45
|
+
### 1. Build runtime packages + CLI
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# repo root
|
|
49
|
+
pnpm --filter @idia-ui/tokens build
|
|
50
|
+
pnpm --filter @idia-ui/theme build
|
|
51
|
+
pnpm --filter @idia-ui/core build
|
|
52
|
+
pnpm --filter @idia-ui/hooks build
|
|
53
|
+
pnpm --filter @idia-ui/motion build
|
|
54
|
+
pnpm --filter @idia-ui/utils build
|
|
55
|
+
pnpm --filter @idia-ui/validators build
|
|
56
|
+
pnpm --filter @idia-ui/cli build
|
|
57
|
+
pnpm --filter create-idia-app build
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### 2. Pack tarballs
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
OUT_DIR=C:\Users\Ojanti\Desktop\Projects_\idia-ui-pack-tarballs
|
|
64
|
+
mkdir %OUT_DIR%
|
|
65
|
+
cd packages/tokens && pnpm pack --pack-destination %OUT_DIR%
|
|
66
|
+
# repeat for theme, core, hooks, motion, utils, validators, cli
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 3. Scaffold outside monorepo
|
|
70
|
+
|
|
71
|
+
```powershell
|
|
72
|
+
cd $env:TEMP
|
|
73
|
+
node C:\Users\Ojanti\Desktop\Projects_\idia-ui\packages\create-idia-app\dist\index.js my-cli-test --skip-install
|
|
74
|
+
cd my-cli-test
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 4. Apply `file:` overrides
|
|
78
|
+
|
|
79
|
+
In generated `package.json`, replace semver `@idia-ui/*` and `@idia-ui/cli` with `file:<tarball>` paths. Add matching `pnpm.overrides` for all `@idia-ui/*` packages (transitive graph).
|
|
80
|
+
|
|
81
|
+
### 5. Install, doctor, dev
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
pnpm install
|
|
85
|
+
pnpm exec idia-ui doctor
|
|
86
|
+
pnpm dev
|
|
87
|
+
# or non-interactive smoke:
|
|
88
|
+
npx expo export --platform web
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
When developing **inside** the monorepo, `create-idia-app` auto-detects `packages/cli/dist/cli.js` and runs doctor via the sibling CLI build (no npm install of `@idia-ui/cli` required for doctor during maintainer smoke).
|
|
92
|
+
|
|
93
|
+
## Generated app contract
|
|
94
|
+
|
|
95
|
+
- `package.json` name + `@idia-ui/*` pinned to `^0.2.0`
|
|
96
|
+
- `app.json` name / slug / scheme renamed from `my-idia-app`
|
|
97
|
+
- `src/navigation/linking.ts` URL prefixes updated
|
|
98
|
+
- `.idia/manifest.json` stub with `idiaCli` + `core` versions
|
|
99
|
+
- `@idia-ui/cli` added to `devDependencies`
|
|
100
|
+
- Post-install: `idia-ui doctor` (non-strict) unless `--skip-install`
|
|
101
|
+
|
|
102
|
+
## Version coupling
|
|
103
|
+
|
|
104
|
+
`create-idia-app@0.2.x` generates apps targeting `@idia-ui/core@0.2.x` and `@idia-ui/cli@0.2.x`.
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
"use strict";
|
|
3
|
+
|
|
4
|
+
// src/scaffold.ts
|
|
5
|
+
var import_node_fs3 = require("fs");
|
|
6
|
+
var import_node_path3 = require("path");
|
|
7
|
+
var import_node_child_process = require("child_process");
|
|
8
|
+
|
|
9
|
+
// src/replace.ts
|
|
10
|
+
var import_node_fs = require("fs");
|
|
11
|
+
var import_node_path = require("path");
|
|
12
|
+
|
|
13
|
+
// src/constants.ts
|
|
14
|
+
var IDIA_UI_VERSION = "0.2.0";
|
|
15
|
+
var CREATE_APP_VERSION = "0.2.0";
|
|
16
|
+
var CLI_VERSION = "0.2.0";
|
|
17
|
+
var TEMPLATE_SLUG = "my-idia-app";
|
|
18
|
+
|
|
19
|
+
// src/replace.ts
|
|
20
|
+
function toKebabCase(name) {
|
|
21
|
+
return name.trim().replace(/[\s_]+/g, "-").replace(/([a-z])([A-Z])/g, "$1-$2").toLowerCase().replace(/[^a-z0-9-]/g, "-").replace(/-+/g, "-").replace(/^-|-$/g, "");
|
|
22
|
+
}
|
|
23
|
+
function validateProjectName(name) {
|
|
24
|
+
const slug = toKebabCase(name);
|
|
25
|
+
if (!slug) {
|
|
26
|
+
throw new Error("Project name is required.");
|
|
27
|
+
}
|
|
28
|
+
if (!/^[a-z][a-z0-9-]*$/.test(slug)) {
|
|
29
|
+
throw new Error(
|
|
30
|
+
`Invalid project name "${name}". Use lowercase letters, numbers, and hyphens (must start with a letter).`
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
return slug;
|
|
34
|
+
}
|
|
35
|
+
function replacePlaceholders(projectDir, projectName) {
|
|
36
|
+
const packageJsonPath = (0, import_node_path.join)(projectDir, "package.json");
|
|
37
|
+
const packageJson = JSON.parse((0, import_node_fs.readFileSync)(packageJsonPath, "utf8"));
|
|
38
|
+
packageJson.name = projectName;
|
|
39
|
+
for (const field of ["dependencies", "devDependencies"]) {
|
|
40
|
+
const deps = packageJson[field];
|
|
41
|
+
if (!deps) continue;
|
|
42
|
+
for (const pkg of Object.keys(deps)) {
|
|
43
|
+
if (pkg.startsWith("@idia-ui/")) {
|
|
44
|
+
deps[pkg] = `^${IDIA_UI_VERSION}`;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
packageJson.devDependencies ??= {};
|
|
49
|
+
packageJson.devDependencies["@idia-ui/cli"] = `^${CLI_VERSION}`;
|
|
50
|
+
(0, import_node_fs.writeFileSync)(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}
|
|
51
|
+
`, "utf8");
|
|
52
|
+
const appJsonPath = (0, import_node_path.join)(projectDir, "app.json");
|
|
53
|
+
const appJson = JSON.parse((0, import_node_fs.readFileSync)(appJsonPath, "utf8"));
|
|
54
|
+
appJson.expo.name = projectName;
|
|
55
|
+
appJson.expo.slug = projectName;
|
|
56
|
+
appJson.expo.scheme = projectName;
|
|
57
|
+
(0, import_node_fs.writeFileSync)(appJsonPath, `${JSON.stringify(appJson, null, 2)}
|
|
58
|
+
`, "utf8");
|
|
59
|
+
const linkingPath = (0, import_node_path.join)(projectDir, "src", "navigation", "linking.ts");
|
|
60
|
+
let linking = (0, import_node_fs.readFileSync)(linkingPath, "utf8");
|
|
61
|
+
linking = linking.replaceAll(TEMPLATE_SLUG, projectName);
|
|
62
|
+
(0, import_node_fs.writeFileSync)(linkingPath, linking, "utf8");
|
|
63
|
+
}
|
|
64
|
+
function writeManifest(projectDir) {
|
|
65
|
+
const manifestDir = (0, import_node_path.join)(projectDir, ".idia");
|
|
66
|
+
(0, import_node_fs.mkdirSync)(manifestDir, { recursive: true });
|
|
67
|
+
const manifestPath = (0, import_node_path.join)(manifestDir, "manifest.json");
|
|
68
|
+
const manifest = {
|
|
69
|
+
idiaCli: CLI_VERSION,
|
|
70
|
+
core: IDIA_UI_VERSION
|
|
71
|
+
};
|
|
72
|
+
(0, import_node_fs.writeFileSync)(manifestPath, `${JSON.stringify(manifest, null, 2)}
|
|
73
|
+
`, "utf8");
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// src/pm.ts
|
|
77
|
+
var PM_VALUES = /* @__PURE__ */ new Set(["pnpm", "npm", "yarn"]);
|
|
78
|
+
function parsePackageManagerFlag(value) {
|
|
79
|
+
if (!value) return void 0;
|
|
80
|
+
const normalized = value.toLowerCase();
|
|
81
|
+
if (!PM_VALUES.has(normalized)) {
|
|
82
|
+
throw new Error(`Invalid --pm value "${value}". Use pnpm, npm, or yarn.`);
|
|
83
|
+
}
|
|
84
|
+
return normalized;
|
|
85
|
+
}
|
|
86
|
+
function detectPackageManager(override) {
|
|
87
|
+
if (override) return override;
|
|
88
|
+
const agent = process.env.npm_config_user_agent ?? "";
|
|
89
|
+
if (agent.includes("pnpm")) return "pnpm";
|
|
90
|
+
if (agent.includes("yarn")) return "yarn";
|
|
91
|
+
const execPath = process.env.npm_execpath ?? "";
|
|
92
|
+
if (execPath.includes("pnpm")) return "pnpm";
|
|
93
|
+
if (execPath.includes("yarn")) return "yarn";
|
|
94
|
+
return "npm";
|
|
95
|
+
}
|
|
96
|
+
function installCommand(pm) {
|
|
97
|
+
switch (pm) {
|
|
98
|
+
case "pnpm":
|
|
99
|
+
return { command: "pnpm", args: ["install"] };
|
|
100
|
+
case "yarn":
|
|
101
|
+
return { command: "yarn", args: ["install"] };
|
|
102
|
+
default:
|
|
103
|
+
return { command: "npm", args: ["install"] };
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
function devCommand(pm) {
|
|
107
|
+
switch (pm) {
|
|
108
|
+
case "pnpm":
|
|
109
|
+
return "pnpm dev";
|
|
110
|
+
case "yarn":
|
|
111
|
+
return "yarn dev";
|
|
112
|
+
default:
|
|
113
|
+
return "npm run dev";
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function idiaUiCommand(pm, subcommand) {
|
|
117
|
+
switch (pm) {
|
|
118
|
+
case "pnpm":
|
|
119
|
+
return { command: "pnpm", args: ["exec", "idia-ui", ...subcommand] };
|
|
120
|
+
case "yarn":
|
|
121
|
+
return { command: "yarn", args: ["idia-ui", ...subcommand] };
|
|
122
|
+
default:
|
|
123
|
+
return { command: "npx", args: ["idia-ui", ...subcommand] };
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// src/doctor.ts
|
|
128
|
+
var import_node_fs2 = require("fs");
|
|
129
|
+
|
|
130
|
+
// src/paths.ts
|
|
131
|
+
var import_node_path2 = require("path");
|
|
132
|
+
function cliEntryPath() {
|
|
133
|
+
const entry = process.argv[1];
|
|
134
|
+
if (!entry) {
|
|
135
|
+
throw new Error("Unable to resolve CLI entry path.");
|
|
136
|
+
}
|
|
137
|
+
return entry;
|
|
138
|
+
}
|
|
139
|
+
function packageRootDir() {
|
|
140
|
+
return (0, import_node_path2.join)((0, import_node_path2.dirname)(cliEntryPath()), "..");
|
|
141
|
+
}
|
|
142
|
+
function templateDir() {
|
|
143
|
+
return (0, import_node_path2.join)(packageRootDir(), "template");
|
|
144
|
+
}
|
|
145
|
+
function monorepoDoctorCliPath() {
|
|
146
|
+
return (0, import_node_path2.join)(packageRootDir(), "..", "cli", "dist", "cli.js");
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// src/doctor.ts
|
|
150
|
+
function resolveMonorepoDoctorCli() {
|
|
151
|
+
const candidate = monorepoDoctorCliPath();
|
|
152
|
+
return (0, import_node_fs2.existsSync)(candidate) ? candidate : null;
|
|
153
|
+
}
|
|
154
|
+
function resolveIdiaUiInvocation(pm, subcommand) {
|
|
155
|
+
const monorepoCli = resolveMonorepoDoctorCli();
|
|
156
|
+
if (monorepoCli) {
|
|
157
|
+
return {
|
|
158
|
+
command: process.execPath,
|
|
159
|
+
args: [monorepoCli, ...subcommand],
|
|
160
|
+
via: "monorepo"
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
const viaPm = idiaUiCommand(pm, subcommand);
|
|
164
|
+
return { ...viaPm, via: "installed" };
|
|
165
|
+
}
|
|
166
|
+
function resolveDoctorInvocation(pm) {
|
|
167
|
+
return resolveIdiaUiInvocation(pm, ["doctor"]);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// src/scaffold.ts
|
|
171
|
+
function resolveTemplateDir() {
|
|
172
|
+
const bundled = templateDir();
|
|
173
|
+
if ((0, import_node_fs3.existsSync)(bundled)) return bundled;
|
|
174
|
+
throw new Error(
|
|
175
|
+
"Template directory missing. Run `pnpm run build` in packages/create-idia-app first."
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
function runCommand(command, args, cwd) {
|
|
179
|
+
const result = (0, import_node_child_process.spawnSync)(command, args, {
|
|
180
|
+
cwd,
|
|
181
|
+
stdio: "inherit",
|
|
182
|
+
shell: process.platform === "win32"
|
|
183
|
+
});
|
|
184
|
+
if (result.error) {
|
|
185
|
+
return { status: result.status, error: result.error };
|
|
186
|
+
}
|
|
187
|
+
return { status: result.status };
|
|
188
|
+
}
|
|
189
|
+
function scaffold(options) {
|
|
190
|
+
const projectName = validateProjectName(options.projectName);
|
|
191
|
+
const projectDir = options.targetDir ? (0, import_node_path3.join)(options.targetDir, projectName) : (0, import_node_path3.join)(process.cwd(), projectName);
|
|
192
|
+
const pm = detectPackageManager(options.pm);
|
|
193
|
+
if ((0, import_node_fs3.existsSync)(projectDir)) {
|
|
194
|
+
if (!options.force) {
|
|
195
|
+
throw new Error(
|
|
196
|
+
`Directory "${projectDir}" already exists. Pass --force to overwrite or choose another name.`
|
|
197
|
+
);
|
|
198
|
+
}
|
|
199
|
+
(0, import_node_fs3.rmSync)(projectDir, { recursive: true, force: true });
|
|
200
|
+
}
|
|
201
|
+
(0, import_node_fs3.mkdirSync)(projectDir, { recursive: true });
|
|
202
|
+
(0, import_node_fs3.cpSync)(resolveTemplateDir(), projectDir, { recursive: true });
|
|
203
|
+
replacePlaceholders(projectDir, projectName);
|
|
204
|
+
writeManifest(projectDir);
|
|
205
|
+
if (!options.noGit) {
|
|
206
|
+
const git = runCommand("git", ["init"], projectDir);
|
|
207
|
+
if (git.error) {
|
|
208
|
+
console.warn("\u26A0 git init skipped:", git.error.message);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
let installed = false;
|
|
212
|
+
let doctorRan = false;
|
|
213
|
+
let doctorExitCode = null;
|
|
214
|
+
let doctorVia = "skipped";
|
|
215
|
+
if (!options.skipInstall) {
|
|
216
|
+
console.log(`
|
|
217
|
+
Installing dependencies with ${pm}\u2026`);
|
|
218
|
+
const install = installCommand(pm);
|
|
219
|
+
const installResult = runCommand(install.command, install.args, projectDir);
|
|
220
|
+
if (installResult.error) {
|
|
221
|
+
throw installResult.error;
|
|
222
|
+
}
|
|
223
|
+
if (installResult.status !== 0) {
|
|
224
|
+
throw new Error(`${pm} install failed with exit code ${installResult.status ?? 1}`);
|
|
225
|
+
}
|
|
226
|
+
installed = true;
|
|
227
|
+
console.log("\nRunning idia-ui doctor (non-strict)\u2026");
|
|
228
|
+
const doctor = resolveDoctorInvocation(pm);
|
|
229
|
+
doctorVia = doctor.via;
|
|
230
|
+
const doctorResult = runCommand(doctor.command, doctor.args, projectDir);
|
|
231
|
+
doctorRan = true;
|
|
232
|
+
doctorExitCode = doctorResult.status;
|
|
233
|
+
if (doctorResult.error) {
|
|
234
|
+
console.warn("\u26A0 idia-ui doctor could not run:", doctorResult.error.message);
|
|
235
|
+
doctorRan = false;
|
|
236
|
+
doctorExitCode = null;
|
|
237
|
+
} else if (doctorExitCode !== 0) {
|
|
238
|
+
console.warn(
|
|
239
|
+
`\u26A0 idia-ui doctor exited with code ${doctorExitCode}. Review warnings above; re-run after fixing peers.`
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
runPostScaffoldAddons(projectDir, pm, options);
|
|
243
|
+
} else {
|
|
244
|
+
console.log("\n--skip-install: skipping dependency install and idia-ui doctor.");
|
|
245
|
+
if (options.withStorybook || options.withBrain) {
|
|
246
|
+
console.warn(
|
|
247
|
+
"\u26A0 --with-storybook / --with-brain require install. After `pnpm install`, run idia-ui add storybook and/or idia-ui add brain."
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
printNextSteps(projectName, projectDir, pm, options);
|
|
252
|
+
return {
|
|
253
|
+
projectDir,
|
|
254
|
+
projectName,
|
|
255
|
+
pm,
|
|
256
|
+
installed,
|
|
257
|
+
doctorRan,
|
|
258
|
+
doctorExitCode,
|
|
259
|
+
doctorVia
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
function runPostScaffoldAddons(projectDir, pm, options) {
|
|
263
|
+
if (options.withStorybook) {
|
|
264
|
+
console.log("\nRunning idia-ui add storybook\u2026");
|
|
265
|
+
const add = resolveIdiaUiInvocation(pm, ["add", "storybook"]);
|
|
266
|
+
const result = runCommand(add.command, add.args, projectDir);
|
|
267
|
+
if (result.error) {
|
|
268
|
+
console.warn("\u26A0 idia-ui add storybook could not run:", result.error.message);
|
|
269
|
+
} else if (result.status !== 0) {
|
|
270
|
+
console.warn(
|
|
271
|
+
`\u26A0 idia-ui add storybook exited with code ${result.status ?? 1}. Re-run manually after fixing peers.`
|
|
272
|
+
);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
if (options.withBrain) {
|
|
276
|
+
console.log("\nRunning idia-ui add brain\u2026");
|
|
277
|
+
const add = resolveIdiaUiInvocation(pm, ["add", "brain"]);
|
|
278
|
+
const result = runCommand(add.command, add.args, projectDir);
|
|
279
|
+
if (result.error) {
|
|
280
|
+
console.warn("\u26A0 idia-ui add brain could not run:", result.error.message);
|
|
281
|
+
} else if (result.status !== 0) {
|
|
282
|
+
console.warn(
|
|
283
|
+
`\u26A0 idia-ui add brain exited with code ${result.status ?? 1}. Re-run manually after fixing peers.`
|
|
284
|
+
);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
function printNextSteps(projectName, projectDir, pm, options) {
|
|
289
|
+
const dev = devCommand(pm);
|
|
290
|
+
console.log("\n\u2713 Project scaffolded successfully\n");
|
|
291
|
+
console.log("Next steps:");
|
|
292
|
+
console.log(` cd ${projectDir}`);
|
|
293
|
+
if (!(0, import_node_fs3.existsSync)((0, import_node_path3.join)(projectDir, "node_modules"))) {
|
|
294
|
+
const install = installCommand(pm);
|
|
295
|
+
console.log(` ${install.command} ${install.args.join(" ")}`);
|
|
296
|
+
}
|
|
297
|
+
console.log(` ${dev}`);
|
|
298
|
+
console.log(` ${pm === "npm" ? "npx idia-ui doctor" : `${pm} exec idia-ui doctor`}`);
|
|
299
|
+
if (!options.withStorybook) {
|
|
300
|
+
console.log(` ${pm === "npm" ? "npx idia-ui add storybook" : `${pm} exec idia-ui add storybook`}`);
|
|
301
|
+
}
|
|
302
|
+
if (!options.withBrain) {
|
|
303
|
+
console.log(` ${pm === "npm" ? "npx idia-ui add brain" : `${pm} exec idia-ui add brain`}`);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// src/index.ts
|
|
308
|
+
function printHelp() {
|
|
309
|
+
console.log(`create-idia-app v${CREATE_APP_VERSION}
|
|
310
|
+
|
|
311
|
+
Usage:
|
|
312
|
+
create-idia-app [project-name] [options]
|
|
313
|
+
|
|
314
|
+
Options:
|
|
315
|
+
--pm <pnpm|npm|yarn> Override package manager detection
|
|
316
|
+
--skip-install Skip install and idia-ui doctor
|
|
317
|
+
--force Overwrite target directory if it exists
|
|
318
|
+
--no-git Skip git init
|
|
319
|
+
--with-storybook Not available (Phase 3) \u2014 prints warning
|
|
320
|
+
--with-brain Not available (Phase 4) \u2014 prints warning
|
|
321
|
+
-h, --help Show help
|
|
322
|
+
-V, --version Show version
|
|
323
|
+
`);
|
|
324
|
+
}
|
|
325
|
+
function parseArgs(argv) {
|
|
326
|
+
const result = {
|
|
327
|
+
projectName: void 0,
|
|
328
|
+
pm: void 0,
|
|
329
|
+
skipInstall: false,
|
|
330
|
+
force: false,
|
|
331
|
+
noGit: false,
|
|
332
|
+
withStorybook: false,
|
|
333
|
+
withBrain: false,
|
|
334
|
+
help: false,
|
|
335
|
+
version: false
|
|
336
|
+
};
|
|
337
|
+
for (let i = 0; i < argv.length; i += 1) {
|
|
338
|
+
const arg = argv[i];
|
|
339
|
+
switch (arg) {
|
|
340
|
+
case "--pm":
|
|
341
|
+
result.pm = parsePackageManagerFlag(argv[++i]);
|
|
342
|
+
break;
|
|
343
|
+
case "--skip-install":
|
|
344
|
+
result.skipInstall = true;
|
|
345
|
+
break;
|
|
346
|
+
case "--force":
|
|
347
|
+
result.force = true;
|
|
348
|
+
break;
|
|
349
|
+
case "--no-git":
|
|
350
|
+
result.noGit = true;
|
|
351
|
+
break;
|
|
352
|
+
case "--with-storybook":
|
|
353
|
+
result.withStorybook = true;
|
|
354
|
+
break;
|
|
355
|
+
case "--with-brain":
|
|
356
|
+
result.withBrain = true;
|
|
357
|
+
break;
|
|
358
|
+
case "-h":
|
|
359
|
+
case "--help":
|
|
360
|
+
result.help = true;
|
|
361
|
+
break;
|
|
362
|
+
case "-V":
|
|
363
|
+
case "--version":
|
|
364
|
+
result.version = true;
|
|
365
|
+
break;
|
|
366
|
+
default:
|
|
367
|
+
if (arg.startsWith("-")) {
|
|
368
|
+
throw new Error(`Unknown option: ${arg}`);
|
|
369
|
+
}
|
|
370
|
+
if (!result.projectName) {
|
|
371
|
+
result.projectName = arg;
|
|
372
|
+
} else {
|
|
373
|
+
throw new Error(`Unexpected argument: ${arg}`);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
return result;
|
|
378
|
+
}
|
|
379
|
+
function main() {
|
|
380
|
+
try {
|
|
381
|
+
const args = parseArgs(process.argv.slice(2));
|
|
382
|
+
if (args.help) {
|
|
383
|
+
printHelp();
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
386
|
+
if (args.version) {
|
|
387
|
+
console.log(CREATE_APP_VERSION);
|
|
388
|
+
return;
|
|
389
|
+
}
|
|
390
|
+
if (!args.projectName) {
|
|
391
|
+
printHelp();
|
|
392
|
+
throw new Error("Project name is required. Example: create-idia-app my-app");
|
|
393
|
+
}
|
|
394
|
+
scaffold({
|
|
395
|
+
projectName: args.projectName,
|
|
396
|
+
targetDir: process.cwd(),
|
|
397
|
+
pm: args.pm,
|
|
398
|
+
skipInstall: args.skipInstall,
|
|
399
|
+
force: args.force,
|
|
400
|
+
noGit: args.noGit,
|
|
401
|
+
withStorybook: args.withStorybook,
|
|
402
|
+
withBrain: args.withBrain
|
|
403
|
+
});
|
|
404
|
+
} catch (error) {
|
|
405
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
406
|
+
console.error(`
|
|
407
|
+
Error: ${message}`);
|
|
408
|
+
process.exit(1);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
main();
|
|
412
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/scaffold.ts","../src/replace.ts","../src/constants.ts","../src/pm.ts","../src/doctor.ts","../src/paths.ts","../src/index.ts"],"sourcesContent":["import { cpSync, existsSync, mkdirSync, rmSync } from 'node:fs'\r\nimport { join } from 'node:path'\r\nimport { spawnSync } from 'node:child_process'\r\n\r\nimport { replacePlaceholders, validateProjectName, writeManifest } from './replace.js'\r\nimport {\r\n detectPackageManager,\r\n devCommand,\r\n installCommand,\r\n type PackageManager,\r\n} from './pm.js'\r\nimport { resolveDoctorInvocation, resolveIdiaUiInvocation } from './doctor.js'\r\nimport { templateDir } from './paths.js'\r\n\r\nexport type ScaffoldOptions = {\r\n projectName: string\r\n targetDir: string\r\n pm?: PackageManager\r\n skipInstall?: boolean\r\n force?: boolean\r\n noGit?: boolean\r\n withStorybook?: boolean\r\n withBrain?: boolean\r\n}\r\n\r\nexport type ScaffoldResult = {\r\n projectDir: string\r\n projectName: string\r\n pm: PackageManager\r\n installed: boolean\r\n doctorRan: boolean\r\n doctorExitCode: number | null\r\n doctorVia: 'monorepo' | 'installed' | 'skipped'\r\n}\r\n\r\nfunction resolveTemplateDir(): string {\r\n const bundled = templateDir()\r\n if (existsSync(bundled)) return bundled\r\n throw new Error(\r\n 'Template directory missing. Run `pnpm run build` in packages/create-idia-app first.',\r\n )\r\n}\r\n\r\nfunction runCommand(\r\n command: string,\r\n args: string[],\r\n cwd: string,\r\n): { status: number | null; error?: Error } {\r\n const result = spawnSync(command, args, {\r\n cwd,\r\n stdio: 'inherit',\r\n shell: process.platform === 'win32',\r\n })\r\n if (result.error) {\r\n return { status: result.status, error: result.error }\r\n }\r\n return { status: result.status }\r\n}\r\n\r\nexport function scaffold(options: ScaffoldOptions): ScaffoldResult {\r\n const projectName = validateProjectName(options.projectName)\r\n const projectDir = options.targetDir\r\n ? join(options.targetDir, projectName)\r\n : join(process.cwd(), projectName)\r\n const pm = detectPackageManager(options.pm)\r\n\r\n if (existsSync(projectDir)) {\r\n if (!options.force) {\r\n throw new Error(\r\n `Directory \"${projectDir}\" already exists. Pass --force to overwrite or choose another name.`,\r\n )\r\n }\r\n rmSync(projectDir, { recursive: true, force: true })\r\n }\r\n\r\n mkdirSync(projectDir, { recursive: true })\r\n cpSync(resolveTemplateDir(), projectDir, { recursive: true })\r\n\r\n replacePlaceholders(projectDir, projectName)\r\n writeManifest(projectDir)\r\n\r\n if (!options.noGit) {\r\n const git = runCommand('git', ['init'], projectDir)\r\n if (git.error) {\r\n console.warn('⚠ git init skipped:', git.error.message)\r\n }\r\n }\r\n\r\n let installed = false\r\n let doctorRan = false\r\n let doctorExitCode: number | null = null\r\n let doctorVia: ScaffoldResult['doctorVia'] = 'skipped'\r\n\r\n if (!options.skipInstall) {\r\n console.log(`\\nInstalling dependencies with ${pm}…`)\r\n const install = installCommand(pm)\r\n const installResult = runCommand(install.command, install.args, projectDir)\r\n if (installResult.error) {\r\n throw installResult.error\r\n }\r\n if (installResult.status !== 0) {\r\n throw new Error(`${pm} install failed with exit code ${installResult.status ?? 1}`)\r\n }\r\n installed = true\r\n\r\n console.log('\\nRunning idia-ui doctor (non-strict)…')\r\n const doctor = resolveDoctorInvocation(pm)\r\n doctorVia = doctor.via\r\n const doctorResult = runCommand(doctor.command, doctor.args, projectDir)\r\n doctorRan = true\r\n doctorExitCode = doctorResult.status\r\n if (doctorResult.error) {\r\n console.warn('⚠ idia-ui doctor could not run:', doctorResult.error.message)\r\n doctorRan = false\r\n doctorExitCode = null\r\n } else if (doctorExitCode !== 0) {\r\n console.warn(\r\n `⚠ idia-ui doctor exited with code ${doctorExitCode}. Review warnings above; re-run after fixing peers.`,\r\n )\r\n }\r\n\r\n runPostScaffoldAddons(projectDir, pm, options)\r\n } else {\r\n console.log('\\n--skip-install: skipping dependency install and idia-ui doctor.')\r\n if (options.withStorybook || options.withBrain) {\r\n console.warn(\r\n '⚠ --with-storybook / --with-brain require install. After `pnpm install`, run idia-ui add storybook and/or idia-ui add brain.',\r\n )\r\n }\r\n }\r\n\r\n printNextSteps(projectName, projectDir, pm, options)\r\n\r\n return {\r\n projectDir,\r\n projectName,\r\n pm,\r\n installed,\r\n doctorRan,\r\n doctorExitCode,\r\n doctorVia,\r\n }\r\n}\r\n\r\nfunction runPostScaffoldAddons(\r\n projectDir: string,\r\n pm: PackageManager,\r\n options: Pick<ScaffoldOptions, 'withStorybook' | 'withBrain'>,\r\n): void {\r\n if (options.withStorybook) {\r\n console.log('\\nRunning idia-ui add storybook…')\r\n const add = resolveIdiaUiInvocation(pm, ['add', 'storybook'])\r\n const result = runCommand(add.command, add.args, projectDir)\r\n if (result.error) {\r\n console.warn('⚠ idia-ui add storybook could not run:', result.error.message)\r\n } else if (result.status !== 0) {\r\n console.warn(\r\n `⚠ idia-ui add storybook exited with code ${result.status ?? 1}. Re-run manually after fixing peers.`,\r\n )\r\n }\r\n }\r\n\r\n if (options.withBrain) {\r\n console.log('\\nRunning idia-ui add brain…')\r\n const add = resolveIdiaUiInvocation(pm, ['add', 'brain'])\r\n const result = runCommand(add.command, add.args, projectDir)\r\n if (result.error) {\r\n console.warn('⚠ idia-ui add brain could not run:', result.error.message)\r\n } else if (result.status !== 0) {\r\n console.warn(\r\n `⚠ idia-ui add brain exited with code ${result.status ?? 1}. Re-run manually after fixing peers.`,\r\n )\r\n }\r\n }\r\n}\r\n\r\nfunction printNextSteps(\r\n projectName: string,\r\n projectDir: string,\r\n pm: PackageManager,\r\n options: Pick<ScaffoldOptions, 'withStorybook' | 'withBrain'>,\r\n): void {\r\n const dev = devCommand(pm)\r\n console.log('\\n✓ Project scaffolded successfully\\n')\r\n console.log('Next steps:')\r\n console.log(` cd ${projectDir}`)\r\n if (!existsSync(join(projectDir, 'node_modules'))) {\r\n const install = installCommand(pm)\r\n console.log(` ${install.command} ${install.args.join(' ')}`)\r\n }\r\n console.log(` ${dev}`)\r\n console.log(` ${pm === 'npm' ? 'npx idia-ui doctor' : `${pm} exec idia-ui doctor`}`)\r\n if (!options.withStorybook) {\r\n console.log(` ${pm === 'npm' ? 'npx idia-ui add storybook' : `${pm} exec idia-ui add storybook`}`)\r\n }\r\n if (!options.withBrain) {\r\n console.log(` ${pm === 'npm' ? 'npx idia-ui add brain' : `${pm} exec idia-ui add brain`}`)\r\n }\r\n}\r\n","import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'\r\nimport { join } from 'node:path'\r\n\r\nimport { CLI_VERSION, IDIA_UI_VERSION, TEMPLATE_SLUG } from './constants.js'\r\n\r\ntype PackageJson = {\r\n name?: string\r\n dependencies?: Record<string, string>\r\n devDependencies?: Record<string, string>\r\n}\r\n\r\nexport function toKebabCase(name: string): string {\r\n return name\r\n .trim()\r\n .replace(/[\\s_]+/g, '-')\r\n .replace(/([a-z])([A-Z])/g, '$1-$2')\r\n .toLowerCase()\r\n .replace(/[^a-z0-9-]/g, '-')\r\n .replace(/-+/g, '-')\r\n .replace(/^-|-$/g, '')\r\n}\r\n\r\nexport function validateProjectName(name: string): string {\r\n const slug = toKebabCase(name)\r\n if (!slug) {\r\n throw new Error('Project name is required.')\r\n }\r\n if (!/^[a-z][a-z0-9-]*$/.test(slug)) {\r\n throw new Error(\r\n `Invalid project name \"${name}\". Use lowercase letters, numbers, and hyphens (must start with a letter).`,\r\n )\r\n }\r\n return slug\r\n}\r\n\r\nexport function replacePlaceholders(projectDir: string, projectName: string): void {\r\n const packageJsonPath = join(projectDir, 'package.json')\r\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as PackageJson\r\n\r\n packageJson.name = projectName\r\n\r\n for (const field of ['dependencies', 'devDependencies'] as const) {\r\n const deps = packageJson[field]\r\n if (!deps) continue\r\n for (const pkg of Object.keys(deps)) {\r\n if (pkg.startsWith('@idia-ui/')) {\r\n deps[pkg] = `^${IDIA_UI_VERSION}`\r\n }\r\n }\r\n }\r\n\r\n packageJson.devDependencies ??= {}\r\n packageJson.devDependencies['@idia-ui/cli'] = `^${CLI_VERSION}`\r\n\r\n writeFileSync(packageJsonPath, `${JSON.stringify(packageJson, null, 2)}\\n`, 'utf8')\r\n\r\n const appJsonPath = join(projectDir, 'app.json')\r\n const appJson = JSON.parse(readFileSync(appJsonPath, 'utf8')) as {\r\n expo: { name: string; slug: string; scheme: string }\r\n }\r\n appJson.expo.name = projectName\r\n appJson.expo.slug = projectName\r\n appJson.expo.scheme = projectName\r\n writeFileSync(appJsonPath, `${JSON.stringify(appJson, null, 2)}\\n`, 'utf8')\r\n\r\n const linkingPath = join(projectDir, 'src', 'navigation', 'linking.ts')\r\n let linking = readFileSync(linkingPath, 'utf8')\r\n linking = linking.replaceAll(TEMPLATE_SLUG, projectName)\r\n writeFileSync(linkingPath, linking, 'utf8')\r\n}\r\n\r\nexport function writeManifest(projectDir: string): void {\r\n const manifestDir = join(projectDir, '.idia')\r\n mkdirSync(manifestDir, { recursive: true })\r\n const manifestPath = join(manifestDir, 'manifest.json')\r\n const manifest = {\r\n idiaCli: CLI_VERSION,\r\n core: IDIA_UI_VERSION,\r\n }\r\n writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`, 'utf8')\r\n}\r\n","/** Monorepo-local @idia-ui/* minor — pins generated app deps (RFC §10.4). */\r\nexport const IDIA_UI_VERSION = '0.2.0'\r\n\r\n/** create-idia-app package version — keep in sync with package.json. */\r\nexport const CREATE_APP_VERSION = '0.2.0'\r\n\r\n/** @idia-ui/cli version written to manifest + devDependency. */\r\nexport const CLI_VERSION = '0.2.0'\r\n\r\nexport const TEMPLATE_SLUG = 'my-idia-app'\r\n","export type PackageManager = 'pnpm' | 'npm' | 'yarn'\r\n\r\nconst PM_VALUES = new Set<PackageManager>(['pnpm', 'npm', 'yarn'])\r\n\r\nexport function parsePackageManagerFlag(value: string | undefined): PackageManager | undefined {\r\n if (!value) return undefined\r\n const normalized = value.toLowerCase() as PackageManager\r\n if (!PM_VALUES.has(normalized)) {\r\n throw new Error(`Invalid --pm value \"${value}\". Use pnpm, npm, or yarn.`)\r\n }\r\n return normalized\r\n}\r\n\r\nexport function detectPackageManager(override?: PackageManager): PackageManager {\r\n if (override) return override\r\n\r\n const agent = process.env.npm_config_user_agent ?? ''\r\n if (agent.includes('pnpm')) return 'pnpm'\r\n if (agent.includes('yarn')) return 'yarn'\r\n\r\n const execPath = process.env.npm_execpath ?? ''\r\n if (execPath.includes('pnpm')) return 'pnpm'\r\n if (execPath.includes('yarn')) return 'yarn'\r\n\r\n return 'npm'\r\n}\r\n\r\nexport function installCommand(pm: PackageManager): { command: string; args: string[] } {\r\n switch (pm) {\r\n case 'pnpm':\r\n return { command: 'pnpm', args: ['install'] }\r\n case 'yarn':\r\n return { command: 'yarn', args: ['install'] }\r\n default:\r\n return { command: 'npm', args: ['install'] }\r\n }\r\n}\r\n\r\nexport function devCommand(pm: PackageManager): string {\r\n switch (pm) {\r\n case 'pnpm':\r\n return 'pnpm dev'\r\n case 'yarn':\r\n return 'yarn dev'\r\n default:\r\n return 'npm run dev'\r\n }\r\n}\r\n\r\nexport function doctorCommand(pm: PackageManager): { command: string; args: string[] } {\r\n return idiaUiCommand(pm, ['doctor'])\r\n}\r\n\r\nexport type IdiaUiCommand = { command: string; args: string[] }\r\n\r\nexport function idiaUiCommand(\r\n pm: PackageManager,\r\n subcommand: string[],\r\n): IdiaUiCommand {\r\n switch (pm) {\r\n case 'pnpm':\r\n return { command: 'pnpm', args: ['exec', 'idia-ui', ...subcommand] }\r\n case 'yarn':\r\n return { command: 'yarn', args: ['idia-ui', ...subcommand] }\r\n default:\r\n return { command: 'npx', args: ['idia-ui', ...subcommand] }\r\n }\r\n}\r\n","import { existsSync } from 'node:fs'\r\n\r\nimport { monorepoDoctorCliPath } from './paths.js'\r\nimport { idiaUiCommand, type PackageManager } from './pm.js'\r\n\r\n/** Monorepo sibling @idia-ui/cli when developing create-idia-app locally. */\r\nexport function resolveMonorepoDoctorCli(): string | null {\r\n const candidate = monorepoDoctorCliPath()\r\n return existsSync(candidate) ? candidate : null\r\n}\r\n\r\nexport function resolveIdiaUiInvocation(\r\n pm: PackageManager,\r\n subcommand: string[],\r\n): { command: string; args: string[]; via: 'monorepo' | 'installed' } {\r\n const monorepoCli = resolveMonorepoDoctorCli()\r\n if (monorepoCli) {\r\n return {\r\n command: process.execPath,\r\n args: [monorepoCli, ...subcommand],\r\n via: 'monorepo',\r\n }\r\n }\r\n\r\n const viaPm = idiaUiCommand(pm, subcommand)\r\n return { ...viaPm, via: 'installed' }\r\n}\r\n\r\nexport function resolveDoctorInvocation(\r\n pm: PackageManager,\r\n): { command: string; args: string[]; via: 'monorepo' | 'installed' } {\r\n return resolveIdiaUiInvocation(pm, ['doctor'])\r\n}\r\n","import { dirname, join } from 'node:path'\r\n\r\n/** CLI entry file (dist/index.js) — reliable in CJS bin bundles. */\r\nfunction cliEntryPath(): string {\r\n const entry = process.argv[1]\r\n if (!entry) {\r\n throw new Error('Unable to resolve CLI entry path.')\r\n }\r\n return entry\r\n}\r\n\r\nexport function packageRootDir(): string {\r\n return join(dirname(cliEntryPath()), '..')\r\n}\r\n\r\nexport function templateDir(): string {\r\n return join(packageRootDir(), 'template')\r\n}\r\n\r\nexport function monorepoDoctorCliPath(): string {\r\n return join(packageRootDir(), '..', 'cli', 'dist', 'cli.js')\r\n}\r\n","import { scaffold } from './scaffold.js'\r\nimport { parsePackageManagerFlag } from './pm.js'\r\nimport { CREATE_APP_VERSION } from './constants.js'\r\n\r\nfunction printHelp(): void {\r\n console.log(`create-idia-app v${CREATE_APP_VERSION}\r\n\r\nUsage:\r\n create-idia-app [project-name] [options]\r\n\r\nOptions:\r\n --pm <pnpm|npm|yarn> Override package manager detection\r\n --skip-install Skip install and idia-ui doctor\r\n --force Overwrite target directory if it exists\r\n --no-git Skip git init\r\n --with-storybook Not available (Phase 3) — prints warning\r\n --with-brain Not available (Phase 4) — prints warning\r\n -h, --help Show help\r\n -V, --version Show version\r\n`)\r\n}\r\n\r\nfunction parseArgs(argv: string[]): {\r\n projectName?: string\r\n pm?: ReturnType<typeof parsePackageManagerFlag>\r\n skipInstall: boolean\r\n force: boolean\r\n noGit: boolean\r\n withStorybook: boolean\r\n withBrain: boolean\r\n help: boolean\r\n version: boolean\r\n} {\r\n const result = {\r\n projectName: undefined as string | undefined,\r\n pm: undefined as ReturnType<typeof parsePackageManagerFlag>,\r\n skipInstall: false,\r\n force: false,\r\n noGit: false,\r\n withStorybook: false,\r\n withBrain: false,\r\n help: false,\r\n version: false,\r\n }\r\n\r\n for (let i = 0; i < argv.length; i += 1) {\r\n const arg = argv[i]\r\n switch (arg) {\r\n case '--pm':\r\n result.pm = parsePackageManagerFlag(argv[++i])\r\n break\r\n case '--skip-install':\r\n result.skipInstall = true\r\n break\r\n case '--force':\r\n result.force = true\r\n break\r\n case '--no-git':\r\n result.noGit = true\r\n break\r\n case '--with-storybook':\r\n result.withStorybook = true\r\n break\r\n case '--with-brain':\r\n result.withBrain = true\r\n break\r\n case '-h':\r\n case '--help':\r\n result.help = true\r\n break\r\n case '-V':\r\n case '--version':\r\n result.version = true\r\n break\r\n default:\r\n if (arg.startsWith('-')) {\r\n throw new Error(`Unknown option: ${arg}`)\r\n }\r\n if (!result.projectName) {\r\n result.projectName = arg\r\n } else {\r\n throw new Error(`Unexpected argument: ${arg}`)\r\n }\r\n }\r\n }\r\n\r\n return result\r\n}\r\n\r\nfunction main(): void {\r\n try {\r\n const args = parseArgs(process.argv.slice(2))\r\n\r\n if (args.help) {\r\n printHelp()\r\n return\r\n }\r\n\r\n if (args.version) {\r\n console.log(CREATE_APP_VERSION)\r\n return\r\n }\r\n\r\n if (!args.projectName) {\r\n printHelp()\r\n throw new Error('Project name is required. Example: create-idia-app my-app')\r\n }\r\n\r\n scaffold({\r\n projectName: args.projectName,\r\n targetDir: process.cwd(),\r\n pm: args.pm,\r\n skipInstall: args.skipInstall,\r\n force: args.force,\r\n noGit: args.noGit,\r\n withStorybook: args.withStorybook,\r\n withBrain: args.withBrain,\r\n })\r\n } catch (error) {\r\n const message = error instanceof Error ? error.message : String(error)\r\n console.error(`\\nError: ${message}`)\r\n process.exit(1)\r\n }\r\n}\r\n\r\nmain()\r\n"],"mappings":"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","names":["import_node_fs","import_node_path","import_node_fs","import_node_path"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-idia-app",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Scaffold an Expo + idia-ui consumer app from the official template",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/idia-ui/idia-ui.git",
|
|
9
|
+
"directory": "packages/create-idia-app"
|
|
10
|
+
},
|
|
11
|
+
"bin": {
|
|
12
|
+
"create-idia-app": "dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"main": "dist/index.js",
|
|
15
|
+
"types": "dist/index.d.ts",
|
|
16
|
+
"files": [
|
|
17
|
+
"dist",
|
|
18
|
+
"template"
|
|
19
|
+
],
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public"
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"prebuild": "node scripts/copy-template.mjs",
|
|
25
|
+
"build": "tsup",
|
|
26
|
+
"dev": "tsup --watch",
|
|
27
|
+
"clean": "rm -rf dist template",
|
|
28
|
+
"typecheck": "tsc --noEmit"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=20"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Always-apply ds-brain rules: read AGENTS.md, use generated registry indexes, do not invent components or variants."
|
|
3
|
+
globs:
|
|
4
|
+
- "**/*"
|
|
5
|
+
alwaysApply: true
|
|
6
|
+
---
|
|
7
|
+
# Idia UI — ds-brain
|
|
8
|
+
|
|
9
|
+
Operational rules for AI coding agents working in this repo.
|
|
10
|
+
|
|
11
|
+
- Read `.idia/brain/AGENTS.md` before design-system work.
|
|
12
|
+
- If authored docs and generated files conflict, authored docs win.
|
|
13
|
+
- `foundations/`
|
|
14
|
+
- `components/`
|
|
15
|
+
- `patterns/`
|
|
16
|
+
- `decisions/`
|
|
17
|
+
- Read `AGENTS.md` (repo root) — **session-start**; mandatory first Read for **any** task (see root `AGENTS.md`).
|
|
18
|
+
- Read `.idia/brain/AGENTS.md` — **gate step 1**; brain entrypoint (this file).
|
|
19
|
+
- Read `.idia/brain/registry/ai-index.generated.json` — **gate step 2**; **STOP** — required before any component or pattern doc.
|
|
20
|
+
- Read `.idia/brain/ai/skills/ds-brain-index/SKILL.md` — **gate step 3**; **required** meta router; read before domain skills and component/pattern docs.
|
|
21
|
+
- Classify **output mode** and **task intent** from the ai-index before opening authored component docs.
|
|
22
|
+
- Read `AGENTS.md` — entry routing and output-mode read lists.
|
|
23
|
+
- Read `.idia/brain/registry/ai-index.generated.json` — **required** gate before component/pattern docs.
|
|
24
|
+
- Read `ds-brain-index` skill (`.idia/brain/ai/skills/ds-brain-index/SKILL.md`) — **required** meta router before domain skills and authored component docs.
|
|
25
|
+
- Classify output mode from the ai-index.
|
|
26
|
+
- Prefer `.idia/brain/registry/ai-index.generated.json` when present.
|
|
27
|
+
- Use `.idia/brain/registry/component-registry.generated.json` for component metadata — do not invent components, props, variants, tokens, or Figma mappings.
|
|
28
|
+
- Do not edit `.idia/brain/` directly.
|
|
29
|
+
- Do not invent components, props, variants, tokens, or Figma mappings.
|
|
30
|
+
- Do not mark a doc `rich` unless required sections are substantive, especially accessibility for interactive components.
|
|
31
|
+
- Do not claim catalog completeness beyond what the pack registries summarize.
|
|
32
|
+
- If a gap is found, report it to the idia-ui maintainers rather than inventing API or docs.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Form composition: action hierarchy, choice controls (radio/select/checkbox), validation patterns."
|
|
3
|
+
globs:
|
|
4
|
+
- "**/forms/**"
|
|
5
|
+
- "**/*Form*"
|
|
6
|
+
- "**/*form*"
|
|
7
|
+
alwaysApply: false
|
|
8
|
+
---
|
|
9
|
+
# Idia UI — Forms
|
|
10
|
+
|
|
11
|
+
Apply when editing form flows, field groups, validation, or choice controls.
|
|
12
|
+
|
|
13
|
+
- Forms collect, validate, and submit structured user input — multiple related values the user enters or edits before a primary action completes the task.
|
|
14
|
+
- Retrieve this pattern plus `patterns/forms.md` and `decisions/action-hierarchy.md`.
|
|
15
|
+
- Retrieve `components/form-section.md` and `components/form-element.md` before generating hierarchy.
|
|
16
|
+
- Retrieve component brain docs for every field you render.
|
|
17
|
+
- Use `FormSection` when there are 2+ logical groups; use built-in `label` on `InputText`/`Select`/`TextArea`/`InputGroup` when possible.
|
|
18
|
+
- Reserve `FormElement` for custom/headless controls or `Toggle` group labels.
|
|
19
|
+
- Apply `FORM_V_GAP` / `FORM_H_GAP` from `foundations/spacing.md` — do not invent spacing tokens.
|
|
20
|
+
- Retrieve this pattern, `patterns/forms.md`, and `patterns/form-composition.md` for layout context.
|
|
21
|
+
- Retrieve `components/form-element.md` and every field component you render.
|
|
22
|
+
- Import validators from `@idia-ui/validators` — do not duplicate regex in screens.
|
|
23
|
+
- Map `formState.errors` to `hasError` + `errorText` on the matching field.
|
|
24
|
+
- Use `mode: 'onSubmit'` as default for short forms; gate on-change revalidation with `isSubmitted`.
|
|
25
|
+
- Set submit `Button` `loading` during async work.
|
|
26
|
+
- Each local action group should have **one primary action** — the control that completes the main task. Secondary actions support cancellation, back navigation, alternative flows, or lower-priority choices. Destructive actions must be visually distinct and must not read as casual alternatives to the primary action.
|
|
27
|
+
- **Form footers** — submit, save, continue, cancel, back (`patterns/forms.md`)
|
|
28
|
+
- **Dialog or sheet action rows** — confirm, dismiss, delete with confirmation (`patterns/modal-routing.md`, `components/confirmation-modal.md`)
|
|
29
|
+
- **Modal `footer` slots** — save/cancel pairs on responsive `Modal` branches (`components/modal.md`)
|
|
30
|
+
- **Wizard step footers** — next/continue vs back/submit on first, middle, and last steps (`patterns/wizard-flows.md`)
|
|
31
|
+
- Choose the control by **selection model**, **visibility needs**, and **visual density**. All Group A choice controls have brain docs — retrieve the cited component doc before generating props.
|
|
32
|
+
- Form task-intent components: avatar-upload, button, checkbox, custom-selection, date-input, date-range-input, form-element, form-section, ….
|
|
33
|
+
- Form foundations: color, spacing, tokens, typography.
|
|
34
|
+
- Retrieve pattern docs from ds-brain index task intent `form` before generating form UI.
|