@strav/cli 0.4.31 → 1.0.0-alpha.5

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 (63) hide show
  1. package/package.json +17 -41
  2. package/src/binder.ts +88 -0
  3. package/src/command.ts +297 -0
  4. package/src/config_list.ts +42 -0
  5. package/src/config_show.ts +50 -0
  6. package/src/console_provider.ts +46 -0
  7. package/src/exit_codes.ts +26 -0
  8. package/src/index.ts +60 -2
  9. package/src/key_generate.ts +66 -0
  10. package/src/make/index.ts +17 -0
  11. package/src/make/make_command_file.ts +27 -0
  12. package/src/make/make_controller.ts +24 -0
  13. package/src/make/make_factory.ts +25 -0
  14. package/src/make/make_job.ts +25 -0
  15. package/src/make/make_mail.ts +27 -0
  16. package/src/make/make_middleware.ts +23 -0
  17. package/src/make/make_migration.ts +48 -0
  18. package/src/make/make_model.ts +91 -0
  19. package/src/make/make_notification.ts +23 -0
  20. package/src/make/make_policy.ts +24 -0
  21. package/src/make/make_provider.ts +29 -0
  22. package/src/make/make_repository.ts +30 -0
  23. package/src/make/make_request.ts +24 -0
  24. package/src/make/make_seeder.ts +23 -0
  25. package/src/make/make_test.ts +22 -0
  26. package/src/make_command.ts +69 -0
  27. package/src/run_cli.ts +121 -0
  28. package/src/scaffold_console_provider.ts +45 -0
  29. package/src/signature.ts +171 -0
  30. package/src/subset_boot.ts +51 -0
  31. package/src/util_console_provider.ts +18 -0
  32. package/src/cli/bootstrap.ts +0 -82
  33. package/src/cli/command_loader.ts +0 -180
  34. package/src/cli/index.ts +0 -3
  35. package/src/cli/strav.ts +0 -13
  36. package/src/commands/db_seed.ts +0 -77
  37. package/src/commands/db_setup_roles.ts +0 -101
  38. package/src/commands/generate_api.ts +0 -93
  39. package/src/commands/generate_key.ts +0 -47
  40. package/src/commands/generate_models.ts +0 -49
  41. package/src/commands/generate_seeder.ts +0 -68
  42. package/src/commands/migration_compare.ts +0 -167
  43. package/src/commands/migration_fresh.ts +0 -148
  44. package/src/commands/migration_generate.ts +0 -84
  45. package/src/commands/migration_rollback.ts +0 -54
  46. package/src/commands/migration_run.ts +0 -45
  47. package/src/commands/package_install.ts +0 -161
  48. package/src/commands/queue_flush.ts +0 -35
  49. package/src/commands/queue_retry.ts +0 -34
  50. package/src/commands/queue_work.ts +0 -101
  51. package/src/commands/scheduler_work.ts +0 -46
  52. package/src/commands/tenant_create.ts +0 -35
  53. package/src/commands/tenant_delete.ts +0 -64
  54. package/src/commands/tenant_list.ts +0 -39
  55. package/src/config/loader.ts +0 -50
  56. package/src/generators/api_generator.ts +0 -1035
  57. package/src/generators/config.ts +0 -113
  58. package/src/generators/doc_generator.ts +0 -996
  59. package/src/generators/index.ts +0 -11
  60. package/src/generators/model_generator.ts +0 -596
  61. package/src/generators/route_generator.ts +0 -187
  62. package/src/generators/test_generator.ts +0 -1667
  63. package/tsconfig.json +0 -5
