@aopslab/domain-kit-docman 0.1.4

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.
Files changed (64) hide show
  1. package/LICENSE +202 -0
  2. package/NOTICE +6 -0
  3. package/README.md +79 -0
  4. package/dist/config/config.d.ts +55 -0
  5. package/dist/config/config.js +176 -0
  6. package/dist/domain-services/index.d.ts +7 -0
  7. package/dist/domain-services/index.js +7 -0
  8. package/dist/domain-services/jwt.d.ts +1 -0
  9. package/dist/domain-services/jwt.js +5 -0
  10. package/dist/domain-services/metrics.d.ts +5 -0
  11. package/dist/domain-services/metrics.js +7 -0
  12. package/dist/domain-services/presets.d.ts +3 -0
  13. package/dist/domain-services/presets.js +4 -0
  14. package/dist/domain-services/provider.d.ts +2 -0
  15. package/dist/domain-services/provider.js +564 -0
  16. package/dist/domain-services/resilience.d.ts +6 -0
  17. package/dist/domain-services/resilience.js +19 -0
  18. package/dist/domain-services/types.d.ts +179 -0
  19. package/dist/domain-services/types.js +1 -0
  20. package/dist/domain-services/unified.d.ts +272 -0
  21. package/dist/domain-services/unified.js +210 -0
  22. package/dist/errors/error.map.d.ts +21 -0
  23. package/dist/errors/error.map.js +47 -0
  24. package/dist/errors/friendly.d.ts +31 -0
  25. package/dist/errors/friendly.js +407 -0
  26. package/dist/errors/i18n.d.ts +4 -0
  27. package/dist/errors/i18n.js +10 -0
  28. package/dist/errors/index.d.ts +3 -0
  29. package/dist/errors/index.js +3 -0
  30. package/dist/index.d.ts +9 -0
  31. package/dist/index.js +7 -0
  32. package/dist/operations/catalog.d.ts +11 -0
  33. package/dist/operations/catalog.js +299 -0
  34. package/dist/operations/contract.d.ts +31 -0
  35. package/dist/operations/contract.js +667 -0
  36. package/dist/operations/dcm.d.ts +58 -0
  37. package/dist/operations/dcm.js +168 -0
  38. package/dist/operations/definition.d.ts +6 -0
  39. package/dist/operations/definition.js +140 -0
  40. package/dist/operations/executor.d.ts +10 -0
  41. package/dist/operations/executor.js +269 -0
  42. package/dist/operations/host-projection.d.ts +11 -0
  43. package/dist/operations/host-projection.js +156 -0
  44. package/dist/operations/index.d.ts +10 -0
  45. package/dist/operations/index.js +10 -0
  46. package/dist/operations/io-types.d.ts +125 -0
  47. package/dist/operations/io-types.js +1 -0
  48. package/dist/operations/schemas.d.ts +10 -0
  49. package/dist/operations/schemas.js +872 -0
  50. package/dist/operations/scope-owned-create.d.ts +3 -0
  51. package/dist/operations/scope-owned-create.js +12 -0
  52. package/dist/operations/tool-input.d.ts +11 -0
  53. package/dist/operations/tool-input.js +357 -0
  54. package/dist/operations/types.d.ts +37 -0
  55. package/dist/operations/types.js +1 -0
  56. package/dist/resources/index.d.ts +1 -0
  57. package/dist/resources/index.js +1 -0
  58. package/dist/resources/resources.docman.server.errors.d.ts +14 -0
  59. package/dist/resources/resources.docman.server.errors.js +36 -0
  60. package/dist/shared/index.d.ts +5 -0
  61. package/dist/shared/index.js +1 -0
  62. package/dist/shared/tool-input-guard.d.ts +1 -0
  63. package/dist/shared/tool-input-guard.js +1 -0
  64. package/package.json +69 -0
