create-astram-app 0.1.2 → 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.
Files changed (101) hide show
  1. package/dist/add-frontend.js +107 -0
  2. package/dist/add-frontend.js.map +1 -0
  3. package/dist/index.js +132 -33
  4. package/dist/index.js.map +1 -1
  5. package/package.json +3 -2
  6. package/template/CLAUDE.md +51 -0
  7. package/template/README.md +43 -44
  8. package/template/_gitignore +6 -0
  9. package/template/frontend/FRONTEND.md +92 -0
  10. package/template/frontend/README.md +16 -0
  11. package/template/frontend/_env.example +6 -0
  12. package/template/frontend/_gitignore +9 -0
  13. package/template/frontend/eslint.config.js +71 -0
  14. package/template/frontend/index.html +13 -0
  15. package/template/frontend/package.json +52 -0
  16. package/template/frontend/public/astram-logo-full.png +0 -0
  17. package/template/frontend/public/astram-logo-white.png +0 -0
  18. package/template/frontend/public/favicon.png +0 -0
  19. package/template/frontend/src/App.jsx +167 -0
  20. package/template/frontend/src/auth/AuthContext.jsx +338 -0
  21. package/template/frontend/src/components/ConfirmDialog.jsx +92 -0
  22. package/template/frontend/src/components/EntityFormModal.jsx +154 -0
  23. package/template/frontend/src/components/EntityList.jsx +480 -0
  24. package/template/frontend/src/components/PageHeader.jsx +54 -0
  25. package/template/frontend/src/components/access/CollapsibleGroup.jsx +34 -0
  26. package/template/frontend/src/components/ui/alert-dialog.tsx +175 -0
  27. package/template/frontend/src/components/ui/alert.tsx +83 -0
  28. package/template/frontend/src/components/ui/avatar.tsx +51 -0
  29. package/template/frontend/src/components/ui/badge.tsx +56 -0
  30. package/template/frontend/src/components/ui/button.tsx +67 -0
  31. package/template/frontend/src/components/ui/card.tsx +92 -0
  32. package/template/frontend/src/components/ui/checkbox.tsx +30 -0
  33. package/template/frontend/src/components/ui/date-field.tsx +47 -0
  34. package/template/frontend/src/components/ui/dialog.tsx +214 -0
  35. package/template/frontend/src/components/ui/dropdown-menu.tsx +255 -0
  36. package/template/frontend/src/components/ui/input-otp.tsx +81 -0
  37. package/template/frontend/src/components/ui/input.tsx +21 -0
  38. package/template/frontend/src/components/ui/label.tsx +46 -0
  39. package/template/frontend/src/components/ui/searchable-select.tsx +459 -0
  40. package/template/frontend/src/components/ui/select.tsx +199 -0
  41. package/template/frontend/src/components/ui/separator.tsx +26 -0
  42. package/template/frontend/src/components/ui/sheet.tsx +139 -0
  43. package/template/frontend/src/components/ui/skeleton.tsx +13 -0
  44. package/template/frontend/src/components/ui/sonner.tsx +23 -0
  45. package/template/frontend/src/components/ui/table.tsx +181 -0
  46. package/template/frontend/src/components/ui/tooltip.tsx +59 -0
  47. package/template/frontend/src/config/branding.js +80 -0
  48. package/template/frontend/src/hooks/useMobile.tsx +21 -0
  49. package/template/frontend/src/index.css +265 -0
  50. package/template/frontend/src/lib/utils.js +7 -0
  51. package/template/frontend/src/main.jsx +27 -0
  52. package/template/frontend/src/pages/Dashboard.jsx +127 -0
  53. package/template/frontend/src/pages/ForgotPassword.jsx +104 -0
  54. package/template/frontend/src/pages/Login.jsx +393 -0
  55. package/template/frontend/src/pages/ResetPassword.jsx +159 -0
  56. package/template/frontend/src/pages/access/AccessForm.jsx +416 -0
  57. package/template/frontend/src/pages/access/AccessPage.jsx +282 -0
  58. package/template/frontend/src/pages/access/RoleActionsMenu.jsx +42 -0
  59. package/template/frontend/src/pages/account/AccountLayout.jsx +229 -0
  60. package/template/frontend/src/pages/account/ChangePasswordPage.jsx +235 -0
  61. package/template/frontend/src/pages/account/ProfilePage.jsx +122 -0
  62. package/template/frontend/src/pages/account/ReenrollPage.jsx +98 -0
  63. package/template/frontend/src/pages/account/TwoFactorPage.jsx +833 -0
  64. package/template/frontend/src/pages/audit/AuditPage.jsx +268 -0
  65. package/template/frontend/src/pages/companies/CompaniesPage.jsx +232 -0
  66. package/template/frontend/src/pages/companies/CompanyForm.jsx +127 -0
  67. package/template/frontend/src/pages/roles/RoleForm.jsx +99 -0
  68. package/template/frontend/src/pages/roles/RolesPage.jsx +207 -0
  69. package/template/frontend/src/pages/users/AssignmentsEditor.jsx +193 -0
  70. package/template/frontend/src/pages/users/MembershipCard.jsx +303 -0
  71. package/template/frontend/src/pages/users/PostingRow.jsx +264 -0
  72. package/template/frontend/src/pages/users/UserForm.jsx +167 -0
  73. package/template/frontend/src/pages/users/UsersPage.jsx +232 -0
  74. package/template/frontend/src/platform/httpClient.js +125 -0
  75. package/template/frontend/src/platform/returnPathStore.js +43 -0
  76. package/template/frontend/src/platform/sessionStore.js +29 -0
  77. package/template/frontend/src/platform/shieldTransport.js +172 -0
  78. package/template/frontend/src/platform/shieldTransport.test.mjs +245 -0
  79. package/template/frontend/src/shell/AppShell.jsx +237 -0
  80. package/template/frontend/src/shell/Sidebar.jsx +257 -0
  81. package/template/frontend/src/shell/nav.js +90 -0
  82. package/template/frontend/src/theme/ThemeProvider.jsx +14 -0
  83. package/template/frontend/src/theme/ThemeToggle.jsx +44 -0
  84. package/template/frontend/tsconfig.json +22 -0
  85. package/template/frontend/vite.config.js +30 -0
  86. package/template/server/_env.example +45 -0
  87. package/template/server/eslint.config.js +95 -0
  88. package/template/server/package.json +49 -0
  89. package/template/server/scripts/dev.mjs +51 -0
  90. package/template/server/scripts/sync-astram-guide.mjs +63 -0
  91. package/template/_env.example +0 -33
  92. package/template/package.json +0 -37
  93. /package/template/{src → server/src}/app.module.ts +0 -0
  94. /package/template/{src → server/src}/features/_gitkeep +0 -0
  95. /package/template/{src → server/src}/health/demo.controller.ts +0 -0
  96. /package/template/{src → server/src}/health/health.controller.ts +0 -0
  97. /package/template/{src → server/src}/main.ts +0 -0
  98. /package/template/{test → server/test}/enforcement.e2e.spec.ts +0 -0
  99. /package/template/{tsconfig.build.json → server/tsconfig.build.json} +0 -0
  100. /package/template/{tsconfig.json → server/tsconfig.json} +0 -0
  101. /package/template/{vitest.config.ts → server/vitest.config.ts} +0 -0
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Dev runner — TypeScript watch + auto-restart, with CORRECT NestJS decorator
3
+ * metadata.
4
+ *
5
+ * WHY not `tsx watch`: tsx uses esbuild, which does NOT emit `emitDecoratorMetadata`.
6
+ * NestJS constructor injection (`constructor(private x: Service)`) depends on that
7
+ * metadata, so under tsx a controller's injected service is `undefined` at runtime
8
+ * (a silent 500 on the first call). `tsc` DOES emit the metadata — so this runner
9
+ * compiles with `tsc --watch` (→ dist/) and runs `node --watch dist/main.js`, giving
10
+ * hot-reload AND correct DI. Same compiler as the production build, no extra deps.
11
+ *
12
+ * `.env` is loaded by the node child via --env-file-if-exists.
13
+ */
14
+
15
+ import { spawn } from 'node:child_process';
16
+ import { existsSync, mkdirSync } from 'node:fs';
17
+
18
+ mkdirSync('dist', { recursive: true });
19
+
20
+ // 1) tsc in watch mode → dist/ (emits decorator metadata; the whole point).
21
+ const tsc = spawn(
22
+ process.execPath,
23
+ [new URL('../node_modules/typescript/bin/tsc', import.meta.url).pathname, '-w', '-p', 'tsconfig.build.json', '--preserveWatchOutput'],
24
+ { stdio: 'inherit' },
25
+ );
26
+
27
+ // 2) Wait for the first emit, then run node --watch on the built entry.
28
+ let started = false;
29
+ const startNode = () => {
30
+ if (started) return;
31
+ if (!existsSync('dist/main.js')) {
32
+ setTimeout(startNode, 300);
33
+ return;
34
+ }
35
+ started = true;
36
+ const node = spawn(
37
+ process.execPath,
38
+ ['--env-file-if-exists=.env', '--watch', 'dist/main.js'],
39
+ { stdio: 'inherit' },
40
+ );
41
+ node.on('exit', (code) => {
42
+ tsc.kill();
43
+ process.exit(code ?? 0);
44
+ });
45
+ };
46
+ setTimeout(startNode, 800);
47
+
48
+ process.on('SIGINT', () => {
49
+ tsc.kill();
50
+ process.exit(0);
51
+ });
@@ -0,0 +1,63 @@
1
+ /**
2
+ * sync-astram-guide — copy the framework's guide docs into `.claude/rules/` so
3
+ * Claude Code reads the CURRENT framework rules.
4
+ *
5
+ * WHY (ADR-0025, the two-layer AI guide): the framework ships its hard rules +
6
+ * capabilities in the installed `@astram/guide` package (in node_modules). Claude
7
+ * Code reliably reads rules from `.claude/rules/` (a documented, symlink-aware
8
+ * location) — but NOT from an @import that points into node_modules. So this script
9
+ * bridges the two: it copies the framework docs from the installed package into the
10
+ * app-root `.claude/rules/`, where the app's CLAUDE.md references them.
11
+ *
12
+ * It runs on `npm install` AND `npm update` (wired as a postinstall in
13
+ * server/package.json), so a FRAMEWORK UPGRADE automatically refreshes the rules —
14
+ * the whole point of the upgrade-safe design. The copied files are GITIGNORED (they
15
+ * are a generated mirror of the framework's version); the developer-owned
16
+ * `.astram/guide/` layer is separate, git-tracked, and NEVER touched by this script.
17
+ *
18
+ * The app root is the monorepo root (one level up from server/), because CLAUDE.md +
19
+ * .claude/ live at the app root and Claude walks UP the tree from wherever you work.
20
+ */
21
+
22
+ import { cpSync, mkdirSync, writeFileSync } from 'node:fs';
23
+ import { dirname, join, resolve } from 'node:path';
24
+ import { fileURLToPath } from 'node:url';
25
+ import { createRequire } from 'node:module';
26
+
27
+ const require = createRequire(import.meta.url);
28
+ const here = dirname(fileURLToPath(import.meta.url)); // server/scripts
29
+ const appRoot = resolve(here, '..', '..'); // monorepo root
30
+ const rulesDir = join(appRoot, '.claude', 'rules');
31
+
32
+ function main() {
33
+ let guide;
34
+ try {
35
+ guide = require('@astram/guide');
36
+ } catch {
37
+ // The framework guide package isn't installed (e.g. a partial install). Skip
38
+ // silently — this is a best-effort refresh, never a hard failure of the install.
39
+ process.stdout.write('[sync-astram-guide] @astram/guide not found — skipped.\n');
40
+ return 0;
41
+ }
42
+
43
+ mkdirSync(rulesDir, { recursive: true });
44
+ // Copy the framework docs into .claude/rules/ (overwrite — they are the framework's
45
+ // to own; on upgrade the newer versions replace the older ones cleanly).
46
+ cpSync(guide.FRAMEWORK_RULES_PATH, join(rulesDir, 'astram-framework-rules.md'));
47
+ cpSync(guide.CAPABILITIES_PATH, join(rulesDir, 'astram-framework-capabilities.md'));
48
+
49
+ // Stamp the synced version so a human/AI can see which framework version's rules
50
+ // are present (and notice when an upgrade changed them).
51
+ writeFileSync(
52
+ join(rulesDir, '.astram-guide-version'),
53
+ `${guide.version}\n`,
54
+ 'utf8',
55
+ );
56
+
57
+ process.stdout.write(
58
+ `[sync-astram-guide] framework rules synced (v${guide.version}) → .claude/rules/\n`,
59
+ );
60
+ return 0;
61
+ }
62
+
63
+ process.exitCode = main();
@@ -1,33 +0,0 @@
1
- # __APP_NAME__ — environment configuration (references only, no secrets).
2
- #
3
- # Every value below has a safe default, so the app boots with NO .env file at all.
4
- # Copy this file to `.env` and override only what you need. `.env` is gitignored.
5
- #
6
- # These are read by `loadAppConfig()` from the installed @astram/guard framework.
7
-
8
- # HTTP port the app listens on (default: 3000).
9
- PORT=3000
10
-
11
- # Runtime environment: development | production | test (default: development).
12
- NODE_ENV=development
13
-
14
- # --- ADR-0018 connection-pool budget (all optional; framework defaults apply) ---
15
- # Uncomment + tune only if your deployment needs to.
16
- # SHIELD_POOL_WORKERS=1
17
- # SHIELD_DB_MAX_CONNECTIONS=50
18
- # SHIELD_POOL_HEADROOM=5
19
- # SHIELD_POOL_MAX_CORE=10
20
- # SHIELD_POOL_MAX_APP_CRUD=10
21
- # SHIELD_POOL_MAX_SCHEMA_SVC=5
22
-
23
- # --- OPTIONAL: real authentication (only if you set ShieldModule.forRoot({ auth: true })) ---
24
- # Auth needs a live MariaDB + Redis and a refresh-token HMAC key. These are
25
- # REQUIRED once auth is enabled (the app fails closed without the HMAC key) — but
26
- # irrelevant (unread) while auth is off. Point them at your MariaDB/Redis.
27
- # SHIELD_DB_HOST=127.0.0.1
28
- # SHIELD_DB_PORT=3306
29
- # SHIELD_DB_USER=shield_core
30
- # SHIELD_DB_PASSWORD=change-me
31
- # SHIELD_DB_DATABASE=shield_identity
32
- # SHIELD_REDIS_URL=redis://127.0.0.1:6379
33
- # SHIELD_REFRESH_HMAC_KEY=change-me-to-a-long-random-secret # REQUIRED when auth is on
@@ -1,37 +0,0 @@
1
- {
2
- "name": "__APP_NAME__",
3
- "version": "0.0.0",
4
- "private": true,
5
- "description": "An Astram consumer app. Depends on the published, immutable framework (@astram/core, @astram/guard, @astram/sdk) and declares enforcement via ShieldModule.forRoot(). Features go in src/features/.",
6
- "type": "commonjs",
7
- "main": "dist/main.js",
8
- "scripts": {
9
- "prebuild": "node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\"",
10
- "build": "tsc -p tsconfig.build.json",
11
- "start": "node dist/main.js",
12
- "dev": "tsx watch src/main.ts",
13
- "test": "vitest run",
14
- "lint": "eslint \"src/**/*.ts\" \"test/**/*.ts\""
15
- },
16
- "dependencies": {
17
- "@astram/core": "^0.1.0",
18
- "@astram/guard": "^0.1.1",
19
- "@astram/sdk": "^0.1.0",
20
- "@nestjs/common": "^11.0.0",
21
- "@nestjs/core": "^11.0.0",
22
- "@nestjs/platform-express": "^11.0.0",
23
- "reflect-metadata": "^0.2.2",
24
- "rxjs": "^7.8.1"
25
- },
26
- "devDependencies": {
27
- "@nestjs/testing": "^11.0.0",
28
- "@types/express": "^5.0.0",
29
- "@types/node": "^22.0.0",
30
- "@types/supertest": "^6.0.2",
31
- "supertest": "^7.0.0",
32
- "tsx": "^4.19.2",
33
- "typescript": "^5.7.0",
34
- "unplugin-swc": "^1.5.1",
35
- "vitest": "^2.1.8"
36
- }
37
- }
File without changes
File without changes
File without changes