anhedral 0.4.2 → 0.6.1
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 +35 -265
- package/assets/anhedral-cli-init-technical.svg +322 -0
- package/assets/anhedral-cli-init.svg +257 -173
- package/dist/bin.js +28 -191
- package/dist/dependencies.d.ts +7 -57
- package/dist/dependencies.js +96 -308
- package/dist/index.d.ts +2 -7
- package/dist/index.js +1 -4
- package/dist/platforms/desktop.js +401 -0
- package/dist/platforms/extension.js +401 -0
- package/dist/platforms/mobile.js +232 -0
- package/dist/project.d.ts +0 -26
- package/dist/standard-products.d.ts +2 -0
- package/dist/standard-products.js +6 -0
- package/dist/standard.d.ts +18 -0
- package/dist/standard.js +595 -0
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/docs/application-stack-standard.md +700 -0
- package/package.json +29 -51
- package/CHANGELOG.md +0 -178
- package/CONTRIBUTING.md +0 -77
- package/SECURITY.md +0 -37
- package/SKILL.md +0 -339
- package/assets/images/svg/ably-symbol-color.svg +0 -8
- package/bin/anhedral.js +0 -2
- package/dist/architecture/contributions.d.ts +0 -28
- package/dist/architecture/contributions.js +0 -125
- package/dist/architecture/index.d.ts +0 -12
- package/dist/architecture/index.js +0 -6
- package/dist/architecture/manifest.d.ts +0 -53
- package/dist/architecture/manifest.js +0 -283
- package/dist/architecture/modules.d.ts +0 -41
- package/dist/architecture/modules.js +0 -187
- package/dist/architecture/plan.d.ts +0 -58
- package/dist/architecture/plan.js +0 -145
- package/dist/architecture/templates.d.ts +0 -10
- package/dist/architecture/templates.js +0 -23
- package/dist/cli.d.ts +0 -32
- package/dist/cli.js +0 -281
- package/dist/composers/root.d.ts +0 -6
- package/dist/composers/root.js +0 -35
- package/dist/print.d.ts +0 -8
- package/dist/print.js +0 -48
- package/dist/prompts.d.ts +0 -6
- package/dist/prompts.js +0 -41
- package/dist/scaffold.d.ts +0 -64
- package/dist/scaffold.js +0 -2102
- package/dist/template-source.d.ts +0 -20
- package/dist/template-source.js +0 -180
- package/dist/templates/api.d.ts +0 -2
- package/dist/templates/api.js +0 -3187
- package/dist/templates/assets-private-proxy.d.ts +0 -3
- package/dist/templates/assets-private-proxy.js +0 -277
- package/dist/templates/desktop.js +0 -792
- package/dist/templates/electron-updater.d.ts +0 -3
- package/dist/templates/electron-updater.js +0 -358
- package/dist/templates/extension.js +0 -856
- package/dist/templates/first-run.d.ts +0 -2
- package/dist/templates/first-run.js +0 -167
- package/dist/templates/mobile.js +0 -861
- package/dist/templates/shared.d.ts +0 -2
- package/dist/templates/shared.js +0 -577
- package/dist/templates/web.d.ts +0 -2
- package/dist/templates/web.js +0 -569
- package/dist/toolchain.d.ts +0 -3
- package/dist/toolchain.js +0 -8
- package/dist/ui.d.ts +0 -33
- package/dist/ui.js +0 -199
- package/dist/workspace-config.d.ts +0 -11
- package/dist/workspace-config.js +0 -372
- package/docs/NORTHSTAR.md +0 -114
- package/docs/conventions.md +0 -94
- package/docs/engineering-principles.md +0 -88
- package/docs/master-stack-map.md +0 -199
- package/docs/output-tree-contract.md +0 -493
- package/docs/references/manual-scaffolding.md +0 -421
- package/docs/references/provisioning.md +0 -577
- package/scripts/render-master-stack-map.mjs +0 -510
- package/templates/api-fastify/apps/api/tsconfig.json +0 -20
- package/templates/catalog.json +0 -23
- package/templates/db-drizzle/packages/db/tsconfig.json +0 -14
- package/templates/desktop-electron/apps/desktop/tsconfig.json +0 -37
- package/templates/extension-wxt/apps/extension/tsconfig.json +0 -41
- package/templates/mobile-expo/apps/mobile/expo-env.d.ts +0 -1
- package/templates/web-next/apps/web/next-env.d.ts +0 -6
- /package/dist/{templates → platforms}/desktop.d.ts +0 -0
- /package/dist/{templates → platforms}/extension.d.ts +0 -0
- /package/dist/{templates → platforms}/mobile.d.ts +0 -0
package/dist/bin.js
CHANGED
|
@@ -1,208 +1,45 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import { APP_MODULES, FEATURE_MODULES, buildAddOptions, buildOptions, buildOptionsForRoot, parseCli, parseNewProjectRequest, parseUiAddOptions, USAGE, } from './cli.js';
|
|
5
|
-
import { doctorProject, scaffoldAddModules, scaffoldProject, scaffoldUiComponents, scaffoldUpgradeProject } from './scaffold.js';
|
|
6
|
-
import { DEFAULT_PROMPT_APP_MODULES, DEFAULT_PROMPT_FEATURE_MODULES, hasUiSelection, parsePromptConfirmation, parsePromptModuleSelection, shouldPromptForInitModules, } from './prompts.js';
|
|
2
|
+
import { argv } from 'node:process';
|
|
3
|
+
import { STANDARD_USAGE, parseStandardOptions, scaffoldStandardProject } from './standard.js';
|
|
7
4
|
import { GENERATOR_VERSION } from './version.js';
|
|
8
5
|
import { PostCommitError } from './transaction.js';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const COMMANDS = ['new', 'init', 'add', 'ui', 'upgrade', 'doctor'];
|
|
12
|
-
const COMMAND_SET = new Set(COMMANDS);
|
|
13
|
-
const UI_TARGET_SET = new Set(UI_TARGETS);
|
|
14
|
-
function isCommand(value) {
|
|
15
|
-
return COMMAND_SET.has(value);
|
|
16
|
-
}
|
|
17
|
-
function writeCliError(error, code, json) {
|
|
18
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
19
|
-
if (json)
|
|
20
|
-
console.error(JSON.stringify({ error: message, code }));
|
|
21
|
-
else
|
|
22
|
-
console.error('Error:', message);
|
|
23
|
-
}
|
|
24
|
-
async function promptForInitModules(args) {
|
|
25
|
-
if (!shouldPromptForInitModules(args, stdin.isTTY === true))
|
|
26
|
-
return args;
|
|
27
|
-
const rl = createInterface({ input: stdin, output: stdout });
|
|
28
|
-
try {
|
|
29
|
-
console.log('Select app surfaces: web, mobile, api, desktop, extension (or "all"/"none")');
|
|
30
|
-
const appAnswer = await rl.question(`App surfaces [${DEFAULT_PROMPT_APP_MODULES.join(', ')}]: `);
|
|
31
|
-
console.log('Select capabilities: db, auth, billing, storage, native-subscriptions, electron-updater (or "all"/"none")');
|
|
32
|
-
const featureAnswer = await rl.question('Capabilities [none]: ');
|
|
33
|
-
const selected = [
|
|
34
|
-
...parsePromptModuleSelection(appAnswer, DEFAULT_PROMPT_APP_MODULES, APP_MODULES),
|
|
35
|
-
...parsePromptModuleSelection(featureAnswer, DEFAULT_PROMPT_FEATURE_MODULES, FEATURE_MODULES),
|
|
36
|
-
];
|
|
37
|
-
if (selected.length === 0)
|
|
38
|
-
throw new Error('Select at least one app surface or capability.');
|
|
39
|
-
const resolution = resolveModules(selected);
|
|
40
|
-
const result = [...args, ...selected.map((moduleName) => `--${moduleName}`)];
|
|
41
|
-
const hasUiClient = resolution.resolvedModules.some((moduleName) => UI_TARGET_SET.has(moduleName));
|
|
42
|
-
if (hasUiClient && !hasUiSelection(args)) {
|
|
43
|
-
console.log('Optionally add starter UI components to each selected client.');
|
|
44
|
-
const componentAnswer = await rl.question('Starter components [none]: ');
|
|
45
|
-
if (componentAnswer.trim())
|
|
46
|
-
result.push(`--ui=${componentAnswer}`);
|
|
47
|
-
}
|
|
48
|
-
if (resolution.resolvedModules.includes('mobile') && !args.some((arg) => arg.startsWith('--native-styling'))) {
|
|
49
|
-
const stylingAnswer = (await rl.question('Expo styling [nativewind]: ')).trim();
|
|
50
|
-
result.push(`--native-styling=${stylingAnswer || 'nativewind'}`);
|
|
51
|
-
}
|
|
52
|
-
console.log(`Requested: ${resolution.requestedModules.join(', ')}`);
|
|
53
|
-
if (resolution.dependencyAddedModules.length > 0) {
|
|
54
|
-
console.log(`Added by dependencies: ${resolution.dependencyAddedModules.join(', ')}`);
|
|
55
|
-
}
|
|
56
|
-
console.log(`Resolved stack: ${resolution.resolvedModules.join(', ')}`);
|
|
57
|
-
const confirmation = await rl.question('Generate this stack? [Y/n]: ');
|
|
58
|
-
if (!parsePromptConfirmation(confirmation))
|
|
59
|
-
throw new Error('Generation cancelled.');
|
|
60
|
-
return result;
|
|
61
|
-
}
|
|
62
|
-
finally {
|
|
63
|
-
rl.close();
|
|
64
|
-
}
|
|
65
|
-
}
|
|
6
|
+
const [command, ...args] = argv.slice(2);
|
|
7
|
+
const json = args.includes('--json');
|
|
66
8
|
async function main() {
|
|
67
|
-
const args = argv.slice(2);
|
|
68
|
-
const command = args[0];
|
|
69
|
-
const rawArgs = args.slice(1);
|
|
70
|
-
const json = rawArgs.includes('--json');
|
|
71
|
-
const verbose = rawArgs.includes('--verbose');
|
|
72
|
-
if (json)
|
|
73
|
-
process.env.ANHEDRAL_QUIET = '1';
|
|
74
|
-
if (verbose)
|
|
75
|
-
process.env.ANHEDRAL_VERBOSE = '1';
|
|
76
|
-
if (command === '--version' || command === '-v') {
|
|
77
|
-
if (json)
|
|
78
|
-
console.log(JSON.stringify({ version: GENERATOR_VERSION }));
|
|
79
|
-
else
|
|
80
|
-
console.log(GENERATOR_VERSION);
|
|
81
|
-
return;
|
|
82
|
-
}
|
|
83
9
|
if (!command || command === '--help' || command === '-h') {
|
|
84
|
-
|
|
85
|
-
console.log(JSON.stringify({ usage: USAGE }));
|
|
86
|
-
else
|
|
87
|
-
console.log(USAGE);
|
|
10
|
+
console.log(json ? JSON.stringify({ usage: STANDARD_USAGE }) : STANDARD_USAGE);
|
|
88
11
|
return;
|
|
89
12
|
}
|
|
90
|
-
if (
|
|
91
|
-
|
|
92
|
-
writeCliError(new Error(`Unknown command: ${command}`), 'UNKNOWN_COMMAND', true);
|
|
93
|
-
else {
|
|
94
|
-
console.error(`Unknown command: ${command}`);
|
|
95
|
-
console.log(USAGE);
|
|
96
|
-
}
|
|
97
|
-
process.exitCode = 1;
|
|
13
|
+
if (command === '--version' || command === '-v') {
|
|
14
|
+
console.log(json ? JSON.stringify({ version: GENERATOR_VERSION }) : GENERATOR_VERSION);
|
|
98
15
|
return;
|
|
99
16
|
}
|
|
100
|
-
if (
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
17
|
+
if (command !== 'new' && command !== 'init') {
|
|
18
|
+
throw new Error(`Unknown command: ${command}. Use new, init, --help, or --version.`);
|
|
19
|
+
}
|
|
20
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
21
|
+
console.log(json ? JSON.stringify({ usage: STANDARD_USAGE }) : STANDARD_USAGE);
|
|
105
22
|
return;
|
|
106
23
|
}
|
|
107
|
-
let
|
|
24
|
+
let options;
|
|
108
25
|
try {
|
|
109
|
-
|
|
110
|
-
case 'new': {
|
|
111
|
-
const request = parseNewProjectRequest(rawArgs);
|
|
112
|
-
const promptedArgs = await promptForInitModules([...request.moduleArgs]);
|
|
113
|
-
const parsed = parseCli(promptedArgs);
|
|
114
|
-
const options = {
|
|
115
|
-
...buildOptionsForRoot(parsed, request.directory),
|
|
116
|
-
initializeGit: parsed.initializeGit ?? true,
|
|
117
|
-
};
|
|
118
|
-
phase = 'execute';
|
|
119
|
-
await scaffoldProject(options);
|
|
120
|
-
if (!options.json && !options.dryRun) {
|
|
121
|
-
console.log(`\nCreated ${options.rootDirectory}\n\nNext:`);
|
|
122
|
-
console.log(` cd ${options.rootDirectory}`);
|
|
123
|
-
if (options.skipInstall)
|
|
124
|
-
console.log(' pnpm install');
|
|
125
|
-
console.log(' pnpm first-run');
|
|
126
|
-
console.log(' pnpm ready');
|
|
127
|
-
console.log('\nThen follow README.md for verification, development, and deployment.');
|
|
128
|
-
}
|
|
129
|
-
break;
|
|
130
|
-
}
|
|
131
|
-
case 'doctor': {
|
|
132
|
-
const unknown = rawArgs.filter((arg) => !['--json', '--verbose'].includes(arg));
|
|
133
|
-
if (unknown.length)
|
|
134
|
-
throw new Error(`Unknown doctor option: ${unknown[0]}`);
|
|
135
|
-
phase = 'execute';
|
|
136
|
-
const report = doctorProject();
|
|
137
|
-
if (json)
|
|
138
|
-
console.log(JSON.stringify(report, null, 2));
|
|
139
|
-
else {
|
|
140
|
-
console.log(report.ok ? 'Anhedral project is healthy.' : 'Anhedral project has drift.');
|
|
141
|
-
console.log(` project: ${report.project.displayName} (${report.project.name})`);
|
|
142
|
-
console.log(` modules: ${report.modules.join(', ')}`);
|
|
143
|
-
console.log(` toolchain: ${report.toolchain}`);
|
|
144
|
-
console.log(` ownership: ${report.ownership.user} user, ${report.ownership.mergeable} mergeable, `
|
|
145
|
-
+ `${report.ownership.managed} managed`);
|
|
146
|
-
for (const issue of report.issues)
|
|
147
|
-
console.log(` ${issue.severity}: ${issue.path}: ${issue.message}`);
|
|
148
|
-
if (report.recommendedActions.length > 0) {
|
|
149
|
-
console.log('\nNext actions:');
|
|
150
|
-
for (const action of report.recommendedActions)
|
|
151
|
-
console.log(` - ${action}`);
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
if (!report.ok)
|
|
155
|
-
process.exitCode = 1;
|
|
156
|
-
break;
|
|
157
|
-
}
|
|
158
|
-
case 'add': {
|
|
159
|
-
const options = buildAddOptions([], parseCli(rawArgs));
|
|
160
|
-
phase = 'execute';
|
|
161
|
-
await scaffoldAddModules(options);
|
|
162
|
-
break;
|
|
163
|
-
}
|
|
164
|
-
case 'ui': {
|
|
165
|
-
if (rawArgs[0] !== 'add')
|
|
166
|
-
throw new Error('Unknown UI command. Use: anhedral ui add <component...>');
|
|
167
|
-
const options = parseUiAddOptions(rawArgs.slice(1));
|
|
168
|
-
phase = 'execute';
|
|
169
|
-
await scaffoldUiComponents(options);
|
|
170
|
-
break;
|
|
171
|
-
}
|
|
172
|
-
case 'upgrade': {
|
|
173
|
-
const unknown = rawArgs.filter((arg) => !['--skip-install', '--dry-run', '--json', '--verbose'].includes(arg));
|
|
174
|
-
if (unknown.length)
|
|
175
|
-
throw new Error(`Unknown upgrade option: ${unknown[0]}`);
|
|
176
|
-
phase = 'execute';
|
|
177
|
-
await scaffoldUpgradeProject({
|
|
178
|
-
skipInstall: rawArgs.includes('--skip-install'),
|
|
179
|
-
dryRun: rawArgs.includes('--dry-run'),
|
|
180
|
-
json,
|
|
181
|
-
});
|
|
182
|
-
break;
|
|
183
|
-
}
|
|
184
|
-
case 'init': {
|
|
185
|
-
const parsed = parseCli(await promptForInitModules(rawArgs));
|
|
186
|
-
const options = {
|
|
187
|
-
...buildOptions(parsed),
|
|
188
|
-
initializeGit: parsed.initializeGit ?? false,
|
|
189
|
-
};
|
|
190
|
-
phase = 'execute';
|
|
191
|
-
await scaffoldProject(options);
|
|
192
|
-
break;
|
|
193
|
-
}
|
|
194
|
-
}
|
|
26
|
+
options = parseStandardOptions(command, args);
|
|
195
27
|
}
|
|
196
28
|
catch (error) {
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
: phase === 'arguments'
|
|
200
|
-
? 'INVALID_ARGUMENT'
|
|
201
|
-
: command === 'doctor'
|
|
202
|
-
? 'DOCTOR_FAILED'
|
|
203
|
-
: 'GENERATION_FAILED';
|
|
204
|
-
writeCliError(error, code, json);
|
|
29
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
30
|
+
console.error(json ? JSON.stringify({ error: message, code: 'INVALID_ARGUMENT' }) : `Error: ${message}`);
|
|
205
31
|
process.exitCode = 1;
|
|
32
|
+
return;
|
|
206
33
|
}
|
|
34
|
+
await scaffoldStandardProject(options);
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
await main();
|
|
38
|
+
}
|
|
39
|
+
catch (error) {
|
|
40
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
41
|
+
const code = error instanceof PostCommitError ? 'POST_COMMIT_FAILED'
|
|
42
|
+
: command === 'new' || command === 'init' ? 'GENERATION_FAILED' : 'UNKNOWN_COMMAND';
|
|
43
|
+
console.error(json ? JSON.stringify({ error: message, code }) : `Error: ${message}`);
|
|
44
|
+
process.exitCode = 1;
|
|
207
45
|
}
|
|
208
|
-
void main();
|
package/dist/dependencies.d.ts
CHANGED
|
@@ -1,60 +1,10 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
export
|
|
6
|
-
dependencies?: DependencyMap;
|
|
7
|
-
devDependencies?: DependencyMap;
|
|
8
|
-
};
|
|
9
|
-
export declare const TOOLCHAIN_DEPENDENCIES: {
|
|
10
|
-
readonly shadcn: "4.13.0";
|
|
11
|
-
readonly wxt: "0.20.27";
|
|
12
|
-
readonly vercel: "56.2.1";
|
|
13
|
-
readonly 'eas-cli': "21.0.1";
|
|
14
|
-
readonly neonctl: "2.33.2";
|
|
15
|
-
readonly wrangler: "4.111.0";
|
|
16
|
-
};
|
|
17
|
-
export declare const SECURITY_OVERRIDES: DependencyMap;
|
|
18
|
-
export declare const ROOT_DEPENDENCIES: DependencyGroup;
|
|
19
|
-
export declare const SHARED_DB_DEPENDENCIES: DependencyGroup;
|
|
20
|
-
export declare const SHARED_PACKAGE_DEPENDENCIES: DependencyGroup;
|
|
21
|
-
export declare const CONTRACTS_DEPENDENCIES: DependencyGroup;
|
|
22
|
-
export declare const API_CLIENT_DEPENDENCIES: DependencyGroup;
|
|
23
|
-
export declare const REALTIME_DEPENDENCIES: DependencyGroup;
|
|
24
|
-
export declare const BACKEND_DEPENDENCIES: DependencyGroup;
|
|
1
|
+
export interface DependencyGroup {
|
|
2
|
+
dependencies?: Record<string, string>;
|
|
3
|
+
devDependencies?: Record<string, string>;
|
|
4
|
+
}
|
|
5
|
+
export declare const DESKTOP_DEPENDENCIES: DependencyGroup;
|
|
25
6
|
export declare const EXTENSION_DEPENDENCIES: DependencyGroup;
|
|
26
|
-
export declare const FRONTEND_ADDON_DEPENDENCIES: DependencyMap;
|
|
27
|
-
export declare const CLERK_SOLANA_PEER_DEPENDENCIES: DependencyMap;
|
|
28
7
|
export declare const MOBILE_APP_DEPENDENCIES: DependencyGroup;
|
|
29
8
|
export declare const MOBILE_NATIVEWIND_DEPENDENCIES: DependencyGroup;
|
|
30
|
-
export declare const
|
|
31
|
-
export declare const
|
|
32
|
-
export declare const DESKTOP_DEPENDENCIES: DependencyGroup;
|
|
33
|
-
export declare const ELECTRON_UPDATER_DEPENDENCIES: DependencyGroup;
|
|
34
|
-
export declare function dependencyManifest(): {
|
|
35
|
-
verifiedAt: string;
|
|
36
|
-
packageManager: string;
|
|
37
|
-
toolchain: {
|
|
38
|
-
readonly shadcn: "4.13.0";
|
|
39
|
-
readonly wxt: "0.20.27";
|
|
40
|
-
readonly vercel: "56.2.1";
|
|
41
|
-
readonly 'eas-cli': "21.0.1";
|
|
42
|
-
readonly neonctl: "2.33.2";
|
|
43
|
-
readonly wrangler: "4.111.0";
|
|
44
|
-
};
|
|
45
|
-
securityOverrides: DependencyMap;
|
|
46
|
-
root: DependencyGroup;
|
|
47
|
-
contracts: DependencyGroup;
|
|
48
|
-
sharedDb: DependencyGroup;
|
|
49
|
-
sharedPackages: DependencyGroup;
|
|
50
|
-
realtime: DependencyGroup;
|
|
51
|
-
backend: DependencyGroup;
|
|
52
|
-
extension: DependencyGroup;
|
|
53
|
-
frontendAddons: DependencyMap;
|
|
54
|
-
mobileApp: DependencyGroup;
|
|
55
|
-
mobileNativewind: DependencyGroup;
|
|
56
|
-
mobileUniwind: DependencyGroup;
|
|
57
|
-
webApp: DependencyGroup;
|
|
58
|
-
desktop: DependencyGroup;
|
|
59
|
-
electronUpdater: DependencyGroup;
|
|
60
|
-
};
|
|
9
|
+
export declare const PACKAGE_MANAGER = "pnpm@10.34.5";
|
|
10
|
+
export declare const EAS_CLI_VERSION = "21.0.1";
|