@@ -0,0 +1,407 @@
1
+ import { XfInputRequiredError, XfMessageType, XfNotFoundError, XfValidationError, failure, invalid, xfAddMsg, } from '@aopslab/xf-core';
2
+ import { RepositoryError } from '@aopslab/xf-db';
3
+ import * as Cause from 'effect/Cause';
4
+ import { FiberFailureCauseId } from 'effect/Runtime';
5
+ const DOMAIN_SCOPE = 'docman';
6
+ const RUNTIME_SQL_PATTERNS = [
7
+ /failed query:/i,
8
+ /\bparams:\s*\[/i,
9
+ /\binsert into\b/i,
10
+ /\bupdate\b.+\bset\b/i,
11
+ /\bdelete from\b/i,
12
+ /\bselect\b.+\bfrom\b/i,
13
+ /\bsqlite/i,
14
+ /\bpostgres/i,
15
+ /\bdrizzle/i,
16
+ ];
17
+ const INPUT_VALIDATION_PATTERNS = [
18
+ /missing_required_arg:/i,
19
+ /unknown_input_arg:/i,
20
+ /tool_input_schema_invalid:/i,
21
+ /validation/i,
22
+ /input required/i,
23
+ ];
24
+ const NOT_FOUND_PATTERNS = [/record not found/i, /not found/i];
25
+ const UNAUTHORIZED_PATTERNS = [/^unauthorized$/i, /auth required/i, /missing access token/i];
26
+ const FORBIDDEN_PATTERNS = [/^forbidden$/i, /permission denied/i];
27
+ const CONFLICT_PATTERNS = [/duplicate/i, /already exists/i, /conflict/i, /e11000/i];
28
+ const RATE_LIMIT_PATTERNS = [/rate limit/i, /too many requests/i, /too many attempts/i];
29
+ const INVALID_REFERENCE_PATTERNS = [
30
+ /\bforeign key\b/i,
31
+ /violates foreign key constraint/i,
32
+ /is not present in table/i,
33
+ /anahtarı mevcut değildir/i,
34
+ ];
35
+ function normalizeNonEmpty(value) {
36
+ if (typeof value !== 'string')
37
+ return undefined;
38
+ const trimmed = value.trim();
39
+ return trimmed.length > 0 ? trimmed : undefined;
40
+ }
41
+ function normalizeRepositoryErrorCode(value) {
42
+ const normalized = normalizeNonEmpty(value);
43
+ switch (normalized) {
44
+ case 'NotFound':
45
+ case 'DeleteRecordNotFound':
46
+ case 'NoRecordReturned':
47
+ case 'ForeignKeyViolation':
48
+ case 'UniqueViolation':
49
+ case 'MultipleRecordsFound':
50
+ case 'MultipleRecordsReturned':
51
+ case 'NotNullViolation':
52
+ case 'CheckViolation':
53
+ return normalized;
54
+ default:
55
+ return undefined;
56
+ }
57
+ }
58
+ function isRepositoryErrorLike(value) {
59
+ return Boolean(value) && typeof value === 'object' && (value instanceof RepositoryError || value._tag === 'RepositoryError');
60
+ }
61
+ function extractCandidateSearchText(value) {
62
+ if (!value)
63
+ return '';
64
+ if (typeof value === 'string')
65
+ return value;
66
+ if (value instanceof Error)
67
+ return value.message;
68
+ if (typeof value === 'object') {
69
+ const message = normalizeNonEmpty(value.message);
70
+ if (message)
71
+ return message;
72
+ try {
73
+ return JSON.stringify(value);
74
+ }
75
+ catch {
76
+ return '';
77
+ }
78
+ }
79
+ return String(value);
80
+ }
81
+ function hasInvalidReferenceSignal(value) {
82
+ const text = extractCandidateSearchText(value);
83
+ return text.length > 0 && matches(INVALID_REFERENCE_PATTERNS, text);
84
+ }
85
+ function extractTrace(error) {
86
+ if (!error || typeof error !== 'object')
87
+ return undefined;
88
+ const rec = error;
89
+ const stage = typeof rec.stage === 'string' ? rec.stage : undefined;
90
+ const operation = typeof rec.operation === 'string' ? rec.operation : undefined;
91
+ if (!stage && !operation)
92
+ return undefined;
93
+ return { stage, operation };
94
+ }
95
+ function unwrapEffectError(error) {
96
+ if (error && typeof error === 'object') {
97
+ const rec = error;
98
+ const key = FiberFailureCauseId;
99
+ const cause = rec[key];
100
+ if (cause) {
101
+ const root = cause;
102
+ const failureCause = Cause.failureOption(root);
103
+ if (failureCause._tag === 'Some')
104
+ return failureCause.value;
105
+ const defect = Cause.dieOption(root);
106
+ if (defect._tag === 'Some')
107
+ return defect.value;
108
+ }
109
+ }
110
+ return error;
111
+ }
112
+ function matches(patterns, value) {
113
+ return patterns.some((rx) => rx.test(value));
114
+ }
115
+ function buildFriendly(partial) {
116
+ return {
117
+ scope: DOMAIN_SCOPE,
118
+ severity: partial.severity ?? 'user',
119
+ ...partial,
120
+ };
121
+ }
122
+ function wrapValidation(error) {
123
+ let field;
124
+ if (error instanceof XfInputRequiredError) {
125
+ const maybeField = error.field;
126
+ field = typeof maybeField === 'string' ? maybeField : undefined;
127
+ }
128
+ return buildFriendly({
129
+ code: `${DOMAIN_SCOPE}.validation`,
130
+ status: 400,
131
+ messages: [{ key: 'error__validation', field, type: 'validation' }],
132
+ logLevel: 'info',
133
+ trace: extractTrace(error),
134
+ cause: error,
135
+ });
136
+ }
137
+ function wrapNotFound(error) {
138
+ return buildFriendly({
139
+ code: `${DOMAIN_SCOPE}.notFound`,
140
+ status: 404,
141
+ messages: [{ key: 'error__notFound' }],
142
+ logLevel: 'info',
143
+ trace: extractTrace(error),
144
+ cause: error,
145
+ });
146
+ }
147
+ function wrapUnauthorized(error) {
148
+ return buildFriendly({
149
+ code: `${DOMAIN_SCOPE}.unauthorized`,
150
+ status: 401,
151
+ messages: [{ key: 'error__unauthorized' }],
152
+ logLevel: 'info',
153
+ trace: extractTrace(error),
154
+ cause: error,
155
+ });
156
+ }
157
+ function wrapForbidden(error) {
158
+ return buildFriendly({
159
+ code: `${DOMAIN_SCOPE}.forbidden`,
160
+ status: 403,
161
+ messages: [{ key: 'error__forbidden' }],
162
+ logLevel: 'info',
163
+ trace: extractTrace(error),
164
+ cause: error,
165
+ });
166
+ }
167
+ function wrapConflict(error) {
168
+ return buildFriendly({
169
+ code: `${DOMAIN_SCOPE}.conflict`,
170
+ status: 409,
171
+ messages: [{ key: 'error__conflict' }],
172
+ logLevel: 'warn',
173
+ trace: extractTrace(error),
174
+ cause: error,
175
+ });
176
+ }
177
+ function wrapRateLimit(error) {
178
+ return buildFriendly({
179
+ code: `${DOMAIN_SCOPE}.rateLimit`,
180
+ status: 429,
181
+ messages: [{ key: 'error__rateLimit' }],
182
+ logLevel: 'warn',
183
+ trace: extractTrace(error),
184
+ cause: error,
185
+ });
186
+ }
187
+ function wrapServiceUnavailable(error) {
188
+ return buildFriendly({
189
+ code: `${DOMAIN_SCOPE}.serviceUnavailable`,
190
+ status: 503,
191
+ messages: [{ key: 'error__serviceUnavailable' }],
192
+ logLevel: 'error',
193
+ severity: 'system',
194
+ trace: extractTrace(error),
195
+ cause: error,
196
+ });
197
+ }
198
+ function wrapUnexpected(error) {
199
+ return buildFriendly({
200
+ code: `${DOMAIN_SCOPE}.unexpected`,
201
+ status: 500,
202
+ messages: [{ key: 'error__unexpected' }],
203
+ logLevel: 'error',
204
+ severity: 'system',
205
+ trace: extractTrace(error),
206
+ cause: error,
207
+ });
208
+ }
209
+ export function toFriendlyError(inputError) {
210
+ const unwrapped = unwrapEffectError(inputError);
211
+ if (unwrapped instanceof XfValidationError || unwrapped instanceof XfInputRequiredError) {
212
+ return wrapValidation(unwrapped);
213
+ }
214
+ if (unwrapped instanceof XfNotFoundError) {
215
+ return wrapNotFound(unwrapped);
216
+ }
217
+ if (hasInvalidReferenceSignal(unwrapped)) {
218
+ return wrapNotFound(unwrapped);
219
+ }
220
+ if (isRepositoryErrorLike(unwrapped)) {
221
+ const code = normalizeRepositoryErrorCode(unwrapped.code);
222
+ if (code === 'NotFound' || code === 'DeleteRecordNotFound' || code === 'NoRecordReturned' || code === 'ForeignKeyViolation') {
223
+ return wrapNotFound(unwrapped);
224
+ }
225
+ if (code === 'UniqueViolation' || code === 'MultipleRecordsFound' || code === 'MultipleRecordsReturned') {
226
+ return wrapConflict(unwrapped);
227
+ }
228
+ if (code === 'NotNullViolation' || code === 'CheckViolation') {
229
+ return wrapValidation(unwrapped);
230
+ }
231
+ const message = normalizeNonEmpty(unwrapped.message) ?? '';
232
+ if (matches(CONFLICT_PATTERNS, message))
233
+ return wrapConflict(unwrapped);
234
+ if (matches(INPUT_VALIDATION_PATTERNS, message))
235
+ return wrapValidation(unwrapped);
236
+ return wrapServiceUnavailable(unwrapped);
237
+ }
238
+ if (unwrapped instanceof Error) {
239
+ const message = normalizeNonEmpty(unwrapped.message) ?? '';
240
+ if (matches(UNAUTHORIZED_PATTERNS, message))
241
+ return wrapUnauthorized(unwrapped);
242
+ if (matches(FORBIDDEN_PATTERNS, message))
243
+ return wrapForbidden(unwrapped);
244
+ if (matches(NOT_FOUND_PATTERNS, message))
245
+ return wrapNotFound(unwrapped);
246
+ if (matches(RATE_LIMIT_PATTERNS, message))
247
+ return wrapRateLimit(unwrapped);
248
+ if (matches(CONFLICT_PATTERNS, message))
249
+ return wrapConflict(unwrapped);
250
+ if (matches(INPUT_VALIDATION_PATTERNS, message))
251
+ return wrapValidation(unwrapped);
252
+ if (matches(RUNTIME_SQL_PATTERNS, message))
253
+ return wrapServiceUnavailable(unwrapped);
254
+ }
255
+ if (typeof unwrapped === 'string') {
256
+ if (matches(UNAUTHORIZED_PATTERNS, unwrapped))
257
+ return wrapUnauthorized(unwrapped);
258
+ if (matches(FORBIDDEN_PATTERNS, unwrapped))
259
+ return wrapForbidden(unwrapped);
260
+ if (matches(NOT_FOUND_PATTERNS, unwrapped))
261
+ return wrapNotFound(unwrapped);
262
+ if (matches(RATE_LIMIT_PATTERNS, unwrapped))
263
+ return wrapRateLimit(unwrapped);
264
+ if (matches(CONFLICT_PATTERNS, unwrapped))
265
+ return wrapConflict(unwrapped);
266
+ if (matches(INPUT_VALIDATION_PATTERNS, unwrapped))
267
+ return wrapValidation(unwrapped);
268
+ if (matches(RUNTIME_SQL_PATTERNS, unwrapped))
269
+ return wrapServiceUnavailable(unwrapped);
270
+ }
271
+ return wrapUnexpected(unwrapped);
272
+ }
273
+ function toResultMessageOptsGeneric(opts) {
274
+ const { code, domain, field, params, trace } = opts;
275
+ return {
276
+ code,
277
+ path: field,
278
+ domain,
279
+ stage: trace?.stage,
280
+ operation: trace?.operation,
281
+ debug: params ? { params } : undefined,
282
+ };
283
+ }
284
+ function sanitizeCause(cause) {
285
+ if (cause instanceof Error) {
286
+ return { name: cause.name, message: cause.message };
287
+ }
288
+ if (cause && typeof cause === 'object') {
289
+ try {
290
+ JSON.stringify(cause);
291
+ return cause;
292
+ }
293
+ catch {
294
+ return undefined;
295
+ }
296
+ }
297
+ return cause;
298
+ }
299
+ function sanitizeParams(params) {
300
+ if (!params || typeof params !== 'object')
301
+ return undefined;
302
+ const out = {};
303
+ for (const [key, value] of Object.entries(params)) {
304
+ if (typeof value === 'string')
305
+ out[key] = value;
306
+ else if (value != null)
307
+ out[key] = String(value);
308
+ }
309
+ return out;
310
+ }
311
+ function sanitizeMessages(messages) {
312
+ return messages.map((message) => ({
313
+ key: String(message.key || ''),
314
+ field: typeof message.field === 'string' ? message.field : undefined,
315
+ params: sanitizeParams(message.params),
316
+ type: message.type === 'validation' ? 'validation' : message.type === 'error' ? 'error' : undefined,
317
+ }));
318
+ }
319
+ function sanitizeTrace(trace) {
320
+ if (!trace || typeof trace !== 'object')
321
+ return undefined;
322
+ const stage = typeof trace.stage === 'string' ? trace.stage : undefined;
323
+ const operation = typeof trace.operation === 'string' ? trace.operation : undefined;
324
+ if (!stage && !operation)
325
+ return undefined;
326
+ return { stage, operation };
327
+ }
328
+ function sanitizeFriendly(friendly) {
329
+ return {
330
+ ...friendly,
331
+ messages: sanitizeMessages(Array.isArray(friendly.messages) ? friendly.messages : []),
332
+ trace: sanitizeTrace(friendly.trace),
333
+ cause: sanitizeCause(friendly.cause),
334
+ };
335
+ }
336
+ function appendMessagesGeneric(result, messages, friendly) {
337
+ return messages.reduce((acc, message) => {
338
+ return xfAddMsg(acc, message.type === 'validation' ? XfMessageType.ValidationErr : XfMessageType.Error, message.key, toResultMessageOptsGeneric({
339
+ code: message.key,
340
+ domain: friendly.scope,
341
+ field: message.field,
342
+ params: message.params,
343
+ trace: friendly.trace,
344
+ }));
345
+ }, result);
346
+ }
347
+ export function friendlyErrorToResult(friendly) {
348
+ const safe = sanitizeFriendly(friendly);
349
+ const [primary, ...rest] = safe.messages.length ? safe.messages : [{ key: 'error__unexpected' }];
350
+ const factory = primary.type === 'validation' ? invalid : failure;
351
+ let result = factory({
352
+ messageText: primary.key,
353
+ opts: toResultMessageOptsGeneric({
354
+ code: primary.key,
355
+ domain: safe.scope,
356
+ field: primary.field,
357
+ params: primary.params,
358
+ trace: safe.trace,
359
+ }),
360
+ error: safe,
361
+ });
362
+ if (rest.length > 0) {
363
+ result = appendMessagesGeneric(result, rest, safe);
364
+ }
365
+ return result;
366
+ }
367
+ export function friendlyErrorToResultI18n(friendly, t) {
368
+ const safe = sanitizeFriendly(friendly);
369
+ const [primary, ...rest] = safe.messages.length ? safe.messages : [{ key: 'error__unexpected' }];
370
+ const primaryText = t(primary.key, primary.params);
371
+ const factory = primary.type === 'validation' ? invalid : failure;
372
+ let result = factory({
373
+ messageText: primaryText,
374
+ opts: toResultMessageOptsGeneric({
375
+ code: primary.key,
376
+ domain: safe.scope,
377
+ field: primary.field,
378
+ params: primary.params,
379
+ trace: safe.trace,
380
+ }),
381
+ error: safe,
382
+ });
383
+ if (rest.length > 0) {
384
+ result = rest.reduce((acc, message) => {
385
+ return xfAddMsg(acc, message.type === 'validation' ? XfMessageType.ValidationErr : XfMessageType.Error, t(message.key, message.params), toResultMessageOptsGeneric({
386
+ code: message.key,
387
+ domain: safe.scope,
388
+ field: message.field,
389
+ params: message.params,
390
+ trace: safe.trace,
391
+ }));
392
+ }, result);
393
+ }
394
+ return result;
395
+ }
396
+ export function friendlyErrorToHttpBody(friendly) {
397
+ const safe = sanitizeFriendly(friendly);
398
+ return {
399
+ ok: false,
400
+ code: safe.code,
401
+ severity: safe.severity,
402
+ messages: safe.messages,
403
+ };
404
+ }
405
+ export function errorToResult(error) {
406
+ return friendlyErrorToResult(toFriendlyError(error));
407
+ }
@@ -0,0 +1,4 @@
1
+ import type { I18nBm } from '@aopslab/xf-i18n/bm';
2
+ import { type XfFriendlyError } from './friendly.js';
3
+ export declare function friendlyErrorToResultWithI18n<TData = unknown, TField extends object = object, TTag extends object = object, TValidation extends object = object>(friendly: XfFriendlyError, i18nBm: I18nBm<TField, TTag, TValidation>, locale?: string): import("@aopslab/xf-core").XfResult<TData, XfFriendlyError>;
4
+ export declare function errorToResultWithI18n<TData = unknown, TField extends object = object, TTag extends object = object, TValidation extends object = object>(error: unknown, i18nBm: I18nBm<TField, TTag, TValidation>, locale?: string): import("@aopslab/xf-core").XfResult<TData, XfFriendlyError>;
@@ -0,0 +1,10 @@
1
+ import { friendlyErrorToResultI18n, toFriendlyError, } from './friendly.js';
2
+ export function friendlyErrorToResultWithI18n(friendly, i18nBm, locale) {
3
+ const t = i18nBm.getTagTranslator({ locale });
4
+ return friendlyErrorToResultI18n(friendly, t);
5
+ }
6
+ export function errorToResultWithI18n(error, i18nBm, locale) {
7
+ const t = i18nBm.getTagTranslator({ locale });
8
+ const friendly = toFriendlyError(error);
9
+ return friendlyErrorToResultI18n(friendly, t);
10
+ }
@@ -0,0 +1,3 @@
1
+ export * from './friendly.js';
2
+ export * from './error.map.js';
3
+ export * from './i18n.js';
@@ -0,0 +1,3 @@
1
+ export * from './friendly.js';
2
+ export * from './error.map.js';
3
+ export * from './i18n.js';
@@ -0,0 +1,9 @@
1
+ export * from './domain-services/types.js';
2
+ export { createDocmanKit, createDocmanKitWithEnv, buildDocmanKitStaticConfig } from './domain-services/unified.js';
3
+ export * from './config/config.js';
4
+ export * from './operations/index.js';
5
+ export type * from '@aopslab/domain-dm-docman/models';
6
+ export type * from '@aopslab/domain-dm-docman/ports';
7
+ export * from './errors/index.js';
8
+ export * from './resources/index.js';
9
+ export * from './shared/index.js';
package/dist/index.js ADDED
@@ -0,0 +1,7 @@
1
+ export * from './domain-services/types.js';
2
+ export { createDocmanKit, createDocmanKitWithEnv, buildDocmanKitStaticConfig } from './domain-services/unified.js';
3
+ export * from './config/config.js';
4
+ export * from './operations/index.js';
5
+ export * from './errors/index.js';
6
+ export * from './resources/index.js';
7
+ export * from './shared/index.js';
@@ -0,0 +1,11 @@
1
+ import type { DocmanOperationSpec } from './types.js';
2
+ export declare function listDocmanOperationSpecs(options?: {
3
+ refresh?: boolean;
4
+ }): DocmanOperationSpec[];
5
+ export declare function getDocmanOperationByToolId(toolId: string, options?: {
6
+ refresh?: boolean;
7
+ }): DocmanOperationSpec | null;
8
+ export declare function getDocmanOperationById(operationId: string, options?: {
9
+ refresh?: boolean;
10
+ }): DocmanOperationSpec | null;
11
+ export { buildDocmanToolIdFromOperation } from './definition.js';