Skip to content

Commit ae1ab04

Browse files
authored
Merge pull request #13 from duangsuse/add-controller-template
Add controller template (with <3 generated by GeekSpec)
2 parents 40cc284 + d57aa37 commit ae1ab04

19 files changed

+3040
-31
lines changed

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,9 @@
2424
/dist/
2525
/nbdist/
2626
/.nb-gradle/
27+
28+
### Haskell ###
29+
*.hi
30+
*.o
31+
32+
GeekCoder

GeekCoder.hs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module Main where
2+
3+
{- GeekSpec API Interface code generator for Spring/Kotlin -}
4+
5+
main = putStrLn "GeekCoder"
6+

README.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
# Spring GeekApk Server [![code size](https://img.shields.io/github/languages/code-size/duangsuse/GeekApk.svg?style=flat-square)](https://github.com/duangsuse/GeekApk/pulse) [![agpl-3.0](https://img.shields.io/github/license/duangsuse/GeekApk.svg?style=flat-square)](https://www.gnu.org/licenses/agpl-3.0.html)
22

3-
<p align="center"><img width="40%" src="https://user-images.githubusercontent.com/10570123/52161551-8321ed00-2701-11e9-963b-18e5791d553c.png" alt="Cup - The Mascot for GeekApk" /></p>
3+
<p align="center">
4+
<img width="40%" src="https://user-images.githubusercontent.com/10570123/52161551-8321ed00-2701-11e9-963b-18e5791d553c.png" alt="Cup - The Mascot for GeekApk" /><br>
5+
<i><sub>(illustration by duangsuse)</sub></i>
6+
</p>
47

58
> The way to get started is to quit talking and begin doing.
69
_— Walt Disney_