@@ -1,187 +0,0 @@
1
- import { join } from 'node:path'
2
- import { Archetype } from '@strav/database/schema/types'
3
- import type { SchemaDefinition } from '@strav/database/schema/types'
4
- import { toSnakeCase, toPascalCase, pluralize } from '@strav/kernel/helpers/strings'
5
- import type { GeneratedFile } from './model_generator.ts'
6
- import type { GeneratorConfig, GeneratorPaths, WriteResult } from './config.ts'
7
- import { resolvePaths, relativeImport, formatAndWrite } from './config.ts'
8
-
9
- /** Archetypes that sit under a parent's /:parentId group. */
10
- const DEPENDENT_ARCHETYPES: Set<Archetype> = new Set([
11
- Archetype.Component,
12
- Archetype.Attribute,
13
- Archetype.Event,
14
- Archetype.Configuration,
15
- Archetype.Contribution,
16
- ])
17
-
18
- // ---------------------------------------------------------------------------
19
- // API routing config
20
- // ---------------------------------------------------------------------------
21
-
22
- export enum ApiRouting {
23
- Prefix = 'prefix',
24
- Subdomain = 'subdomain',
25
- }
26
-
27
- export interface ApiRoutingConfig {
28
- routing: ApiRouting
29
- prefix: string
30
- subdomain: string
31
- }
32
-
33
- const API_DEFAULTS: ApiRoutingConfig = {
34
- routing: ApiRouting.Prefix,
35
- prefix: '/api',
36
- subdomain: 'api',
37
- }
38
-
39
- // ---------------------------------------------------------------------------
40
- // RouteGenerator
41
- // ---------------------------------------------------------------------------
42
-
43
- /**
44
- * Generate a `start/api_routes.ts` file that wires all non-association
45
- * schemas to the router using `router.resource()` — fully derived from
46
- * archetype and parent relationships.
47
- *
48
- * Routing mode (prefix vs subdomain) is read from `config/http.ts`.
49
- */
50
- export default class RouteGenerator {
51
- private apiConfig: ApiRoutingConfig
52
- private paths: GeneratorPaths
53
-
54
- constructor(
55
- private schemas: SchemaDefinition[],
56
- config?: GeneratorConfig,
57
- apiConfig?: Partial<ApiRoutingConfig>
58
- ) {
59
- this.apiConfig = { ...API_DEFAULTS, ...apiConfig }
60
- this.paths = resolvePaths(config)
61
- }
62
-
63
- /** Generate the route file contents without writing to disk. */
64
- generate(): GeneratedFile[] {
65
- return [this.generateRouteFile()]
66
- }
67
-
68
- /** Generate, format with Prettier, and write the route file to disk. */
69
- async writeAll(force?: boolean): Promise<WriteResult> {
70
- const files = this.generate()
71
- return formatAndWrite(files, { force })
72
- }
73
-
74
- // ---------------------------------------------------------------------------
75
- // Core generation
76
- // ---------------------------------------------------------------------------
77
-
78
- private generateRouteFile(): GeneratedFile {
79
- const routable = this.schemas.filter(s => s.archetype !== Archetype.Association)
80
-
81
- // Group schemas by parent (null = root level)
82
- const childrenOf = new Map<string | null, SchemaDefinition[]>()
83
- for (const s of routable) {
84
- const parent = DEPENDENT_ARCHETYPES.has(s.archetype) ? (s.parents?.[0] ?? null) : null
85
- if (!childrenOf.has(parent)) childrenOf.set(parent, [])
86
- childrenOf.get(parent)!.push(s)
87
- }
88
-
89
- const lines: string[] = [
90
- '// Generated by Strav — DO NOT EDIT',
91
- `import { router } from '@strav/http/http'`,
92
- `import { auth } from '@strav/http/auth'`,
93
- '',
94
- ]
95
-
96
- // Controller imports (from barrel)
97
- const controllerImport = relativeImport(this.paths.routes, this.paths.controllers)
98
- const controllerNames = routable.map(s => toPascalCase(s.name) + 'Controller')
99
- lines.push(`import { ${controllerNames.join(', ')} } from '${controllerImport}'`)
100
-
101
- lines.push('')
102
- if (this.apiConfig.routing === ApiRouting.Subdomain) {
103
- lines.push(
104
- `router.group({ subdomain: '${this.apiConfig.subdomain}', middleware: [auth()] }, r => {`
105
- )
106
- } else {
107
- lines.push(
108
- `router.group({ prefix: '${this.apiConfig.prefix}', middleware: [auth()] }, r => {`
109
- )
110
- }
111
-
112
- // Root-level resources (entity, reference)
113
- const roots = childrenOf.get(null) ?? []
114
- for (const s of roots) {
115
- const className = toPascalCase(s.name) + 'Controller'
116
- const routePath = '/' + this.routeSegment(s.name)
117
- lines.push(` r.resource('${routePath}', ${className})`)
118
- }
119
-
120
- // Parent groups — each parent with dependent children gets a group
121
- for (const [parentName, children] of childrenOf) {
122
- if (parentName === null) continue
123
-
124
- const parentSegment = this.routeSegment(parentName)
125
-
126
- lines.push('')
127
- lines.push(` r.group({ prefix: '/${parentSegment}/:parentId' }, r => {`)
128
-
129
- for (const child of children) {
130
- const className = toPascalCase(child.name) + 'Controller'
131
- const childPath = '/' + this.childSegment(child.name, parentName)
132
-
133
- if (child.archetype === Archetype.Configuration) {
134
- lines.push(` r.resource('${childPath}', ${className}).singleton()`)
135
- } else {
136
- lines.push(` r.resource('${childPath}', ${className})`)
137
- }
138
- }
139
-
140
- lines.push(` })`)
141
- }
142
-
143
- lines.push('})')
144
- lines.push('')
145
-
146
- return {
147
- path: join(this.paths.routes, 'api_routes.ts'),
148
- content: lines.join('\n'),
149
- }
150
- }
151
-
152
- // ---------------------------------------------------------------------------
153
- // Helpers
154
- // ---------------------------------------------------------------------------
155
-
156
- private routeSegment(name: string): string {
157
- return toRouteSegment(name)
158
- }
159
-
160
- private childSegment(childName: string, parentName: string): string {
161
- return toChildSegment(childName, parentName)
162
- }
163
- }
164
-
165
- // ---------------------------------------------------------------------------
166
- // Exported helpers (shared with TestGenerator)
167
- // ---------------------------------------------------------------------------
168
-
169
- /** Pluralized, hyphenated URL segment for a schema name. */
170
- export function toRouteSegment(name: string): string {
171
- return pluralize(toSnakeCase(name)).replace(/_/g, '-')
172
- }
173
-
174
- /**
175
- * URL segment for a dependent schema, stripping the parent prefix when the
176
- * child name starts with the parent name (e.g. post_content → contents).
177
- */
178
- export function toChildSegment(childName: string, parentName: string): string {
179
- const parentSnake = toSnakeCase(parentName)
180
- let childSnake = toSnakeCase(childName)
181
-
182
- if (childSnake.startsWith(parentSnake + '_')) {
183
- childSnake = childSnake.slice(parentSnake.length + 1)
184
- }
185
-
186
- return pluralize(childSnake).replace(/_/g, '-')
187
- }