1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 | 'use strict'
|
37 |
|
38 | const route = require('apeman-app-route')
|
39 | const restSpec = require('./specifying/rest_spec')
|
40 | const assert = require('assert')
|
41 | const co = require('co')
|
42 |
|
43 | const apemanmodel = require('apemanmodel')
|
44 | const restRoute = require('./routing/rest_route')
|
45 |
|
46 | const {
|
47 | CreateEndpoint,
|
48 | DestroyEndpoint,
|
49 | Endpoint,
|
50 | ListEndpoint,
|
51 | OneEndpoint,
|
52 | RelatedCreateEndpoint,
|
53 | RelatedDestroyEndpoint,
|
54 | RelatedListEndpoint,
|
55 | RelatedOneEndpoint,
|
56 | RelatedUpdateEndpoint,
|
57 | RelationCreateEndpoint,
|
58 | RelationDestroyEndpoint,
|
59 | RelationListEndpoint,
|
60 | RelationUpdateEndpoint,
|
61 | UpdateEndpoint,
|
62 | SpecEndpoint
|
63 | } = require('./endpoints')
|
64 |
|
65 | const {
|
66 | BulkCreateEndpoint,
|
67 | BulkDestroyEndpoint,
|
68 | BulkRelatedCreateEndpoint,
|
69 | BulkRelatedDestroyEndpoint,
|
70 | BulkRelatedUpdateEndpoint,
|
71 | BulkRelationCreateEndpoint,
|
72 | BulkRelationDestroyEndpoint,
|
73 | BulkUpdateEndpoint
|
74 | } = require('./endpoints/bulk')
|
75 |
|
76 | const debug = require('debug')('apeman:app:rest')
|
77 |
|
78 |
|
79 | function create (model, options = {}) {
|
80 | assert.ok(model, 'model is required.')
|
81 | debug(`Register rest for model: ${model}`)
|
82 |
|
83 | let type = apemanmodel.toType(model)
|
84 |
|
85 | let pathname = String(options.pathname || `/${type}`).replace(/\/$/, '')
|
86 |
|
87 | let { associations } = model
|
88 | let {
|
89 | knock,
|
90 | spec,
|
91 | list,
|
92 | create,
|
93 | bulkUpdate,
|
94 | bulkDestroy,
|
95 | one,
|
96 | update,
|
97 | destroy,
|
98 | relatedList,
|
99 | relatedCreate,
|
100 | relatedUpdateBulk,
|
101 | relatedDestroyBulk,
|
102 | relatedOne,
|
103 | relatedUpdate,
|
104 | relatedDestroy,
|
105 | relationList,
|
106 | relationCreate,
|
107 | relationUpdate,
|
108 | relationDestroy
|
109 | } = options
|
110 |
|
111 | let rest = restRoute.bind(restRoute, model)
|
112 |
|
113 | let routes = {
|
114 | [`${pathname || '/'}`]: {
|
115 | 'HEAD': rest('knock', knock, true),
|
116 | 'OPTIONS': rest('spec', spec, new SpecEndpoint({pathname})),
|
117 | 'GET': rest('list', list, new ListEndpoint({}), {}),
|
118 | 'POST': rest('create', create, new CreateEndpoint({})),
|
119 | 'PATCH': rest('bulkUpdate', bulkUpdate, new BulkUpdateEndpoint({})),
|
120 | 'DELETE': rest('bulkDestroy', bulkDestroy, new BulkDestroyEndpoint({}))
|
121 | },
|
122 | [`${pathname}/:id`]: {
|
123 | 'GET': rest('one', one, new OneEndpoint({})),
|
124 | 'PATCH': rest('update', update, new UpdateEndpoint({})),
|
125 | 'DELETE': rest('destroy', destroy, new DestroyEndpoint({}))
|
126 | }
|
127 | }
|
128 |
|
129 | for (let name of Object.keys(associations || {})) {
|
130 | let association = associations[ name ]
|
131 |
|
132 | let associate = co.wrap(function * associate (ctx, next) {
|
133 | ctx.state.association = association
|
134 | yield next()
|
135 | })
|
136 |
|
137 | routes[ `${pathname}/:id/${name}` ] = {
|
138 | 'GET': [
|
139 | associate,
|
140 | ...rest('relatedList', relatedList, new RelatedListEndpoint({}))
|
141 | ],
|
142 | 'POST': [
|
143 | associate,
|
144 | ...rest('relatedCreate', relatedCreate, new RelatedCreateEndpoint({}))
|
145 | ],
|
146 | 'PATCH': [
|
147 | associate,
|
148 | ...rest('relatedUpdateBulk', relatedUpdateBulk, new BulkRelatedUpdateEndpoint({})),
|
149 | ],
|
150 | 'DELETE': [
|
151 | associate,
|
152 | ...rest('relatedDestroyBulk', relatedDestroyBulk, new BulkRelatedDestroyEndpoint({}))
|
153 | ]
|
154 | }
|
155 |
|
156 | routes[ `${pathname}/:id/${name}/:related_id` ] = {
|
157 | 'GET': [
|
158 | associate,
|
159 | ...rest('relatedOne', relatedOne, new RelatedOneEndpoint({}))
|
160 | ],
|
161 | 'PATCH': [
|
162 | associate,
|
163 | ...rest('relatedUpdate', relatedUpdate, new RelatedUpdateEndpoint({}))
|
164 | ],
|
165 | 'DELETE': [
|
166 | associate,
|
167 | ...rest('relatedDestroy', relatedDestroy, new RelatedDestroyEndpoint({}))
|
168 | ]
|
169 | }
|
170 |
|
171 | routes[ `${pathname}/:id/relationships/${name}` ] = {
|
172 | 'GET': [
|
173 | associate,
|
174 | ...rest('relationList', relationList, new RelationListEndpoint({}))
|
175 | ],
|
176 | 'POST': [
|
177 | associate,
|
178 | ...rest('relationCreate', relationCreate, new RelationCreateEndpoint({}))
|
179 | ],
|
180 | 'PATCH': [
|
181 | associate,
|
182 | ...rest('relationUpdate', relationUpdate, new RelationUpdateEndpoint({}))
|
183 | ],
|
184 | 'DELETE': [
|
185 | associate,
|
186 | ...rest('relationDestroy', relationDestroy, new RelationDestroyEndpoint({}))
|
187 | ]
|
188 | }
|
189 | }
|
190 |
|
191 | let app = route(routes)
|
192 |
|
193 | Object.assign(app, {
|
194 | |
195 |
|
196 |
|
197 | $desc: 'Restful endpoint.',
|
198 | |
199 |
|
200 |
|
201 | $spec: restSpec(model, { pathname })
|
202 |
|
203 | })
|
204 | return app
|
205 | }
|
206 |
|
207 | module.exports = create
|