code_writer.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
const parser = require('./geekspec_parser');
2+
const fs = require('fs');
3+
4+
var code = fs.readFileSync('./geekapk_v1b_api.geekspec').toString();
5+
6+
code = code.replace(/#.*/g, '');
7+
8+
console.log(code);
9+
10+
console.log("\n\n\n")
11+
12+
let ast = parser.parse(code);
13+
14+
console.log(JSON.stringify(ast, null, 2));
15+
16+
function walkOption(o) {
17+
return o;
18+
}
19+
20+
function walkOptions(os) {
21+
if (os == null) return "";
22+
return "{" + os.map(walkOption).join(",") + "}";
23+
}
24+
25+
function walkArg(a) {
26+
return `${a.name}${a.required ? '!' : '?'}${walkOptions(a.options)}`;
27+
}
28+
29+
function walkArgs(as) {
30+
return as.map(walkArg)
31+
}
32+
33+
function walkReturn(r) {
34+
if (r == null) return "noting";
35+
if (typeof r != 'object') return r;
36+
if (Array.isArray(r)) {
37+
return r.map(e => `${e.type}:${e.name}`)
38+
}
39+
return `${r.type} of ${r.of}`;
40+
}
41+
42+
43+
function walkInterface(i) {
44+
console.log()
45+
console.log(`${i.method} ${i.url}: \t ${i.name}(${walkArgs(i.args)})`);
46+
console.log(` Returning ${walkReturn(i.return)}`)
47+
}
48+
49+
50+
ast.forEach(walkInterface);

geekapk_v1b_api.geekspec

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
# All APIs for GeekApk v1.0b except apiHint
2+
# author duangsuse
3+
# version 1.0b
4+
# spec JsonRpc
5+
# GeekSpec DSL definition: https://github.com/duangsuse/GeekApk/blob/add-controller-template/geekspec_dsl_parser.pegjs
6+
7+
#@ Auth user scheme(Token, Cookie): uid=gaUser tok=gaHash
8+
#@ Auth serverAdmin scheme(Token, Cookie): uid=gaUser tok=gaHash admin_tok=gaModTok
9+
10+
## Server Info API section
11+
12+
serverVersion() -> plain
13+
= /serverVersion
14+
15+
serverDescription() -> plain
16+
= /serverDescription
17+
18+
serverBoot() -> datetime
19+
= /serverBoot
20+
21+
serverDetail() -> object:string
22+
= /serverDetail
23+
24+
25+
## Server ADMIN api section
26+
## All ADMIN apis except deleteApp, transferAppCategory, deleteComment, flagUser should have serverAdmin permission
27+
28+
POST@createUser(username:String) -> object:GeekUser
29+
= /admin/makeUser
30+
31+
PUT@resetSharedHash(uid-path:UserId, shash:String?) -> plain
32+
= /admin/resetMetaHash/{uid}
33+
34+
DELETE@deleteUser(uid-path:UserId) -> object:GeekUser
35+
= /admin/dropUser/{uid}
36+
37+
#### Requires superuser session
38+
PUT@flagUser(uid-path:UserId, flag:Int) -> object:GeekUser
39+
= /admin/flagUser/{uid}
40+
41+
POST@createCategory(name:String) -> object:Category
42+
= /admin/makeCategory
43+
44+
PUT@renameCategory(id-path:CategoryId, name:String) -> object:Category
45+
= /admin/nameCategory/{id}
46+
47+
DELETE@deleteCategory(id-path:CategoryId) -> object:Category
48+
= /admin/dropCategory/{id}
49+
50+
#### Requires superuser session
51+
DELETE@deleteApp(aid-path:AppId) -> object:App
52+
= /admin/dropApp/{aid}
53+
54+
#### Requires superuser session
55+
PUT@transferAppCategory(aid-path:AppId, cid:CategoryId) -> [$aid:number, $old:number, $new:number]
56+
= /admin/moveApp/{aid}
57+
58+
PUT@transferAppOwner(aid-path:AppId, uid:UserId) -> [$aid:number, $old:number, $new:number]
59+
= /admin/transferApp/{aid}
60+
61+
DELETE@deleteAppUpdate(aid-path:AppId, rev-path:Int) -> object:AppUpdate
62+
= /admin/dropAppUpdate/{aid}/{rev}
63+
64+
#### Requires superuser session
65+
DELETE@deleteComment(cid-path:CommentId) -> [$cid:number, $deletedSubComments:number]
66+
= /admin/dropComment/{cid}
67+
68+
69+
70+
## GeekApk Categories section
71+
72+
categoryList() -> array:Category
73+
= category/all
74+
75+
categoryName(id-path:CategoryId) -> plain
76+
= category/{id}
77+
78+
79+
80+
## GeekApk Users section
81+
82+
readUser(id-path:UserId) -> object:GeekUser
83+
= user/{id}
84+
85+
86+
### Requires user permission
87+
PUT@updateUser(id-path:UserId, prop:String{username, nickname, avatar, bio, metaApp}, value-body:String)
88+
-> [$user:number, $prop:string, $old:string, $new:string]
89+
= user/{id}
90+
91+
PUT@resetHash(id-path:UserId, shash:String, hash:String)
92+
-> [$id:number, $newShash:string, $newHash:string]
93+
= user/{id}/hash
94+
95+
checkHash(id-path:UserId, hash:String)
96+
-> [$valid:boolean, $message:string]
97+
= user/{id}/checkHash
98+
99+
listUser(sort:String?{created, followers}, sliceFrom:UserSize?, sliceTo:UserSize?) -> array:GeekUser
100+
= user/all
101+
102+
listMetaUser(sort:String?{created, followers}, sliceFrom:UserSize?, sliceTo:UserSize?) -> array:GeekUser
103+
= user/allHasMetaApp
104+
105+
searchUser(type:String?{username, nickname, bio}, kw-path:String, sort:String?{created, followers}) -> array:GeekUser
106+
= user/search/{kw}
107+
108+
PUT@updateOnlineTime(id-path:UserId)
109+
= user/{id}/online
110+
111+
## GeekApk Timeline section
112+
113+
readUserTimeline(uid-path:UserId, type:Int?, sliceFrom:TimelineSize?, sliceTo:TimelineSize?) -> array:Timeline
114+
= /timeline/{uid}
115+
116+
readAllTimeline(type:Int?, sliceFrom:TimelineSize?, sliceTo:TimelineSize?) -> array:Timeline
117+
= /timeline/all
118+
119+
bulkReadUserTimeline(uids-path:String, type:Int?, sliceFrom:TimelineSize?, sliceTo:TimelineSize?) -> array:Timeline
120+
= /timeline/bulk/{uids}
121+
122+
getUserTimelineCount(uid-path:UserId) -> number
123+
= /timeline/check/{uid}
124+
125+
getBulkUserTimelineCount(uids-path:String) -> number
126+
= /timeline/check/{uids}
127+
128+
## GeekApk notifications section
129+
### All interface access requires user(owner) permission
130+
131+
readMineNotifications() -> array:Notification
132+
= /notification/active
133+
134+
readAllMineNotifications(sliceFrom:NotificationSize?, sliceTo:NotificationSize?) -> array:Notification
135+
= /notification/all
136+
137+
markNotifications(start:NotificationSize, end:NotificationSize?, stat:String{active, inactive}) -> number
138+
= /notification/mark
139+
140+
getNotificationCount() -> number
141+
= /notification/count
142+
143+
## GeekApk Apps section
144+
### All non-GET interface access requires (readwrite) user(owner) permission
145+
146+
readApp(aid-path:AppId) -> object:App
147+
= /app/{aid}
148+
149+
PUT@updateApp(aid-path:AppId, attr:String{package, icon, name, screenshots, readme}, val-body:String)
150+
-> [$attr:String, $oldVal:String]
151+
= /app/{aid}
152+
153+
POST@createApp(package:String, category:CategoryId) -> object:App
154+
= /app
155+
156+
findAppWithPackageName(package-path:String) -> object:App
157+
= /app/package/{package}
158+
159+
listApp(inCategory:CategoryId?, sort:String?{updated, comments, stars, created}, sliceFrom:AppSize?, sliceTo:AppSize?)
160+
-> array:App = /app/all
161+
162+
DELETE@dropApp(aid-path:AppId) -> object:App
163+
= /app/{aid}
164+
165+
searchApp(inCategory:CategoryId?, content-path:String, type:String{name, package, icon, readme}, sort:String?{updated, comments, stars, created})
166+
= /app/search/{content}
167+
168+
### GeekApk app collaborators
169+
POST@addCollab(uid:UserId, aid-path:AppId)
170+
= /app/{aid}/collab
171+
172+
DELETE@removeCollab(uid:UserId, aid-path:AppId)
173+
= /app/{aid}/collab
174+
175+
collaborators(aid-path:AppId) -> array:number
176+
= /app/collaborators/{aid}
177+
178+
collaborated(uid-path:UserId) -> array:number
179+
= /app/collaborated/{uid}
180+
181+
182+
## GeekApk Application updates
183+
### All non-GET interface access requires (readwrite) user(owner) permission
184+
185+
readReversions(aid-path:AppId) -> array:AppUpdate
186+
= /appUpdate/{aid}
187+
188+
checkLastReversions(aids-path:String) -> array:number
189+
= /appUpdate/check/{aids}
190+
191+
readReversion(aid-path:AppId, rev-path:Int) -> object:AppUpdate
192+
= /appUpdate/{aid}/{rev}
193+
194+
POST@createReversion(aid-path:AppId, rev-path:Int) -> [$aid:number, $rev:number]
195+
= /appUpdate/{aid}/{rev}
196+
197+
PUT@updateReversion(aid-path:AppId, rev-path:Int, attr:String{version, install, updates, minsdk}, val-body:String) -> [$attr:string, $oldVal:string]
198+
= /appUpdate/{aid}/{rev}
199+
200+
DELETE@dropReversion(aid-path:AppId, rev-path:Int) -> object:AppUpdate
201+
= /appUpdate/{aid}/{rev}
202+
203+
## GeekApk comments
204+
### All non-GET interface access requires (readwrite) user(owner) permission
205+
206+
searchComment(inApp:AppId?, user:UserId?, repliesTo:CommentId?, content-path:String) -> array:Comment
207+
= /comment/search/{content}
208+
209+
listCommentInApp(aid-path:AppId, sliceFrom:CommentSize?, sliceTo:CommentSize?) -> array:Comment
210+
= /comment/{aid}
211+
212+
listSubComment(cid-path:CommentId) -> array:Comment
213+
= /comment/subOf/{cid}
214+
215+
listAllComment(inApp:AppId?, user:UserId?, sliceFrom:CommentSize?, sliceTo:CommentSize?) -> array:Comment
216+
= /comment/all
217+
218+
POST@createComment(aid-path:AppId, content:String) -> object:Comment
219+
= /comment/{aid}
220+
221+
PUT@editComment(cid-path:CommentId) -> [$oldContent:string, $newContent:string]
222+
= /comment/edit/{cid}
223+
224+
DELETE@deleteComment(cid-path:CommentId) -> object:Comment
225+
= /comment/delete/{cid}
226+
227+
## GeekApk App Star and Follow
228+
### All non-GET interface access requires (non-banned) user(possibly owner) permission
229+
230+
### Star (User -* App)
231+
232+
POST@follow(uid-path:UserId) -> [$oldCount:number, $newCount:number]
233+
= /follow/{uid}
234+
235+
DELETE@unfollow(uid-path:UserId) -> [$oldCount:number, $newCount:number]
236+
= /follow/{uid}
237+
238+
followers(uid-path:UserId) -> array:GeekUser
239+
= /follow/followers/{uid}
240+
241+
following(uid-path:UserId) -> array:GeekUser
242+
= /follow/{uid}
243+
244+
### Follow (User -> User)
245+
246+
POST@star(aid-path:AppId) -> [$oldCount:number, $newCount:number]
247+
= /star/{aid}
248+
249+
DELETE@unStar(aid-path:AppId) -> [$oldCount:number, $newCount:number]
250+
= /star/{aid}
251+
252+
stargazers(aid-path:AppId) -> array:App
253+
= /star/{aid}
254+
255+
stars(uid-path:UserId) -> array:App
256+
= /star/user/{uid}

geekspec_dsl_parser.pegjs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@
44
let head = xs => xs[0]
55
}
66

