anhedral 0.1.10 → 0.4.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 (87) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/CONTRIBUTING.md +73 -0
  3. package/LICENSE +196 -17
  4. package/README.md +202 -145
  5. package/SECURITY.md +37 -0
  6. package/SKILL.md +244 -0
  7. package/bin/anhedral.js +1 -1
  8. package/dist/architecture/contributions.d.ts +28 -0
  9. package/dist/architecture/contributions.js +125 -0
  10. package/dist/architecture/index.d.ts +12 -0
  11. package/dist/architecture/index.js +6 -0
  12. package/dist/architecture/manifest.d.ts +53 -0
  13. package/dist/architecture/manifest.js +283 -0
  14. package/dist/architecture/modules.d.ts +37 -0
  15. package/dist/architecture/modules.js +184 -0
  16. package/dist/architecture/plan.d.ts +58 -0
  17. package/dist/architecture/plan.js +145 -0
  18. package/dist/architecture/templates.d.ts +10 -0
  19. package/dist/architecture/templates.js +23 -0
  20. package/dist/bin.d.ts +2 -0
  21. package/dist/bin.js +179 -0
  22. package/dist/cli.d.ts +24 -2
  23. package/dist/cli.js +189 -21
  24. package/dist/composers/root.d.ts +6 -0
  25. package/dist/composers/root.js +35 -0
  26. package/dist/dependencies.d.ts +31 -9
  27. package/dist/dependencies.js +227 -60
  28. package/dist/index.d.ts +8 -2
  29. package/dist/index.js +5 -31
  30. package/dist/print.js +15 -0
  31. package/dist/prompts.d.ts +5 -0
  32. package/dist/prompts.js +19 -0
  33. package/dist/render.d.ts +11 -0
  34. package/dist/render.js +74 -0
  35. package/dist/scaffold.d.ts +64 -12
  36. package/dist/scaffold.js +1726 -1150
  37. package/dist/template-source.d.ts +20 -0
  38. package/dist/template-source.js +180 -0
  39. package/dist/templates/api.d.ts +2 -0
  40. package/dist/templates/api.js +3122 -0
  41. package/dist/templates/assets-private-proxy.d.ts +3 -0
  42. package/dist/templates/assets-private-proxy.js +277 -0
  43. package/dist/templates/desktop.d.ts +2 -0
  44. package/dist/templates/desktop.js +639 -0
  45. package/dist/templates/electron-updater.d.ts +3 -0
  46. package/dist/templates/electron-updater.js +358 -0
  47. package/dist/templates/extension.d.ts +1 -1
  48. package/dist/templates/extension.js +322 -248
  49. package/dist/templates/mobile.d.ts +2 -0
  50. package/dist/templates/mobile.js +720 -0
  51. package/dist/templates/shared.d.ts +2 -0
  52. package/dist/templates/shared.js +520 -0
  53. package/dist/templates/web.d.ts +2 -0
  54. package/dist/templates/web.js +412 -0
  55. package/dist/toolchain.d.ts +0 -8
  56. package/dist/toolchain.js +0 -21
  57. package/dist/transaction.d.ts +22 -0
  58. package/dist/transaction.js +822 -0
  59. package/dist/ui.d.ts +33 -0
  60. package/dist/ui.js +199 -0
  61. package/dist/util.d.ts +1 -5
  62. package/dist/util.js +70 -159
  63. package/dist/version.d.ts +2 -0
  64. package/dist/version.js +2 -0
  65. package/dist/workspace-config.d.ts +11 -0
  66. package/dist/workspace-config.js +372 -0
  67. package/docs/conventions.md +92 -0
  68. package/docs/master-stack-map.md +192 -0
  69. package/docs/output-tree-contract.md +482 -0
  70. package/docs/references/manual-scaffolding.md +403 -0
  71. package/docs/references/provisioning.md +220 -0
  72. package/package.json +57 -13
  73. package/templates/api-fastify/apps/api/tsconfig.json +20 -0
  74. package/templates/catalog.json +23 -0
  75. package/templates/db-drizzle/packages/db/tsconfig.json +14 -0
  76. package/templates/desktop-electron/apps/desktop/tsconfig.json +37 -0
  77. package/templates/extension-wxt/apps/extension/tsconfig.json +41 -0
  78. package/templates/mobile-expo/apps/mobile/expo-env.d.ts +1 -0
  79. package/templates/web-next/apps/web/next-env.d.ts +6 -0
  80. package/dist/branding.d.ts +0 -5
  81. package/dist/branding.js +0 -17
  82. package/dist/commands.d.ts +0 -7
  83. package/dist/commands.js +0 -24
  84. package/dist/templates/backend.d.ts +0 -2
  85. package/dist/templates/backend.js +0 -2115
  86. package/dist/templates/frontend.d.ts +0 -2
  87. package/dist/templates/frontend.js +0 -1268
