@tstdl/base 0.92.139 → 0.92.140

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/ai/ai.service.js CHANGED
@@ -155,7 +155,7 @@ let AiService = AiService_1 = class AiService {
155
155
  break;
156
156
  }
157
157
  catch (error) {
158
- if ((i < 20) && isError(error) && ((error['status'] == 429) || (error['status'] == 503))) {
158
+ if ((i < 20) && isError(error) && (error.message.includes('429 Too Many Requests') || (error.message.includes('503 Service Unavailable')))) {
159
159
  this.#logger.verbose('429 Too Many Requests - trying again in 15 seconds');
160
160
  const canceled = await cancelableTimeout(15 * millisecondsPerSecond, getShutdownSignal());
161
161
  if (!canceled) {
@@ -0,0 +1,14 @@
1
+ export declare class CssVariables implements Disposable {
2
+ #private;
3
+ readonly selector: string;
4
+ readonly prefix: string;
5
+ constructor(selector: string | null, prefix?: string);
6
+ [Symbol.dispose](): void;
7
+ set(name: string, value: string): void;
8
+ setMany(variables: Record<string, string> | [string, string][]): void;
9
+ get(name: string): string | null;
10
+ delete(name: string): void;
11
+ clear(): void;
12
+ private _prefix;
13
+ }
14
+ export declare function cssVariables(selector?: string | null, prefix?: string): CssVariables;
@@ -0,0 +1,55 @@
1
+ import { objectEntries } from '../utils/object/object.js';
2
+ import { isArray } from '../utils/type-guards.js';
3
+ export class CssVariables {
4
+ #styleSheet = new CSSStyleSheet();
5
+ #cssRule;
6
+ selector;
7
+ prefix;
8
+ constructor(selector, prefix = '') {
9
+ this.selector = selector ?? ':root';
10
+ this.prefix = prefix;
11
+ document.adoptedStyleSheets.push(this.#styleSheet);
12
+ this.#cssRule = createCssRule(this.#styleSheet, `${this.selector} {}`);
13
+ }
14
+ [Symbol.dispose]() {
15
+ const index = document.adoptedStyleSheets.indexOf(this.#styleSheet);
16
+ if (index != -1) {
17
+ document.adoptedStyleSheets.splice(index, 1);
18
+ }
19
+ }
20
+ set(name, value) {
21
+ const prefixed = this._prefix(name);
22
+ this.#cssRule.style.setProperty(prefixed, value);
23
+ }
24
+ setMany(variables) {
25
+ const entries = isArray(variables) ? variables : objectEntries(variables);
26
+ for (const [name, value] of entries) {
27
+ this.set(name, value);
28
+ }
29
+ }
30
+ get(name) {
31
+ const prefixed = this._prefix(name);
32
+ const rawValue = this.#cssRule.style.getPropertyValue(prefixed);
33
+ if (rawValue.length == 0) {
34
+ return null;
35
+ }
36
+ return rawValue;
37
+ }
38
+ delete(name) {
39
+ const prefixed = this._prefix(name);
40
+ this.#cssRule.style.removeProperty(prefixed);
41
+ }
42
+ clear() {
43
+ this.#cssRule.style.cssText = '';
44
+ }
45
+ _prefix(name) {
46
+ return name.startsWith('--') ? name : `--${this.prefix}${name}`;
47
+ }
48
+ }
49
+ export function cssVariables(selector = null, prefix = '') {
50
+ return new CssVariables(selector, prefix);
51
+ }
52
+ function createCssRule(styleSheet, rule) {
53
+ const index = styleSheet.insertRule(rule);
54
+ return styleSheet.cssRules[index];
55
+ }
package/css/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './css-variables.js';
package/css/index.js ADDED
@@ -0,0 +1 @@
1
+ export * from './css-variables.js';
@@ -1,3 +1,4 @@
1
+ import { ServerSentEvents } from '../../sse/server-sent-events.js';
1
2
  import { Document, DocumentCategory, DocumentRequest, DocumentRequestsTemplate, DocumentRequestTemplate, DocumentType } from '../models/index.js';
2
3
  import { DocumentCategoryView, DocumentManagementData, DocumentRequestsTemplateData } from '../service-models/index.js';
3
4
  export type DocumentManagementApiDefinition = typeof documentManagementApiDefinition;
@@ -13,6 +14,15 @@ export declare const documentManagementApiDefinition: {
13
14
  result: typeof DocumentManagementData;
14
15
  credentials: true;
15
16
  };
17
+ loadDataStream: {
18
+ resource: string;
19
+ method: "GET";
20
+ parameters: import("../../schema/index.js").ObjectSchema<{
21
+ collectionIds: string | string[];
22
+ }>;
23
+ result: typeof ServerSentEvents;
24
+ credentials: true;
25
+ };
16
26
  loadDocumentRequestsTemplateData: {
17
27
  resource: string;
18
28
  method: "GET";
@@ -346,6 +356,15 @@ declare const _DocumentManagementApi: import("../../api/client/index.js").ApiCli
346
356
  result: typeof DocumentManagementData;
347
357
  credentials: true;
348
358
  };
359
+ loadDataStream: {
360
+ resource: string;
361
+ method: "GET";
362
+ parameters: import("../../schema/index.js").ObjectSchema<{
363
+ collectionIds: string | string[];
364
+ }>;
365
+ result: typeof ServerSentEvents;
366
+ credentials: true;
367
+ };
349
368
  loadDocumentRequestsTemplateData: {
350
369
  resource: string;
351
370
  method: "GET";
@@ -8,6 +8,7 @@ import { compileClient } from '../../api/client/index.js';
8
8
  import { defineApi } from '../../api/index.js';
9
9
  import { ReplaceClass } from '../../injector/decorators.js';
10
10
  import { array, boolean, literal, number, object, optional, string } from '../../schema/index.js';
11
+ import { ServerSentEvents } from '../../sse/server-sent-events.js';
11
12
  import { Document, DocumentCategory, DocumentRequest, DocumentRequestsTemplate, DocumentRequestTemplate, DocumentType } from '../models/index.js';
12
13
  import { addOrArchiveDocumentToOrFromCollectionParametersSchema, applyDocumentRequestsTemplateParametersSchema, createDocumentCategoryParametersSchema, createDocumentParametersSchema, createDocumentRequestParametersSchema, createDocumentRequestsTemplateParametersSchema, createDocumentRequestTemplateParametersSchema, createDocumentTypeParametersSchema, deleteDocumentRequestParametersSchema, deleteDocumentRequestsTemplateParametersSchema, deleteDocumentRequestTemplateParametersSchema, DocumentCategoryView, DocumentManagementData, DocumentRequestsTemplateData, loadDataParametersSchema, updateDocumentParametersSchema, updateDocumentRequestParametersSchema, updateDocumentRequestsTemplateParametersSchema, updateDocumentRequestTemplateParametersSchema } from '../service-models/index.js';
13
14
  export const documentManagementApiDefinition = defineApi({
@@ -20,6 +21,13 @@ export const documentManagementApiDefinition = defineApi({
20
21
  result: DocumentManagementData,
21
22
  credentials: true,
22
23
  },
24
+ loadDataStream: {
25
+ resource: 'data/stream',
26
+ method: 'GET',
27
+ parameters: loadDataParametersSchema,
28
+ result: ServerSentEvents,
29
+ credentials: true,
30
+ },
23
31
  loadDocumentRequestsTemplateData: {
24
32
  resource: 'views/document-requests-template-data',
25
33
  method: 'GET',
@@ -1,8 +1,9 @@
1
- import type { ApiController, ApiRequestContext, ApiServerResult } from '../../../api/index.js';
1
+ import { type ApiController, type ApiRequestContext, type ApiServerResult } from '../../../api/index.js';
2
2
  import { type DocumentManagementApiDefinition } from '../../../document-management/api/index.js';
3
3
  export declare class DocumentManagementApiController implements ApiController<DocumentManagementApiDefinition> {
4
4
  #private;
5
5
  loadData(context: ApiRequestContext<DocumentManagementApiDefinition, 'loadData'>): Promise<ApiServerResult<DocumentManagementApiDefinition, 'loadData'>>;
6
+ loadDataStream(context: ApiRequestContext<DocumentManagementApiDefinition, 'loadDataStream'>): Promise<ApiServerResult<DocumentManagementApiDefinition, 'loadDataStream'>>;
6
7
  loadDocumentRequestsTemplateData(context: ApiRequestContext<DocumentManagementApiDefinition, 'loadDocumentRequestsTemplateData'>): Promise<ApiServerResult<DocumentManagementApiDefinition, 'loadDocumentRequestsTemplateData'>>;
7
8
  loadAvailableCategories(context: ApiRequestContext<DocumentManagementApiDefinition, 'loadAvailableCategories'>): Promise<ApiServerResult<DocumentManagementApiDefinition, 'loadAvailableCategories'>>;
8
9
  loadContent(context: ApiRequestContext<DocumentManagementApiDefinition, 'loadContent'>): Promise<ApiServerResult<DocumentManagementApiDefinition, 'loadContent'>>;
@@ -4,17 +4,23 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
+ var _a;
8
+ var DocumentManagementApiController_1;
9
+ import { match, P } from 'ts-pattern';
10
+ import { createErrorResponse } from '../../../api/index.js';
7
11
  import { apiController } from '../../../api/server/index.js';
8
12
  import { documentManagementApiDefinition } from '../../../document-management/api/index.js';
9
13
  import { DocumentRequestCollectionAssignment } from '../../../document-management/models/document-request-collection-assignment.model.js';
10
14
  import { ForbiddenError, NotImplementedError } from '../../../errors/index.js';
11
15
  import { HttpServerResponse } from '../../../http/index.js';
12
16
  import { inject } from '../../../injector/index.js';
17
+ import { Logger } from '../../../logger/logger.js';
13
18
  import { injectRepository } from '../../../orm/server/repository.js';
19
+ import { ServerSentEventsSource } from '../../../sse/server-sent-events-source.js';
14
20
  import { toArray } from '../../../utils/array/index.js';
15
- import { match, P } from 'ts-pattern';
21
+ import { tryIgnoreAsync } from '../../../utils/try-ignore.js';
16
22
  import { DocumentCategoryTypeService, DocumentFileService, DocumentManagementAuthorizationService, DocumentManagementService, DocumentRequestService, DocumentService } from '../services/index.js';
17
- let DocumentManagementApiController = class DocumentManagementApiController {
23
+ let DocumentManagementApiController = DocumentManagementApiController_1 = class DocumentManagementApiController {
18
24
  #authorizationService = inject(DocumentManagementAuthorizationService);
19
25
  #documentCategoryTypeService = inject(DocumentCategoryTypeService);
20
26
  #documentFileService = inject(DocumentFileService);
@@ -22,6 +28,7 @@ let DocumentManagementApiController = class DocumentManagementApiController {
22
28
  #documentRequestService = inject(DocumentRequestService);
23
29
  #documentRequestCollectionAssignmentRepository = injectRepository(DocumentRequestCollectionAssignment);
24
30
  #documentService = inject(DocumentService);
31
+ #logger = inject(Logger, DocumentManagementApiController_1.name);
25
32
  async loadData(context) {
26
33
  const token = await context.getToken();
27
34
  for (const collectionId of context.parameters.collectionIds) {
@@ -32,6 +39,30 @@ let DocumentManagementApiController = class DocumentManagementApiController {
32
39
  }
33
40
  return await this.#documentManagementService.loadData(toArray(context.parameters.collectionIds));
34
41
  }
42
+ async loadDataStream(context) {
43
+ const token = await context.getToken();
44
+ for (const collectionId of context.parameters.collectionIds) {
45
+ const allowed = await this.#authorizationService.canReadCollection(collectionId, token);
46
+ if (!allowed) {
47
+ throw new ForbiddenError(`You are not allowed to read collection ${collectionId}`);
48
+ }
49
+ }
50
+ const stream = this.#documentManagementService.loadDataStream(toArray(context.parameters.collectionIds));
51
+ const eventSource = new ServerSentEventsSource();
52
+ void (async () => {
53
+ try {
54
+ for await (const chunk of stream) {
55
+ await eventSource.sendJson({ name: 'data', data: chunk });
56
+ }
57
+ }
58
+ catch (error) {
59
+ this.#logger.error(error);
60
+ await tryIgnoreAsync(async () => await eventSource.sendJson({ name: 'error', data: createErrorResponse(error).error }));
61
+ await tryIgnoreAsync(async () => await eventSource.close());
62
+ }
63
+ })();
64
+ return eventSource;
65
+ }
35
66
  async loadDocumentRequestsTemplateData(context) {
36
67
  const token = await context.getToken();
37
68
  const allowed = await this.#authorizationService.canReadDocumentRequestsTemplates(token);
@@ -172,7 +203,7 @@ let DocumentManagementApiController = class DocumentManagementApiController {
172
203
  throw new NotImplementedError();
173
204
  }
174
205
  };
175
- DocumentManagementApiController = __decorate([
206
+ DocumentManagementApiController = DocumentManagementApiController_1 = __decorate([
176
207
  apiController(documentManagementApiDefinition)
177
208
  ], DocumentManagementApiController);
178
209
  export { DocumentManagementApiController };
@@ -10,6 +10,7 @@ export declare class DocumentManagementService extends Transactional {
10
10
  * @param documentId The ID of the document to retrieve collection IDs for.
11
11
  */
12
12
  getRelevantDocumentCollectionIds(documentId: string): Promise<string[]>;
13
+ loadDataStream(collectionIds: string[]): ReadableStream<DocumentManagementData>;
13
14
  loadData(collectionIds: string[]): Promise<DocumentManagementData>;
14
15
  loadDocumentRequestsTemplateData(): Promise<DocumentRequestsTemplateData>;
15
16
  initializeCategoriesAndTypes<CategoryKey extends string, TypeKey extends string, DocumentPropertyKey extends string>(categoryLabels: Record<CategoryKey, string>, categoryParents: Record<CategoryKey, CategoryKey | null>, typeLabels: Record<TypeKey, string>, typeCategories: Record<TypeKey, CategoryKey>, propertyKeys: Record<DocumentPropertyKey, [DocumentPropertyDataType, string]>, typeProperties: Record<TypeKey, DocumentPropertyKey[]>): Promise<{
@@ -13,6 +13,7 @@ import { distinct } from '../../../utils/array/index.js';
13
13
  import { compareByValueSelectionToOrder } from '../../../utils/comparison.js';
14
14
  import { groupToMap, groupToSingleMap } from '../../../utils/iterable-helpers/index.js';
15
15
  import { fromEntries, objectEntries } from '../../../utils/object/index.js';
16
+ import { timeout } from '../../../utils/timing.js';
16
17
  import { assertDefinedPass, isDefined, isNotNull, isNotNullOrUndefined, isNull, isUndefined } from '../../../utils/type-guards.js';
17
18
  import { DocumentApproval, DocumentAssignmentScope, DocumentAssignmentTask, DocumentCategory, DocumentCollection, DocumentCollectionAssignment, DocumentRequest, DocumentRequestCollectionAssignment, DocumentRequestTemplate, DocumentRequestsTemplate, DocumentType, DocumentTypeProperty, DocumentValidationExecution, DocumentWorkflowStep } from '../../models/index.js';
18
19
  import { documentAssignmentScope, documentAssignmentTask, documentCollectionAssignment, documentRequest, documentRequestCollectionAssignment } from '../schemas.js';
@@ -64,6 +65,15 @@ let DocumentManagementService = class DocumentManagementService extends Transact
64
65
  const result = await union(this.#documentService.session.with(directAssignments).selectDistinct().from(directAssignments), this.#documentService.session.with(requestAssignments).selectDistinct().from(requestAssignments), this.#documentService.session.with(assignmentScopes).selectDistinct().from(assignmentScopes));
65
66
  return result.map((row) => row.collectionId);
66
67
  }
68
+ loadDataStream(collectionIds) {
69
+ return new ReadableStream({
70
+ pull: async (controller) => {
71
+ const data = await this.loadData(collectionIds);
72
+ controller.enqueue(data);
73
+ await timeout(1000);
74
+ },
75
+ });
76
+ }
67
77
  async loadData(collectionIds) {
68
78
  return await this.transaction(async (tx) => {
69
79
  const [collections, collectionsMetadataMap, documentCollectionAssignments, requestAssignments, assignmentScopes, categories, types] = await Promise.all([
@@ -34,7 +34,7 @@ const streamingApiDefinition = defineApi({
34
34
  method: 'POST',
35
35
  resource: 'echo',
36
36
  body: ReadableStream,
37
- result: ReadableStream
37
+ result: ReadableStream,
38
38
  },
39
39
  events: {
40
40
  method: 'GET',
@@ -42,21 +42,21 @@ const streamingApiDefinition = defineApi({
42
42
  result: ServerSentEvents,
43
43
  cors: {
44
44
  accessControlAllowOrigin: '*',
45
- accessControlAllowMethods: 'GET'
46
- }
47
- }
48
- }
45
+ accessControlAllowMethods: 'GET',
46
+ },
47
+ },
48
+ },
49
49
  });
50
50
  let StreamingApi = class StreamingApi {
51
51
  echo({ request, body }) {
52
52
  return HttpServerResponse.fromObject({
53
53
  headers: {
54
54
  'Content-Type': request.headers.contentType,
55
- 'Content-Length': request.headers.contentLength
55
+ 'Content-Length': request.headers.contentLength,
56
56
  },
57
57
  body: {
58
- stream: body
59
- }
58
+ stream: body,
59
+ },
60
60
  });
61
61
  }
62
62
  events(_data) {
@@ -314,10 +314,10 @@ export declare const TstdlDocumentPropertyConfiguration: {
314
314
  readonly amount: ["decimal", "Betrag"];
315
315
  readonly currency: ["text", "Währung"];
316
316
  readonly "due-date": ["date", "Fälligkeitsdatum"];
317
- readonly "start-date": ["date", "Startdatum (Periode)"];
318
- readonly "end-date": ["date", "Enddatum (Periode)"];
317
+ readonly "start-date": ["date", "Startdatum"];
318
+ readonly "end-date": ["date", "Enddatum"];
319
319
  readonly status: ["text", "Status"];
320
- readonly "case-number": ["text", "Fall-/Aktenzeichen (Recht)"];
320
+ readonly "case-number": ["text", "Fall-/Aktenzeichen"];
321
321
  readonly "meeting-date": ["date", "Sitzungsdatum"];
322
322
  };
323
323
  export declare const TstdlDocumentTypeProperties: {
@@ -360,10 +360,10 @@ export const TstdlDocumentPropertyConfiguration = {
360
360
  [TstdlDocumentProperty.Amount]: [DocumentPropertyDataType.Decimal, 'Betrag'],
361
361
  [TstdlDocumentProperty.Currency]: [DocumentPropertyDataType.Text, 'Währung'],
362
362
  [TstdlDocumentProperty.DueDate]: [DocumentPropertyDataType.Date, 'Fälligkeitsdatum'],
363
- [TstdlDocumentProperty.StartDate]: [DocumentPropertyDataType.Date, 'Startdatum (Periode)'],
364
- [TstdlDocumentProperty.EndDate]: [DocumentPropertyDataType.Date, 'Enddatum (Periode)'],
363
+ [TstdlDocumentProperty.StartDate]: [DocumentPropertyDataType.Date, 'Startdatum'],
364
+ [TstdlDocumentProperty.EndDate]: [DocumentPropertyDataType.Date, 'Enddatum'],
365
365
  [TstdlDocumentProperty.Status]: [DocumentPropertyDataType.Text, 'Status'],
366
- [TstdlDocumentProperty.CaseNumber]: [DocumentPropertyDataType.Text, 'Fall-/Aktenzeichen (Recht)'],
366
+ [TstdlDocumentProperty.CaseNumber]: [DocumentPropertyDataType.Text, 'Fall-/Aktenzeichen'],
367
367
  [TstdlDocumentProperty.MeetingDate]: [DocumentPropertyDataType.Date, 'Sitzungsdatum'],
368
368
  };
369
369
  export const TstdlDocumentTypeProperties = {
@@ -22,6 +22,7 @@ import { WebServerModule } from '../../module/index.js';
22
22
  import { configureS3ObjectStorage } from '../../object-storage/index.js';
23
23
  import { configureOrm } from '../../orm/server/index.js';
24
24
  import { configurePostgresQueue, migratePostgresQueueSchema } from '../../queue/postgres/index.js';
25
+ import { configureDefaultSignalsImplementation } from '../../signals/implementation/configure.js';
25
26
  import { boolean, positiveInteger, string } from '../../utils/config-parser.js';
26
27
  import { TstdlCategoryParents, TstdlDocumentCategoryLabels, TstdlDocumentPropertyConfiguration, TstdlDocumentTypeCategories, TstdlDocumentTypeLabels, TstdlDocumentTypeProperties } from './categories-and-types.js';
27
28
  const config = {
@@ -84,6 +85,7 @@ async function bootstrap() {
84
85
  configureNodeHttpServer();
85
86
  configurePostgresQueue();
86
87
  configureLocalMessageBus();
88
+ configureDefaultSignalsImplementation();
87
89
  configureOrm({
88
90
  connection: {
89
91
  host: config.database.host,
package/file/mime-type.js CHANGED
@@ -1,4 +1,4 @@
1
- import { fileTypeFromBuffer, fileTypeFromFile, fileTypeFromStream } from 'file-type';
1
+ import { fileTypeFromBuffer, fileTypeFromFile, fileTypeFromStream } from 'file-type/node';
2
2
  import { isReadableStream, isString, isUint8Array } from '../utils/type-guards.js';
3
3
  import { match } from 'ts-pattern';
4
4
  import { mimeTypesMap } from './mime-types.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tstdl/base",
3
- "version": "0.92.139",
3
+ "version": "0.92.140",
4
4
  "author": "Patrick Hein",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -51,6 +51,7 @@
51
51
  "./browser": "./browser/index.js",
52
52
  "./cancellation": "./cancellation/index.js",
53
53
  "./cookie": "./cookie/index.js",
54
+ "./css": "./css/index.js",
54
55
  "./data-structures": "./data-structures/index.js",
55
56
  "./database": "./database/index.js",
56
57
  "./database/mongo": "./database/mongo/index.js",
@@ -144,7 +145,7 @@
144
145
  "peerDependencies": {
145
146
  "@elastic/elasticsearch": "^9.0",
146
147
  "@google-cloud/storage": "7.16",
147
- "@google/genai": "^1.0",
148
+ "@google/genai": "^1.1",
148
149
  "@tstdl/angular": "^0.92",
149
150
  "@zxcvbn-ts/core": "^3.0",
150
151
  "@zxcvbn-ts/language-common": "^3.0",
@@ -42,11 +42,11 @@ export class ServerSentEventsSource {
42
42
  await this.#writer.write(message);
43
43
  }
44
44
  async sendJson({ name, data, id, retry }) {
45
- return this.sendText({
45
+ await this.sendText({
46
46
  name,
47
47
  data: JSON.stringify(data),
48
48
  id,
49
- retry
49
+ retry,
50
50
  });
51
51
  }
52
52
  }
@@ -49,7 +49,7 @@ export function filterObject(object, predicate) {
49
49
  }
50
50
  export async function filterObjectAsync(object, predicate) {
51
51
  const entries = objectEntries(object);
52
- const mappedEntries = await toArrayAsync(filterAsync(entries, async ([key, value]) => predicate(value, key)));
52
+ const mappedEntries = await toArrayAsync(filterAsync(entries, async ([key, value]) => await predicate(value, key)));
53
53
  return Object.fromEntries(mappedEntries);
54
54
  }
55
55
  export function filterUndefinedFromRecord(record) {