7-
GeekSpec = specs:(_ ApiSpec _)* { return specs.map(x => head(filterIsNotArray(x))); }
7+
GeekSpec = specs:(__ ApiSpec __)* { return specs.map(x => head(filterIsNotArray(x))); }
8+
9+
SingleLineComment
10+
= "#" !lineTerminator .*
811

912
entityName = letter+
1013
interfaceName = letter+
1114
urlPath "url letters" = (letter / [:/.{}?&=%])+
1215
argName = letter+
1316
possibleValue = letter+
14-
fieldName = letter+
17+
fieldName = simpleletter+
1518

1619
httpMethod
1720
= "GET" / "POST"
@@ -37,7 +40,7 @@ ApiSpec =
3740
method: method,
3841
name: name.join(''),
3942
args: a == null ? [] : [a].concat(as.map(ra => ra[3])),
40-
return : isNotUndef(typeof rtxd) ? rtxd[2] : null,
43+
return : isNotUndef(typeof rtxd) ? (rtxd == null ? null : rtxd[2]) : null,
4144
url: url.join('')
4245
};
4346
}
@@ -56,6 +59,7 @@ OptionVals = '{' _ pv:possibleValue? pvs:(_ ',' _ possibleValue)* _ '}' {
5659

5760
ReturnType
5861
= axo:("array" / "object") ':' a:Atom { return { type: axo, of: ((typeof a != 'string') ? a.join('') : a) }; }
62+
/ a:Atom { return ((typeof a != 'string') ? a.join('') : a); }
5963

6064
Atom = "boolean" / "number"
6165
/ "string" / "datetime"
@@ -66,13 +70,22 @@ Dict = '[' _ di:DictItem? dis:(_ ',' _ DictItem)* _ ']' {
6670
}
6771

6872
DictItem
69-
= ReturnType
73+
= !'$' rt:ReturnType { return { type: rt }; }
7074
/ '$' name:fieldName ':' rt:ReturnType {
7175
return { name: name.join(''), type: rt };
7276
}
7377

7478
_ "whitespace"
7579
= [ \t\n\r]*
7680

81+
__ "comment or whitespace"
82+
= SingleLineComment / _
83+
7784
letter "letter"
85+
= [A-Za-z0-9_\-:]
86+
87+
simpleletter "simple letter"
7888
= [A-Za-z0-9_\-]
89+
90+
lineTerminator
91+
= [\n\r\u2028\u2029]

0 commit comments

Comments
 (0)