package/dist/render.js ADDED
@@ -0,0 +1,74 @@
1
+ import { createHash } from 'node:crypto';
2
+ const PACKAGE_NAME_PATTERN = /^(?:@[a-z0-9][a-z0-9._-]*\/)?[a-z0-9][a-z0-9._-]*$/;
3
+ const MAX_PACKAGE_NAME_LENGTH = 214;
4
+ const RESERVED_PACKAGE_NAMES = new Set(['node_modules', 'favicon.ico']);
5
+ /** Serialize an arbitrary value as a JavaScript/TypeScript string literal. */
6
+ export function jsString(value) {
7
+ return JSON.stringify(value);
8
+ }
9
+ /** Escape text placed directly in HTML rather than in a JS string. */
10
+ export function htmlText(value) {
11
+ return value
12
+ .replace(/&/g, '&')
13
+ .replace(/</g, '&lt;')
14
+ .replace(/>/g, '&gt;')
15
+ .replace(/"/g, '&quot;')
16
+ .replace(/'/g, '&#39;');
17
+ }
18
+ /** Keep generated Markdown headings on one line and prevent heading/code injection. */
19
+ export function markdownHeading(value) {
20
+ const normalized = value.replace(/[\r\n]+/g, ' ').trim() || 'Anhedral App';
21
+ return normalized.replace(/([\\`*_{}\[\]()<>#+.!|~-])/g, '\\$1');
22
+ }
23
+ export function assertPackageName(value) {
24
+ const leafName = value.slice(value.lastIndexOf('/') + 1);
25
+ if (value.length > MAX_PACKAGE_NAME_LENGTH
26
+ || !PACKAGE_NAME_PATTERN.test(value)
27
+ || RESERVED_PACKAGE_NAMES.has(leafName)) {
28
+ throw new Error(`Invalid package name: ${value}`);
29
+ }
30
+ return value;
31
+ }
32
+ function compactPackageSegment(value, maximumLength) {
33
+ if (value.length <= maximumLength)
34
+ return value;
35
+ if (maximumLength <= 9)
36
+ return value.slice(0, maximumLength).replace(/[._-]+$/g, '') || 'a';
37
+ const digest = createHash('sha256').update(value, 'utf8').digest('hex').slice(0, 8);
38
+ const prefix = value.slice(0, maximumLength - digest.length - 1).replace(/[._-]+$/g, '') || 'app';
39
+ return `${prefix}-${digest}`;
40
+ }
41
+ /** Derive a valid, deterministic unscoped npm package name from arbitrary text. */
42
+ export function packageNameFromText(value) {
43
+ let normalized = value
44
+ .normalize('NFKD')
45
+ .replace(/\p{Mark}+/gu, '')
46
+ .trim()
47
+ .toLowerCase()
48
+ .replace(/[^a-z0-9._-]+/g, '-')
49
+ .replace(/^[._-]+|[._-]+$/g, '');
50
+ if (!normalized)
51
+ normalized = 'anhedral-app';
52
+ if (RESERVED_PACKAGE_NAMES.has(normalized))
53
+ normalized = `anhedral-${normalized}`;
54
+ return assertPackageName(compactPackageSegment(normalized, MAX_PACKAGE_NAME_LENGTH));
55
+ }
56
+ export function childPackageName(projectName, suffix) {
57
+ assertPackageName(projectName);
58
+ const normalizedSuffix = packageNameFromText(suffix);
59
+ const separator = projectName.lastIndexOf('/');
60
+ if (separator >= 0) {
61
+ const scope = projectName.slice(0, separator + 1);
62
+ const leaf = compactPackageSegment(`${projectName.slice(separator + 1)}-${normalizedSuffix}`, MAX_PACKAGE_NAME_LENGTH - scope.length);
63
+ return assertPackageName(`${scope}${leaf}`);
64
+ }
65
+ return assertPackageName(compactPackageSegment(`${projectName}-${normalizedSuffix}`, MAX_PACKAGE_NAME_LENGTH));
66
+ }
67
+ export function identifierSegment(value) {
68
+ const segment = value
69
+ .normalize('NFKD')
70
+ .toLowerCase()
71
+ .replace(/[^a-z0-9]+/g, '-')
72
+ .replace(/^-+|-+$/g, '');
73
+ return segment || 'app';
74
+ }
@@ -1,24 +1,76 @@
1
1
  import { type ToolchainChannel } from './toolchain.js';
2
- export type FrontendMode = 'expo';
3
- export type AuthMode = 'clerk';
4
- export type PaymentsMode = 'revenuecat_stripe';
2
+ import { type ModuleId } from './architecture/index.js';
3
+ import { type NativeStylingLibrary, type UiTarget } from './ui.js';
4
+ export type AppSelections = {
5
+ web: boolean;
6
+ mobile: boolean;
7
+ api: boolean;
8
+ desktop: boolean;
9
+ extension: boolean;
10
+ };
11
+ export type FeatureSelections = {
12
+ database: boolean;
13
+ auth: boolean;
14
+ billing: boolean;
15
+ storage: boolean;
16
+ nativeSubscriptions: boolean;
17
+ electronUpdater: boolean;
18
+ };
5
19
  export interface InitOptions {
6
20
  projectName: string;
7
21
  displayName: string;
8
- auth: AuthMode;
9
- payments: PaymentsMode;
10
- db: 'neon';
11
- orm: 'drizzle';
12
- storage: 'r2';
13
- api: 'fastify';
22
+ modules: ModuleId[];
14
23
  skipInstall: boolean;
24
+ dryRun: boolean;
25
+ json: boolean;
15
26
  toolchainChannel: ToolchainChannel;
27
+ uiComponents?: string[];
28
+ nativeStyling?: NativeStylingLibrary;
29
+ /** Destination root. Omit to scaffold the current working directory. */
30
+ rootDirectory?: string;
31
+ }
32
+ export interface AddOptions {
33
+ modules: ModuleId[];
34
+ skipInstall: boolean;
35
+ dryRun: boolean;
36
+ json: boolean;
37
+ toolchainChannel?: ToolchainChannel;
38
+ }
39
+ export interface UiAddOptions {
40
+ components: string[];
41
+ targets: UiTarget[];
42
+ skipInstall: boolean;
43
+ dryRun: boolean;
44
+ json: boolean;
45
+ }
46
+ export interface UpgradeOptions {
47
+ skipInstall: boolean;
48
+ dryRun: boolean;
49
+ json: boolean;
16
50
  }
17
51
  export interface ProjectOptions {
18
52
  projectName: string;
19
53
  displayName: string;
20
- githubOrg: string | null;
21
- frontendUrl?: string;
54
+ apps: AppSelections;
55
+ features: FeatureSelections;
22
56
  skipInstall?: boolean;
57
+ nativeStyling?: NativeStylingLibrary;
23
58
  }
24
- export declare function scaffoldProject(options: InitOptions): Promise<void>;
59
+ export declare function supportsMobileInstallNode(version: string): boolean;
60
+ export type DoctorIssue = {
61
+ path: string;
62
+ severity: 'error' | 'warning';
63
+ message: string;
64
+ };
65
+ export type DoctorReport = {
66
+ ok: boolean;
67
+ schemaVersion: number;
68
+ generatorVersion: string;
69
+ issues: DoctorIssue[];
70
+ };
71
+ export declare function isSupportedProjectUpgrade(fromVersion: string, toVersion: string): boolean;
72
+ export declare function scaffoldProject(inputOptions: InitOptions): Promise<void>;
73
+ export declare function scaffoldUiComponents(uiOptions: UiAddOptions): Promise<void>;
74
+ export declare function scaffoldUpgradeProject(upgradeOptions: UpgradeOptions): Promise<void>;
75
+ export declare function scaffoldAddModules(addOptions: AddOptions): Promise<void>;
76
+ export declare function doctorProject(): DoctorReport;