@steedos/service-rest 2.5.3-beta.19

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/README.md ADDED
@@ -0,0 +1,6 @@
1
+
2
+ # Actions
3
+
4
+ ## find
5
+
6
+ ## ...
package/consts.js ADDED
@@ -0,0 +1,10 @@
1
+ /*
2
+ * @Author: sunhaolin@hotoa.com
3
+ * @Date: 2023-06-12 17:20:40
4
+ * @LastEditors: sunhaolin@hotoa.com
5
+ * @LastEditTime: 2023-06-12 17:21:09
6
+ * @Description:
7
+ */
8
+ module.exports = {
9
+ QUERY_DOCS_TOP: 5000,
10
+ }
package/package.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "@steedos/service-rest",
3
+ "version": "2.5.3-beta.19",
4
+ "main": "package.service.js",
5
+ "private": false,
6
+ "publishConfig": {
7
+ "access": "public"
8
+ },
9
+ "keywords": [
10
+ "steedos"
11
+ ],
12
+ "scripts": {},
13
+ "description": "steedos package",
14
+ "repository": {},
15
+ "license": "MIT",
16
+ "dependencies": {
17
+ "@steedos/objectql": "2.5.3-beta.19",
18
+ "@steedos/service-object-mixin": "2.5.3-beta.19",
19
+ "lodash": "^4.17.21"
20
+ }
21
+ }
@@ -0,0 +1,417 @@
1
+ /*
2
+ * @Author: sunhaolin@hotoa.com
3
+ * @Date: 2023-03-23 15:12:14
4
+ * @LastEditors: sunhaolin@hotoa.com
5
+ * @LastEditTime: 2023-06-15 13:50:16
6
+ * @Description:
7
+ */
8
+ "use strict";
9
+ // @ts-check
10
+ const serviceObjectMixin = require('@steedos/service-object-mixin');
11
+ const { QUERY_DOCS_TOP } = require('./consts')
12
+ const _ = require('lodash')
13
+ const { getObject } = require('@steedos/objectql');
14
+
15
+ /**
16
+ * @typedef {import('moleculer').Context} Context Moleculer's Context
17
+ */
18
+ module.exports = {
19
+ name: 'rest',
20
+ namespace: "steedos",
21
+ mixins: [serviceObjectMixin],
22
+
23
+ /**
24
+ * Settings
25
+ */
26
+ settings: {
27
+ // Base path
28
+ rest: "/rest",
29
+ },
30
+
31
+ /**
32
+ * Dependencies
33
+ */
34
+ dependencies: [],
35
+
36
+ /**
37
+ * Actions
38
+ */
39
+ actions: {
40
+ health: {
41
+ rest: {
42
+ method: "GET",
43
+ path: "/health"
44
+ },
45
+ async handler(ctx) {
46
+ return 'ok'
47
+ }
48
+ },
49
+ /**
50
+ * @api {POST} /api/v1/rest/:objectName/listRecords 获取列表
51
+ * @apiVersion 0.0.0
52
+ * @apiName find
53
+ * @apiGroup @steedos/service-rest
54
+ * @apiParam {String} objectName 对象API Name,如:contracts
55
+ * @apiBody {String[]} [fields] 字段名,如:["name", "description"]
56
+ * @apiBody {Object[]} [filters] 过滤条件,如:[['name', '=', 'test'],['amount', '>', 100]]
57
+ * @apiBody {Number} [top] 获取条数,如:10,最多5000
58
+ * @apiBody {Number} [skip] 跳过条数,如:10
59
+ * @apiBody {String} [sort] 排序,如:'name desc'
60
+ * @apiSuccess {Object[]} listRecords 记录列表
61
+ * @apiSuccessExample {json} Success-Response:
62
+ * HTTP/1.1 200 OK
63
+ * {
64
+ * records: [{
65
+ * "_id": "5e7d1b9b9c9d4400001d1b9b",
66
+ * "name": "test",
67
+ * ...
68
+ * }]
69
+ * }
70
+ * @apiErrorExample {json} Error-Response:
71
+ * HTTP/1.1 404 Error
72
+ * {
73
+ * "error": "Service 'rest.contracts' is not found.",
74
+ * "detail": {
75
+ * "code": "404",
76
+ * "type": "SERVICE_NOT_FOUND",
77
+ * "data": {
78
+ * "action": "rest.contracts"
79
+ * }
80
+ * }
81
+ * }
82
+ */
83
+ find: {
84
+ rest: {
85
+ method: "POST",
86
+ path: "/:objectName/listRecords"
87
+ },
88
+ params: {
89
+ objectName: { type: "string" },
90
+ fields: { type: 'array', items: "string", optional: true },
91
+ filters: [{ type: 'array', optional: true }, { type: 'string', optional: true }],
92
+ top: { type: 'number', optional: true },
93
+ skip: { type: 'number', optional: true },
94
+ sort: { type: 'string', optional: true }
95
+ },
96
+ async handler(ctx) {
97
+ const params = ctx.params
98
+ const { objectName } = params
99
+ const userSession = ctx.meta.user;
100
+
101
+ if (_.has(params, "top")) { // 如果top小于1,不返回数据
102
+ if (params.top < 1) {
103
+ return []
104
+ }
105
+ if (params.top > QUERY_DOCS_TOP) {
106
+ params.top = QUERY_DOCS_TOP // 最多返回5000条数据
107
+ }
108
+ }
109
+
110
+ const query = {}
111
+ if (_.has(params, "filters")) {
112
+ query.filters = params.filters
113
+ }
114
+ if (_.has(params, "fields")) {
115
+ query.fields = params.fields
116
+ }
117
+ if (_.has(params, "top")) {
118
+ query.top = params.top
119
+ }
120
+ if (_.has(params, "skip")) {
121
+ query.skip = params.skip
122
+ }
123
+ if (_.has(params, "sort")) {
124
+ query.sort = params.sort
125
+ }
126
+ const records = await this.find(objectName, query, userSession)
127
+ return {
128
+ records
129
+ }
130
+ }
131
+ },
132
+ /**
133
+ * @api {GET} /api/v1/rest/:objectName/:id 获取单条记录
134
+ * @apiVersion 0.0.0
135
+ * @apiName findOne
136
+ * @apiGroup @steedos/service-rest
137
+ * @apiParam {String} objectName 对象API Name,如:contracts
138
+ * @apiParam {String} id 记录id,如:5e7d1b9b9c9d4400001d1b9b
139
+ * @apiQuery {String} [fields] 字段名,如:'["name","description"]'
140
+ * @apiSuccess {Object} record 记录信息
141
+ * @apiSuccessExample {json} Success-Response:
142
+ * HTTP/1.1 200 OK
143
+ * {
144
+ * "_id": "5e7d1b9b9c9d4400001d1b9b",
145
+ * "name": "test",
146
+ * ...
147
+ * }
148
+ * @apiErrorExample {json} Error-Response:
149
+ * HTTP/1.1 404 Error
150
+ * {
151
+ * "error": "Service 'rest.contracts' is not found.",
152
+ * "detail": {
153
+ * "code": "404",
154
+ * "type": "SERVICE_NOT_FOUND",
155
+ * "data": {
156
+ * "action": "rest.contracts"
157
+ * }
158
+ * }
159
+ * }
160
+ */
161
+ findOne: {
162
+ rest: {
163
+ method: "GET",
164
+ path: "/:objectName/:id"
165
+ },
166
+ params: {
167
+ objectName: { type: "string" },
168
+ id: { type: "any" },
169
+ fields: { type: 'string', optional: true },
170
+ },
171
+ async handler(ctx) {
172
+ const { objectName, id, fields } = ctx.params
173
+ const userSession = ctx.meta.user;
174
+ const query = {}
175
+ if (fields) {
176
+ query.fields = JSON.parse(fields)
177
+ }
178
+ return this.findOne(objectName, id, query, userSession)
179
+ }
180
+ },
181
+ /**
182
+ * @api {POST} /api/v1/rest/:objectName 新增记录
183
+ * @apiVersion 0.0.0
184
+ * @apiName insert
185
+ * @apiGroup @steedos/service-rest
186
+ * @apiParam {String} objectName 对象API Name,如:contracts
187
+ * @apiBody {Object} doc 新增的内容,如:{ name: 'test', description: 'test' }
188
+ * @apiSuccess {Object} record 新记录信息
189
+ * @apiSuccessExample {json} Success-Response:
190
+ * HTTP/1.1 200 OK
191
+ * {
192
+ * "_id": "5e7d1b9b9c9d4400001d1b9b",
193
+ * "name": "test",
194
+ * ...
195
+ * }
196
+ * @apiErrorExample {json} Error-Response:
197
+ * HTTP/1.1 404 Error
198
+ * {
199
+ * "error": "Service 'rest.contracts' is not found.",
200
+ * "detail": {
201
+ * "code": "404",
202
+ * "type": "SERVICE_NOT_FOUND",
203
+ * "data": {
204
+ * "action": "rest.contracts"
205
+ * }
206
+ * }
207
+ * }
208
+ */
209
+ insert: {
210
+ rest: {
211
+ method: "POST",
212
+ path: "/:objectName"
213
+ },
214
+ params: {
215
+ objectName: { type: "string" },
216
+ doc: { type: "object" }
217
+ },
218
+ async handler(ctx) {
219
+ const userSession = ctx.meta.user;
220
+ const { objectName, doc } = ctx.params;
221
+ const object = getObject(objectName)
222
+ let data = '';
223
+ if (_.isString(doc)) {
224
+ data = JSON.parse(doc);
225
+ } else {
226
+ data = JSON.parse(JSON.stringify(doc));
227
+ }
228
+ if (userSession && (await object.getField('space'))) {
229
+ data.space = userSession.spaceId;
230
+ }
231
+ return this.insert(objectName, data, userSession)
232
+ }
233
+ },
234
+ /**
235
+ * @api {PUT} /api/v1/rest/:objectName/:id 更新记录
236
+ * @apiVersion 0.0.0
237
+ * @apiName update
238
+ * @apiGroup @steedos/service-rest
239
+ * @apiParam {String} objectName 对象API Name,如:contracts
240
+ * @apiParam {String} id 记录id,如:5e7d1b9b9c9d4400001d1b9b
241
+ * @apiBody {Object} doc 更新的内容,如:{ name: 'test', description: 'test' }
242
+ * @apiSuccess {Object} record 新记录信息
243
+ * @apiSuccessExample {json} Success-Response:
244
+ * HTTP/1.1 200 OK
245
+ * {
246
+ * "_id": "5e7d1b9b9c9d4400001d1b9b",
247
+ * "name": "test",
248
+ * ...
249
+ * }
250
+ * @apiErrorExample {json} Error-Response:
251
+ * HTTP/1.1 404 Error
252
+ * {
253
+ * "error": "Service 'rest.contracts' is not found.",
254
+ * "detail": {
255
+ * "code": "404",
256
+ * "type": "SERVICE_NOT_FOUND",
257
+ * "data": {
258
+ * "action": "rest.contracts"
259
+ * }
260
+ * }
261
+ * }
262
+ */
263
+ update: {
264
+ rest: {
265
+ method: "PUT",
266
+ path: "/:objectName/:id"
267
+ },
268
+ params: {
269
+ objectName: { type: "string" },
270
+ id: { type: "any" },
271
+ doc: { type: "object" }
272
+ },
273
+ async handler(ctx) {
274
+ const userSession = ctx.meta.user;
275
+ const { objectName, id, doc } = ctx.params;
276
+ let data = '';
277
+ if (_.isString(doc)) {
278
+ data = JSON.parse(doc);
279
+ } else {
280
+ data = JSON.parse(JSON.stringify(doc));
281
+ }
282
+ delete data.space;
283
+ return this.update(objectName, id, data, userSession)
284
+ }
285
+ },
286
+ /**
287
+ * @api {DELETE} /api/v1/rest/:objectName/:id 删除记录
288
+ * @apiVersion 0.0.0
289
+ * @apiName delete
290
+ * @apiGroup @steedos/service-rest
291
+ * @apiParam {String} objectName 对象API Name,如:contracts
292
+ * @apiParam {String} id 记录id,如:5e7d1b9b9c9d4400001d1b9b
293
+ * @apiSuccess {Object} record 新记录信息
294
+ * @apiSuccessExample {json} Success-Response:
295
+ * HTTP/1.1 200 OK
296
+ * {
297
+ * "deleted": true,
298
+ * "id": "5e7d1b9b9c9d4400001d1b9b",
299
+ * }
300
+ * @apiErrorExample {json} Error-Response:
301
+ * HTTP/1.1 404 Error
302
+ * {
303
+ * "error": "Service 'rest.contracts' is not found.",
304
+ * "detail": {
305
+ * "code": "404",
306
+ * "type": "SERVICE_NOT_FOUND",
307
+ * "data": {
308
+ * "action": "rest.contracts"
309
+ * }
310
+ * }
311
+ * }
312
+ */
313
+ delete: {
314
+ rest: {
315
+ method: "DELETE",
316
+ path: "/:objectName/:id"
317
+ },
318
+ params: {
319
+ objectName: { type: "string" },
320
+ id: { type: "any" }
321
+ },
322
+ async handler(ctx) {
323
+ const userSession = ctx.meta.user;
324
+ const { objectName, id } = ctx.params;
325
+ const objectConfig = await getObject(objectName).getConfig()
326
+ const enableTrash = objectConfig.enable_trash
327
+ if (!enableTrash) {
328
+ await this.delete(objectName, id, userSession)
329
+ } else {
330
+ const data = {
331
+ is_deleted: true,
332
+ deleted: new Date(),
333
+ deleted_by: userSession ? userSession.userId : null
334
+ }
335
+ await this.update(objectName, id, data, userSession)
336
+ }
337
+ return {
338
+ "deleted": true,
339
+ "id": id
340
+ }
341
+ }
342
+ },
343
+
344
+ },
345
+
346
+ /**
347
+ * Events
348
+ */
349
+ events: {
350
+
351
+ },
352
+
353
+ /**
354
+ * Methods
355
+ */
356
+ methods: {
357
+ find: {
358
+ async handler(objectName, query, userSession) {
359
+ const obj = this.getObject(objectName)
360
+ if (objectName == 'users') {
361
+ return await obj.find(query)
362
+ }
363
+ return await obj.find(query, userSession)
364
+ }
365
+ },
366
+ findOne: {
367
+ async handler(objectName, id, query, userSession) {
368
+ const obj = this.getObject(objectName)
369
+ if (objectName == 'users') {
370
+ return await obj.findOne(id, query)
371
+ }
372
+ return await obj.findOne(id, query, userSession)
373
+ }
374
+ },
375
+ insert: {
376
+ async handler(objectName, doc, userSession) {
377
+ const obj = this.getObject(objectName)
378
+ return await obj.insert(doc, userSession)
379
+ }
380
+ },
381
+ update: {
382
+ async handler(objectName, id, doc, userSession) {
383
+ const obj = this.getObject(objectName)
384
+ return await obj.update(id, doc, userSession)
385
+ }
386
+ },
387
+ delete: {
388
+ async handler(objectName, id, userSession) {
389
+ const obj = this.getObject(objectName)
390
+ return await obj.delete(id, userSession)
391
+ }
392
+ },
393
+ },
394
+
395
+ /**
396
+ * Service created lifecycle event handler
397
+ */
398
+ created() {
399
+ },
400
+
401
+ merged(schema) {
402
+ },
403
+
404
+ /**
405
+ * Service started lifecycle event handler
406
+ */
407
+ async started() {
408
+
409
+ },
410
+
411
+ /**
412
+ * Service stopped lifecycle event handler
413
+ */
414
+ async stopped() {
415
+
416
+ }
417
+ };