@doctorus/common 0.0.0 → 0.0.2
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 +391 -1
- package/lib/index.d.ts +2 -3
- package/lib/index.js +17 -8
- package/lib/operations/actions.d.ts +41 -0
- package/lib/operations/actions.js +54 -0
- package/lib/operations/index.d.ts +4 -0
- package/lib/operations/index.js +19 -0
- package/lib/operations/operation.d.ts +32 -0
- package/lib/operations/operation.js +61 -0
- package/lib/operations/predefined.d.ts +85 -0
- package/lib/operations/predefined.js +112 -0
- package/lib/operations/resources.d.ts +68 -0
- package/lib/operations/resources.js +140 -0
- package/lib/ssm/index.d.ts +2 -0
- package/lib/ssm/index.js +12 -0
- package/lib/ssm/keys.d.ts +27 -0
- package/lib/ssm/keys.js +32 -0
- package/lib/ssm/utils.d.ts +75 -0
- package/lib/ssm/utils.js +105 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1 +1,391 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @doctorus/common
|
|
2
|
+
|
|
3
|
+
Common TypeScript utilities for Doctorus - A shared library for managing operations, SSM parameters, and access control across infrastructure stacks and frontend applications.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/@doctorus/common)
|
|
6
|
+
[](https://github.com/DoctorusRepoOwner/common/blob/main/LICENSE)
|
|
7
|
+
|
|
8
|
+
## Installation
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
npm install @doctorus/common
|
|
12
|
+
# or
|
|
13
|
+
pnpm add @doctorus/common
|
|
14
|
+
# or
|
|
15
|
+
yarn add @doctorus/common
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
- 🔐 **Operations Module** - Resource-Action pattern for access control and audit logging
|
|
21
|
+
- 🗄️ **SSM Parameters** - AWS SSM Parameter Store utilities with environment support
|
|
22
|
+
- 📋 **Type Safety** - Full TypeScript support with comprehensive type definitions
|
|
23
|
+
- 🏥 **Medical & Public Resources** - Separate categorization for HIPAA compliance
|
|
24
|
+
- ✅ **100% Test Coverage** - Thoroughly tested and production-ready
|
|
25
|
+
|
|
26
|
+
## Modules
|
|
27
|
+
|
|
28
|
+
### 1. Operations Module
|
|
29
|
+
|
|
30
|
+
Manage operations in `RESOURCE:ACTION` format for access control, audit logging, and permission management.
|
|
31
|
+
|
|
32
|
+
#### Basic Usage
|
|
33
|
+
|
|
34
|
+
```typescript
|
|
35
|
+
import { Operation, Operations, Resource, Action } from '@doctorus/common';
|
|
36
|
+
|
|
37
|
+
// Use predefined operations
|
|
38
|
+
const operation = Operations.PATIENT_READ;
|
|
39
|
+
console.log(operation.toString()); // "PATIENT:READ"
|
|
40
|
+
|
|
41
|
+
// Create custom operations
|
|
42
|
+
const customOp = new Operation(Resource.PRESCRIPTION, Action.PRESCRIBE);
|
|
43
|
+
console.log(customOp.toString()); // "PRESCRIPTION:PRESCRIBE"
|
|
44
|
+
|
|
45
|
+
// Parse from string
|
|
46
|
+
const parsed = Operation.fromString("MEDICAL_SERVICE:SCHEDULE");
|
|
47
|
+
if (parsed) {
|
|
48
|
+
console.log(parsed.resource); // Resource.MEDICAL_SERVICE
|
|
49
|
+
console.log(parsed.action); // Action.SCHEDULE
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Compare operations
|
|
53
|
+
const op1 = Operations.PATIENT_READ;
|
|
54
|
+
const op2 = Operations.PATIENT_READ;
|
|
55
|
+
console.log(op1.equals(op2)); // true
|
|
56
|
+
|
|
57
|
+
// Convert to JSON
|
|
58
|
+
const json = operation.toJSON();
|
|
59
|
+
// { resource: "PATIENT", action: "READ", operation: "PATIENT:READ" }
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
#### Resources
|
|
63
|
+
|
|
64
|
+
Resources are categorized as **Medical** (require special access control) or **Public** (standard access control):
|
|
65
|
+
|
|
66
|
+
**Medical Resources:**
|
|
67
|
+
- Patient: `PATIENT`, `PATIENT_MEDICAL_NOTES`, `PATIENT_MEDICAL_PROPERTIES`, `PATIENT_PAYMENT`
|
|
68
|
+
- Medical Services: `MEDICAL_SERVICE`, `MEDICAL_SERVICE_NOTE`, `MEDICAL_SERVICE_SCHEDULE`, `MEDICAL_SERVICE_FEES`, `MEDICAL_SERVICE_STATUS`
|
|
69
|
+
- Clinical: `MEDICAL_RECORD`, `MEDICAL_HISTORY`, `PRESCRIPTION`, `DIAGNOSIS`, `OBSERVATION`, `MEDICATION`, `ALLERGY`, `IMMUNIZATION`, `PROCEDURE`
|
|
70
|
+
- Measurements: `CLINICAL_NOTE`, `VITAL_SIGNS`, `MEASURE_MODEL`, `CALCULATED_MEASURE_MODEL`
|
|
71
|
+
- Diagnostics: `LAB_RESULT`, `IMAGING`
|
|
72
|
+
|
|
73
|
+
**Public Resources:**
|
|
74
|
+
- Account: `ACCOUNT`, `ACCOUNT_OWNERSHIP`, `ACCOUNT_PREFERENCES`
|
|
75
|
+
- User: `USER`, `CONTACT`
|
|
76
|
+
- Documents: `UPLOADED_DOCUMENT`, `DOCUMENT_LAYOUT`, `GENERATED_DOCUMENT`, `DOCUMENT_MODEL`, `SNIPPET`
|
|
77
|
+
- System: `NOTIFICATION`, `REPORT`, `AUDIT_LOG`, `SYSTEM`, `SETTINGS`, `MEMBERSHIP`, `LOCATION`, `TASK_TYPE`
|
|
78
|
+
|
|
79
|
+
#### Actions
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
// CRUD operations
|
|
83
|
+
Action.CREATE, Action.READ, Action.UPDATE, Action.DELETE, Action.PUT, Action.LIST
|
|
84
|
+
|
|
85
|
+
// General actions
|
|
86
|
+
Action.MANAGE, Action.VIEW, Action.SEARCH
|
|
87
|
+
|
|
88
|
+
// Medical-specific actions
|
|
89
|
+
Action.PRESCRIBE, Action.DIAGNOSE, Action.SIGN, Action.VERIFY,
|
|
90
|
+
Action.SCHEDULE, Action.CANCEL, Action.APPROVE, Action.REJECT
|
|
91
|
+
|
|
92
|
+
// Medical service actions
|
|
93
|
+
Action.SET_MEDICAL_SERVICE_STATUS, Action.SET_MEDICAL_SERVICE_FEES
|
|
94
|
+
|
|
95
|
+
// Patient-specific actions
|
|
96
|
+
Action.UPDATE_STATUS, Action.VIEW_PATIENTS,
|
|
97
|
+
Action.PUT_PATIENT_PAYMENT, Action.DELETE_PATIENT_PAYMENT
|
|
98
|
+
|
|
99
|
+
// Data operations
|
|
100
|
+
Action.EXPORT, Action.IMPORT, Action.ARCHIVE, Action.RESTORE,
|
|
101
|
+
Action.SHARE, Action.DOWNLOAD, Action.UPLOAD
|
|
102
|
+
|
|
103
|
+
// System operations
|
|
104
|
+
Action.LOGIN, Action.LOGOUT, Action.CONFIGURE, Action.AUDIT
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
#### Helper Functions
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
import {
|
|
111
|
+
isMedicalResource,
|
|
112
|
+
isPublicResource,
|
|
113
|
+
getAllOperations,
|
|
114
|
+
getOperationsByResource,
|
|
115
|
+
getOperationsByAction
|
|
116
|
+
} from '@doctorus/common';
|
|
117
|
+
|
|
118
|
+
// Check resource type
|
|
119
|
+
if (isMedicalResource(Resource.PATIENT)) {
|
|
120
|
+
// Apply HIPAA-compliant access controls
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (isPublicResource(Resource.USER)) {
|
|
124
|
+
// Apply standard access controls
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// Get all predefined operations
|
|
128
|
+
const allOps = getAllOperations();
|
|
129
|
+
|
|
130
|
+
// Filter operations by resource
|
|
131
|
+
const patientOps = getOperationsByResource(Resource.PATIENT);
|
|
132
|
+
// [PATIENT_CREATE, PATIENT_READ, PATIENT_UPDATE, ...]
|
|
133
|
+
|
|
134
|
+
// Filter operations by action
|
|
135
|
+
const createOps = getOperationsByAction(Action.CREATE);
|
|
136
|
+
// [PATIENT_CREATE, USER_CREATE, MEDICAL_RECORD_CREATE, ...]
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
#### Predefined Operations
|
|
140
|
+
|
|
141
|
+
Commonly used operations are predefined for convenience:
|
|
142
|
+
|
|
143
|
+
```typescript
|
|
144
|
+
// Account operations
|
|
145
|
+
Operations.ACCOUNT_CREATE, Operations.ACCOUNT_READ, Operations.ACCOUNT_UPDATE,
|
|
146
|
+
Operations.ACCOUNT_DELETE, Operations.ACCOUNT_MANAGE
|
|
147
|
+
|
|
148
|
+
// Patient operations
|
|
149
|
+
Operations.PATIENT_CREATE, Operations.PATIENT_READ, Operations.PATIENT_UPDATE,
|
|
150
|
+
Operations.PATIENT_DELETE, Operations.PATIENT_LIST, Operations.PATIENT_VIEW,
|
|
151
|
+
Operations.PATIENT_UPDATE_STATUS
|
|
152
|
+
|
|
153
|
+
// Medical service operations
|
|
154
|
+
Operations.MEDICAL_SERVICE_CREATE, Operations.MEDICAL_SERVICE_READ,
|
|
155
|
+
Operations.MEDICAL_SERVICE_UPDATE, Operations.MEDICAL_SERVICE_DELETE,
|
|
156
|
+
Operations.MEDICAL_SERVICE_MANAGE, Operations.MEDICAL_SERVICE_SCHEDULE,
|
|
157
|
+
Operations.MEDICAL_SERVICE_CANCEL, Operations.MEDICAL_SERVICE_SET_STATUS,
|
|
158
|
+
Operations.MEDICAL_SERVICE_SET_FEES
|
|
159
|
+
|
|
160
|
+
// Prescription operations
|
|
161
|
+
Operations.PRESCRIPTION_CREATE, Operations.PRESCRIPTION_READ,
|
|
162
|
+
Operations.PRESCRIPTION_UPDATE, Operations.PRESCRIPTION_SIGN,
|
|
163
|
+
Operations.PRESCRIPTION_PRESCRIBE
|
|
164
|
+
|
|
165
|
+
// User operations
|
|
166
|
+
Operations.USER_CREATE, Operations.USER_READ, Operations.USER_UPDATE,
|
|
167
|
+
Operations.USER_DELETE, Operations.USER_LOGIN, Operations.USER_LOGOUT
|
|
168
|
+
|
|
169
|
+
// ... and many more
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### 2. SSM Parameters Module
|
|
173
|
+
|
|
174
|
+
Utilities for managing AWS SSM Parameter Store keys with environment support.
|
|
175
|
+
|
|
176
|
+
#### Basic Usage
|
|
177
|
+
|
|
178
|
+
```typescript
|
|
179
|
+
import {
|
|
180
|
+
SSM_PARAM_KEY,
|
|
181
|
+
buildSSMPath,
|
|
182
|
+
buildSSMPathWithPrefix,
|
|
183
|
+
extractEnvFromPath,
|
|
184
|
+
extractKeyFromPath,
|
|
185
|
+
isEnvAgnostic
|
|
186
|
+
} from '@doctorus/common';
|
|
187
|
+
|
|
188
|
+
// Build environment-specific path
|
|
189
|
+
const path = buildSSMPath('prod', SSM_PARAM_KEY.COGNITO_USER_POOL_ID);
|
|
190
|
+
console.log(path); // "/prod/user-pool-id"
|
|
191
|
+
|
|
192
|
+
// Build environment-agnostic path (for shared/central account parameters)
|
|
193
|
+
const sharedPath = buildSSMPath(null, SSM_PARAM_KEY.DB_USER);
|
|
194
|
+
console.log(sharedPath); // "/db-user"
|
|
195
|
+
|
|
196
|
+
// Build path with custom prefix
|
|
197
|
+
const customPath = buildSSMPathWithPrefix(
|
|
198
|
+
'/myapp/prod',
|
|
199
|
+
SSM_PARAM_KEY.GRAPHQL_API_ID
|
|
200
|
+
);
|
|
201
|
+
console.log(customPath); // "/myapp/prod/graphql-api-id"
|
|
202
|
+
|
|
203
|
+
// Extract environment from path
|
|
204
|
+
const env = extractEnvFromPath('/prod/user-pool-id');
|
|
205
|
+
console.log(env); // "prod"
|
|
206
|
+
|
|
207
|
+
// Extract key from path
|
|
208
|
+
const key = extractKeyFromPath('/prod/user-pool-id');
|
|
209
|
+
console.log(key); // SSM_PARAM_KEY.COGNITO_USER_POOL_ID
|
|
210
|
+
|
|
211
|
+
// Check if path is environment-agnostic
|
|
212
|
+
console.log(isEnvAgnostic('/db-user')); // true
|
|
213
|
+
console.log(isEnvAgnostic('/prod/user-pool-id')); // false
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
#### Available SSM Parameter Keys
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
SSM_PARAM_KEY.COGNITO_USER_POOL_ID
|
|
220
|
+
SSM_PARAM_KEY.COGNITO_USER_POOL_WEB_CLIENT_ID
|
|
221
|
+
SSM_PARAM_KEY.COGNITO_OAUTH_DOMAIN
|
|
222
|
+
SSM_PARAM_KEY.RUM_GUEST_ROLE_ARN
|
|
223
|
+
SSM_PARAM_KEY.RUM_IDENTITY_POOL_ID
|
|
224
|
+
SSM_PARAM_KEY.RUM_APP_ID
|
|
225
|
+
SSM_PARAM_KEY.GRAPHQL_HTTP_URL
|
|
226
|
+
SSM_PARAM_KEY.GRAPHQL_WS_URL
|
|
227
|
+
SSM_PARAM_KEY.GRAPHQL_HOST
|
|
228
|
+
SSM_PARAM_KEY.GRAPHQL_API_ID
|
|
229
|
+
SSM_PARAM_KEY.MEDICAL_ASSETS_AWS_CLOUDFRONT_PRIVATE_KEY
|
|
230
|
+
SSM_PARAM_KEY.MEDICAL_ASSETS_AWS_CLOUDFRONT_KEY_ID
|
|
231
|
+
SSM_PARAM_KEY.MEDICAL_ASSETS_BUCKET_NAME
|
|
232
|
+
SSM_PARAM_KEY.PUBLIC_ASSETS_BUCKET_NAME
|
|
233
|
+
SSM_PARAM_KEY.DB_USER
|
|
234
|
+
SSM_PARAM_KEY.DB_PASSWORD
|
|
235
|
+
SSM_PARAM_KEY.MEDICAL_ASSETS_DISTRIBUTION_DOMAIN_NAME
|
|
236
|
+
SSM_PARAM_KEY.BASE_HOST
|
|
237
|
+
SSM_PARAM_KEY.EMAIL_FROM_ADDRESS
|
|
238
|
+
SSM_PARAM_KEY.EVENT_API_REAL_TIME_DNS
|
|
239
|
+
SSM_PARAM_KEY.EVENT_API_HTTP_DNS
|
|
240
|
+
SSM_PARAM_KEY.NOTIFIED_EVENT_ACTIONS
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
## Use Cases
|
|
244
|
+
|
|
245
|
+
### 1. Access Control
|
|
246
|
+
|
|
247
|
+
```typescript
|
|
248
|
+
import { Operation, isMedicalResource } from '@doctorus/common';
|
|
249
|
+
|
|
250
|
+
function checkPermission(userPermissions: string[], operation: Operation): boolean {
|
|
251
|
+
// Check if user has permission for this operation
|
|
252
|
+
const hasPermission = userPermissions.includes(operation.toString());
|
|
253
|
+
|
|
254
|
+
// Apply additional checks for medical resources
|
|
255
|
+
if (isMedicalResource(operation.resource)) {
|
|
256
|
+
// Enforce HIPAA compliance, additional logging, etc.
|
|
257
|
+
return hasPermission && user.hasHIPAAAccess;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return hasPermission;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Usage
|
|
264
|
+
const canRead = checkPermission(
|
|
265
|
+
userPermissions,
|
|
266
|
+
Operations.PATIENT_READ
|
|
267
|
+
);
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### 2. Audit Logging
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
import { Operation, Operations } from '@doctorus/common';
|
|
274
|
+
|
|
275
|
+
interface AuditLog {
|
|
276
|
+
timestamp: Date;
|
|
277
|
+
userId: string;
|
|
278
|
+
operation: string;
|
|
279
|
+
resourceId: string;
|
|
280
|
+
success: boolean;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
function logAudit(
|
|
284
|
+
userId: string,
|
|
285
|
+
operation: Operation,
|
|
286
|
+
resourceId: string,
|
|
287
|
+
success: boolean
|
|
288
|
+
) {
|
|
289
|
+
const log: AuditLog = {
|
|
290
|
+
timestamp: new Date(),
|
|
291
|
+
userId,
|
|
292
|
+
operation: operation.toString(),
|
|
293
|
+
resourceId,
|
|
294
|
+
success
|
|
295
|
+
};
|
|
296
|
+
|
|
297
|
+
// Store in audit log database
|
|
298
|
+
auditLogService.create(log);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Usage
|
|
302
|
+
logAudit('user123', Operations.PRESCRIPTION_PRESCRIBE, 'rx-456', true);
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
### 3. Infrastructure Configuration
|
|
306
|
+
|
|
307
|
+
```typescript
|
|
308
|
+
import { buildSSMPath, SSM_PARAM_KEY } from '@doctorus/common';
|
|
309
|
+
import { StringParameter } from 'aws-cdk-lib/aws-ssm';
|
|
310
|
+
|
|
311
|
+
// In your CDK stack
|
|
312
|
+
const env = 'prod';
|
|
313
|
+
|
|
314
|
+
const userPoolId = StringParameter.valueFromLookup(
|
|
315
|
+
this,
|
|
316
|
+
buildSSMPath(env, SSM_PARAM_KEY.COGNITO_USER_POOL_ID)
|
|
317
|
+
);
|
|
318
|
+
|
|
319
|
+
const graphqlUrl = StringParameter.valueFromLookup(
|
|
320
|
+
this,
|
|
321
|
+
buildSSMPath(env, SSM_PARAM_KEY.GRAPHQL_HTTP_URL)
|
|
322
|
+
);
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
### 4. Frontend Configuration
|
|
326
|
+
|
|
327
|
+
```typescript
|
|
328
|
+
import { buildSSMPath, SSM_PARAM_KEY } from '@doctorus/common';
|
|
329
|
+
import { SSM } from '@aws-sdk/client-ssm';
|
|
330
|
+
|
|
331
|
+
async function loadConfig(environment: string) {
|
|
332
|
+
const ssm = new SSM();
|
|
333
|
+
|
|
334
|
+
const params = [
|
|
335
|
+
SSM_PARAM_KEY.COGNITO_USER_POOL_ID,
|
|
336
|
+
SSM_PARAM_KEY.GRAPHQL_HTTP_URL,
|
|
337
|
+
SSM_PARAM_KEY.RUM_APP_ID
|
|
338
|
+
];
|
|
339
|
+
|
|
340
|
+
const config: Record<string, string> = {};
|
|
341
|
+
|
|
342
|
+
for (const param of params) {
|
|
343
|
+
const path = buildSSMPath(environment, param);
|
|
344
|
+
const response = await ssm.getParameter({ Name: path });
|
|
345
|
+
config[param] = response.Parameter?.Value || '';
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return config;
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
## Development
|
|
353
|
+
|
|
354
|
+
```bash
|
|
355
|
+
# Install dependencies
|
|
356
|
+
pnpm install
|
|
357
|
+
|
|
358
|
+
# Run tests
|
|
359
|
+
pnpm test
|
|
360
|
+
|
|
361
|
+
# Build
|
|
362
|
+
pnpm build
|
|
363
|
+
|
|
364
|
+
# Run projen (regenerate configuration)
|
|
365
|
+
pnpm projen
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
## Testing
|
|
369
|
+
|
|
370
|
+
The library includes comprehensive tests with 100% coverage:
|
|
371
|
+
|
|
372
|
+
```bash
|
|
373
|
+
pnpm test
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
## Contributing
|
|
377
|
+
|
|
378
|
+
Contributions are welcome! Please feel free to submit a Pull Request.
|
|
379
|
+
|
|
380
|
+
## License
|
|
381
|
+
|
|
382
|
+
Apache-2.0
|
|
383
|
+
|
|
384
|
+
## Related
|
|
385
|
+
|
|
386
|
+
- [AWS Systems Manager Parameter Store](https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-parameter-store.html)
|
|
387
|
+
- [AWS CDK](https://aws.amazon.com/cdk/)
|
|
388
|
+
|
|
389
|
+
---
|
|
390
|
+
|
|
391
|
+
Built with ❤️ for Doctorus
|
package/lib/index.d.ts
CHANGED
|
@@ -1,3 +1,2 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
3
|
-
}
|
|
1
|
+
export * from "./ssm";
|
|
2
|
+
export * from "./operations";
|
package/lib/index.js
CHANGED
|
@@ -1,10 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
Object.
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
7
|
}
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./ssm"), exports);
|
|
18
|
+
__exportStar(require("./operations"), exports);
|
|
19
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7OztBQUFBLHdDQUFzQjtBQUN0QiwrQ0FBNkIiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tIFwiLi9zc21cIjtcbmV4cG9ydCAqIGZyb20gXCIuL29wZXJhdGlvbnNcIjtcbiJdfQ==
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Action types for operations
|
|
3
|
+
*/
|
|
4
|
+
export declare enum Action {
|
|
5
|
+
CREATE = "CREATE",
|
|
6
|
+
READ = "READ",
|
|
7
|
+
UPDATE = "UPDATE",
|
|
8
|
+
DELETE = "DELETE",
|
|
9
|
+
PUT = "PUT",
|
|
10
|
+
LIST = "LIST",
|
|
11
|
+
MANAGE = "MANAGE",
|
|
12
|
+
VIEW = "VIEW",
|
|
13
|
+
SEARCH = "SEARCH",
|
|
14
|
+
GRANT = "GRANT",
|
|
15
|
+
REVOKE = "REVOKE",
|
|
16
|
+
PRESCRIBE = "PRESCRIBE",
|
|
17
|
+
DIAGNOSE = "DIAGNOSE",
|
|
18
|
+
SCHEDULE = "SCHEDULE",
|
|
19
|
+
CANCEL = "CANCEL",
|
|
20
|
+
APPROVE = "APPROVE",
|
|
21
|
+
REJECT = "REJECT",
|
|
22
|
+
SIGN = "SIGN",
|
|
23
|
+
VERIFY = "VERIFY",
|
|
24
|
+
SET_MEDICAL_SERVICE_STATUS = "SET_MEDICAL_SERVICE_STATUS",
|
|
25
|
+
SET_MEDICAL_SERVICE_FEES = "SET_MEDICAL_SERVICE_FEES",
|
|
26
|
+
UPDATE_STATUS = "UPDATE_STATUS",
|
|
27
|
+
VIEW_PATIENTS = "VIEW_PATIENTS",
|
|
28
|
+
PUT_PATIENT_PAYMENT = "PUT_PATIENT_PAYMENT",
|
|
29
|
+
DELETE_PATIENT_PAYMENT = "DELETE_PATIENT_PAYMENT",
|
|
30
|
+
EXPORT = "EXPORT",
|
|
31
|
+
IMPORT = "IMPORT",
|
|
32
|
+
ARCHIVE = "ARCHIVE",
|
|
33
|
+
RESTORE = "RESTORE",
|
|
34
|
+
SHARE = "SHARE",
|
|
35
|
+
DOWNLOAD = "DOWNLOAD",
|
|
36
|
+
UPLOAD = "UPLOAD",
|
|
37
|
+
LOGIN = "LOGIN",
|
|
38
|
+
LOGOUT = "LOGOUT",
|
|
39
|
+
CONFIGURE = "CONFIGURE",
|
|
40
|
+
AUDIT = "AUDIT"
|
|
41
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Action = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Action types for operations
|
|
6
|
+
*/
|
|
7
|
+
var Action;
|
|
8
|
+
(function (Action) {
|
|
9
|
+
// CRUD operations
|
|
10
|
+
Action["CREATE"] = "CREATE";
|
|
11
|
+
Action["READ"] = "READ";
|
|
12
|
+
Action["UPDATE"] = "UPDATE";
|
|
13
|
+
Action["DELETE"] = "DELETE";
|
|
14
|
+
Action["PUT"] = "PUT";
|
|
15
|
+
Action["LIST"] = "LIST";
|
|
16
|
+
// General actions
|
|
17
|
+
Action["MANAGE"] = "MANAGE";
|
|
18
|
+
Action["VIEW"] = "VIEW";
|
|
19
|
+
Action["SEARCH"] = "SEARCH";
|
|
20
|
+
// Access control
|
|
21
|
+
Action["GRANT"] = "GRANT";
|
|
22
|
+
Action["REVOKE"] = "REVOKE";
|
|
23
|
+
// Medical specific
|
|
24
|
+
Action["PRESCRIBE"] = "PRESCRIBE";
|
|
25
|
+
Action["DIAGNOSE"] = "DIAGNOSE";
|
|
26
|
+
Action["SCHEDULE"] = "SCHEDULE";
|
|
27
|
+
Action["CANCEL"] = "CANCEL";
|
|
28
|
+
Action["APPROVE"] = "APPROVE";
|
|
29
|
+
Action["REJECT"] = "REJECT";
|
|
30
|
+
Action["SIGN"] = "SIGN";
|
|
31
|
+
Action["VERIFY"] = "VERIFY";
|
|
32
|
+
// Medical service specific
|
|
33
|
+
Action["SET_MEDICAL_SERVICE_STATUS"] = "SET_MEDICAL_SERVICE_STATUS";
|
|
34
|
+
Action["SET_MEDICAL_SERVICE_FEES"] = "SET_MEDICAL_SERVICE_FEES";
|
|
35
|
+
// Patient specific
|
|
36
|
+
Action["UPDATE_STATUS"] = "UPDATE_STATUS";
|
|
37
|
+
Action["VIEW_PATIENTS"] = "VIEW_PATIENTS";
|
|
38
|
+
Action["PUT_PATIENT_PAYMENT"] = "PUT_PATIENT_PAYMENT";
|
|
39
|
+
Action["DELETE_PATIENT_PAYMENT"] = "DELETE_PATIENT_PAYMENT";
|
|
40
|
+
// Data operations
|
|
41
|
+
Action["EXPORT"] = "EXPORT";
|
|
42
|
+
Action["IMPORT"] = "IMPORT";
|
|
43
|
+
Action["ARCHIVE"] = "ARCHIVE";
|
|
44
|
+
Action["RESTORE"] = "RESTORE";
|
|
45
|
+
Action["SHARE"] = "SHARE";
|
|
46
|
+
Action["DOWNLOAD"] = "DOWNLOAD";
|
|
47
|
+
Action["UPLOAD"] = "UPLOAD";
|
|
48
|
+
// System operations
|
|
49
|
+
Action["LOGIN"] = "LOGIN";
|
|
50
|
+
Action["LOGOUT"] = "LOGOUT";
|
|
51
|
+
Action["CONFIGURE"] = "CONFIGURE";
|
|
52
|
+
Action["AUDIT"] = "AUDIT";
|
|
53
|
+
})(Action || (exports.Action = Action = {}));
|
|
54
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWN0aW9ucy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9vcGVyYXRpb25zL2FjdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUE7O0dBRUc7QUFDSCxJQUFZLE1Bb0RYO0FBcERELFdBQVksTUFBTTtJQUNoQixrQkFBa0I7SUFDbEIsMkJBQWlCLENBQUE7SUFDakIsdUJBQWEsQ0FBQTtJQUNiLDJCQUFpQixDQUFBO0lBQ2pCLDJCQUFpQixDQUFBO0lBQ2pCLHFCQUFXLENBQUE7SUFDWCx1QkFBYSxDQUFBO0lBRWIsa0JBQWtCO0lBQ2xCLDJCQUFpQixDQUFBO0lBQ2pCLHVCQUFhLENBQUE7SUFDYiwyQkFBaUIsQ0FBQTtJQUVqQixpQkFBaUI7SUFDakIseUJBQWUsQ0FBQTtJQUNmLDJCQUFpQixDQUFBO0lBRWpCLG1CQUFtQjtJQUNuQixpQ0FBdUIsQ0FBQTtJQUN2QiwrQkFBcUIsQ0FBQTtJQUNyQiwrQkFBcUIsQ0FBQTtJQUNyQiwyQkFBaUIsQ0FBQTtJQUNqQiw2QkFBbUIsQ0FBQTtJQUNuQiwyQkFBaUIsQ0FBQTtJQUNqQix1QkFBYSxDQUFBO0lBQ2IsMkJBQWlCLENBQUE7SUFFakIsMkJBQTJCO0lBQzNCLG1FQUF5RCxDQUFBO0lBQ3pELCtEQUFxRCxDQUFBO0lBRXJELG1CQUFtQjtJQUNuQix5Q0FBK0IsQ0FBQTtJQUMvQix5Q0FBK0IsQ0FBQTtJQUMvQixxREFBMkMsQ0FBQTtJQUMzQywyREFBaUQsQ0FBQTtJQUVqRCxrQkFBa0I7SUFDbEIsMkJBQWlCLENBQUE7SUFDakIsMkJBQWlCLENBQUE7SUFDakIsNkJBQW1CLENBQUE7SUFDbkIsNkJBQW1CLENBQUE7SUFDbkIseUJBQWUsQ0FBQTtJQUNmLCtCQUFxQixDQUFBO0lBQ3JCLDJCQUFpQixDQUFBO0lBRWpCLG9CQUFvQjtJQUNwQix5QkFBZSxDQUFBO0lBQ2YsMkJBQWlCLENBQUE7SUFDakIsaUNBQXVCLENBQUE7SUFDdkIseUJBQWUsQ0FBQTtBQUNqQixDQUFDLEVBcERXLE1BQU0sc0JBQU4sTUFBTSxRQW9EakIiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcbiAqIEFjdGlvbiB0eXBlcyBmb3Igb3BlcmF0aW9uc1xuICovXG5leHBvcnQgZW51bSBBY3Rpb24ge1xuICAvLyBDUlVEIG9wZXJhdGlvbnNcbiAgQ1JFQVRFID0gXCJDUkVBVEVcIixcbiAgUkVBRCA9IFwiUkVBRFwiLFxuICBVUERBVEUgPSBcIlVQREFURVwiLFxuICBERUxFVEUgPSBcIkRFTEVURVwiLFxuICBQVVQgPSBcIlBVVFwiLFxuICBMSVNUID0gXCJMSVNUXCIsXG5cbiAgLy8gR2VuZXJhbCBhY3Rpb25zXG4gIE1BTkFHRSA9IFwiTUFOQUdFXCIsXG4gIFZJRVcgPSBcIlZJRVdcIixcbiAgU0VBUkNIID0gXCJTRUFSQ0hcIixcblxuICAvLyBBY2Nlc3MgY29udHJvbFxuICBHUkFOVCA9IFwiR1JBTlRcIixcbiAgUkVWT0tFID0gXCJSRVZPS0VcIixcblxuICAvLyBNZWRpY2FsIHNwZWNpZmljXG4gIFBSRVNDUklCRSA9IFwiUFJFU0NSSUJFXCIsXG4gIERJQUdOT1NFID0gXCJESUFHTk9TRVwiLFxuICBTQ0hFRFVMRSA9IFwiU0NIRURVTEVcIixcbiAgQ0FOQ0VMID0gXCJDQU5DRUxcIixcbiAgQVBQUk9WRSA9IFwiQVBQUk9WRVwiLFxuICBSRUpFQ1QgPSBcIlJFSkVDVFwiLFxuICBTSUdOID0gXCJTSUdOXCIsXG4gIFZFUklGWSA9IFwiVkVSSUZZXCIsXG5cbiAgLy8gTWVkaWNhbCBzZXJ2aWNlIHNwZWNpZmljXG4gIFNFVF9NRURJQ0FMX1NFUlZJQ0VfU1RBVFVTID0gXCJTRVRfTUVESUNBTF9TRVJWSUNFX1NUQVRVU1wiLFxuICBTRVRfTUVESUNBTF9TRVJWSUNFX0ZFRVMgPSBcIlNFVF9NRURJQ0FMX1NFUlZJQ0VfRkVFU1wiLFxuXG4gIC8vIFBhdGllbnQgc3BlY2lmaWNcbiAgVVBEQVRFX1NUQVRVUyA9IFwiVVBEQVRFX1NUQVRVU1wiLFxuICBWSUVXX1BBVElFTlRTID0gXCJWSUVXX1BBVElFTlRTXCIsXG4gIFBVVF9QQVRJRU5UX1BBWU1FTlQgPSBcIlBVVF9QQVRJRU5UX1BBWU1FTlRcIixcbiAgREVMRVRFX1BBVElFTlRfUEFZTUVOVCA9IFwiREVMRVRFX1BBVElFTlRfUEFZTUVOVFwiLFxuXG4gIC8vIERhdGEgb3BlcmF0aW9uc1xuICBFWFBPUlQgPSBcIkVYUE9SVFwiLFxuICBJTVBPUlQgPSBcIklNUE9SVFwiLFxuICBBUkNISVZFID0gXCJBUkNISVZFXCIsXG4gIFJFU1RPUkUgPSBcIlJFU1RPUkVcIixcbiAgU0hBUkUgPSBcIlNIQVJFXCIsXG4gIERPV05MT0FEID0gXCJET1dOTE9BRFwiLFxuICBVUExPQUQgPSBcIlVQTE9BRFwiLFxuXG4gIC8vIFN5c3RlbSBvcGVyYXRpb25zXG4gIExPR0lOID0gXCJMT0dJTlwiLFxuICBMT0dPVVQgPSBcIkxPR09VVFwiLFxuICBDT05GSUdVUkUgPSBcIkNPTkZJR1VSRVwiLFxuICBBVURJVCA9IFwiQVVESVRcIixcbn1cbiJdfQ==
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { Resource, MEDICAL_RESOURCES, PUBLIC_RESOURCES, isMedicalResource, isPublicResource, } from "./resources";
|
|
2
|
+
export { Action } from "./actions";
|
|
3
|
+
export { Operation } from "./operation";
|
|
4
|
+
export { Operations, getAllOperations, getOperationsByResource, getOperationsByAction, } from "./predefined";
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getOperationsByAction = exports.getOperationsByResource = exports.getAllOperations = exports.Operations = exports.Operation = exports.Action = exports.isPublicResource = exports.isMedicalResource = exports.PUBLIC_RESOURCES = exports.MEDICAL_RESOURCES = exports.Resource = void 0;
|
|
4
|
+
var resources_1 = require("./resources");
|
|
5
|
+
Object.defineProperty(exports, "Resource", { enumerable: true, get: function () { return resources_1.Resource; } });
|
|
6
|
+
Object.defineProperty(exports, "MEDICAL_RESOURCES", { enumerable: true, get: function () { return resources_1.MEDICAL_RESOURCES; } });
|
|
7
|
+
Object.defineProperty(exports, "PUBLIC_RESOURCES", { enumerable: true, get: function () { return resources_1.PUBLIC_RESOURCES; } });
|
|
8
|
+
Object.defineProperty(exports, "isMedicalResource", { enumerable: true, get: function () { return resources_1.isMedicalResource; } });
|
|
9
|
+
Object.defineProperty(exports, "isPublicResource", { enumerable: true, get: function () { return resources_1.isPublicResource; } });
|
|
10
|
+
var actions_1 = require("./actions");
|
|
11
|
+
Object.defineProperty(exports, "Action", { enumerable: true, get: function () { return actions_1.Action; } });
|
|
12
|
+
var operation_1 = require("./operation");
|
|
13
|
+
Object.defineProperty(exports, "Operation", { enumerable: true, get: function () { return operation_1.Operation; } });
|
|
14
|
+
var predefined_1 = require("./predefined");
|
|
15
|
+
Object.defineProperty(exports, "Operations", { enumerable: true, get: function () { return predefined_1.Operations; } });
|
|
16
|
+
Object.defineProperty(exports, "getAllOperations", { enumerable: true, get: function () { return predefined_1.getAllOperations; } });
|
|
17
|
+
Object.defineProperty(exports, "getOperationsByResource", { enumerable: true, get: function () { return predefined_1.getOperationsByResource; } });
|
|
18
|
+
Object.defineProperty(exports, "getOperationsByAction", { enumerable: true, get: function () { return predefined_1.getOperationsByAction; } });
|
|
19
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvb3BlcmF0aW9ucy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSx5Q0FNcUI7QUFMbkIscUdBQUEsUUFBUSxPQUFBO0FBQ1IsOEdBQUEsaUJBQWlCLE9BQUE7QUFDakIsNkdBQUEsZ0JBQWdCLE9BQUE7QUFDaEIsOEdBQUEsaUJBQWlCLE9BQUE7QUFDakIsNkdBQUEsZ0JBQWdCLE9BQUE7QUFFbEIscUNBQW1DO0FBQTFCLGlHQUFBLE1BQU0sT0FBQTtBQUNmLHlDQUF3QztBQUEvQixzR0FBQSxTQUFTLE9BQUE7QUFDbEIsMkNBS3NCO0FBSnBCLHdHQUFBLFVBQVUsT0FBQTtBQUNWLDhHQUFBLGdCQUFnQixPQUFBO0FBQ2hCLHFIQUFBLHVCQUF1QixPQUFBO0FBQ3ZCLG1IQUFBLHFCQUFxQixPQUFBIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0IHtcbiAgUmVzb3VyY2UsXG4gIE1FRElDQUxfUkVTT1VSQ0VTLFxuICBQVUJMSUNfUkVTT1VSQ0VTLFxuICBpc01lZGljYWxSZXNvdXJjZSxcbiAgaXNQdWJsaWNSZXNvdXJjZSxcbn0gZnJvbSBcIi4vcmVzb3VyY2VzXCI7XG5leHBvcnQgeyBBY3Rpb24gfSBmcm9tIFwiLi9hY3Rpb25zXCI7XG5leHBvcnQgeyBPcGVyYXRpb24gfSBmcm9tIFwiLi9vcGVyYXRpb25cIjtcbmV4cG9ydCB7XG4gIE9wZXJhdGlvbnMsXG4gIGdldEFsbE9wZXJhdGlvbnMsXG4gIGdldE9wZXJhdGlvbnNCeVJlc291cmNlLFxuICBnZXRPcGVyYXRpb25zQnlBY3Rpb24sXG59IGZyb20gXCIuL3ByZWRlZmluZWRcIjtcbiJdfQ==
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Action } from "./actions";
|
|
2
|
+
import { Resource } from "./resources";
|
|
3
|
+
/**
|
|
4
|
+
* Operation in RESOURCE:ACTION format
|
|
5
|
+
*/
|
|
6
|
+
export declare class Operation {
|
|
7
|
+
readonly resource: Resource;
|
|
8
|
+
readonly action: Action;
|
|
9
|
+
/**
|
|
10
|
+
* Create operation from string
|
|
11
|
+
* @param operationString - String in RESOURCE:ACTION format
|
|
12
|
+
* @returns Operation instance or null if invalid
|
|
13
|
+
*/
|
|
14
|
+
static fromString(operationString: string): Operation | null;
|
|
15
|
+
constructor(resource: Resource, action: Action);
|
|
16
|
+
/**
|
|
17
|
+
* Get operation string in RESOURCE:ACTION format
|
|
18
|
+
*/
|
|
19
|
+
toString(): string;
|
|
20
|
+
/**
|
|
21
|
+
* Check if two operations are equal
|
|
22
|
+
*/
|
|
23
|
+
equals(other: Operation): boolean;
|
|
24
|
+
/**
|
|
25
|
+
* Convert to JSON representation
|
|
26
|
+
*/
|
|
27
|
+
toJSON(): {
|
|
28
|
+
resource: Resource;
|
|
29
|
+
action: Action;
|
|
30
|
+
operation: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Operation = void 0;
|
|
4
|
+
const actions_1 = require("./actions");
|
|
5
|
+
const resources_1 = require("./resources");
|
|
6
|
+
/**
|
|
7
|
+
* Operation in RESOURCE:ACTION format
|
|
8
|
+
*/
|
|
9
|
+
class Operation {
|
|
10
|
+
resource;
|
|
11
|
+
action;
|
|
12
|
+
/**
|
|
13
|
+
* Create operation from string
|
|
14
|
+
* @param operationString - String in RESOURCE:ACTION format
|
|
15
|
+
* @returns Operation instance or null if invalid
|
|
16
|
+
*/
|
|
17
|
+
static fromString(operationString) {
|
|
18
|
+
const parts = operationString.split(":");
|
|
19
|
+
if (parts.length !== 2) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
const [resourceStr, actionStr] = parts;
|
|
23
|
+
// Validate resource
|
|
24
|
+
if (!Object.values(resources_1.Resource).includes(resourceStr)) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
// Validate action
|
|
28
|
+
if (!Object.values(actions_1.Action).includes(actionStr)) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
return new Operation(resourceStr, actionStr);
|
|
32
|
+
}
|
|
33
|
+
constructor(resource, action) {
|
|
34
|
+
this.resource = resource;
|
|
35
|
+
this.action = action;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Get operation string in RESOURCE:ACTION format
|
|
39
|
+
*/
|
|
40
|
+
toString() {
|
|
41
|
+
return `${this.resource}:${this.action}`;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Check if two operations are equal
|
|
45
|
+
*/
|
|
46
|
+
equals(other) {
|
|
47
|
+
return this.resource === other.resource && this.action === other.action;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Convert to JSON representation
|
|
51
|
+
*/
|
|
52
|
+
toJSON() {
|
|
53
|
+
return {
|
|
54
|
+
resource: this.resource,
|
|
55
|
+
action: this.action,
|
|
56
|
+
operation: this.toString(),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.Operation = Operation;
|
|
61
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3BlcmF0aW9uLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL29wZXJhdGlvbnMvb3BlcmF0aW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLHVDQUFtQztBQUNuQywyQ0FBdUM7QUFFdkM7O0dBRUc7QUFDSCxNQUFhLFNBQVM7SUE0QkY7SUFDQTtJQTVCbEI7Ozs7T0FJRztJQUNILE1BQU0sQ0FBQyxVQUFVLENBQUMsZUFBdUI7UUFDdkMsTUFBTSxLQUFLLEdBQUcsZUFBZSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUN6QyxJQUFJLEtBQUssQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDdkIsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO1FBRUQsTUFBTSxDQUFDLFdBQVcsRUFBRSxTQUFTLENBQUMsR0FBRyxLQUFLLENBQUM7UUFFdkMsb0JBQW9CO1FBQ3BCLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLG9CQUFRLENBQUMsQ0FBQyxRQUFRLENBQUMsV0FBdUIsQ0FBQyxFQUFFLENBQUM7WUFDL0QsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO1FBRUQsa0JBQWtCO1FBQ2xCLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLGdCQUFNLENBQUMsQ0FBQyxRQUFRLENBQUMsU0FBbUIsQ0FBQyxFQUFFLENBQUM7WUFDekQsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO1FBRUQsT0FBTyxJQUFJLFNBQVMsQ0FBQyxXQUF1QixFQUFFLFNBQW1CLENBQUMsQ0FBQztJQUNyRSxDQUFDO0lBRUQsWUFDa0IsUUFBa0IsRUFDbEIsTUFBYztRQURkLGFBQVEsR0FBUixRQUFRLENBQVU7UUFDbEIsV0FBTSxHQUFOLE1BQU0sQ0FBUTtJQUM3QixDQUFDO0lBRUo7O09BRUc7SUFDSCxRQUFRO1FBQ04sT0FBTyxHQUFHLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO0lBQzNDLENBQUM7SUFFRDs7T0FFRztJQUNILE1BQU0sQ0FBQyxLQUFnQjtRQUNyQixPQUFPLElBQUksQ0FBQyxRQUFRLEtBQUssS0FBSyxDQUFDLFFBQVEsSUFBSSxJQUFJLENBQUMsTUFBTSxLQUFLLEtBQUssQ0FBQyxNQUFNLENBQUM7SUFDMUUsQ0FBQztJQUVEOztPQUVHO0lBQ0gsTUFBTTtRQUNKLE9BQU87WUFDTCxRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVE7WUFDdkIsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO1lBQ25CLFNBQVMsRUFBRSxJQUFJLENBQUMsUUFBUSxFQUFFO1NBQzNCLENBQUM7SUFDSixDQUFDO0NBQ0Y7QUF4REQsOEJBd0RDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQWN0aW9uIH0gZnJvbSBcIi4vYWN0aW9uc1wiO1xuaW1wb3J0IHsgUmVzb3VyY2UgfSBmcm9tIFwiLi9yZXNvdXJjZXNcIjtcblxuLyoqXG4gKiBPcGVyYXRpb24gaW4gUkVTT1VSQ0U6QUNUSU9OIGZvcm1hdFxuICovXG5leHBvcnQgY2xhc3MgT3BlcmF0aW9uIHtcbiAgLyoqXG4gICAqIENyZWF0ZSBvcGVyYXRpb24gZnJvbSBzdHJpbmdcbiAgICogQHBhcmFtIG9wZXJhdGlvblN0cmluZyAtIFN0cmluZyBpbiBSRVNPVVJDRTpBQ1RJT04gZm9ybWF0XG4gICAqIEByZXR1cm5zIE9wZXJhdGlvbiBpbnN0YW5jZSBvciBudWxsIGlmIGludmFsaWRcbiAgICovXG4gIHN0YXRpYyBmcm9tU3RyaW5nKG9wZXJhdGlvblN0cmluZzogc3RyaW5nKTogT3BlcmF0aW9uIHwgbnVsbCB7XG4gICAgY29uc3QgcGFydHMgPSBvcGVyYXRpb25TdHJpbmcuc3BsaXQoXCI6XCIpO1xuICAgIGlmIChwYXJ0cy5sZW5ndGggIT09IDIpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IFtyZXNvdXJjZVN0ciwgYWN0aW9uU3RyXSA9IHBhcnRzO1xuXG4gICAgLy8gVmFsaWRhdGUgcmVzb3VyY2VcbiAgICBpZiAoIU9iamVjdC52YWx1ZXMoUmVzb3VyY2UpLmluY2x1ZGVzKHJlc291cmNlU3RyIGFzIFJlc291cmNlKSkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgLy8gVmFsaWRhdGUgYWN0aW9uXG4gICAgaWYgKCFPYmplY3QudmFsdWVzKEFjdGlvbikuaW5jbHVkZXMoYWN0aW9uU3RyIGFzIEFjdGlvbikpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiBuZXcgT3BlcmF0aW9uKHJlc291cmNlU3RyIGFzIFJlc291cmNlLCBhY3Rpb25TdHIgYXMgQWN0aW9uKTtcbiAgfVxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyByZWFkb25seSByZXNvdXJjZTogUmVzb3VyY2UsXG4gICAgcHVibGljIHJlYWRvbmx5IGFjdGlvbjogQWN0aW9uLFxuICApIHt9XG5cbiAgLyoqXG4gICAqIEdldCBvcGVyYXRpb24gc3RyaW5nIGluIFJFU09VUkNFOkFDVElPTiBmb3JtYXRcbiAgICovXG4gIHRvU3RyaW5nKCk6IHN0cmluZyB7XG4gICAgcmV0dXJuIGAke3RoaXMucmVzb3VyY2V9OiR7dGhpcy5hY3Rpb259YDtcbiAgfVxuXG4gIC8qKlxuICAgKiBDaGVjayBpZiB0d28gb3BlcmF0aW9ucyBhcmUgZXF1YWxcbiAgICovXG4gIGVxdWFscyhvdGhlcjogT3BlcmF0aW9uKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMucmVzb3VyY2UgPT09IG90aGVyLnJlc291cmNlICYmIHRoaXMuYWN0aW9uID09PSBvdGhlci5hY3Rpb247XG4gIH1cblxuICAvKipcbiAgICogQ29udmVydCB0byBKU09OIHJlcHJlc2VudGF0aW9uXG4gICAqL1xuICB0b0pTT04oKTogeyByZXNvdXJjZTogUmVzb3VyY2U7IGFjdGlvbjogQWN0aW9uOyBvcGVyYXRpb246IHN0cmluZyB9IHtcbiAgICByZXR1cm4ge1xuICAgICAgcmVzb3VyY2U6IHRoaXMucmVzb3VyY2UsXG4gICAgICBhY3Rpb246IHRoaXMuYWN0aW9uLFxuICAgICAgb3BlcmF0aW9uOiB0aGlzLnRvU3RyaW5nKCksXG4gICAgfTtcbiAgfVxufVxuIl19
|