@strav/cli 0.4.30 → 1.0.0-alpha.4

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 -77
  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,46 +0,0 @@
1
- import type { Command } from 'commander'
2
- import chalk from 'chalk'
3
- import path from 'node:path'
4
- import { bootstrap, shutdown } from '../cli/bootstrap.ts'
5
- import Scheduler from '@strav/queue/scheduler/scheduler'
6
- import SchedulerRunner from '@strav/queue/scheduler/runner'
7
-
8
- export function register(program: Command): void {
9
- program
10
- .command('schedule')
11
- .alias('scheduler:work')
12
- .description('Start the task scheduler')
13
- .action(async () => {
14
- let db
15
- try {
16
- const { db: database } = await bootstrap()
17
- db = database
18
-
19
- // Load user's scheduled tasks
20
- const schedulesPath = path.resolve('app/schedules.ts')
21
- await import(schedulesPath)
22
-
23
- const taskCount = Scheduler.tasks.length
24
- if (taskCount === 0) {
25
- console.log(chalk.yellow('No tasks registered. Add tasks in app/schedules.ts'))
26
- return
27
- }
28
-
29
- console.log(chalk.cyan(`Scheduler starting with ${taskCount} task(s)...`))
30
- for (const task of Scheduler.tasks) {
31
- console.log(chalk.dim(` ${task.name}`))
32
- }
33
- console.log(chalk.dim(' Press Ctrl+C to stop.\n'))
34
-
35
- const runner = new SchedulerRunner()
36
- await runner.start()
37
-
38
- console.log(chalk.dim('\nScheduler stopped.'))
39
- } catch (err) {
40
- console.error(chalk.red(`Error: ${err instanceof Error ? err.message : err}`))
41
- process.exit(1)
42
- } finally {
43
- if (db) await shutdown(db)
44
- }
45
- })
46
- }
@@ -1,35 +0,0 @@
1
- import type { Command } from 'commander'
2
- import chalk from 'chalk'
3
- import { bootstrap, shutdown } from '../cli/bootstrap.ts'
4
- import TenantManager from '@strav/database/database/tenant/manager'
5
- import { ensureTenantTable } from '@strav/database/database/tenant/seed'
6
-
7
- export function register(program: Command): void {
8
- program
9
- .command('tenant:create')
10
- .description('Create a new tenant')
11
- .requiredOption('--slug <slug>', 'Unique tenant slug (used for subdomain/URLs)')
12
- .requiredOption('--name <name>', 'Tenant display name')
13
- .action(async (opts: { slug: string; name: string }) => {
14
- let db
15
- try {
16
- const { db: database } = await bootstrap()
17
- db = database
18
-
19
- await ensureTenantTable(db.bypass, db.tenantIdType)
20
- const manager = new TenantManager(db)
21
-
22
- const tenant = await manager.create({ slug: opts.slug, name: opts.name })
23
-
24
- console.log(chalk.green('\nTenant created:'))
25
- console.log(chalk.dim(` id: ${tenant.id}`))
26
- console.log(chalk.dim(` slug: ${tenant.slug}`))
27
- console.log(chalk.dim(` name: ${tenant.name}`))
28
- } catch (err) {
29
- console.error(chalk.red(`Error: ${err instanceof Error ? err.message : err}`))
30
- process.exit(1)
31
- } finally {
32
- if (db) await shutdown(db)
33
- }
34
- })
35
- }
@@ -1,64 +0,0 @@
1
- import type { Command } from 'commander'
2
- import chalk from 'chalk'
3
- import { createInterface } from 'node:readline'
4
- import { bootstrap, shutdown } from '../cli/bootstrap.ts'
5
- import TenantManager from '@strav/database/database/tenant/manager'
6
- import { ensureTenantTable } from '@strav/database/database/tenant/seed'
7
-
8
- export function register(program: Command): void {
9
- program
10
- .command('tenant:delete <id>')
11
- .description('Delete a tenant and cascade-delete all their rows')
12
- .option('-f, --force', 'Skip the confirmation prompt')
13
- .action(async (id: string, opts: { force?: boolean }) => {
14
- let db
15
- try {
16
- const { db: database } = await bootstrap()
17
- db = database
18
-
19
- await ensureTenantTable(db.bypass, db.tenantIdType)
20
- const manager = new TenantManager(db)
21
-
22
- const tenant = await manager.find(id)
23
- if (!tenant) {
24
- console.error(chalk.red(`Tenant not found: ${id}`))
25
- process.exit(1)
26
- }
27
-
28
- if (!opts.force) {
29
- console.log(
30
- chalk.red('WARNING: ') +
31
- `This will delete tenant "${tenant.slug}" and ` +
32
- chalk.red('cascade-delete all their data') +
33
- ' across every tenant-scoped table.'
34
- )
35
- const challenge = tenant.slug
36
- console.log(`\n Type ${chalk.yellow(challenge)} to confirm:\n`)
37
-
38
- const answer = await prompt(' > ')
39
- if (answer.trim() !== challenge) {
40
- console.error(chalk.red('\nConfirmation does not match. Operation cancelled.'))
41
- process.exit(1)
42
- }
43
- }
44
-
45
- await manager.delete(id)
46
- console.log(chalk.green(`\nTenant "${tenant.slug}" deleted.`))
47
- } catch (err) {
48
- console.error(chalk.red(`Error: ${err instanceof Error ? err.message : err}`))
49
- process.exit(1)
50
- } finally {
51
- if (db) await shutdown(db)
52
- }
53
- })
54
- }
55
-
56
- function prompt(question: string): Promise<string> {
57
- const rl = createInterface({ input: process.stdin, output: process.stdout })
58
- return new Promise(resolve => {
59
- rl.question(question, answer => {
60
- rl.close()
61
- resolve(answer)
62
- })
63
- })
64
- }
@@ -1,39 +0,0 @@
1
- import type { Command } from 'commander'
2
- import chalk from 'chalk'
3
- import { bootstrap, shutdown } from '../cli/bootstrap.ts'
4
- import TenantManager from '@strav/database/database/tenant/manager'
5
- import { ensureTenantTable } from '@strav/database/database/tenant/seed'
6
-
7
- export function register(program: Command): void {
8
- program
9
- .command('tenant:list')
10
- .description('List all tenants')
11
- .action(async () => {
12
- let db
13
- try {
14
- const { db: database } = await bootstrap()
15
- db = database
16
-
17
- await ensureTenantTable(db.bypass, db.tenantIdType)
18
- const manager = new TenantManager(db)
19
- const tenants = await manager.list()
20
-
21
- if (tenants.length === 0) {
22
- console.log(chalk.yellow('No tenants found.'))
23
- return
24
- }
25
-
26
- console.log(chalk.cyan(`\n${tenants.length} tenant(s):\n`))
27
- for (const t of tenants) {
28
- console.log(` ${chalk.green(t.slug)}`)
29
- console.log(chalk.dim(` id: ${t.id}`))
30
- console.log(chalk.dim(` name: ${t.name}`))
31
- }
32
- } catch (err) {
33
- console.error(chalk.red(`Error: ${err instanceof Error ? err.message : err}`))
34
- process.exit(1)
35
- } finally {
36
- if (db) await shutdown(db)
37
- }
38
- })
39
- }
@@ -1,50 +0,0 @@
1
- import { join } from 'node:path'
2
- import type { GeneratorConfig, GeneratorPaths } from '../generators/config.ts'
3
- import { resolvePaths } from '../generators/config.ts'
4
- import {
5
- type TenantIdType,
6
- DEFAULT_TENANT_ID_TYPE,
7
- } from '@strav/database/database/tenant/id_type'
8
-
9
- /**
10
- * Load the generator configuration from the project's config/generators.ts file.
11
- * Falls back to defaults if the file doesn't exist.
12
- */
13
- export async function loadGeneratorConfig(): Promise<GeneratorConfig | undefined> {
14
- try {
15
- return (await import(join(process.cwd(), 'config/generators.ts'))).default
16
- } catch {
17
- return undefined
18
- }
19
- }
20
-
21
- /**
22
- * Get the fully resolved database paths from the configuration.
23
- */
24
- export async function getDatabasePaths(): Promise<{ schemas: string; migrations: string }> {
25
- const config = await loadGeneratorConfig()
26
- const paths = resolvePaths(config)
27
- return { schemas: paths.schemas, migrations: paths.migrations }
28
- }
29
-
30
- /**
31
- * Get all resolved paths from the configuration.
32
- */
33
- export async function getAllPaths(): Promise<GeneratorPaths> {
34
- const config = await loadGeneratorConfig()
35
- return resolvePaths(config)
36
- }
37
-
38
- /**
39
- * Read `database.tenant.idType` from `config/database.ts` for code-only
40
- * generators (generate:models, generate:api) that don't connect to the DB.
41
- * Falls back to the framework default if the config file or key is absent.
42
- */
43
- export async function loadTenantIdType(): Promise<TenantIdType> {
44
- try {
45
- const dbConfig = (await import(join(process.cwd(), 'config/database.ts'))).default
46
- return (dbConfig?.tenant?.idType as TenantIdType | undefined) ?? DEFAULT_TENANT_ID_TYPE
47
- } catch {
48
- return DEFAULT_TENANT_ID_TYPE
49
- }
50
- }