anhedral 0.4.1 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. package/README.md +29 -256
  2. package/assets/anhedral-cli-init-technical.svg +322 -0
  3. package/assets/anhedral-cli-init.svg +257 -173
  4. package/dist/bin.js +28 -162
  5. package/dist/dependencies.d.ts +7 -56
  6. package/dist/dependencies.js +96 -305
  7. package/dist/index.d.ts +2 -7
  8. package/dist/index.js +1 -4
  9. package/dist/{templates → platforms}/desktop.d.ts +1 -1
  10. package/dist/{templates → platforms}/desktop.js +28 -266
  11. package/dist/{templates → platforms}/extension.d.ts +1 -1
  12. package/dist/platforms/extension.js +401 -0
  13. package/dist/{templates → platforms}/mobile.d.ts +1 -1
  14. package/dist/platforms/mobile.js +232 -0
  15. package/dist/project.d.ts +4 -0
  16. package/dist/project.js +1 -0
  17. package/dist/standard-products.d.ts +2 -0
  18. package/dist/standard-products.js +6 -0
  19. package/dist/standard.d.ts +18 -0
  20. package/dist/standard.js +578 -0
  21. package/dist/version.d.ts +1 -1
  22. package/dist/version.js +1 -1
  23. package/docs/application-stack-standard.md +700 -0
  24. package/package.json +34 -49
  25. package/CHANGELOG.md +0 -132
  26. package/CONTRIBUTING.md +0 -73
  27. package/SECURITY.md +0 -37
  28. package/SKILL.md +0 -244
  29. package/assets/images/svg/ably-symbol-color.svg +0 -8
  30. package/bin/anhedral.js +0 -2
  31. package/dist/architecture/contributions.d.ts +0 -28
  32. package/dist/architecture/contributions.js +0 -125
  33. package/dist/architecture/index.d.ts +0 -12
  34. package/dist/architecture/index.js +0 -6
  35. package/dist/architecture/manifest.d.ts +0 -53
  36. package/dist/architecture/manifest.js +0 -283
  37. package/dist/architecture/modules.d.ts +0 -37
  38. package/dist/architecture/modules.js +0 -184
  39. package/dist/architecture/plan.d.ts +0 -58
  40. package/dist/architecture/plan.js +0 -145
  41. package/dist/architecture/templates.d.ts +0 -10
  42. package/dist/architecture/templates.js +0 -23
  43. package/dist/cli.d.ts +0 -32
  44. package/dist/cli.js +0 -235
  45. package/dist/composers/root.d.ts +0 -6
  46. package/dist/composers/root.js +0 -35
  47. package/dist/print.d.ts +0 -8
  48. package/dist/print.js +0 -48
  49. package/dist/prompts.d.ts +0 -5
  50. package/dist/prompts.js +0 -19
  51. package/dist/scaffold.d.ts +0 -76
  52. package/dist/scaffold.js +0 -1895
  53. package/dist/template-source.d.ts +0 -20
  54. package/dist/template-source.js +0 -180
  55. package/dist/templates/api.d.ts +0 -2
  56. package/dist/templates/api.js +0 -3122
  57. package/dist/templates/assets-private-proxy.d.ts +0 -3
  58. package/dist/templates/assets-private-proxy.js +0 -277
  59. package/dist/templates/electron-updater.d.ts +0 -3
  60. package/dist/templates/electron-updater.js +0 -358
  61. package/dist/templates/extension.js +0 -732
  62. package/dist/templates/mobile.js +0 -720
  63. package/dist/templates/shared.d.ts +0 -2
  64. package/dist/templates/shared.js +0 -520
  65. package/dist/templates/web.d.ts +0 -2
  66. package/dist/templates/web.js +0 -412
  67. package/dist/toolchain.d.ts +0 -3
  68. package/dist/toolchain.js +0 -8
  69. package/dist/ui.d.ts +0 -33
  70. package/dist/ui.js +0 -199
  71. package/dist/workspace-config.d.ts +0 -11
  72. package/dist/workspace-config.js +0 -372
  73. package/docs/conventions.md +0 -92
  74. package/docs/master-stack-map.md +0 -199
  75. package/docs/output-tree-contract.md +0 -482
  76. package/docs/references/manual-scaffolding.md +0 -403
  77. package/docs/references/provisioning.md +0 -220
  78. package/scripts/render-master-stack-map.mjs +0 -510
  79. package/templates/api-fastify/apps/api/tsconfig.json +0 -20
  80. package/templates/catalog.json +0 -23
  81. package/templates/db-drizzle/packages/db/tsconfig.json +0 -14
  82. package/templates/desktop-electron/apps/desktop/tsconfig.json +0 -37
  83. package/templates/extension-wxt/apps/extension/tsconfig.json +0 -41
  84. package/templates/mobile-expo/apps/mobile/expo-env.d.ts +0 -1
  85. package/templates/web-next/apps/web/next-env.d.ts +0 -6
package/dist/bin.js CHANGED
@@ -1,179 +1,45 @@
1
1
  #!/usr/bin/env node
