Skip to content

Commit 987dc07

Browse files
chore: wip
1 parent e8f182f commit 987dc07

File tree

7 files changed

+73
-145
lines changed

7 files changed

+73
-145
lines changed

app/Models/User.ts

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import { faker } from '@stacksjs/faker'
33
import { capitalize } from '@stacksjs/strings'
44
import type { Model } from '@stacksjs/types'
55
import { schema } from '@stacksjs/validation'
6-
import type { User } from 'actions/src/orm/user'
76

87
export default {
98
name: 'User', // defaults to the sanitized file name
@@ -30,16 +29,7 @@ export default {
3029
count: 100,
3130
},
3231

33-
useApi: {
34-
uri: 'users', // your-url.com/api/users
35-
middleware: ['Api'], // defaults to `[]`
36-
37-
routes: {
38-
index: 'UserIndexOrmAction',
39-
show: 'UserShowOrmAction',
40-
destroy: 'UserDestroyOrmAction',
41-
},
42-
},
32+
useApi: true,
4333

4434
observe: true,
4535

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { Action } from '@stacksjs/actions'
2+
import User from '../../orm/src/models/User'
3+
import type { UserRequestType } from '../../types/requests'
4+
5+
export default new Action({
6+
name: 'User Store',
7+
description: 'User Store ORM Action',
8+
method: 'POST',
9+
async handle(request: UserRequestType) {
10+
await request.validate()
11+
12+
const model = await User.create(request.all())
13+
14+
return model
15+
},
16+
})
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Action } from '@stacksjs/actions'
2+
import User from '../../orm/src/models/User'
3+
import type { UserRequestType } from '../../types/requests'
4+
5+
export default new Action({
6+
name: 'User Update',
7+
description: 'User Update ORM Action',
8+
method: 'PATCH',
9+
async handle(request: UserRequestType) {
10+
await request.validate()
11+
12+
const id = request.getParam('id')
13+
const model = await User.findOrFail(Number(id))
14+
15+
return model.update(request.all())
16+
},
17+
})

storage/framework/api/openapi.json

