aiplang 2.6.2 → 2.7.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.
- package/aiplang-knowledge.md +104 -63
- package/bin/aiplang.js +18 -1
- package/package.json +1 -1
- package/server/server.js +1 -1
package/aiplang-knowledge.md
CHANGED
|
@@ -1,98 +1,139 @@
|
|
|
1
|
-
# aiplang —
|
|
2
|
-
|
|
3
|
-
Generate ONLY aiplang code. No React, HTML, or other frameworks. No explanations unless asked.
|
|
1
|
+
# aiplang — LLM reference
|
|
2
|
+
Generate ONLY `.aip` syntax. Zero explanation. Zero React. Zero HTML frameworks.
|
|
4
3
|
|
|
5
|
-
##
|
|
4
|
+
## Config directives (before model/api/pages)
|
|
6
5
|
```
|
|
7
|
-
~env VAR required
|
|
8
|
-
~db sqlite ./app.db
|
|
6
|
+
~env VAR required # fail if missing
|
|
7
|
+
~db sqlite ./app.db # or: postgres $DATABASE_URL
|
|
9
8
|
~auth jwt $JWT_SECRET expire=7d
|
|
10
|
-
~mail smtp host=x user=$U pass=$P
|
|
11
|
-
~s3 $KEY secret=$S bucket=$B region=us-east-1 prefix=
|
|
9
|
+
~mail smtp host=x user=$U pass=$P from=no-reply@x.com
|
|
10
|
+
~s3 $KEY secret=$S bucket=$B region=us-east-1 prefix=up/ maxSize=10mb allow=image/jpeg,image/png
|
|
12
11
|
~stripe $KEY webhook=$WH success=/ok cancel=/pricing
|
|
13
12
|
~plan free=price_x pro=price_y
|
|
14
13
|
~admin /admin
|
|
15
14
|
~use cors origins=https://x.com
|
|
16
15
|
~use rate-limit max=100 window=60s
|
|
17
16
|
~use helmet | ~use logger | ~use compression
|
|
18
|
-
~plugin ./
|
|
17
|
+
~plugin ./plugins/custom.js
|
|
18
|
+
```
|
|
19
19
|
|
|
20
|
+
## Model
|
|
21
|
+
```
|
|
20
22
|
model Name {
|
|
21
|
-
id
|
|
22
|
-
field
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
id : uuid : pk auto
|
|
24
|
+
field : text : required
|
|
25
|
+
email : text : required unique
|
|
26
|
+
password : text : required hashed
|
|
27
|
+
count : int : default=0
|
|
28
|
+
price : float
|
|
29
|
+
active : bool : default=true
|
|
30
|
+
at : timestamp
|
|
31
|
+
data : json
|
|
32
|
+
kind : enum : a,b,c : default=a
|
|
33
|
+
~soft-delete # adds deleted_at, filters from queries
|
|
34
|
+
~belongs OtherModel # adds other_model_id FK
|
|
25
35
|
}
|
|
26
|
-
|
|
27
|
-
|
|
36
|
+
```
|
|
37
|
+
Types: `uuid text int float bool timestamp json enum`
|
|
38
|
+
Modifiers: `pk auto required unique hashed default=val index`
|
|
28
39
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
~
|
|
40
|
+
## API — ALWAYS one blank line between ops, return is last
|
|
41
|
+
```
|
|
42
|
+
api POST /path {
|
|
43
|
+
~guard auth # auth | admin | subscribed | owner
|
|
44
|
+
~validate field required | field email | field min=8 | field max=100 | field numeric | field in:a,b,c
|
|
33
45
|
~unique Model field $body.field | 409
|
|
34
|
-
~hash field
|
|
35
|
-
~check password $body.pw $user.pw | 401
|
|
46
|
+
~hash field # bcrypt the field before insert
|
|
47
|
+
~check password $body.pw $user.pw | 401 # bcrypt compare
|
|
48
|
+
~query page=1 limit=20 # query params with defaults
|
|
36
49
|
~mail $user.email "Subject" "Body"
|
|
37
50
|
~dispatch jobName $body
|
|
38
51
|
~emit event.name $body
|
|
39
|
-
$var = Model.findBy(field=$body.field)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return
|
|
46
|
-
return
|
|
52
|
+
$var = Model.findBy(field=$body.field) # assign to $var
|
|
53
|
+
$var = Model.find($params.id)
|
|
54
|
+
insert Model($body) # sets $inserted
|
|
55
|
+
update Model($params.id, $body) # sets $updated
|
|
56
|
+
delete Model($params.id) # soft or hard delete
|
|
57
|
+
restore Model($params.id)
|
|
58
|
+
return $inserted 201 # status optional, default 200
|
|
59
|
+
return $updated
|
|
60
|
+
return $var
|
|
61
|
+
return $auth.user
|
|
62
|
+
return jwt($inserted) 201 # return JWT token
|
|
47
63
|
return jwt($user) 200
|
|
64
|
+
return Model.all(order=created_at desc)
|
|
65
|
+
return Model.paginate($page, $limit)
|
|
66
|
+
return Model.count()
|
|
67
|
+
return Model.sum(field)
|
|
68
|
+
return Model.findBy(field=$body.field)
|
|
48
69
|
}
|
|
70
|
+
```
|
|
49
71
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
~
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
72
|
+
## Pages
|
|
73
|
+
```
|
|
74
|
+
%id theme /route # id=any, theme=dark|light|acid|#bg,#text,#accent, route=/path
|
|
75
|
+
~theme accent=#hex bg=#hex text=#hex font=Name radius=1rem surface=#hex navbg=#hex spacing=5rem
|
|
76
|
+
@list = [] # reactive state — [] for arrays, {} for objects, "str", 0
|
|
77
|
+
@obj = {}
|
|
78
|
+
~mount GET /api/path => @list # fetch on page load → assign to @list
|
|
79
|
+
~mount GET /api/path => @obj
|
|
80
|
+
~interval 15000 GET /api/path => @obj # repeat every N ms (always pair with ~mount)
|
|
58
81
|
```
|
|
59
82
|
|
|
60
83
|
## All blocks
|
|
61
84
|
```
|
|
62
85
|
nav{Brand>/path:Link>/path:Link}
|
|
63
|
-
hero{Title|
|
|
64
|
-
|
|
86
|
+
hero{Title|Subtitle>/path:CTA}
|
|
87
|
+
hero{Title|Sub>/path:CTA|img:https://url} # split layout with image
|
|
88
|
+
stats{@obj.field:Label|99%:Uptime|$0:Free}
|
|
65
89
|
row2{icon>Title>Body} | row3{...} | row4{...}
|
|
66
90
|
sect{Title|Optional body}
|
|
67
|
-
table @list { Col:field | edit PUT /api/{id} | delete /api/{id} | empty: msg }
|
|
68
|
-
form POST /api => @list.push($result) { Label:type:placeholder | Label:select:a,b,c }
|
|
69
|
-
form POST /api => redirect /
|
|
70
|
-
pricing{Name>
|
|
71
|
-
faq{Question?>Answer
|
|
72
|
-
testimonial{Name, Role
|
|
73
|
-
gallery{https://img1|https://img2|https://img3}
|
|
74
|
-
btn{Label > METHOD /api/path}
|
|
91
|
+
table @list { Col:field | Col:field | edit PUT /api/path/{id} | delete /api/path/{id} | empty: msg }
|
|
92
|
+
form POST /api/path => @list.push($result) { Label:type:placeholder | Label:select:a,b,c }
|
|
93
|
+
form POST /api/path => redirect /dashboard { Label:type | Label:password }
|
|
94
|
+
pricing{Name>$0/mo>Desc>/path:CTA | Name>$19/mo>Desc>/path:CTA}
|
|
95
|
+
faq{Question?>Answer. | Q2?>A2.}
|
|
96
|
+
testimonial{Name, Role|"Quote."|img:https://url}
|
|
97
|
+
gallery{https://img1 | https://img2 | https://img3}
|
|
98
|
+
btn{Label > METHOD /api/path}
|
|
99
|
+
btn{Label > DELETE /api/path > confirm:Are you sure?}
|
|
75
100
|
select @filterVar { All | Active | Inactive }
|
|
76
101
|
if @var { blocks }
|
|
77
|
-
raw{<div>any HTML</div>}
|
|
102
|
+
raw{<div>any HTML or embed</div>}
|
|
78
103
|
foot{© 2025 Name>/path:Link}
|
|
79
104
|
```
|
|
80
105
|
|
|
81
|
-
##
|
|
82
|
-
`animate:fade-up
|
|
83
|
-
`class:my-class`
|
|
106
|
+
## Animate any block
|
|
107
|
+
`block{...} animate:fade-up` · `animate:fade-in` · `animate:blur-in` · `animate:stagger` · `animate:slide-left` · `animate:zoom-in`
|
|
84
108
|
|
|
85
|
-
##
|
|
86
|
-
|
|
109
|
+
## Multiple pages — separate with ---
|
|
110
|
+
```
|
|
111
|
+
%home dark /
|
|
112
|
+
nav{...}
|
|
113
|
+
hero{...}
|
|
114
|
+
---
|
|
115
|
+
%dashboard dark /dashboard
|
|
116
|
+
@data = []
|
|
117
|
+
~mount GET /api/data => @data
|
|
118
|
+
table @data { ... }
|
|
119
|
+
---
|
|
120
|
+
%login dark /login
|
|
121
|
+
form POST /api/auth/login => redirect /dashboard { Email:email | Password:password }
|
|
122
|
+
```
|
|
87
123
|
|
|
88
|
-
##
|
|
89
|
-
`
|
|
124
|
+
## Icons (use in row blocks)
|
|
125
|
+
`rocket bolt shield chart star check globe gear fire money bell mail user lock eye tag search home`
|
|
90
126
|
|
|
91
|
-
##
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
127
|
+
## S3 auto-routes (generated when ~s3 configured)
|
|
128
|
+
`POST /api/upload` · `DELETE /api/upload/:key` · `GET /api/upload/presign?key=x&expires=3600`
|
|
129
|
+
|
|
130
|
+
## Stripe auto-routes (generated when ~stripe configured)
|
|
131
|
+
`POST /api/stripe/checkout {plan,email}` · `POST /api/stripe/portal` · `GET /api/stripe/subscription` · `POST /api/stripe/webhook`
|
|
132
|
+
Webhooks auto-handled: checkout.completed → sets user.plan, subscription.deleted → resets to free
|
|
133
|
+
|
|
134
|
+
## Run
|
|
135
|
+
```bash
|
|
136
|
+
npx aiplang start app.aip # full-stack
|
|
137
|
+
npx aiplang serve # frontend dev
|
|
138
|
+
npx aiplang build pages/ # static build
|
|
139
|
+
```
|
package/bin/aiplang.js
CHANGED
|
@@ -5,7 +5,7 @@ const fs = require('fs')
|
|
|
5
5
|
const path = require('path')
|
|
6
6
|
const http = require('http')
|
|
7
7
|
|
|
8
|
-
const VERSION = '2.
|
|
8
|
+
const VERSION = '2.7.0'
|
|
9
9
|
const RUNTIME_DIR = path.join(__dirname, '..', 'runtime')
|
|
10
10
|
const cmd = process.argv[2]
|
|
11
11
|
const args = process.argv.slice(3)
|
|
@@ -121,6 +121,23 @@ api GET /api/me {
|
|
|
121
121
|
return $auth.user
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
api GET /api/users {
|
|
125
|
+
~guard admin
|
|
126
|
+
~query page=1
|
|
127
|
+
return User.paginate($page, 20)
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
api PUT /api/users/:id {
|
|
131
|
+
~guard admin
|
|
132
|
+
update User($id, $body)
|
|
133
|
+
return $updated
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
api DELETE /api/users/:id {
|
|
137
|
+
~guard admin
|
|
138
|
+
delete User($id)
|
|
139
|
+
}
|
|
140
|
+
|
|
124
141
|
api GET /api/stats {
|
|
125
142
|
return User.count()
|
|
126
143
|
}
|
package/package.json
CHANGED
package/server/server.js
CHANGED
|
@@ -1435,7 +1435,7 @@ async function startServer(aipFile, port = 3000) {
|
|
|
1435
1435
|
|
|
1436
1436
|
// Health
|
|
1437
1437
|
srv.addRoute('GET', '/health', (req, res) => res.json(200, {
|
|
1438
|
-
status:'ok', version:'2.
|
|
1438
|
+
status:'ok', version:'2.7.0',
|
|
1439
1439
|
models: app.models.map(m=>m.name),
|
|
1440
1440
|
routes: app.apis.length, pages: app.pages.length,
|
|
1441
1441
|
admin: app.admin?.prefix || null,
|