2
- import { createInterface } from 'node:readline/promises';
3
- import { argv, stdin, stdout } from 'node:process';
4
- import { 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, parsePromptModules, 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
- function writeCliError(error, code, json) {
10
- const message = error instanceof Error ? error.message : String(error);
11
- if (json)
12
- console.error(JSON.stringify({ error: message, code }));
13
- else
14
- console.error('Error:', message);
15
- }
16
- function splitAddArgs(args) {
17
- const moduleNames = [];
18
- const flagArgs = [];
19
- for (let index = 0; index < args.length; index += 1) {
20
- const arg = args[index];
21
- if (arg === '--toolchain') {
22
- flagArgs.push(arg);
23
- if (args[index + 1] != null) {
24
- flagArgs.push(args[index + 1]);
25
- index += 1;
26
- }
27
- continue;
28
- }
29
- if (arg.startsWith('--')) {
30
- flagArgs.push(arg);
31
- continue;
32
- }
33
- moduleNames.push(arg);
34
- }
35
- return { moduleNames, flagArgs };
36
- }
37
- async function promptForInitModules(args) {
38
- if (!shouldPromptForInitModules(args, stdin.isTTY === true))
39
- return args;
40
- const rl = createInterface({ input: stdin, output: stdout });
41
- try {
42
- console.log('Select app surfaces: web, mobile, api, desktop, extension');
43
- const appAnswer = await rl.question('App surfaces [all]: ');
44
- console.log('Select backend features: db, auth, billing, storage, native-subscriptions, electron-updater');
45
- const featureAnswer = await rl.question('Backend features [all]: ');
46
- const selected = [
47
- ...parsePromptModules(appAnswer, DEFAULT_PROMPT_APP_MODULES),
48
- ...parsePromptModules(featureAnswer, DEFAULT_PROMPT_FEATURE_MODULES),
49
- ];
50
- const result = [...args, ...selected.map((moduleName) => `--${moduleName}`)];
51
- const hasUiClient = selected.some((moduleName) => ['web', 'mobile', 'desktop', 'extension'].includes(moduleName));
52
- if (hasUiClient && !hasUiSelection(args)) {
53
- console.log('Optionally add starter UI components to each selected client.');
54
- const componentAnswer = await rl.question('Starter components [none]: ');
55
- if (componentAnswer.trim())
56
- result.push(`--ui=${componentAnswer}`);
57
- }
58
- if (selected.includes('mobile') && !args.some((arg) => arg.startsWith('--native-styling'))) {
59
- const stylingAnswer = (await rl.question('Expo styling [nativewind]: ')).trim();
60
- result.push(`--native-styling=${stylingAnswer || 'nativewind'}`);
61
- }
62
- return result;
63
- }
64
- finally {
65
- rl.close();
66
- }
67
- }
6
+ const [command, ...args] = argv.slice(2);
7
+ const json = args.includes('--json');
68
8
  async function main() {
69
- const args = argv.slice(2);
70
- const command = args[0];
71
- const rawArgs = args.slice(1);
72
- const json = rawArgs.includes('--json');
73
- const verbose = rawArgs.includes('--verbose');
74
- if (json)
75
- process.env.ANHEDRAL_QUIET = '1';
76
- if (verbose)
77
- process.env.ANHEDRAL_VERBOSE = '1';
78
- if (command === '--version' || command === '-v') {
79
- if (json)
80
- console.log(JSON.stringify({ version: GENERATOR_VERSION }));
81
- else
82
- console.log(GENERATOR_VERSION);
83
- return;
84
- }
85
9
  if (!command || command === '--help' || command === '-h') {
86
- if (json)
87
- console.log(JSON.stringify({ usage: USAGE }));
88
- else
89
- console.log(USAGE);
10
+ console.log(json ? JSON.stringify({ usage: STANDARD_USAGE }) : STANDARD_USAGE);
90
11
  return;
91
12
  }
92
- if (!['new', 'init', 'add', 'ui', 'upgrade', 'doctor'].includes(command)) {
93
- if (json)
94
- writeCliError(new Error(`Unknown command: ${command}`), 'UNKNOWN_COMMAND', true);
95
- else {
96
- console.error(`Unknown command: ${command}`);
97
- console.log(USAGE);
98
- }
99
- process.exitCode = 1;
13
+ if (command === '--version' || command === '-v') {
14
+ console.log(json ? JSON.stringify({ version: GENERATOR_VERSION }) : GENERATOR_VERSION);
100
15
  return;
101
16
  }
102
- if (rawArgs.includes('--help') || rawArgs.includes('-h')) {
103
- if (json)
104
- console.log(JSON.stringify({ usage: USAGE }));
105
- else
106
- console.log(USAGE);
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);
107
22
  return;
108
23
  }
109
- let phase = 'arguments';
24
+ let options;
110
25
  try {
111
- if (command === 'new') {
112
- const request = parseNewProjectRequest(rawArgs);
113
- const promptedArgs = await promptForInitModules([...request.moduleArgs]);
114
- const options = buildOptionsForRoot(parseCli(promptedArgs), request.directory);
115
- phase = 'execute';
116
- await scaffoldProject(options);
117
- if (!options.json && !options.dryRun) {
118
- console.log(`\nCreated ${options.rootDirectory}\nNext: cd ${options.rootDirectory}\nThen follow README.md to configure the selected providers and start the app.`);
119
- }
120
- }
121
- else if (command === 'doctor') {
122
- const unknown = rawArgs.filter((arg) => !['--json', '--verbose'].includes(arg));
123
- if (unknown.length)
124
- throw new Error(`Unknown doctor option: ${unknown[0]}`);
125
- phase = 'execute';
126
- const report = doctorProject();
127
- if (json)
128
- console.log(JSON.stringify(report, null, 2));
129
- else {
130
- console.log(report.ok ? 'Anhedral project is healthy.' : 'Anhedral project has drift.');
131
- for (const issue of report.issues)
132
- console.log(` ${issue.severity}: ${issue.path}: ${issue.message}`);
133
- }
134
- if (!report.ok)
135
- process.exitCode = 1;
136
- }
137
- else if (command === 'add') {
138
- const { moduleNames, flagArgs } = splitAddArgs(rawArgs);
139
- const options = buildAddOptions(moduleNames, parseCli(flagArgs));
140
- phase = 'execute';
141
- await scaffoldAddModules(options);
142
- }
143
- else if (command === 'ui') {
144
- if (rawArgs[0] !== 'add')
145
- throw new Error('Unknown UI command. Use: anhedral ui add <component...>');
146
- const options = parseUiAddOptions(rawArgs.slice(1));
147
- phase = 'execute';
148
- await scaffoldUiComponents(options);
149
- }
150
- else if (command === 'upgrade') {
151
- const unknown = rawArgs.filter((arg) => !['--skip-install', '--dry-run', '--json', '--verbose'].includes(arg));
152
- if (unknown.length)
153
- throw new Error(`Unknown upgrade option: ${unknown[0]}`);
154
- phase = 'execute';
155
- await scaffoldUpgradeProject({
156
- skipInstall: rawArgs.includes('--skip-install'),
157
- dryRun: rawArgs.includes('--dry-run'),
158
- json,
159
- });
160
- }
161
- else {
162
- const options = buildOptions(parseCli(await promptForInitModules(rawArgs)));
163
- phase = 'execute';
164
- await scaffoldProject(options);
165
- }
26
+ options = parseStandardOptions(command, args);
166
27
  }
167
28
  catch (error) {
168
- const code = error instanceof PostCommitError
169
- ? 'POST_COMMIT_FAILED'
170
- : phase === 'arguments'
171
- ? 'INVALID_ARGUMENT'
172
- : command === 'doctor'
173
- ? 'DOCTOR_FAILED'
174
- : 'GENERATION_FAILED';
175
- 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}`);
176
31
  process.exitCode = 1;
32
+ return;
177
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;
178
45
  }
179
- void main();
@@ -1,59 +1,10 @@
1
- export declare const PACKAGE_MANAGER = "pnpm@10.34.5";
2
- export declare const NODE_ENGINE = "^20.19.0 || >=22.12.0";
3
- export declare const MOBILE_NODE_ENGINE = "^22.13.0 || ^24.3.0 || >=25";
4
- export type DependencyMap = Record<string, string>;
5
- export type DependencyGroup = {
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
7
  export declare const MOBILE_APP_DEPENDENCIES: DependencyGroup;
28
8
  export declare const MOBILE_NATIVEWIND_DEPENDENCIES: DependencyGroup;
29
- export declare const MOBILE_UNIWIND_DEPENDENCIES: DependencyGroup;
30
- export declare const WEB_APP_DEPENDENCIES: DependencyGroup;
31
- export declare const DESKTOP_DEPENDENCIES: DependencyGroup;
32
- export declare const ELECTRON_UPDATER_DEPENDENCIES: DependencyGroup;
33
- export declare function dependencyManifest(): {
34
- verifiedAt: string;
35
- packageManager: string;
36
- toolchain: {
37
- readonly shadcn: "4.13.0";
38
- readonly wxt: "0.20.27";
39
- readonly vercel: "56.2.1";
40
- readonly 'eas-cli': "21.0.1";
41
- readonly neonctl: "2.33.2";
42
- readonly wrangler: "4.111.0";
43
- };
44
- securityOverrides: DependencyMap;
45
- root: DependencyGroup;
46
- contracts: DependencyGroup;
47
- sharedDb: DependencyGroup;
48
- sharedPackages: DependencyGroup;
49
- realtime: DependencyGroup;
50
- backend: DependencyGroup;
51
- extension: DependencyGroup;
52
- frontendAddons: DependencyMap;
53
- mobileApp: DependencyGroup;
54
- mobileNativewind: DependencyGroup;
55
- mobileUniwind: DependencyGroup;
56
- webApp: DependencyGroup;
57
- desktop: DependencyGroup;
58
- electronUpdater: DependencyGroup;
59
- };
9
+ export declare const PACKAGE_MANAGER = "pnpm@10.34.5";
10
+ export declare const EAS_CLI_VERSION = "21.0.1";