Lines changed: 1 addition & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,93 +1,4 @@
1-
{
2-
"openapi": "3.0.0",
3-
"info": { "title": "Generated API", "version": "1.0.0" },
4-
"paths": {
5-
"/api/foo/bar/{id}": {
6-
"get": {
7-
"summary": ".api.foo.bar.{id}",
8-
"parameters": [],
9-
"responses": {
10-
"200": {
11-
"description": "Successful response",
12-
"content": {
13-
"application/json": {
14-
"schema": { "type": "object", "properties": {} }
15-
}
16-
}
17-
}
18-
}
19-
}
20-
},
21-
"/api": {
22-
"get": {
23-
"summary": ".api",
24-
"parameters": [],
25-
"responses": {
26-
"200": {
27-
"description": "Successful response",
28-
"content": {
29-
"application/json": {
30-
"schema": { "type": "object", "properties": {} }
31-
}
32-
}
33-
}
34-
}
35-
}
36-
},
37-
"/api/hello/world": {
38-
"get": {
39-
"summary": ".api.hello.world",
40-
"parameters": [],
41-
"responses": {
42-
"200": {
43-
"description": "Successful response",
44-
"content": {
45-
"application/json": {
46-
"schema": { "type": "object", "properties": {} }
47-
}
48-
}
49-
}
50-
}
51-
}
52-
},
53-
"/api/email/subscribe": {
54-
"post": {
55-
"summary": ".api.email.subscribe",
56-
"operationId": "Actions/SubscriberEmailAction",
57-
"parameters": [],
58-
"responses": {
59-
"201": {
60-
"description": "Successful response",
61-
"content": {
62-
"application/json": {
63-
"schema": { "type": "object", "properties": {} }
64-
}
65-
}
66-
}
67-
}
68-
}
69-
},
70-
"/api/login": {
71-
"post": {
72-
"summary": ".api.login",
73-
"operationId": "Actions/LoginAction",
74-
"parameters": [],
75-
"responses": {
76-
"201": {
77-
"description": "Successful response",
78-
"content": {
79-
"application/json": {
80-
"schema": { "type": "object", "properties": {} }
81-
}
82-
}
83-
}
84-
}
85-
}
86-
},
87-
"/api/users": {
88-
"get": {
89-
"summary": ".api.users",
90-
"operationId": "storage/framework/actions/src/UserIndexOrmAction.ts",
1+
{"openapi":"3.0.0","info":{"title":"Generated API","version":"1.0.0"},"paths":{"/api/foo/bar/{id}":{"get":{"summary":".api.foo.bar.{id}","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api":{"get":{"summary":".api","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/hello/world":{"get":{"summary":".api.hello.world","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/email/subscribe":{"post":{"summary":".api.email.subscribe","operationId":"Actions/SubscriberEmailAction","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/login":{"post":{"summary":".api.login","operationId":"Actions/LoginAction","parameters":[],"responses":{"201":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/users":{"get":{"summary":".api.users","operationId":"storage/framework/actions/src/UserIndexOrmAction.ts","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/users/{id}":{"get":{"summary":".api.users.{id}","operationId":"storage/framework/actions/src/UserShowOrmAction.ts","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}},"delete":{"summary":".api.users.{id}","operationId":"storage/framework/actions/src/UserDestroyOrmAction.ts","parameters":[],"responses":{"204":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}},"/api/health":{"get":{"summary":".api.health","parameters":[],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"type":"object","properties":{}}}}}}}}},"components":{"schemas":{}}} "operationId": "storage/framework/actions/src/UserIndexOrmAction.ts",
912
"parameters": [],
923
"responses": {
934
"200": {

storage/framework/core/orm/src/utils.ts

Lines changed: 30 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ export async function writeModelRequest() {
393393
requestWrite.write(typeString)
394394
}
395395

396-
export async function writeOrmActions(apiRoute: string, modelName: String): Promise<void> {
396+
export async function writeOrmActions(apiRoute: string, modelName: String, actionPath?: string): Promise<void> {
397397
const formattedApiRoute = apiRoute.charAt(0).toUpperCase() + apiRoute.slice(1)
398398

399399
let method = 'GET'
@@ -466,7 +466,9 @@ export async function writeOrmActions(apiRoute: string, modelName: String): Prom
466466
})
467467
`
468468

469-
const actionFile = path.builtUserActionsPath(`src/${modelName}${formattedApiRoute}OrmAction.ts`)
469+
const actionName = actionPath || `${modelName}${formattedApiRoute}OrmAction.ts`
470+
471+
const actionFile = path.builtUserActionsPath(`src/${actionName}`)
470472

471473
if (fs.existsSync(actionFile)) return
472474

@@ -540,27 +542,6 @@ function parseRule(rule: string): FieldArrayElement | null {
540542
)
541543
}
542544

543-
export async function lookupFile(fileName: string): Promise<string | null> {
544-
const ormDirectory = path.builtUserActionsPath('src', { relative: true })
545-
const filePath = path.join(ormDirectory, fileName)
546-
const pathExists = fs.existsSync(filePath)
547-
548-
// Check if the directory exists
549-
if (pathExists) {
550-
return filePath
551-
}
552-
553-
const actionDirectory = path.userActionsPath()
554-
const actionFilePath = path.join(actionDirectory, fileName)
555-
const fileExists = fs.existsSync(actionFilePath)
556-
557-
if (fileExists) {
558-
return actionFilePath
559-
}
560-
561-
return null
562-
}
563-
564545
export async function generateApiRoutes(modelFiles: string[]) {
565546
const file = Bun.file(path.frameworkPath(`orm/routes.ts`))
566547
const writer = file.writer()
@@ -595,36 +576,45 @@ export async function generateApiRoutes(modelFiles: string[]) {
595576

596577
if (model.traits.useApi.routes && Object.keys(model.traits.useApi.routes).length > 0) {
597578
const apiRoutes = model.traits.useApi.routes
579+
598580
for (const apiRoute in apiRoutes) {
599581
if (Object.prototype.hasOwnProperty.call(apiRoutes, apiRoute)) {
600-
let path: string | null = ''
582+
const routePath = apiRoutes[apiRoute as keyof typeof apiRoutes]
601583

602-
await writeOrmActions(apiRoute as string, modelName)
584+
await writeOrmActions(apiRoute as string, modelName, routePath)
603585

604-
const routePath = apiRoutes[apiRoute as keyof typeof apiRoutes]
605586
if (typeof routePath !== 'string') {
606587
throw new Error(`Invalid route path for ${apiRoute}`)
607588
}
608589

609-
path = `${routePath}.ts`
610-
611-
if (!path.includes('/')) {
612-
path = await lookupFile(path)
613-
}
614-
615-
if (!path) {
616-
throw { message: 'Action Not Found!' }
617-
}
590+
const path = `${routePath}.ts`
618591

619-
if (apiRoute === 'index') routeString += `route.get('${uri}', '${path}')\n\n`
620-
if (apiRoute === 'show') routeString += `route.get('${uri}/{id}', '${path}')\n\n`
621-
if (apiRoute === 'store') routeString += `route.post('${uri}', '${path}')\n\n`
622-
if (apiRoute === 'update') routeString += `route.patch('${uri}/{id}', '${path}')\n\n`
623-
if (apiRoute === 'destroy') routeString += `route.delete('${uri}/{id}', '${path}')\n\n`
592+
if (apiRoute === 'index') routeString += `route.get('${uri}', '${path}').${middlewareString}\n\n`
593+
if (apiRoute === 'show') routeString += `route.get('${uri}/{id}', '${path}').${middlewareString}\n\n`
594+
if (apiRoute === 'store') routeString += `route.post('${uri}', '${path}').${middlewareString}\n\n`
595+
if (apiRoute === 'update') routeString += `route.patch('${uri}/{id}', '${path}').${middlewareString}\n\n`
596+
if (apiRoute === 'destroy')
597+
routeString += `route.delete('${uri}/{id}', '${path}').${middlewareString}\n\n`
624598
}
625599
}
626600
}
627601
}
602+
603+
if (typeof model.traits.useApi === 'boolean' && model.traits?.useApi) {
604+
const uri = tableName
605+
606+
const apiRoutes = ['index', 'show', 'store', 'update', 'destroy']
607+
608+
for (const apiRoute of apiRoutes) {
609+
await writeOrmActions(apiRoute as string, modelName)
610+
611+
if (apiRoute === 'index') routeString += `route.get('${uri}', '${path}').middleware(['Api'])\n\n`
612+
if (apiRoute === 'show') routeString += `route.get('${uri}/{id}', '${path}').middleware(['Api'])\n\n`
613+
if (apiRoute === 'store') routeString += `route.post('${uri}', '${path}').middleware(['Api'])\n\n`
614+
if (apiRoute === 'update') routeString += `route.patch('${uri}/{id}', '${path}').middleware(['Api'])\n\n`
615+
if (apiRoute === 'destroy') routeString += `route.delete('${uri}/{id}', '${path}').middleware(['Api'])\n\n`
616+
}
617+
}
628618
}
629619
}
630620

storage/framework/core/types/src/model.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export type AuthOptions = {
2323

2424
type ActionPath = string
2525
type ActionName = string
26-
type Action = ActionPath | ActionName
26+
type Action = ActionPath | ActionName | undefined
2727

2828
export type ApiRoutes = 'index' | 'show' | 'store' | 'update' | 'destroy'
2929

storage/framework/orm/routes.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11
import { route } from '@stacksjs/router'
22

3-
route.get('users', 'storage/framework/actions/src/UserIndexOrmAction.ts')
3+
route.get('users', '[object Object]').middleware(['Api'])
44

5-
route.get('users/{id}', 'storage/framework/actions/src/UserShowOrmAction.ts')
5+
route.get('users/{id}', '[object Object]').middleware(['Api'])
66

7-
route.delete('users/{id}', 'storage/framework/actions/src/UserDestroyOrmAction.ts')
7+
route.post('users', '[object Object]').middleware(['Api'])
8+
9+
route.patch('users/{id}', '[object Object]').middleware(['Api'])
10+
11+
route.delete('users/{id}', '[object Object]').middleware(['Api'])

0 commit comments

Comments
 (0)