@mantiq/cli 0.1.6 → 0.2.0-rc.1

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mantiq/cli",
3
- "version": "0.1.6",
3
+ "version": "0.2.0-rc.1",
4
4
  "description": "Command runner, code generators, dev server",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -43,14 +43,16 @@
43
43
  "LICENSE"
44
44
  ],
45
45
  "scripts": {
46
- "build": "bun build ./src/index.ts --outdir ./dist --target bun",
46
+ "build": "bun build ./src/index.ts --outdir ./dist --target bun --packages=external",
47
47
  "test": "bun test",
48
48
  "typecheck": "tsc --noEmit",
49
49
  "clean": "rm -rf dist"
50
50
  },
51
51
  "devDependencies": {
52
52
  "bun-types": "latest",
53
- "typescript": "^5.7.0"
53
+ "typescript": "^5.7.0",
54
+ "@mantiq/core": "workspace:*",
55
+ "@mantiq/database": "workspace:*"
54
56
  },
55
57
  "peerDependencies": {
56
58
  "@mantiq/core": "^0.1.0",
@@ -0,0 +1,34 @@
1
+ import { GeneratorCommand } from './GeneratorCommand.ts'
2
+ import type { ParsedArgs } from '../Parser.ts'
3
+
4
+ export class MakeJobCommand extends GeneratorCommand {
5
+ override name = 'make:job'
6
+ override description = 'Create a new job class'
7
+ override usage = 'make:job <name>'
8
+
9
+ override directory() { return 'app/Jobs' }
10
+ override suffix() { return '' }
11
+
12
+ override stub(name: string): string {
13
+ return `import { Job } from '@mantiq/queue'
14
+
15
+ export class ${name} extends Job {
16
+ override tries = 3
17
+ override backoff = 10
18
+
19
+ constructor(public readonly data: Record<string, any> = {}) {
20
+ super()
21
+ }
22
+
23
+ override async handle(): Promise<void> {
24
+ // TODO: implement ${name} job logic
25
+ }
26
+
27
+ override async failed(error: Error): Promise<void> {
28
+ // TODO: handle failure (e.g., log, notify)
29
+ console.error(\`${name} failed: \${error.message}\`)
30
+ }
31
+ }
32
+ `
33
+ }
34
+ }
@@ -0,0 +1,34 @@
1
+ import { GeneratorCommand } from './GeneratorCommand.ts'
2
+ import type { ParsedArgs } from '../Parser.ts'
3
+
4
+ export class MakeMailCommand extends GeneratorCommand {
5
+ override name = 'make:mail'
6
+ override description = 'Create a new mailable class'
7
+ override usage = 'make:mail <name>'
8
+
9
+ override directory() { return 'app/Mail' }
10
+ override suffix() { return '' }
11
+
12
+ override stub(name: string): string {
13
+ return `import { Mailable } from '@mantiq/mail'
14
+
15
+ export class ${name} extends Mailable {
16
+ constructor(private readonly data: Record<string, any> = {}) {
17
+ super()
18
+ }
19
+
20
+ override build(): void {
21
+ this.setSubject('${this.toSubject(name)}')
22
+ this.html(\`
23
+ <h1>${this.toSubject(name)}</h1>
24
+ <p>This is the ${name} mailable.</p>
25
+ \`)
26
+ }
27
+ }
28
+ `
29
+ }
30
+
31
+ private toSubject(name: string): string {
32
+ return name.replace(/([A-Z])/g, ' $1').trim()
33
+ }
34
+ }
@@ -0,0 +1,49 @@
1
+ import { GeneratorCommand } from './GeneratorCommand.ts'
2
+ import type { ParsedArgs } from '../Parser.ts'
3
+
4
+ export class MakeNotificationCommand extends GeneratorCommand {
5
+ override name = 'make:notification'
6
+ override description = 'Create a new notification class'
7
+ override usage = 'make:notification <name>'
8
+
9
+ override directory() { return 'app/Notifications' }
10
+ override suffix() { return '' }
11
+
12
+ override stub(name: string): string {
13
+ return `import { Notification } from '@mantiq/notify'
14
+ import type { Notifiable } from '@mantiq/notify'
15
+
16
+ export class ${name} extends Notification {
17
+ constructor(private readonly data: Record<string, any> = {}) {
18
+ super()
19
+ }
20
+
21
+ override via(notifiable: Notifiable): string[] {
22
+ return ['mail', 'database']
23
+ }
24
+
25
+ override toMail(notifiable: Notifiable): any {
26
+ return {
27
+ subject: '${this.toSubject(name)}',
28
+ html: '<p>${this.toSubject(name)}</p>',
29
+ }
30
+ }
31
+
32
+ override toDatabase(notifiable: Notifiable): Record<string, any> {
33
+ return {
34
+ type: '${this.toSnake(name)}',
35
+ ...this.data,
36
+ }
37
+ }
38
+ }
39
+ `
40
+ }
41
+
42
+ private toSubject(name: string): string {
43
+ return name.replace(/([A-Z])/g, ' $1').trim()
44
+ }
45
+
46
+ private toSnake(name: string): string {
47
+ return name.replace(/([A-Z])/g, '_$1').toLowerCase().replace(/^_/, '')
48
+ }
49
+ }
@@ -0,0 +1,47 @@
1
+ import { GeneratorCommand } from './GeneratorCommand.ts'
2
+ import type { ParsedArgs } from '../Parser.ts'
3
+
4
+ export class MakePolicyCommand extends GeneratorCommand {
5
+ override name = 'make:policy'
6
+ override description = 'Create a new policy class'
7
+ override usage = 'make:policy <name> [--model=ModelName]'
8
+
9
+ override directory() { return 'app/Policies' }
10
+ override suffix() { return 'Policy' }
11
+
12
+ override stub(name: string, args: ParsedArgs): string {
13
+ const modelName = (args.flags['model'] as string) ?? name
14
+ const modelImport = `import { ${modelName} } from '../Models/${modelName}.ts'`
15
+
16
+ return `import { Policy } from '@mantiq/auth'
17
+ ${modelImport}
18
+
19
+ export class ${name}Policy extends Policy {
20
+ /**
21
+ * Called before any other policy method.
22
+ * Return true to allow, false to deny, null to continue to the specific check.
23
+ */
24
+ // before(user: any, ability: string): boolean | null {
25
+ // if (user.role === 'admin') return true
26
+ // return null
27
+ // }
28
+
29
+ view(user: any, ${modelName.toLowerCase()}: ${modelName}): boolean {
30
+ return true
31
+ }
32
+
33
+ create(user: any): boolean {
34
+ return true
35
+ }
36
+
37
+ update(user: any, ${modelName.toLowerCase()}: ${modelName}): boolean {
38
+ return user.getAuthIdentifier() === ${modelName.toLowerCase()}.getAttribute('user_id')
39
+ }
40
+
41
+ delete(user: any, ${modelName.toLowerCase()}: ${modelName}): boolean {
42
+ return user.getAuthIdentifier() === ${modelName.toLowerCase()}.getAttribute('user_id')
43
+ }
44
+ }
45
+ `
46
+ }
47
+ }
@@ -74,6 +74,20 @@ export class TinkerCommand extends Command {
74
74
  }
75
75
  }
