@tstdl/base 0.93.173 → 0.93.174
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/genkit/tests/multi-region.test.js +1 -1
- package/ai/genkit/tests/token-limit-fallback.test.js +1 -1
- package/api/server/middlewares/cors.middleware.js +9 -6
- package/authentication/client/authentication.service.d.ts +1 -1
- package/authentication/client/authentication.service.js +5 -4
- package/document-management/tests/ai-config-integration.test.js +4 -4
- package/document-management/tests/document-validation-ai-overrides.test.js +3 -0
- package/http/server/http-server-response.d.ts +1 -1
- package/http/server/http-server-response.js +13 -5
- package/logger/tests/pretty-print.test.js +2 -2
- package/package.json +1 -2
|
@@ -6,7 +6,7 @@ import { CircuitBreakerProvider } from '../../../circuit-breaker/provider.js';
|
|
|
6
6
|
import { Logger } from '../../../logger/logger.js';
|
|
7
7
|
import { setupIntegrationTest } from '../../../testing/index.js';
|
|
8
8
|
import { vertexAiMultiLocation } from '../multi-region.plugin.js';
|
|
9
|
-
vi.mock('
|
|
9
|
+
vi.mock('../../../utils/array/index.js', async (importOriginal) => {
|
|
10
10
|
const actual = await importOriginal();
|
|
11
11
|
return {
|
|
12
12
|
...actual,
|
|
@@ -7,7 +7,7 @@ import { Logger } from '../../../logger/logger.js';
|
|
|
7
7
|
import { setupIntegrationTest } from '../../../testing/index.js';
|
|
8
8
|
import { timeout } from '../../../utils/timing.js';
|
|
9
9
|
import { vertexAiMultiLocation } from '../multi-region.plugin.js';
|
|
10
|
-
vi.mock('
|
|
10
|
+
vi.mock('../../../utils/array/index.js', async (importOriginal) => {
|
|
11
11
|
const actual = await importOriginal();
|
|
12
12
|
return {
|
|
13
13
|
...actual,
|
|
@@ -14,6 +14,7 @@ export function corsMiddleware(options = {}) {
|
|
|
14
14
|
const origin = request.headers.tryGetSingle('Origin');
|
|
15
15
|
const allowCredentials = (await resolveApiEndpointDataProvider(request, context, cors.accessControlAllowCredentials)) ?? endpointDefinition?.credentials;
|
|
16
16
|
if (isDefined(origin)) {
|
|
17
|
+
let allowOriginValidationFailed = false;
|
|
17
18
|
if (isDefined(cors.accessControlAllowOrigin) && !response.headers.has('Access-Control-Allow-Origin')) {
|
|
18
19
|
const allowedOrigin = await resolveApiEndpointDataProvider(request, context, cors.accessControlAllowOrigin);
|
|
19
20
|
if (isDefined(allowedOrigin)) {
|
|
@@ -26,9 +27,8 @@ export function corsMiddleware(options = {}) {
|
|
|
26
27
|
response.headers.append('Vary', 'Origin');
|
|
27
28
|
}
|
|
28
29
|
}
|
|
29
|
-
else
|
|
30
|
-
|
|
31
|
-
return;
|
|
30
|
+
else {
|
|
31
|
+
allowOriginValidationFailed = true;
|
|
32
32
|
}
|
|
33
33
|
}
|
|
34
34
|
}
|
|
@@ -39,11 +39,14 @@ export function corsMiddleware(options = {}) {
|
|
|
39
39
|
response.headers.set('Access-Control-Allow-Origin', origin);
|
|
40
40
|
response.headers.append('Vary', 'Origin');
|
|
41
41
|
}
|
|
42
|
-
else
|
|
43
|
-
|
|
44
|
-
return;
|
|
42
|
+
else {
|
|
43
|
+
allowOriginValidationFailed = true;
|
|
45
44
|
}
|
|
46
45
|
}
|
|
46
|
+
if (isOptions && allowOriginValidationFailed && !response.headers.has('Access-Control-Allow-Origin')) {
|
|
47
|
+
response.statusCode = 403;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
47
50
|
}
|
|
48
51
|
if (isOptions) {
|
|
49
52
|
const customAllowMethods = await resolveApiEndpointDataProvider(request, context, cors.accessControlAllowMethods);
|
|
@@ -26,7 +26,7 @@ export declare class AuthenticationClientService<AdditionalTokenPayload extends
|
|
|
26
26
|
private readonly logger;
|
|
27
27
|
private readonly disposeSignal;
|
|
28
28
|
private readonly forceRefreshRequested;
|
|
29
|
-
private readonly
|
|
29
|
+
private readonly forceRefreshSubject;
|
|
30
30
|
private clockOffset;
|
|
31
31
|
private initialized;
|
|
32
32
|
private refreshLoopPromise;
|
|
@@ -7,7 +7,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
|
|
|
7
7
|
var __metadata = (this && this.__metadata) || function (k, v) {
|
|
8
8
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
|
9
9
|
};
|
|
10
|
-
import { Subject, filter, firstValueFrom, from, race,
|
|
10
|
+
import { Subject, filter, firstValueFrom, from, race, takeUntil, timer } from 'rxjs';
|
|
11
11
|
import { CancellationSignal } from '../../cancellation/token.js';
|
|
12
12
|
import { BadRequestError } from '../../errors/bad-request.error.js';
|
|
13
13
|
import { ForbiddenError } from '../../errors/forbidden.error.js';
|
|
@@ -72,7 +72,7 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
72
72
|
logger = inject(Logger, 'AuthenticationService');
|
|
73
73
|
disposeSignal = inject(CancellationSignal).fork();
|
|
74
74
|
forceRefreshRequested = signal(false);
|
|
75
|
-
|
|
75
|
+
forceRefreshSubject = new Subject();
|
|
76
76
|
clockOffset = 0;
|
|
77
77
|
initialized = false;
|
|
78
78
|
refreshLoopPromise;
|
|
@@ -267,6 +267,7 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
267
267
|
this.setAdditionalData(data);
|
|
268
268
|
}
|
|
269
269
|
this.forceRefreshRequested.set(true);
|
|
270
|
+
this.forceRefreshSubject.next();
|
|
270
271
|
}
|
|
271
272
|
/**
|
|
272
273
|
* Refresh the token.
|
|
@@ -404,7 +405,7 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
404
405
|
timer(Math.max(10, delayMs)),
|
|
405
406
|
from(this.disposeSignal),
|
|
406
407
|
this.token$.pipe(filter((t) => t?.exp !== referenceExp)),
|
|
407
|
-
this.
|
|
408
|
+
this.forceRefreshSubject,
|
|
408
409
|
]), { defaultValue: undefined });
|
|
409
410
|
while (this.disposeSignal.isUnset) {
|
|
410
411
|
const token = this.token();
|
|
@@ -428,9 +429,9 @@ let AuthenticationClientService = class AuthenticationClientService {
|
|
|
428
429
|
const currentNow = this.estimatedServerTimestampSeconds();
|
|
429
430
|
const currentBuffer = calculateRefreshBufferSeconds(currentToken);
|
|
430
431
|
const stillNeedsRefresh = this.forceRefreshRequested() || (currentNow >= currentToken.exp - currentBuffer);
|
|
431
|
-
this.forceRefreshRequested.set(false);
|
|
432
432
|
if (stillNeedsRefresh) {
|
|
433
433
|
await this.refresh();
|
|
434
|
+
this.forceRefreshRequested.set(false);
|
|
434
435
|
}
|
|
435
436
|
});
|
|
436
437
|
// If lock is held by another instance/tab, wait briefly for it to finish (passive sync)
|
|
@@ -90,10 +90,10 @@ describe('DocumentManagementAiService Integration', () => {
|
|
|
90
90
|
await runInInjectionContext(injector, async () => {
|
|
91
91
|
await aiService.extractData(tenantId, document.id);
|
|
92
92
|
const lastCall = mockGenerate.mock.calls[0][0];
|
|
93
|
-
const
|
|
94
|
-
const
|
|
95
|
-
expect(
|
|
96
|
-
expect(
|
|
93
|
+
const userPrompt = lastCall.prompt;
|
|
94
|
+
const userPromptText = userPrompt.map((p) => p.text).join('\n');
|
|
95
|
+
expect(userPromptText).toContain('Format the title of the document exactly as follows: INV-{{Date}}');
|
|
96
|
+
expect(userPromptText).toContain('Focus on items.');
|
|
97
97
|
});
|
|
98
98
|
});
|
|
99
99
|
test('classifyDocumentType should include granular instructions in prompt', async () => {
|
|
@@ -6,6 +6,7 @@ import { object, string } from '../../schema/index.js';
|
|
|
6
6
|
import { setupIntegrationTest } from '../../testing/index.js';
|
|
7
7
|
import { isString } from '../../utils/type-guards.js';
|
|
8
8
|
import { DocumentManagementConfiguration } from '../server/module.js';
|
|
9
|
+
import { DocumentFileService } from '../server/services/document-file.service.js';
|
|
9
10
|
import { DocumentManagementAiProviderService, DocumentManagementAncillaryService } from '../server/services/index.js';
|
|
10
11
|
import { AiValidationExecutor } from '../server/validators/ai-validation-executor.js';
|
|
11
12
|
import { TestDocumentManagementAncillaryService } from './helper.js';
|
|
@@ -41,6 +42,7 @@ describe('AiValidationExecutor Overrides', () => {
|
|
|
41
42
|
injector.register(DocumentManagementAiProviderService, { useValue: mockAiProvider });
|
|
42
43
|
injector.register(DocumentManagementAncillaryService, { useToken: TestDocumentManagementAncillaryService });
|
|
43
44
|
injector.register(DocumentManagementConfiguration, { useValue: { fileObjectStorageModule: 'docs', fileUploadObjectStorageModule: 'uploads', filePreviewObjectStorageModule: 'previews' } });
|
|
45
|
+
injector.register(DocumentFileService, { useValue: { getContent: vi.fn().mockResolvedValue(new Uint8Array([1, 2, 3])) } });
|
|
44
46
|
});
|
|
45
47
|
afterAll(async () => {
|
|
46
48
|
await injector?.dispose();
|
|
@@ -66,6 +68,7 @@ describe('AiValidationExecutor Overrides', () => {
|
|
|
66
68
|
const context = {
|
|
67
69
|
execution: { tenantId },
|
|
68
70
|
definition: { identifier: 'test-validation' },
|
|
71
|
+
document: { id: 'test-doc', mimeType: 'application/pdf' },
|
|
69
72
|
};
|
|
70
73
|
await executor.publicExecute(context);
|
|
71
74
|
const call = generateSpy.mock.calls[0][0];
|
|
@@ -23,9 +23,9 @@ export type HttpServerResponseOptions = {
|
|
|
23
23
|
};
|
|
24
24
|
export declare class HttpServerResponse {
|
|
25
25
|
#private;
|
|
26
|
+
readonly headers: HttpHeaders;
|
|
26
27
|
statusCode: number | undefined;
|
|
27
28
|
statusMessage: string | undefined;
|
|
28
|
-
headers: HttpHeaders;
|
|
29
29
|
get body(): HttpServerResponseBody | undefined;
|
|
30
30
|
set body(value: HttpServerResponseBody | undefined);
|
|
31
31
|
get bodyType(): HttpServerResponseBodyType;
|
|
@@ -5,9 +5,9 @@ import { HttpHeaders } from '../http-headers.js';
|
|
|
5
5
|
export class HttpServerResponse {
|
|
6
6
|
#body;
|
|
7
7
|
#bodyType;
|
|
8
|
+
headers = new HttpHeaders();
|
|
8
9
|
statusCode;
|
|
9
10
|
statusMessage;
|
|
10
|
-
headers;
|
|
11
11
|
get body() {
|
|
12
12
|
return this.#body;
|
|
13
13
|
}
|
|
@@ -35,10 +35,18 @@ export class HttpServerResponse {
|
|
|
35
35
|
});
|
|
36
36
|
}
|
|
37
37
|
update(options) {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
if (isDefined(options.statusCode)) {
|
|
39
|
+
this.statusCode = options.statusCode;
|
|
40
|
+
}
|
|
41
|
+
if (isDefined(options.statusMessage)) {
|
|
42
|
+
this.statusMessage = options.statusMessage;
|
|
43
|
+
}
|
|
44
|
+
if (isDefined(options.headers)) {
|
|
45
|
+
this.headers.setMany(options.headers);
|
|
46
|
+
}
|
|
47
|
+
if (isDefined(options.body)) {
|
|
48
|
+
this.body = options.body;
|
|
49
|
+
}
|
|
42
50
|
if (isDefined(options.cookies)) {
|
|
43
51
|
for (const [name, cookie] of objectEntries(options.cookies)) {
|
|
44
52
|
this.headers.append('Set-Cookie', formatSetCookie(name, cookie.value, cookie));
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { describe, expect, it, vi } from 'vitest';
|
|
2
2
|
// Mock supports before importing PrettyPrintLogFormatter
|
|
3
|
-
vi.mock('
|
|
3
|
+
vi.mock('../../supports.js', () => ({
|
|
4
4
|
supportsColoredStdout: true,
|
|
5
5
|
supportsColoredStderr: true,
|
|
6
6
|
}));
|
|
7
|
-
import { LogLevel } from '../level.js';
|
|
8
7
|
import { PrettyPrintLogFormatter } from '../formatters/pretty-print.js';
|
|
8
|
+
import { LogLevel } from '../level.js';
|
|
9
9
|
describe('PrettyPrintLogFormatter', () => {
|
|
10
10
|
const formatter = new PrettyPrintLogFormatter();
|
|
11
11
|
it('should format a log entry with an error and no context', () => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tstdl/base",
|
|
3
|
-
"version": "0.93.
|
|
3
|
+
"version": "0.93.174",
|
|
4
4
|
"author": "Patrick Hein",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -203,7 +203,6 @@
|
|
|
203
203
|
"typedoc-plugin-missing-exports": "4.1",
|
|
204
204
|
"typescript": "5.9",
|
|
205
205
|
"typescript-eslint": "8.57",
|
|
206
|
-
"vite-tsconfig-paths": "6.1",
|
|
207
206
|
"vitest": "4.1"
|
|
208
207
|
}
|
|
209
208
|
}
|