@smartsoft001/crud-shell-app-services 1.1.91 → 2.67.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/.eslintrc +13 -0
- package/README.md +25 -4
- package/jest.config.ts +27 -0
- package/package.json +2 -36
- package/project.json +43 -0
- package/src/index.ts +1 -0
- package/src/lib/services/crud/crud.service.spec.ts +228 -0
- package/src/lib/services/crud/crud.service.ts +284 -0
- package/src/lib/services/index.ts +5 -0
- package/tsconfig.json +13 -0
- package/tsconfig.lib.json +11 -0
- package/tsconfig.spec.json +20 -0
- package/src/index.d.ts +0 -1
- package/src/index.js +0 -5
- package/src/index.js.map +0 -1
- package/src/lib/services/crud/crud.service.d.ts +0 -55
- package/src/lib/services/crud/crud.service.js +0 -232
- package/src/lib/services/crud/crud.service.js.map +0 -1
- package/src/lib/services/index.d.ts +0 -3
- package/src/lib/services/index.js +0 -10
- package/src/lib/services/index.js.map +0 -1
- package/test-setup.js +0 -1
- package/test-setup.js.map +0 -1
- /package/{test-setup.d.ts → test-setup.ts} +0 -0
package/.eslintrc
ADDED
package/README.md
CHANGED
|
@@ -1,7 +1,28 @@
|
|
|
1
|
-
# crud-shell-app-services
|
|
1
|
+
# 📦 @smartsoft001/crud-shell-app-services
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
 
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## 🚀 Usage
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
`npm i @smartsoft001/crud-shell-app-services`
|
|
8
|
+
|
|
9
|
+
## 🛠️ Services & Methods
|
|
10
|
+
|
|
11
|
+
### CrudService
|
|
12
|
+
|
|
13
|
+
Methods:
|
|
14
|
+
<table>
|
|
15
|
+
<tr><td>create</td><td>Creates a new entity and returns its ID.</td></tr>
|
|
16
|
+
<tr><td>createMany</td><td>Creates multiple entities in bulk.</td></tr>
|
|
17
|
+
<tr><td>readById</td><td>Retrieves an entity by its ID.</td></tr>
|
|
18
|
+
<tr><td>read</td><td>Retrieves a list of entities with filtering support.</td></tr>
|
|
19
|
+
<tr><td>readBySpec</td><td>Retrieves entities using a specification object.</td></tr>
|
|
20
|
+
<tr><td>update</td><td>Updates an entity by its ID.</td></tr>
|
|
21
|
+
<tr><td>updatePartial</td><td>Partially updates an entity by its ID.</td></tr>
|
|
22
|
+
<tr><td>delete</td><td>Deletes an entity by its ID.</td></tr>
|
|
23
|
+
<tr><td>uploadAttachment</td><td>Uploads an attachment for an entity.</td></tr>
|
|
24
|
+
<tr><td>getAttachmentInfo</td><td>Retrieves information about an attachment.</td></tr>
|
|
25
|
+
<tr><td>getAttachmentStream</td><td>Retrieves a stream for an attachment.</td></tr>
|
|
26
|
+
<tr><td>deleteAttachment</td><td>Deletes an attachment by its ID.</td></tr>
|
|
27
|
+
<tr><td>changes</td><td>Returns an observable for entity change events.</td></tr>
|
|
28
|
+
</table>
|
package/jest.config.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/* eslint-disable */
|
|
2
|
+
export default {
|
|
3
|
+
globals: {},
|
|
4
|
+
transform: {
|
|
5
|
+
'^.+\\.[tj]sx?$': [
|
|
6
|
+
'ts-jest',
|
|
7
|
+
{
|
|
8
|
+
tsConfig: '<rootDir>/tsconfig.spec.json',
|
|
9
|
+
},
|
|
10
|
+
],
|
|
11
|
+
},
|
|
12
|
+
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx'],
|
|
13
|
+
coverageDirectory: '../../../../coverage/packages/crud/shell/app-services',
|
|
14
|
+
displayName: 'crud-shell-app-services',
|
|
15
|
+
testEnvironment: 'node',
|
|
16
|
+
preset: '../../../../jest.preset.js',
|
|
17
|
+
/* TODO: Update to latest Jest snapshotFormat
|
|
18
|
+
* By default Nx has kept the older style of Jest Snapshot formats
|
|
19
|
+
* to prevent breaking of any existing tests with snapshots.
|
|
20
|
+
* It's recommend you update to the latest format.
|
|
21
|
+
* You can do this by removing snapshotFormat property
|
|
22
|
+
* and running tests with --update-snapshot flag.
|
|
23
|
+
* Example: From within the project directory, run "nx test --update-snapshot"
|
|
24
|
+
* More info: https://jestjs.io/docs/upgrading-to-jest29#snapshot-format
|
|
25
|
+
*/
|
|
26
|
+
snapshotFormat: { escapeString: true, printBasicPrototype: true },
|
|
27
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@smartsoft001/crud-shell-app-services",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.67.0",
|
|
4
4
|
"description": "Utils to crud",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -16,39 +16,5 @@
|
|
|
16
16
|
"bugs": {
|
|
17
17
|
"url": "https://github.com/emiljuchnikowski/smartsoft/issues"
|
|
18
18
|
},
|
|
19
|
-
"homepage": "https://github.com/emiljuchnikowski/smartsoft#readme"
|
|
20
|
-
"dependencies": {
|
|
21
|
-
"@angular/common": "16.1.3",
|
|
22
|
-
"@angular/core": "16.1.3",
|
|
23
|
-
"@angular/platform-browser-dynamic": "16.1.3",
|
|
24
|
-
"@nestjs/axios": "3.0.0",
|
|
25
|
-
"@nestjs/common": "^10.0.5",
|
|
26
|
-
"@nestjs/passport": "^10.0.0",
|
|
27
|
-
"@nestjs/terminus": "^10.0.1",
|
|
28
|
-
"@nestjs/typeorm": "^10.0.0",
|
|
29
|
-
"combined-stream": "^1.0.8",
|
|
30
|
-
"flatted": "^3.2.4",
|
|
31
|
-
"guid-typescript": "1.0.9",
|
|
32
|
-
"lodash": "^4.17.20",
|
|
33
|
-
"lodash-decorators": "^6.0.1",
|
|
34
|
-
"md5": "2.3.0",
|
|
35
|
-
"mongodb": "5.6.0",
|
|
36
|
-
"passport-jwt": "4.0.0",
|
|
37
|
-
"reflect-metadata": "0.1.13",
|
|
38
|
-
"rxjs": "7.8.1"
|
|
39
|
-
},
|
|
40
|
-
"peerDependencies": {
|
|
41
|
-
"@smartsoft001/crud-domain": "1.1.91",
|
|
42
|
-
"@smartsoft001/crud-shell-dtos": "1.1.91",
|
|
43
|
-
"@smartsoft001/domain-core": "1.1.91",
|
|
44
|
-
"@smartsoft001/models": "1.1.91",
|
|
45
|
-
"@smartsoft001/mongo": "1.1.91",
|
|
46
|
-
"@smartsoft001/nestjs": "1.1.91",
|
|
47
|
-
"@smartsoft001/users": "1.1.91",
|
|
48
|
-
"@smartsoft001/utils": "1.1.91",
|
|
49
|
-
"util": "0.12.5",
|
|
50
|
-
"tslib": "2.5.3"
|
|
51
|
-
},
|
|
52
|
-
"main": "./src/index.js",
|
|
53
|
-
"types": "./src/index.d.ts"
|
|
19
|
+
"homepage": "https://github.com/emiljuchnikowski/smartsoft#readme"
|
|
54
20
|
}
|
package/project.json
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "crud-shell-app-services",
|
|
3
|
+
"$schema": "../../../../node_modules/nx/schemas/project-schema.json",
|
|
4
|
+
"sourceRoot": "packages/crud/shell/app-services/src",
|
|
5
|
+
"projectType": "library",
|
|
6
|
+
"generators": {},
|
|
7
|
+
"targets": {
|
|
8
|
+
"lint": {
|
|
9
|
+
"executor": "@nx/eslint:lint",
|
|
10
|
+
"outputs": ["{options.outputFile}"],
|
|
11
|
+
"options": {
|
|
12
|
+
"lintFilePatterns": [
|
|
13
|
+
"packages/crud/shell/app-services/**/*.{ts,tsx,js,jsx}",
|
|
14
|
+
"packages/crud/shell/app-services/package.json"
|
|
15
|
+
],
|
|
16
|
+
"tsConfig": [
|
|
17
|
+
"packages/crud/shell/app-services/tsconfig.lib.json",
|
|
18
|
+
"packages/crud/shell/app-services/tsconfig.spec.json"
|
|
19
|
+
]
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
"test": {
|
|
23
|
+
"executor": "@nx/jest:jest",
|
|
24
|
+
"options": {
|
|
25
|
+
"jestConfig": "packages/crud/shell/app-services/jest.config.ts",
|
|
26
|
+
"passWithNoTests": true
|
|
27
|
+
},
|
|
28
|
+
"outputs": ["{workspaceRoot}/coverage/packages/crud/shell/app-services"]
|
|
29
|
+
},
|
|
30
|
+
"build": {
|
|
31
|
+
"executor": "@nx/esbuild:esbuild",
|
|
32
|
+
"options": {
|
|
33
|
+
"outputPath": "dist/packages/crud/shell/app-services",
|
|
34
|
+
"tsConfig": "packages/crud/shell/app-services/tsconfig.lib.json",
|
|
35
|
+
"packageJson": "packages/crud/shell/app-services/package.json",
|
|
36
|
+
"main": "packages/crud/shell/app-services/src/index.ts",
|
|
37
|
+
"assets": ["packages/crud/shell/app-services/*.md"]
|
|
38
|
+
},
|
|
39
|
+
"outputs": ["{options.outputPath}"]
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
"tags": ["scope:crud", "type:shell"]
|
|
43
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lib/services';
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
import { of, Observable } from 'rxjs';
|
|
2
|
+
|
|
3
|
+
import { CrudService } from './crud.service';
|
|
4
|
+
|
|
5
|
+
jest.mock('@smartsoft001/utils', () => ({
|
|
6
|
+
PasswordService: { hash: jest.fn(async (v) => 'hashed-' + v) },
|
|
7
|
+
GuidService: { create: jest.fn(() => 'guid') },
|
|
8
|
+
}));
|
|
9
|
+
|
|
10
|
+
const mockUser = { id: 'u', username: 'test', permissions: ['p'] };
|
|
11
|
+
const mockData = { id: 'id', password: 'pw', passwordConfirm: 'pw' };
|
|
12
|
+
const mockRepo = () => ({
|
|
13
|
+
create: jest.fn(),
|
|
14
|
+
createMany: jest.fn(),
|
|
15
|
+
getById: jest.fn().mockResolvedValue({ id: 'id', password: 'pw' }),
|
|
16
|
+
getByCriteria: jest
|
|
17
|
+
.fn()
|
|
18
|
+
.mockResolvedValue({ data: [{ id: 'id', password: 'pw' }], totalCount: 1 }),
|
|
19
|
+
update: jest.fn(),
|
|
20
|
+
updatePartial: jest.fn(),
|
|
21
|
+
delete: jest.fn(),
|
|
22
|
+
clear: jest.fn(),
|
|
23
|
+
changesByCriteria: jest.fn(() => of({})),
|
|
24
|
+
});
|
|
25
|
+
const mockAttachRepo = () => ({
|
|
26
|
+
upload: jest.fn(),
|
|
27
|
+
getInfo: jest
|
|
28
|
+
.fn()
|
|
29
|
+
.mockResolvedValue({ fileName: 'f', contentType: 'c', length: 1 }),
|
|
30
|
+
getStream: jest.fn().mockResolvedValue({}),
|
|
31
|
+
delete: jest.fn(),
|
|
32
|
+
});
|
|
33
|
+
const mockPerm = () => ({ valid: jest.fn() });
|
|
34
|
+
|
|
35
|
+
describe('crud-app-services: CrudService', () => {
|
|
36
|
+
let service: CrudService<any>;
|
|
37
|
+
let repository: any;
|
|
38
|
+
let attachmentRepository: any;
|
|
39
|
+
let permissionService: any;
|
|
40
|
+
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
repository = mockRepo();
|
|
43
|
+
attachmentRepository = mockAttachRepo();
|
|
44
|
+
permissionService = mockPerm();
|
|
45
|
+
service = new CrudService(
|
|
46
|
+
permissionService,
|
|
47
|
+
repository,
|
|
48
|
+
attachmentRepository,
|
|
49
|
+
);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe('create', () => {
|
|
53
|
+
it('should create and return id', async () => {
|
|
54
|
+
const id = await service.create({ ...mockData }, mockUser);
|
|
55
|
+
expect(typeof id).toBe('string');
|
|
56
|
+
});
|
|
57
|
+
it('should log and throw on error', async () => {
|
|
58
|
+
permissionService.valid.mockImplementation(() => {
|
|
59
|
+
throw new Error('fail');
|
|
60
|
+
});
|
|
61
|
+
await expect(service.create({ ...mockData }, mockUser)).rejects.toThrow(
|
|
62
|
+
'fail',
|
|
63
|
+
);
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
describe('createMany', () => {
|
|
68
|
+
it('should create many and return data', async () => {
|
|
69
|
+
const data = await service.createMany([{ ...mockData }], mockUser, {
|
|
70
|
+
mode: undefined,
|
|
71
|
+
});
|
|
72
|
+
expect(Array.isArray(data)).toBe(true);
|
|
73
|
+
});
|
|
74
|
+
it('should clear repo if mode is replace', async () => {
|
|
75
|
+
await service.createMany([{ ...mockData }], mockUser, {
|
|
76
|
+
mode: 'replace',
|
|
77
|
+
});
|
|
78
|
+
expect(repository.clear).toHaveBeenCalled();
|
|
79
|
+
});
|
|
80
|
+
it('should log and throw on error', async () => {
|
|
81
|
+
permissionService.valid.mockImplementation(() => {
|
|
82
|
+
throw new Error('fail');
|
|
83
|
+
});
|
|
84
|
+
await expect(
|
|
85
|
+
service.createMany([{ ...mockData }], mockUser, { mode: undefined }),
|
|
86
|
+
).rejects.toThrow('fail');
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe('readById', () => {
|
|
91
|
+
it('should return result without password', async () => {
|
|
92
|
+
const res = await service.readById('id', mockUser);
|
|
93
|
+
expect(res.password).toBeUndefined();
|
|
94
|
+
});
|
|
95
|
+
it('should log and throw on error', async () => {
|
|
96
|
+
repository.getById.mockImplementation(() => {
|
|
97
|
+
throw new Error('fail');
|
|
98
|
+
});
|
|
99
|
+
await expect(service.readById('id', mockUser)).rejects.toThrow('fail');
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
describe('read', () => {
|
|
104
|
+
it('should return data and totalCount', async () => {
|
|
105
|
+
const res = await service.read({}, {}, mockUser);
|
|
106
|
+
expect(res).toHaveProperty('data');
|
|
107
|
+
});
|
|
108
|
+
it('should log and throw on error', async () => {
|
|
109
|
+
repository.getByCriteria.mockImplementation(() => {
|
|
110
|
+
throw new Error('fail');
|
|
111
|
+
});
|
|
112
|
+
await expect(service.read({}, {}, mockUser)).rejects.toThrow('fail');
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe('readBySpec', () => {
|
|
117
|
+
it('should call read with spec', async () => {
|
|
118
|
+
const spy = jest
|
|
119
|
+
.spyOn(service, 'read')
|
|
120
|
+
.mockResolvedValue({ data: [], totalCount: 0 });
|
|
121
|
+
await service.readBySpec({ criteria: {} }, {}, mockUser);
|
|
122
|
+
expect(spy).toHaveBeenCalled();
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
|
|
126
|
+
describe('update', () => {
|
|
127
|
+
it('should update', async () => {
|
|
128
|
+
await service.update('id', { ...mockData }, mockUser);
|
|
129
|
+
expect(repository.update).toHaveBeenCalled();
|
|
130
|
+
});
|
|
131
|
+
it('should log and throw on error', async () => {
|
|
132
|
+
repository.update.mockImplementation(() => {
|
|
133
|
+
throw new Error('fail');
|
|
134
|
+
});
|
|
135
|
+
await expect(
|
|
136
|
+
service.update('id', { ...mockData }, mockUser),
|
|
137
|
+
).rejects.toThrow('fail');
|
|
138
|
+
});
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
describe('updatePartial', () => {
|
|
142
|
+
it('should updatePartial', async () => {
|
|
143
|
+
await service.updatePartial('id', { ...mockData }, mockUser);
|
|
144
|
+
expect(repository.updatePartial).toHaveBeenCalled();
|
|
145
|
+
});
|
|
146
|
+
it('should log and throw on error', async () => {
|
|
147
|
+
repository.updatePartial.mockImplementation(() => {
|
|
148
|
+
throw new Error('fail');
|
|
149
|
+
});
|
|
150
|
+
await expect(
|
|
151
|
+
service.updatePartial('id', { ...mockData }, mockUser),
|
|
152
|
+
).rejects.toThrow('fail');
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
describe('delete', () => {
|
|
157
|
+
it('should delete', async () => {
|
|
158
|
+
await service.delete('id', mockUser);
|
|
159
|
+
expect(repository.delete).toHaveBeenCalled();
|
|
160
|
+
});
|
|
161
|
+
it('should log and throw on error', async () => {
|
|
162
|
+
repository.delete.mockImplementation(() => {
|
|
163
|
+
throw new Error('fail');
|
|
164
|
+
});
|
|
165
|
+
await expect(service.delete('id', mockUser)).rejects.toThrow('fail');
|
|
166
|
+
});
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
describe('uploadAttachment', () => {
|
|
170
|
+
it('should upload and return id', async () => {
|
|
171
|
+
const fakeStream = {
|
|
172
|
+
pipe: jest.fn(),
|
|
173
|
+
addListener: jest.fn(),
|
|
174
|
+
on: jest.fn(),
|
|
175
|
+
once: jest.fn(),
|
|
176
|
+
emit: jest.fn(),
|
|
177
|
+
removeListener: jest.fn(),
|
|
178
|
+
destroy: jest.fn(),
|
|
179
|
+
off: jest.fn(),
|
|
180
|
+
removeAllListeners: jest.fn(),
|
|
181
|
+
setMaxListeners: jest.fn(),
|
|
182
|
+
getMaxListeners: jest.fn(),
|
|
183
|
+
listeners: jest.fn(),
|
|
184
|
+
rawListeners: jest.fn(),
|
|
185
|
+
prependListener: jest.fn(),
|
|
186
|
+
prependOnceListener: jest.fn(),
|
|
187
|
+
eventNames: jest.fn(),
|
|
188
|
+
listenerCount: jest.fn(),
|
|
189
|
+
};
|
|
190
|
+
const id = await service.uploadAttachment({
|
|
191
|
+
id: '',
|
|
192
|
+
fileName: '',
|
|
193
|
+
stream: fakeStream,
|
|
194
|
+
mimeType: '',
|
|
195
|
+
encoding: '',
|
|
196
|
+
});
|
|
197
|
+
expect(typeof id).toBe('string');
|
|
198
|
+
});
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
describe('getAttachmentInfo', () => {
|
|
202
|
+
it('should get info', async () => {
|
|
203
|
+
const info = await service.getAttachmentInfo('id');
|
|
204
|
+
expect(info).toHaveProperty('fileName');
|
|
205
|
+
});
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
describe('getAttachmentStream', () => {
|
|
209
|
+
it('should get stream', async () => {
|
|
210
|
+
const stream = await service.getAttachmentStream('id');
|
|
211
|
+
expect(stream).toBeDefined();
|
|
212
|
+
});
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
describe('deleteAttachment', () => {
|
|
216
|
+
it('should delete attachment', async () => {
|
|
217
|
+
await service.deleteAttachment('id');
|
|
218
|
+
expect(attachmentRepository.delete).toHaveBeenCalled();
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
describe('changes', () => {
|
|
223
|
+
it('should return observable', () => {
|
|
224
|
+
const obs = service.changes({});
|
|
225
|
+
expect(obs instanceof Observable).toBe(true);
|
|
226
|
+
});
|
|
227
|
+
});
|
|
228
|
+
});
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { Injectable, Logger } from '@nestjs/common';
|
|
2
|
+
import { ICreateManyOptions } from '@smartsoft001/crud-domain';
|
|
3
|
+
import { ItemChangedData } from '@smartsoft001/crud-shell-dtos';
|
|
4
|
+
import {
|
|
5
|
+
DomainValidationError,
|
|
6
|
+
IAttachmentRepository,
|
|
7
|
+
IEntity,
|
|
8
|
+
IItemRepository,
|
|
9
|
+
ISpecification,
|
|
10
|
+
} from '@smartsoft001/domain-core';
|
|
11
|
+
import { castModel, getInvalidFields, isModel } from '@smartsoft001/models';
|
|
12
|
+
import { PermissionService } from '@smartsoft001/nestjs';
|
|
13
|
+
import { IUser } from '@smartsoft001/users';
|
|
14
|
+
import { GuidService, PasswordService } from '@smartsoft001/utils';
|
|
15
|
+
import * as CombinedStream from 'combined-stream';
|
|
16
|
+
import { Guid } from 'guid-typescript';
|
|
17
|
+
import { Memoize } from 'lodash-decorators';
|
|
18
|
+
import { Observable } from 'rxjs';
|
|
19
|
+
|
|
20
|
+
import { Readable, Stream } from 'stream';
|
|
21
|
+
|
|
22
|
+
@Injectable()
|
|
23
|
+
export class CrudService<T extends IEntity<string>> {
|
|
24
|
+
private _logger = new Logger(CrudService.name, { timestamp: true });
|
|
25
|
+
|
|
26
|
+
constructor(
|
|
27
|
+
protected readonly permissionService: PermissionService,
|
|
28
|
+
protected readonly repository: IItemRepository<T>,
|
|
29
|
+
protected readonly attachmentRepository: IAttachmentRepository<T>,
|
|
30
|
+
) {}
|
|
31
|
+
|
|
32
|
+
async create(data: T, user: IUser): Promise<string> {
|
|
33
|
+
data.id = Guid.raw();
|
|
34
|
+
|
|
35
|
+
try {
|
|
36
|
+
this.permissionService.valid('create', user);
|
|
37
|
+
|
|
38
|
+
castModel(data, 'create', user.permissions);
|
|
39
|
+
this.checkValidCreate(data, user.permissions);
|
|
40
|
+
|
|
41
|
+
if (data['password']) {
|
|
42
|
+
data['password'] = await PasswordService.hash(data['password']);
|
|
43
|
+
}
|
|
44
|
+
if (data['passwordConfirm']) {
|
|
45
|
+
delete data['passwordConfirm'];
|
|
46
|
+
}
|
|
47
|
+
await this.repository.create(data, user);
|
|
48
|
+
|
|
49
|
+
return data.id;
|
|
50
|
+
} catch (e) {
|
|
51
|
+
this._logger.error(e);
|
|
52
|
+
throw e;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async createMany(
|
|
57
|
+
data: T[],
|
|
58
|
+
user: IUser,
|
|
59
|
+
options: ICreateManyOptions,
|
|
60
|
+
): Promise<T[]> {
|
|
61
|
+
data.forEach((item) => {
|
|
62
|
+
item.id = Guid.raw();
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
this.permissionService.valid('create', user);
|
|
67
|
+
|
|
68
|
+
data.forEach((item) => {
|
|
69
|
+
castModel(item, 'create', user.permissions);
|
|
70
|
+
this.checkValidCreate(item, user.permissions);
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
if (options && options.mode === 'replace') {
|
|
74
|
+
await this.repository.clear(user);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
for (let index = 0; index < data.length; index++) {
|
|
78
|
+
const item = data[index];
|
|
79
|
+
|
|
80
|
+
if (item['password']) {
|
|
81
|
+
item['password'] = await PasswordService.hash(item['password']);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (item['passwordConfirm']) {
|
|
85
|
+
delete item['passwordConfirm'];
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
await this.repository.createMany(data, user);
|
|
90
|
+
} catch (e) {
|
|
91
|
+
this._logger.error(e);
|
|
92
|
+
throw e;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
return data;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
async readById(id: string, user: IUser): Promise<T> {
|
|
99
|
+
try {
|
|
100
|
+
this.permissionService.valid('read', user);
|
|
101
|
+
const result = await this.repository.getById(id);
|
|
102
|
+
delete result['password'];
|
|
103
|
+
|
|
104
|
+
return result;
|
|
105
|
+
} catch (e) {
|
|
106
|
+
this._logger.error(e);
|
|
107
|
+
throw e;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
async read(
|
|
112
|
+
criteria: any,
|
|
113
|
+
options: any,
|
|
114
|
+
user: IUser,
|
|
115
|
+
): Promise<{ data: T[]; totalCount: number }> {
|
|
116
|
+
try {
|
|
117
|
+
this.permissionService.valid('read', user);
|
|
118
|
+
const result = await this.repository.getByCriteria(criteria, options);
|
|
119
|
+
result.data.forEach((item) => delete item['password']);
|
|
120
|
+
|
|
121
|
+
return result;
|
|
122
|
+
} catch (e) {
|
|
123
|
+
this._logger.error(e);
|
|
124
|
+
throw e;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
readBySpec(
|
|
129
|
+
spec: ISpecification,
|
|
130
|
+
options: any,
|
|
131
|
+
user: IUser,
|
|
132
|
+
): Promise<{ data: T[]; totalCount: number }> {
|
|
133
|
+
return this.read(spec.criteria, options, user);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
async update(id: string, data: T, user: IUser): Promise<void> {
|
|
137
|
+
try {
|
|
138
|
+
data.id = id;
|
|
139
|
+
this.permissionService.valid('update', user);
|
|
140
|
+
|
|
141
|
+
castModel(data, 'update', user.permissions);
|
|
142
|
+
this.checkValidUpdate(data, user.permissions);
|
|
143
|
+
|
|
144
|
+
if (data['password']) {
|
|
145
|
+
data['password'] = await PasswordService.hash(data['password']);
|
|
146
|
+
}
|
|
147
|
+
if (data['passwordConfirm']) {
|
|
148
|
+
delete data['passwordConfirm'];
|
|
149
|
+
}
|
|
150
|
+
await this.repository.update(data, user);
|
|
151
|
+
} catch (e) {
|
|
152
|
+
this._logger.error(e);
|
|
153
|
+
throw e;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
async updatePartial(
|
|
158
|
+
id: string,
|
|
159
|
+
data: Partial<T>,
|
|
160
|
+
user: IUser,
|
|
161
|
+
): Promise<void> {
|
|
162
|
+
try {
|
|
163
|
+
data.id = id;
|
|
164
|
+
|
|
165
|
+
this.permissionService.valid('update', user);
|
|
166
|
+
|
|
167
|
+
castModel(data, 'update', user.permissions);
|
|
168
|
+
this.checkValidUpdatePartial(data, user.permissions);
|
|
169
|
+
|
|
170
|
+
if (data['password']) {
|
|
171
|
+
data['password'] = await PasswordService.hash(data['password']);
|
|
172
|
+
}
|
|
173
|
+
if (data['passwordConfirm']) {
|
|
174
|
+
delete data['passwordConfirm'];
|
|
175
|
+
}
|
|
176
|
+
await this.repository.updatePartial(data as Partial<T> & { id }, user);
|
|
177
|
+
} catch (e) {
|
|
178
|
+
this._logger.error(e);
|
|
179
|
+
throw e;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
async delete(id: string, user: IUser): Promise<void> {
|
|
184
|
+
try {
|
|
185
|
+
this.permissionService.valid('delete', user);
|
|
186
|
+
|
|
187
|
+
await this.repository.delete(id, user);
|
|
188
|
+
} catch (e) {
|
|
189
|
+
this._logger.error(e);
|
|
190
|
+
throw e;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
async uploadAttachment(
|
|
195
|
+
data: {
|
|
196
|
+
id: string;
|
|
197
|
+
fileName: string;
|
|
198
|
+
stream: Stream;
|
|
199
|
+
mimeType: string;
|
|
200
|
+
encoding: string;
|
|
201
|
+
},
|
|
202
|
+
options?: { streamCallback?: (r) => void; start?: number },
|
|
203
|
+
): Promise<string> {
|
|
204
|
+
if (!data.id) {
|
|
205
|
+
data.id = GuidService.create();
|
|
206
|
+
}
|
|
207
|
+
let oldId = null;
|
|
208
|
+
|
|
209
|
+
if (options?.start) {
|
|
210
|
+
oldId = data.id;
|
|
211
|
+
const stream = await this.attachmentRepository.getStream(data.id, {
|
|
212
|
+
start: 0,
|
|
213
|
+
end: options.start - 1,
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
const combinedStream = CombinedStream.create();
|
|
217
|
+
combinedStream.append(stream);
|
|
218
|
+
combinedStream.append(data.stream);
|
|
219
|
+
|
|
220
|
+
data.stream = combinedStream;
|
|
221
|
+
data.id = GuidService.create();
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
this.attachmentRepository.upload(data, options);
|
|
225
|
+
|
|
226
|
+
if (oldId) await this.attachmentRepository.delete(data.id);
|
|
227
|
+
|
|
228
|
+
return data.id;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
@Memoize()
|
|
232
|
+
getAttachmentInfo(
|
|
233
|
+
id: string,
|
|
234
|
+
): Promise<{ fileName: string; contentType: string; length: number }> {
|
|
235
|
+
return this.attachmentRepository.getInfo(id);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
getAttachmentStream(
|
|
239
|
+
id: string,
|
|
240
|
+
options?: { start: number; end: number },
|
|
241
|
+
): Promise<Readable> {
|
|
242
|
+
return this.attachmentRepository.getStream(id, options);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
async deleteAttachment(id: string): Promise<void> {
|
|
246
|
+
return this.attachmentRepository.delete(id);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
changes(criteria: { id?: string }): Observable<ItemChangedData> {
|
|
250
|
+
return this.repository.changesByCriteria(criteria);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
private checkValidCreate(item: T, permissions: Array<string>): void {
|
|
254
|
+
const array = getInvalidFields(item, 'create', permissions);
|
|
255
|
+
|
|
256
|
+
if (array.length) {
|
|
257
|
+
throw new DomainValidationError('Required fields: ' + array.join(', '));
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
private checkValidUpdate(item: T, permissions: Array<string>): void {
|
|
262
|
+
const array = getInvalidFields(item, 'update', permissions);
|
|
263
|
+
|
|
264
|
+
if (array.length) {
|
|
265
|
+
throw new DomainValidationError('Required fields: ' + array.join(', '));
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
private checkValidUpdatePartial(
|
|
270
|
+
item: Partial<T>,
|
|
271
|
+
permissions: Array<string>,
|
|
272
|
+
): void {
|
|
273
|
+
if (!isModel(item)) return;
|
|
274
|
+
|
|
275
|
+
const keys = Object.keys(item);
|
|
276
|
+
const array = getInvalidFields(item, 'update', permissions).filter(
|
|
277
|
+
(invalidField) => keys.some((key) => key === invalidField),
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
if (array.length) {
|
|
281
|
+
throw new DomainValidationError('Required fields: ' + array.join(', '));
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
}
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"outDir": "../../../../dist/out-tsc",
|
|
6
|
+
"declaration": true,
|
|
7
|
+
"types": ["node"]
|
|
8
|
+
},
|
|
9
|
+
"exclude": ["**/*.spec.ts", "**/*.test.ts", "jest.config.ts"],
|
|
10
|
+
"include": ["**/*.ts"]
|
|
11
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"extends": "./tsconfig.json",
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"outDir": "../../../../dist/out-tsc",
|
|
5
|
+
"module": "commonjs",
|
|
6
|
+
"types": ["jest", "node"]
|
|
7
|
+
},
|
|
8
|
+
"include": [
|
|
9
|
+
"**/*.spec.ts",
|
|
10
|
+
"**/*.test.ts",
|
|
11
|
+
"**/*.spec.tsx",
|
|
12
|
+
"**/*.test.tsx",
|
|
13
|
+
"**/*.spec.js",
|
|
14
|
+
"**/*.test.js",
|
|
15
|
+
"**/*.spec.jsx",
|
|
16
|
+
"**/*.test.jsx",
|
|
17
|
+
"**/*.d.ts",
|
|
18
|
+
"jest.config.ts"
|
|
19
|
+
]
|
|
20
|
+
}
|
package/src/index.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./lib/services";
|
package/src/index.js
DELETED
package/src/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../libs/crud/shell/app-services/src/index.ts"],"names":[],"mappings":";;;AAAA,yDAA+B"}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
import { Observable } from "rxjs";
|
|
3
|
-
import { Readable, Stream } from "stream";
|
|
4
|
-
import { IUser } from "@smartsoft001/users";
|
|
5
|
-
import { IAttachmentRepository, IEntity, IItemRepository, ISpecification } from "@smartsoft001/domain-core";
|
|
6
|
-
import { ICreateManyOptions } from "@smartsoft001/crud-domain";
|
|
7
|
-
import { ItemChangedData } from "@smartsoft001/crud-shell-dtos";
|
|
8
|
-
import { PermissionService } from "@smartsoft001/nestjs";
|
|
9
|
-
export declare class CrudService<T extends IEntity<string>> {
|
|
10
|
-
protected readonly permissionService: PermissionService;
|
|
11
|
-
protected readonly repository: IItemRepository<T>;
|
|
12
|
-
protected readonly attachmentRepository: IAttachmentRepository<T>;
|
|
13
|
-
private _logger;
|
|
14
|
-
constructor(permissionService: PermissionService, repository: IItemRepository<T>, attachmentRepository: IAttachmentRepository<T>);
|
|
15
|
-
create(data: T, user: IUser): Promise<string>;
|
|
16
|
-
createMany(data: T[], user: IUser, options: ICreateManyOptions): Promise<T[]>;
|
|
17
|
-
readById(id: string, user: IUser): Promise<T>;
|
|
18
|
-
read(criteria: any, options: any, user: IUser): Promise<{
|
|
19
|
-
data: T[];
|
|
20
|
-
totalCount: number;
|
|
21
|
-
}>;
|
|
22
|
-
readBySpec(spec: ISpecification, options: any, user: IUser): Promise<{
|
|
23
|
-
data: T[];
|
|
24
|
-
totalCount: number;
|
|
25
|
-
}>;
|
|
26
|
-
update(id: string, data: T, user: IUser): Promise<void>;
|
|
27
|
-
updatePartial(id: string, data: Partial<T>, user: IUser): Promise<void>;
|
|
28
|
-
delete(id: string, user: IUser): Promise<void>;
|
|
29
|
-
uploadAttachment(data: {
|
|
30
|
-
id: string;
|
|
31
|
-
fileName: string;
|
|
32
|
-
stream: Stream;
|
|
33
|
-
mimeType: string;
|
|
34
|
-
encoding: string;
|
|
35
|
-
}, options?: {
|
|
36
|
-
streamCallback?: (r: any) => void;
|
|
37
|
-
start?: number;
|
|
38
|
-
}): Promise<string>;
|
|
39
|
-
getAttachmentInfo(id: string): Promise<{
|
|
40
|
-
fileName: string;
|
|
41
|
-
contentType: string;
|
|
42
|
-
length: number;
|
|
43
|
-
}>;
|
|
44
|
-
getAttachmentStream(id: string, options?: {
|
|
45
|
-
start: number;
|
|
46
|
-
end: number;
|
|
47
|
-
}): Promise<Readable>;
|
|
48
|
-
deleteAttachment(id: string): Promise<void>;
|
|
49
|
-
changes(criteria: {
|
|
50
|
-
id?: string;
|
|
51
|
-
}): Observable<ItemChangedData>;
|
|
52
|
-
private checkValidCreate;
|
|
53
|
-
private checkValidUpdate;
|
|
54
|
-
private checkValidUpdatePartial;
|
|
55
|
-
}
|
|
@@ -1,232 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var CrudService_1;
|
|
3
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.CrudService = void 0;
|
|
5
|
-
const tslib_1 = require("tslib");
|
|
6
|
-
const common_1 = require("@nestjs/common");
|
|
7
|
-
const guid_typescript_1 = require("guid-typescript");
|
|
8
|
-
const lodash_decorators_1 = require("lodash-decorators");
|
|
9
|
-
const CombinedStream = require("combined-stream");
|
|
10
|
-
const domain_core_1 = require("@smartsoft001/domain-core");
|
|
11
|
-
const nestjs_1 = require("@smartsoft001/nestjs");
|
|
12
|
-
const models_1 = require("@smartsoft001/models");
|
|
13
|
-
const utils_1 = require("@smartsoft001/utils");
|
|
14
|
-
let CrudService = exports.CrudService = CrudService_1 = class CrudService {
|
|
15
|
-
constructor(permissionService, repository, attachmentRepository) {
|
|
16
|
-
this.permissionService = permissionService;
|
|
17
|
-
this.repository = repository;
|
|
18
|
-
this.attachmentRepository = attachmentRepository;
|
|
19
|
-
this._logger = new common_1.Logger(CrudService_1.name, { timestamp: true });
|
|
20
|
-
}
|
|
21
|
-
create(data, user) {
|
|
22
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
23
|
-
data.id = guid_typescript_1.Guid.raw();
|
|
24
|
-
try {
|
|
25
|
-
this.permissionService.valid("create", user);
|
|
26
|
-
(0, models_1.castModel)(data, "create", user.permissions);
|
|
27
|
-
this.checkValidCreate(data, user.permissions);
|
|
28
|
-
if (data['password']) {
|
|
29
|
-
data['password'] = yield utils_1.PasswordService.hash(data['password']);
|
|
30
|
-
}
|
|
31
|
-
if (data['passwordConfirm']) {
|
|
32
|
-
delete data['passwordConfirm'];
|
|
33
|
-
}
|
|
34
|
-
yield this.repository.create(data, user);
|
|
35
|
-
return data.id;
|
|
36
|
-
}
|
|
37
|
-
catch (e) {
|
|
38
|
-
this._logger.error(e);
|
|
39
|
-
throw e;
|
|
40
|
-
}
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
createMany(data, user, options) {
|
|
44
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
45
|
-
data.forEach((item) => {
|
|
46
|
-
item.id = guid_typescript_1.Guid.raw();
|
|
47
|
-
});
|
|
48
|
-
try {
|
|
49
|
-
this.permissionService.valid("create", user);
|
|
50
|
-
data.forEach((item) => {
|
|
51
|
-
(0, models_1.castModel)(item, "create", user.permissions);
|
|
52
|
-
this.checkValidCreate(item, user.permissions);
|
|
53
|
-
});
|
|
54
|
-
if (options && options.mode === 'replace') {
|
|
55
|
-
yield this.repository.clear(user);
|
|
56
|
-
}
|
|
57
|
-
for (let index = 0; index < data.length; index++) {
|
|
58
|
-
const item = data[index];
|
|
59
|
-
if (item['password']) {
|
|
60
|
-
item['password'] = yield utils_1.PasswordService.hash(item['password']);
|
|
61
|
-
}
|
|
62
|
-
if (item['passwordConfirm']) {
|
|
63
|
-
delete item['passwordConfirm'];
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
yield this.repository.createMany(data, user);
|
|
67
|
-
}
|
|
68
|
-
catch (e) {
|
|
69
|
-
this._logger.error(e);
|
|
70
|
-
throw e;
|
|
71
|
-
}
|
|
72
|
-
return data;
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
readById(id, user) {
|
|
76
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
77
|
-
try {
|
|
78
|
-
this.permissionService.valid("read", user);
|
|
79
|
-
const result = yield this.repository.getById(id);
|
|
80
|
-
delete result['password'];
|
|
81
|
-
return result;
|
|
82
|
-
}
|
|
83
|
-
catch (e) {
|
|
84
|
-
this._logger.error(e);
|
|
85
|
-
throw e;
|
|
86
|
-
}
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
read(criteria, options, user) {
|
|
90
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
91
|
-
try {
|
|
92
|
-
this.permissionService.valid("read", user);
|
|
93
|
-
const result = yield this.repository.getByCriteria(criteria, options);
|
|
94
|
-
result.data.forEach(item => delete item['password']);
|
|
95
|
-
return result;
|
|
96
|
-
}
|
|
97
|
-
catch (e) {
|
|
98
|
-
this._logger.error(e);
|
|
99
|
-
throw e;
|
|
100
|
-
}
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
readBySpec(spec, options, user) {
|
|
104
|
-
return this.read(spec.criteria, options, user);
|
|
105
|
-
}
|
|
106
|
-
update(id, data, user) {
|
|
107
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
108
|
-
try {
|
|
109
|
-
data.id = id;
|
|
110
|
-
this.permissionService.valid("update", user);
|
|
111
|
-
(0, models_1.castModel)(data, 'update', user.permissions);
|
|
112
|
-
this.checkValidUpdate(data, user.permissions);
|
|
113
|
-
if (data['password']) {
|
|
114
|
-
data['password'] = yield utils_1.PasswordService.hash(data['password']);
|
|
115
|
-
}
|
|
116
|
-
if (data['passwordConfirm']) {
|
|
117
|
-
delete data['passwordConfirm'];
|
|
118
|
-
}
|
|
119
|
-
yield this.repository.update(data, user);
|
|
120
|
-
}
|
|
121
|
-
catch (e) {
|
|
122
|
-
this._logger.error(e);
|
|
123
|
-
throw e;
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
updatePartial(id, data, user) {
|
|
128
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
129
|
-
try {
|
|
130
|
-
data.id = id;
|
|
131
|
-
this.permissionService.valid("update", user);
|
|
132
|
-
(0, models_1.castModel)(data, 'update', user.permissions);
|
|
133
|
-
this.checkValidUpdatePartial(data, user.permissions);
|
|
134
|
-
if (data["password"]) {
|
|
135
|
-
data["password"] = yield utils_1.PasswordService.hash(data["password"]);
|
|
136
|
-
}
|
|
137
|
-
if (data['passwordConfirm']) {
|
|
138
|
-
delete data['passwordConfirm'];
|
|
139
|
-
}
|
|
140
|
-
yield this.repository.updatePartial(data, user);
|
|
141
|
-
}
|
|
142
|
-
catch (e) {
|
|
143
|
-
this._logger.error(e);
|
|
144
|
-
throw e;
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
}
|
|
148
|
-
delete(id, user) {
|
|
149
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
150
|
-
try {
|
|
151
|
-
this.permissionService.valid("delete", user);
|
|
152
|
-
yield this.repository.delete(id, user);
|
|
153
|
-
}
|
|
154
|
-
catch (e) {
|
|
155
|
-
this._logger.error(e);
|
|
156
|
-
throw e;
|
|
157
|
-
}
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
uploadAttachment(data, options) {
|
|
161
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
162
|
-
if (!data.id) {
|
|
163
|
-
data.id = utils_1.GuidService.create();
|
|
164
|
-
}
|
|
165
|
-
let oldId = null;
|
|
166
|
-
if (options === null || options === void 0 ? void 0 : options.start) {
|
|
167
|
-
oldId = data.id;
|
|
168
|
-
const stream = yield this.attachmentRepository.getStream(data.id, {
|
|
169
|
-
start: 0,
|
|
170
|
-
end: options.start - 1
|
|
171
|
-
});
|
|
172
|
-
const combinedStream = CombinedStream.create();
|
|
173
|
-
combinedStream.append(stream);
|
|
174
|
-
combinedStream.append(data.stream);
|
|
175
|
-
data.stream = combinedStream;
|
|
176
|
-
data.id = utils_1.GuidService.create();
|
|
177
|
-
}
|
|
178
|
-
this.attachmentRepository.upload(data, options);
|
|
179
|
-
if (oldId)
|
|
180
|
-
yield this.attachmentRepository.delete(data.id);
|
|
181
|
-
return data.id;
|
|
182
|
-
});
|
|
183
|
-
}
|
|
184
|
-
getAttachmentInfo(id) {
|
|
185
|
-
return this.attachmentRepository.getInfo(id);
|
|
186
|
-
}
|
|
187
|
-
getAttachmentStream(id, options) {
|
|
188
|
-
return this.attachmentRepository.getStream(id, options);
|
|
189
|
-
}
|
|
190
|
-
deleteAttachment(id) {
|
|
191
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
192
|
-
return this.attachmentRepository.delete(id);
|
|
193
|
-
});
|
|
194
|
-
}
|
|
195
|
-
changes(criteria) {
|
|
196
|
-
return this.repository.changesByCriteria(criteria);
|
|
197
|
-
}
|
|
198
|
-
checkValidCreate(item, permissions) {
|
|
199
|
-
const array = (0, models_1.getInvalidFields)(item, "create", permissions);
|
|
200
|
-
if (array.length) {
|
|
201
|
-
throw new domain_core_1.DomainValidationError("Required fields: " + array.join(", "));
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
checkValidUpdate(item, permissions) {
|
|
205
|
-
const array = (0, models_1.getInvalidFields)(item, "update", permissions);
|
|
206
|
-
if (array.length) {
|
|
207
|
-
throw new domain_core_1.DomainValidationError("Required fields: " + array.join(", "));
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
checkValidUpdatePartial(item, permissions) {
|
|
211
|
-
if (!(0, models_1.isModel)(item))
|
|
212
|
-
return;
|
|
213
|
-
const keys = Object.keys(item);
|
|
214
|
-
const array = (0, models_1.getInvalidFields)(item, "update", permissions).filter((invalidField) => keys.some((key) => key === invalidField));
|
|
215
|
-
if (array.length) {
|
|
216
|
-
throw new domain_core_1.DomainValidationError("Required fields: " + array.join(", "));
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
};
|
|
220
|
-
tslib_1.__decorate([
|
|
221
|
-
(0, lodash_decorators_1.Memoize)(),
|
|
222
|
-
tslib_1.__metadata("design:type", Function),
|
|
223
|
-
tslib_1.__metadata("design:paramtypes", [String]),
|
|
224
|
-
tslib_1.__metadata("design:returntype", Promise)
|
|
225
|
-
], CrudService.prototype, "getAttachmentInfo", null);
|
|
226
|
-
exports.CrudService = CrudService = CrudService_1 = tslib_1.__decorate([
|
|
227
|
-
(0, common_1.Injectable)(),
|
|
228
|
-
tslib_1.__metadata("design:paramtypes", [nestjs_1.PermissionService,
|
|
229
|
-
domain_core_1.IItemRepository,
|
|
230
|
-
domain_core_1.IAttachmentRepository])
|
|
231
|
-
], CrudService);
|
|
232
|
-
//# sourceMappingURL=crud.service.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"crud.service.js","sourceRoot":"","sources":["../../../../../../../../../libs/crud/shell/app-services/src/lib/services/crud/crud.service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SERVICES = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
|
-
const crud_service_1 = require("./crud/crud.service");
|
|
6
|
-
tslib_1.__exportStar(require("./crud/crud.service"), exports);
|
|
7
|
-
exports.SERVICES = [
|
|
8
|
-
crud_service_1.CrudService
|
|
9
|
-
];
|
|
10
|
-
//# sourceMappingURL=index.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../../../../libs/crud/shell/app-services/src/lib/services/index.ts"],"names":[],"mappings":";;;;AAAA,sDAAgD;AAEhD,8DAAoC;AAEvB,QAAA,QAAQ,GAAG;IACpB,0BAAW;CACd,CAAC"}
|
package/test-setup.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
//# sourceMappingURL=test-setup.js.map
|
package/test-setup.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"test-setup.js","sourceRoot":"","sources":["../../../../../libs/crud/shell/app-services/test-setup.ts"],"names":[],"mappings":""}
|
|
File without changes
|