76
76
 
77
+ // ── Auto-import factories ─────────────────────────────────────────────
78
+ const factoriesDir = `${process.cwd()}/database/factories`
79
+ if (existsSync(factoriesDir)) {
80
+ const files = readdirSync(factoriesDir).filter((f) => f.endsWith('.ts'))
81
+ for (const file of files) {
82
+ try {
83
+ const mod = await import(`${factoriesDir}/${file}`)
84
+ const name = file.replace(/\.ts$/, '')
85
+ const cls = mod[name] ?? mod.default ?? Object.values(mod)[0]
86
+ if (cls) context[name] = cls
87
+ } catch {}
88
+ }
89
+ }
90
+
77
91
  // ── Assign to globalThis ─────────────────────────────────────────────
78
92
  for (const [key, value] of Object.entries(context)) {
79
93
  ;(globalThis as any)[key] = value
package/src/index.ts CHANGED
@@ -34,6 +34,10 @@ export { MakeRequestCommand } from './commands/MakeRequestCommand.ts'
34
34
  export { MakeRuleCommand } from './commands/MakeRuleCommand.ts'
35
35
  export { MakeSeederCommand } from './commands/MakeSeederCommand.ts'
36
36
  export { MakeTestCommand } from './commands/MakeTestCommand.ts'
37
+ export { MakeMailCommand } from './commands/MakeMailCommand.ts'
38
+ export { MakeNotificationCommand } from './commands/MakeNotificationCommand.ts'
39
+ export { MakeJobCommand } from './commands/MakeJobCommand.ts'
40
+ export { MakePolicyCommand } from './commands/MakePolicyCommand.ts'
37
41
 
38
42
  // Utility commands
39
43
  export { AboutCommand } from './commands/AboutCommand.ts'