@tstdl/base 0.93.123 → 0.93.126
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 +6 -6
- package/ai/index.d.ts +2 -6
- package/ai/index.js +2 -6
- package/ai/parser/index.d.ts +1 -0
- package/ai/parser/index.js +1 -0
- package/ai/parser/parser.d.ts +12 -0
- package/ai/parser/parser.js +28 -0
- package/ai/prompts/build.d.ts +21 -0
- package/ai/prompts/build.js +25 -0
- package/ai/prompts/index.d.ts +2 -0
- package/ai/prompts/index.js +2 -0
- package/ai/prompts/instructions-formatter.d.ts +9 -22
- package/ai/prompts/instructions-formatter.js +20 -7
- package/ai/prompts/instructions.js +1 -1
- package/ai/prompts/steering.d.ts +27 -0
- package/ai/prompts/steering.js +54 -0
- package/ai/tests/instructions-formatter.test.js +115 -0
- package/ai/tests/steering.test.js +37 -0
- package/application/application.d.ts +2 -1
- package/application/application.js +3 -0
- package/authentication/client/module.d.ts +1 -1
- package/authentication/client/module.js +4 -5
- package/authentication/tests/authentication-ancillary.service.test.js +1 -1
- package/authentication/tests/authentication.api-controller.test.js +3 -1
- package/authentication/tests/authentication.api-request-token.provider.test.js +1 -1
- package/authentication/tests/authentication.client-service.test.js +1 -1
- package/authentication/tests/authentication.service.test.js +1 -1
- package/authentication/tests/subject.service.test.js +1 -1
- package/circuit-breaker/tests/circuit-breaker.test.js +1 -1
- package/document-management/api/document-management.api.d.ts +16 -16
- package/document-management/api/document-management.api.js +12 -12
- package/document-management/models/ai-configuration.d.ts +59 -0
- package/document-management/models/ai-configuration.js +1 -0
- package/document-management/models/document-assignment-scope.model.js +2 -4
- package/document-management/models/document-assignment-task.model.js +2 -4
- package/document-management/models/document-collection-assignment.model.js +2 -4
- package/document-management/models/document-collection.model.js +2 -3
- package/document-management/models/document-content.model.d.ts +6 -0
- package/document-management/models/document-content.model.js +32 -0
- package/document-management/models/document-property-value.model.js +1 -2
- package/document-management/models/document-request-collection-assignment.model.js +2 -4
- package/document-management/models/document-request.model.js +2 -4
- package/document-management/models/document-tag-assignment.model.js +2 -3
- package/document-management/models/document-validation-execution-related-document.model.js +2 -4
- package/document-management/models/document-validation-execution.model.js +2 -5
- package/document-management/models/document-workflow.model.d.ts +2 -1
- package/document-management/models/document-workflow.model.js +4 -5
- package/document-management/models/document.model.js +2 -3
- package/document-management/models/index.d.ts +2 -0
- package/document-management/models/index.js +2 -0
- package/document-management/server/api/document-management.api.d.ts +7 -7
- package/document-management/server/api/document-management.api.js +9 -9
- package/document-management/server/configure.d.ts +4 -1
- package/document-management/server/configure.js +9 -4
- package/document-management/server/drizzle/{0000_silly_chimera.sql → 0000_curious_nighthawk.sql} +8 -28
- package/document-management/server/drizzle/meta/0000_snapshot.json +14 -286
- package/document-management/server/drizzle/meta/_journal.json +2 -2
- package/document-management/server/module.d.ts +2 -0
- package/document-management/server/module.js +1 -0
- package/document-management/server/schemas.d.ts +2 -1
- package/document-management/server/services/document-file.service.d.ts +6 -6
- package/document-management/server/services/document-file.service.js +7 -81
- package/document-management/server/services/document-management-ai-provider.service.d.ts +66 -0
- package/document-management/server/services/document-management-ai-provider.service.js +2 -0
- package/document-management/server/services/document-management-ai.service.d.ts +44 -7
- package/document-management/server/services/document-management-ai.service.js +332 -329
- package/document-management/server/services/document-validation.service.d.ts +1 -1
- package/document-management/server/services/document-workflow.service.d.ts +4 -3
- package/document-management/server/services/document-workflow.service.js +26 -9
- package/document-management/server/services/document.service.d.ts +7 -3
- package/document-management/server/services/document.service.js +13 -4
- package/document-management/server/services/index.d.ts +1 -0
- package/document-management/server/services/index.js +1 -0
- package/document-management/server/validators/ai-validation-executor.d.ts +419 -12
- package/document-management/server/validators/ai-validation-executor.js +51 -46
- package/document-management/server/validators/single-document-validation-executor.d.ts +1 -3
- package/document-management/server/validators/single-document-validation-executor.js +2 -4
- package/document-management/service-models/document.service-model.d.ts +3 -3
- package/document-management/service-models/document.service-model.js +1 -1
- package/document-management/tests/ai-config-hierarchy.test.d.ts +1 -0
- package/document-management/tests/ai-config-hierarchy.test.js +64 -0
- package/document-management/tests/ai-config-integration.test.d.ts +1 -0
- package/document-management/tests/ai-config-integration.test.js +125 -0
- package/document-management/tests/ai-config-merge.test.d.ts +1 -0
- package/document-management/tests/ai-config-merge.test.js +38 -0
- package/document-management/tests/document-management-ai-overrides.test.d.ts +1 -0
- package/document-management/tests/document-management-ai-overrides.test.js +64 -0
- package/document-management/tests/document-management-core.test.js +6 -6
- package/document-management/tests/document-management.api.test.js +5 -5
- package/document-management/tests/document-statistics.service.test.js +10 -6
- package/document-management/tests/document-validation-ai-overrides.test.d.ts +1 -0
- package/document-management/tests/document-validation-ai-overrides.test.js +85 -0
- package/document-management/tests/document.service.test.js +15 -11
- package/document-management/tests/enum-helpers.test.js +5 -5
- package/examples/document-management/ai-provider.d.ts +20 -0
- package/examples/document-management/ai-provider.js +74 -0
- package/examples/document-management/main.js +9 -6
- package/examples/injector/graph-example.d.ts +1 -0
- package/examples/injector/graph-example.js +340 -0
- package/injector/decorators.d.ts +4 -4
- package/injector/decorators.js +5 -6
- package/injector/forward-ref.d.ts +15 -0
- package/injector/forward-ref.js +20 -0
- package/injector/graph.d.ts +113 -0
- package/injector/graph.js +631 -0
- package/injector/index.d.ts +2 -0
- package/injector/index.js +2 -0
- package/injector/inject.d.ts +15 -15
- package/injector/injector.d.ts +101 -13
- package/injector/injector.js +103 -59
- package/injector/resolve-chain.d.ts +20 -6
- package/injector/resolve-chain.js +39 -14
- package/injector/tests/advanced.test.d.ts +1 -0
- package/injector/tests/advanced.test.js +116 -0
- package/injector/tests/async-init.test.d.ts +1 -0
- package/injector/tests/async-init.test.js +77 -0
- package/injector/tests/basic.test.d.ts +1 -0
- package/injector/tests/basic.test.js +114 -0
- package/injector/tests/hierarchical.test.d.ts +1 -0
- package/injector/tests/hierarchical.test.js +59 -0
- package/injector/tests/lifecycles.test.d.ts +1 -0
- package/injector/tests/lifecycles.test.js +109 -0
- package/injector/token.d.ts +2 -1
- package/injector/token.js +4 -1
- package/injector/type-info.d.ts +1 -5
- package/injector/types.d.ts +4 -10
- package/logger/tests/pretty-print.test.d.ts +1 -0
- package/logger/{formatters → tests}/pretty-print.test.js +1 -1
- package/logger/transports/console.d.ts +3 -2
- package/logger/transports/console.js +4 -3
- package/notification/api/notification.api.d.ts +26 -6
- package/notification/api/notification.api.js +15 -4
- package/notification/client/notification-client.d.ts +6 -0
- package/notification/client/notification-client.js +13 -3
- package/notification/models/in-app-notification.model.d.ts +9 -3
- package/notification/models/in-app-notification.model.js +32 -11
- package/notification/models/notification-log.model.js +2 -3
- package/notification/server/api/notification.api-controller.d.ts +1 -0
- package/notification/server/api/notification.api-controller.js +7 -1
- package/notification/server/drizzle/{0000_oval_rage.sql → 0000_wise_pyro.sql} +22 -4
- package/notification/server/drizzle/meta/0000_snapshot.json +249 -37
- package/notification/server/drizzle/meta/_journal.json +2 -2
- package/notification/server/module.d.ts +5 -0
- package/notification/server/module.js +6 -1
- package/notification/server/providers/in-app-channel-provider.js +1 -0
- package/notification/server/schemas.d.ts +3 -2
- package/notification/server/schemas.js +3 -2
- package/notification/server/services/notification.service.d.ts +11 -6
- package/notification/server/services/notification.service.js +138 -42
- package/notification/tests/notification-api.test.js +16 -6
- package/notification/tests/notification-client.test.d.ts +1 -0
- package/notification/tests/{unit/notification-client.test.js → notification-client.test.js} +5 -5
- package/notification/tests/notification-flow.test.js +45 -7
- package/notification/tests/notification-sse.service.test.js +1 -1
- package/notification/tests/notification-type.service.test.js +1 -1
- package/object-storage/s3/s3.object-storage.js +3 -0
- package/object-storage/s3/tests/s3.object-storage.integration.test.js +1 -1
- package/orm/server/drizzle/schema-converter.js +5 -3
- package/orm/tests/repository-attributes.test.js +10 -17
- package/orm/tests/repository-cti-mapping.test.js +2 -2
- package/orm/tests/repository-cti-soft-delete.test.js +1 -1
- package/orm/tests/repository-cti.test.js +19 -33
- package/orm/tests/repository-extra-coverage.test.js +1 -1
- package/orm/tests/repository-search.test.js +5 -2
- package/orm/tests/schema-converter.test.js +1 -0
- package/orm/tests/transaction-safety.test.js +1 -1
- package/package.json +7 -9
- package/rate-limit/tests/postgres-rate-limiter.test.js +6 -16
- package/renderer/d2.d.ts +77 -0
- package/renderer/d2.js +68 -0
- package/renderer/graphviz.d.ts +47 -0
- package/renderer/graphviz.js +58 -0
- package/renderer/index.d.ts +4 -0
- package/renderer/index.js +4 -0
- package/renderer/typst.d.ts +57 -0
- package/renderer/typst.js +62 -0
- package/rpc/adapters/readable-stream.adapter.d.ts +3 -0
- package/rpc/adapters/readable-stream.adapter.js +5 -1
- package/rpc/rpc.js +28 -3
- package/rpc/tests/rpc.integration.test.js +3 -1
- package/schema/schemas/nullable.js +1 -1
- package/task-queue/task-queue.d.ts +2 -0
- package/task-queue/task-queue.js +6 -2
- package/task-queue/tests/complex.test.js +1 -1
- package/task-queue/tests/dependencies.test.js +3 -3
- package/task-queue/tests/extensive-dependencies.test.js +1 -1
- package/task-queue/tests/queue.test.js +1 -1
- package/task-queue/tests/worker.test.js +4 -7
- package/test5.js +52 -8
- package/{unit-test → testing}/integration-setup.d.ts +1 -0
- package/{unit-test → testing}/integration-setup.js +13 -0
- package/utils/base64.d.ts +7 -0
- package/utils/base64.js +10 -1
- package/utils/noop.d.ts +7 -1
- package/utils/noop.js +7 -1
- package/ai/ai-file.service.d.ts +0 -57
- package/ai/ai-file.service.js +0 -233
- package/ai/ai-session.d.ts +0 -38
- package/ai/ai-session.js +0 -50
- package/ai/ai.service.d.ts +0 -126
- package/ai/ai.service.js +0 -481
- package/ai/functions.d.ts +0 -9
- package/ai/functions.js +0 -38
- package/ai/module.d.ts +0 -26
- package/ai/module.js +0 -25
- package/ai/types.d.ts +0 -229
- package/ai/types.js +0 -33
- package/latex/index.d.ts +0 -1
- package/latex/index.js +0 -1
- package/typst/index.d.ts +0 -1
- package/typst/index.js +0 -1
- package/typst/render.d.ts +0 -23
- package/typst/render.js +0 -32
- /package/{logger/formatters/pretty-print.test.d.ts → ai/tests/instructions-formatter.test.d.ts} +0 -0
- /package/{notification/tests/unit/notification-client.test.d.ts → ai/tests/steering.test.d.ts} +0 -0
- /package/{latex/render.d.ts → renderer/latex.d.ts} +0 -0
- /package/{latex/render.js → renderer/latex.js} +0 -0
- /package/{unit-test → testing}/index.d.ts +0 -0
- /package/{unit-test → testing}/index.js +0 -0
|
@@ -3,7 +3,7 @@ import { beforeAll, beforeEach, describe, expect, it, vi } from 'vitest';
|
|
|
3
3
|
import { CircuitBreakerState } from '../../../circuit-breaker/index.js';
|
|
4
4
|
import { CircuitBreakerProvider } from '../../../circuit-breaker/provider.js';
|
|
5
5
|
import { Logger } from '../../../logger/logger.js';
|
|
6
|
-
import { setupIntegrationTest } from '../../../
|
|
6
|
+
import { setupIntegrationTest } from '../../../testing/index.js';
|
|
7
7
|
import { vertexAiMultiLocation } from '../multi-region.plugin.js';
|
|
8
8
|
vi.mock('#/utils/array/index.js', async (importOriginal) => {
|
|
9
9
|
const actual = await importOriginal();
|
|
@@ -30,19 +30,19 @@ describe('Genkit vertexai-multi-location Plugin Tests', () => {
|
|
|
30
30
|
const { injector } = await setupIntegrationTest({ modules: { circuitBreaker: true } });
|
|
31
31
|
cbProvider = injector.resolve(CircuitBreakerProvider);
|
|
32
32
|
logger = injector.resolve(Logger, 'Test');
|
|
33
|
+
});
|
|
34
|
+
beforeEach(async () => {
|
|
35
|
+
vi.clearAllMocks();
|
|
33
36
|
ai = genkit({
|
|
34
37
|
plugins: [
|
|
35
38
|
vertexAiMultiLocation({
|
|
36
39
|
locations: ['region-1', 'region-2'],
|
|
37
40
|
circuitBreakerProvider: cbProvider,
|
|
38
41
|
logger,
|
|
39
|
-
circuitBreakerConfig: { resetTimeout: 1000000 },
|
|
42
|
+
circuitBreakerConfig: { resetTimeout: 1000000, threshold: 1 },
|
|
40
43
|
}),
|
|
41
44
|
],
|
|
42
45
|
});
|
|
43
|
-
});
|
|
44
|
-
beforeEach(async () => {
|
|
45
|
-
vi.clearAllMocks();
|
|
46
46
|
const config = { threshold: 1, resetTimeout: 1000000 };
|
|
47
47
|
await cbProvider.provide('genkit:vertex-ai:location:region-1', config).recordSuccess();
|
|
48
48
|
await cbProvider.provide('genkit:vertex-ai:location:region-2', config).recordSuccess();
|
|
@@ -101,7 +101,7 @@ describe('Genkit vertexai-multi-location Plugin Tests', () => {
|
|
|
101
101
|
locations,
|
|
102
102
|
circuitBreakerProvider: cbProvider,
|
|
103
103
|
logger,
|
|
104
|
-
circuitBreakerConfig: { resetTimeout: 1000000 },
|
|
104
|
+
circuitBreakerConfig: { resetTimeout: 1000000, threshold: 1 },
|
|
105
105
|
}),
|
|
106
106
|
],
|
|
107
107
|
});
|
package/ai/index.d.ts
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
3
|
-
export * from './ai.service.js';
|
|
4
|
-
export * from './functions.js';
|
|
5
|
-
export * from './module.js';
|
|
1
|
+
export * from './genkit/index.js';
|
|
2
|
+
export * from './parser/index.js';
|
|
6
3
|
export * from './prompts/index.js';
|
|
7
|
-
export * from './types.js';
|
package/ai/index.js
CHANGED
|
@@ -1,7 +1,3 @@
|
|
|
1
|
-
export * from './
|
|
2
|
-
export * from './
|
|
3
|
-
export * from './ai.service.js';
|
|
4
|
-
export * from './functions.js';
|
|
5
|
-
export * from './module.js';
|
|
1
|
+
export * from './genkit/index.js';
|
|
2
|
+
export * from './parser/index.js';
|
|
6
3
|
export * from './prompts/index.js';
|
|
7
|
-
export * from './types.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './parser.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './parser.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AIs sometimes return the string "null" instead of an actual null value. This function converts such strings to null, while leaving other strings unchanged.
|
|
3
|
+
*/
|
|
4
|
+
export declare function parseAiNullableText(text: string | null): string | null;
|
|
5
|
+
/**
|
|
6
|
+
* Convert the output of AIs that is supposed to be a date into a numeric date (days since epoch). If the input is invalid, returns null (if allowNull is true) or the fallback value (if provided), or throws an error otherwise.
|
|
7
|
+
* @param dateOrString
|
|
8
|
+
* @param allowNull
|
|
9
|
+
* @param fallback
|
|
10
|
+
*/
|
|
11
|
+
export declare function parseAiDateToNumericDate<F>(dateOrString: Date | string, allowNull: false, fallback?: F): number | F;
|
|
12
|
+
export declare function parseAiDateToNumericDate<F>(dateOrString: Date | string, allowNull?: boolean, fallback?: F): number | null | F;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { dateToNumericDate } from '../../utils/date-time.js';
|
|
2
|
+
import { isDate } from '../../utils/type-guards.js';
|
|
3
|
+
/**
|
|
4
|
+
* AIs sometimes return the string "null" instead of an actual null value. This function converts such strings to null, while leaving other strings unchanged.
|
|
5
|
+
*/
|
|
6
|
+
export function parseAiNullableText(text) {
|
|
7
|
+
if (text == 'null') {
|
|
8
|
+
return null;
|
|
9
|
+
}
|
|
10
|
+
return text;
|
|
11
|
+
}
|
|
12
|
+
export function parseAiDateToNumericDate(dateOrString, allowNull = true, fallback) {
|
|
13
|
+
if (isDate(dateOrString)) {
|
|
14
|
+
return dateToNumericDate(dateOrString);
|
|
15
|
+
}
|
|
16
|
+
const date = new Date(dateOrString);
|
|
17
|
+
if (Number.isNaN(date.getTime())) {
|
|
18
|
+
console.warn(`Invalid date string from AI: ${dateOrString}`);
|
|
19
|
+
if (allowNull) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
if (arguments.length >= 3) {
|
|
23
|
+
return fallback;
|
|
24
|
+
}
|
|
25
|
+
throw new Error(`Invalid date string from AI: ${dateOrString}`);
|
|
26
|
+
}
|
|
27
|
+
return dateToNumericDate(date);
|
|
28
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Part } from 'genkit';
|
|
2
|
+
import type { ObjectLiteral } from '../../types/types.js';
|
|
3
|
+
import { type Instructions } from './instructions-formatter.js';
|
|
4
|
+
export type AiMergeData = {
|
|
5
|
+
baseSystemInstructions: Instructions;
|
|
6
|
+
baseUserInstructions: Instructions;
|
|
7
|
+
additionalSystemInstructions?: Instructions | string;
|
|
8
|
+
additionalUserInstructions?: Instructions | string;
|
|
9
|
+
systemInstructionsOverride?: (instructions: Instructions) => Instructions | string;
|
|
10
|
+
userInstructionsOverride?: (instructions: Instructions) => Instructions | string;
|
|
11
|
+
data?: ObjectLiteral;
|
|
12
|
+
language?: string;
|
|
13
|
+
media?: {
|
|
14
|
+
mimeType: string;
|
|
15
|
+
content: Uint8Array<ArrayBuffer>;
|
|
16
|
+
};
|
|
17
|
+
};
|
|
18
|
+
export declare function buildPrompts(data: AiMergeData): {
|
|
19
|
+
systemPrompt: Part[];
|
|
20
|
+
userPrompt: Part[];
|
|
21
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { encodeDataUrl } from '../../utils/base64.js';
|
|
2
|
+
import { objectKeys } from '../../utils/object/object.js';
|
|
3
|
+
import { isDefined, isString } from '../../utils/type-guards.js';
|
|
4
|
+
import { formatData } from './format.js';
|
|
5
|
+
import { formatInstructions, sections } from './instructions-formatter.js';
|
|
6
|
+
import { languagePrompt } from './steering.js';
|
|
7
|
+
export function buildPrompts(data) {
|
|
8
|
+
const systemInstructions = (isDefined(data.additionalSystemInstructions) && (isString(data.additionalSystemInstructions) || (objectKeys(data.additionalSystemInstructions).length > 0)))
|
|
9
|
+
? [data.baseSystemInstructions, { 'Additional Instructions': data.additionalSystemInstructions }]
|
|
10
|
+
: data.baseSystemInstructions;
|
|
11
|
+
const dataInstructions = isDefined(data.data) ? { Data: `\`\`\`toon\n${formatData(data.data)}\n\`\`\`` } : undefined;
|
|
12
|
+
const outputLanguageInstructions = isDefined(data.language) ? { 'Output Language': languagePrompt(data.language) } : undefined;
|
|
13
|
+
const userInstructions = sections(((isDefined(data.additionalUserInstructions) && (isString(data.additionalUserInstructions) || (objectKeys(data.additionalUserInstructions).length > 0)))
|
|
14
|
+
? [dataInstructions, data.baseUserInstructions, { 'Additional Instructions': data.additionalUserInstructions }, outputLanguageInstructions]
|
|
15
|
+
: [dataInstructions, data.baseUserInstructions, outputLanguageInstructions]).filter(isDefined));
|
|
16
|
+
const systemInstructionsOverride = data.systemInstructionsOverride?.(systemInstructions) ?? systemInstructions;
|
|
17
|
+
const systemPrompt = isString(systemInstructionsOverride) ? systemInstructionsOverride : formatInstructions(systemInstructionsOverride);
|
|
18
|
+
const userInstructionsOverride = data.userInstructionsOverride?.(userInstructions) ?? userInstructions;
|
|
19
|
+
const userPrompt = isString(userInstructionsOverride) ? userInstructionsOverride : formatInstructions(userInstructionsOverride);
|
|
20
|
+
const mediaUrl = isDefined(data.media) ? encodeDataUrl(data.media.mimeType, data.media.content) : undefined;
|
|
21
|
+
return {
|
|
22
|
+
systemPrompt: [{ text: systemPrompt }],
|
|
23
|
+
userPrompt: isDefined(mediaUrl) ? [{ media: { url: mediaUrl } }, { text: userPrompt }] : [{ text: userPrompt }],
|
|
24
|
+
};
|
|
25
|
+
}
|
package/ai/prompts/index.d.ts
CHANGED
package/ai/prompts/index.js
CHANGED
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
export type ListStyle = 'sections' | 'ordered' | 'unordered';
|
|
8
8
|
/**
|
|
9
9
|
* The content of an instructions list, which can be either:
|
|
10
|
-
* - An array of strings
|
|
10
|
+
* - An array of strings or nested instructions.
|
|
11
11
|
* - A nested `Instructions` object (key-value pairs or further lists).
|
|
12
12
|
*/
|
|
13
|
-
export type InstructionsListContent = string[] | Instructions;
|
|
13
|
+
export type InstructionsListContent = (string | Instructions)[] | Instructions;
|
|
14
14
|
/**
|
|
15
15
|
* A container representing a specific grouping of instructions with a defined style.
|
|
16
16
|
* This is usually created via factory functions like `sections()`, `orderedList()`, or `unorderedList()`.
|
|
@@ -24,12 +24,12 @@ export type InstructionsList = {
|
|
|
24
24
|
items: InstructionsListContent;
|
|
25
25
|
};
|
|
26
26
|
/**
|
|
27
|
-
* A recursive
|
|
28
|
-
*
|
|
27
|
+
* A recursive structure for defining structured instructions.
|
|
28
|
+
* Can be a simple string, an array of strings or instructions, or a dictionary.
|
|
29
29
|
*/
|
|
30
|
-
export type Instructions = {
|
|
31
|
-
[key: string]:
|
|
32
|
-
};
|
|
30
|
+
export type Instructions = string | {
|
|
31
|
+
[key: string]: Instructions | InstructionsList;
|
|
32
|
+
} | Instructions[];
|
|
33
33
|
/**
|
|
34
34
|
* Creates a container where content is rendered as Markdown sections.
|
|
35
35
|
* Keys in the object map become headers (e.g., `# Key`), and nested items reset indentation.
|
|
@@ -70,19 +70,6 @@ export declare function unorderedList(items: InstructionsListContent): Instructi
|
|
|
70
70
|
* @param items - The list items or map.
|
|
71
71
|
*/
|
|
72
72
|
export declare function unorderedList(instruction: string, items: InstructionsListContent): InstructionsList;
|
|
73
|
-
|
|
74
|
-
* Formats a structured instructions object into a string representation suitable for AI prompts (Markdown).
|
|
75
|
-
*
|
|
76
|
-
* It recursively handles:
|
|
77
|
-
* - `sections`: Creates headers (H1, H2...).
|
|
78
|
-
* - `ordered` / `unordered`: Creates indented lists.
|
|
79
|
-
* - `Instructions`: Objects are formatted as key-value pairs (e.g., `- **Key:** Value`).
|
|
80
|
-
*
|
|
81
|
-
* @param node - The root instructions object, array, or instructions list wrapper.
|
|
82
|
-
* @param options - Formatting options.
|
|
83
|
-
* @param options.initialDepth - The starting indentation level (default: 0).
|
|
84
|
-
* @returns A formatted string.
|
|
85
|
-
*/
|
|
86
|
-
export declare function formatInstructions(node: Instructions | InstructionsList | string[], options?: {
|
|
73
|
+
export declare const formatInstructions: (node: Instructions | InstructionsList, options?: {
|
|
87
74
|
initialDepth?: number;
|
|
88
|
-
})
|
|
75
|
+
}) => string;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { memoize } from '../../utils/function/memoize.js';
|
|
1
2
|
import { hasOwnProperty, objectEntries } from '../../utils/object/object.js';
|
|
2
3
|
import { assertDefined, isArray, isDefined, isObject, isString } from '../../utils/type-guards.js';
|
|
3
4
|
// --- Factories ---
|
|
@@ -21,7 +22,7 @@ function isInstructionsList(obj) {
|
|
|
21
22
|
return isObject(obj) && hasOwnProperty(obj, 'style') && hasOwnProperty(obj, 'items');
|
|
22
23
|
}
|
|
23
24
|
// --- Formatter Logic ---
|
|
24
|
-
const INDENT_SIZE =
|
|
25
|
+
const INDENT_SIZE = 4;
|
|
25
26
|
function getPrefix(style, index, sectionDepth) {
|
|
26
27
|
switch (style) {
|
|
27
28
|
case 'ordered':
|
|
@@ -58,6 +59,12 @@ function formatWithHangingIndent(text, baseIndent, prefix) {
|
|
|
58
59
|
* Main recursive formatter.
|
|
59
60
|
*/
|
|
60
61
|
function processNode(node, context) {
|
|
62
|
+
// 0. Handle Strings
|
|
63
|
+
if (isString(node)) {
|
|
64
|
+
const isSection = context.style == 'sections';
|
|
65
|
+
const currentBaseIndent = ' '.repeat(isSection ? 0 : context.indentDepth * INDENT_SIZE);
|
|
66
|
+
return formatWithHangingIndent(node, currentBaseIndent, '');
|
|
67
|
+
}
|
|
61
68
|
// 1. Unwrap InstructionsList (The Wrapper)
|
|
62
69
|
// If the node is a wrapper, we adopt its style and instruction, then process its items.
|
|
63
70
|
if (isInstructionsList(node)) {
|
|
@@ -65,7 +72,7 @@ function processNode(node, context) {
|
|
|
65
72
|
// If this Wrapper is a root node, the instruction is usually printed by the caller or ignored.
|
|
66
73
|
// If this Wrapper is a value of a key, the key printer handles the instruction.
|
|
67
74
|
// However, if we have a "Root Wrapper" with an instruction (rare in your example), handle it:
|
|
68
|
-
const header = node.instruction ? `${node.instruction}\n` : '';
|
|
75
|
+
const header = node.instruction ? `${node.instruction.trim()}\n\n` : '';
|
|
69
76
|
// Determine next context
|
|
70
77
|
const nextContext = {
|
|
71
78
|
indentDepth: context.indentDepth, // Wrappers don't indent themselves, their content does
|
|
@@ -78,11 +85,14 @@ function processNode(node, context) {
|
|
|
78
85
|
const isSection = context.style == 'sections';
|
|
79
86
|
const currentBaseIndent = ' '.repeat(isSection ? 0 : context.indentDepth * INDENT_SIZE);
|
|
80
87
|
const separator = isSection ? '\n\n' : '\n';
|
|
81
|
-
// 2. Handle Arrays
|
|
88
|
+
// 2. Handle Arrays
|
|
82
89
|
if (isArray(node)) {
|
|
83
90
|
return node.map((item, index) => {
|
|
84
91
|
const prefix = getPrefix(context.style, index, context.sectionDepth);
|
|
85
|
-
|
|
92
|
+
if (isString(item)) {
|
|
93
|
+
return formatWithHangingIndent(item, currentBaseIndent, prefix);
|
|
94
|
+
}
|
|
95
|
+
return processNode(item, context);
|
|
86
96
|
}).join(separator);
|
|
87
97
|
}
|
|
88
98
|
// 3. Handle Objects (Key-Value Maps)
|
|
@@ -145,6 +155,7 @@ function processNode(node, context) {
|
|
|
145
155
|
return `${headerLine}${bodySeparator}${body}`;
|
|
146
156
|
}).join(separator);
|
|
147
157
|
}
|
|
158
|
+
export const formatInstructions = memoize(
|
|
148
159
|
/**
|
|
149
160
|
* Formats a structured instructions object into a string representation suitable for AI prompts (Markdown).
|
|
150
161
|
*
|
|
@@ -158,17 +169,19 @@ function processNode(node, context) {
|
|
|
158
169
|
* @param options.initialDepth - The starting indentation level (default: 0).
|
|
159
170
|
* @returns A formatted string.
|
|
160
171
|
*/
|
|
161
|
-
|
|
172
|
+
function formatInstructions(node, options = {}) {
|
|
162
173
|
// Heuristic: If passing a raw object, assume it's a Root Section unless specified otherwise.
|
|
163
174
|
// If passing a Wrapper, the Wrapper dictates the style.
|
|
164
175
|
const initialStyle = isInstructionsList(node)
|
|
165
176
|
? node.style
|
|
166
177
|
: isArray(node)
|
|
167
178
|
? 'unordered'
|
|
168
|
-
:
|
|
179
|
+
: isString(node)
|
|
180
|
+
? 'unordered'
|
|
181
|
+
: 'sections';
|
|
169
182
|
return processNode(node, {
|
|
170
183
|
indentDepth: options.initialDepth ?? 0,
|
|
171
184
|
sectionDepth: 1,
|
|
172
185
|
style: initialStyle,
|
|
173
186
|
}).trim();
|
|
174
|
-
}
|
|
187
|
+
});
|
|
@@ -2,7 +2,7 @@ import { unorderedList } from './instructions-formatter.js';
|
|
|
2
2
|
export const jsonOutputInstructions = {
|
|
3
3
|
'JSON Output': unorderedList({
|
|
4
4
|
'Schema Compliance': 'Generate valid JSON that strictly matches the provided schema.',
|
|
5
|
-
'Nullable fields with missing data': 'Must be set to literal `null
|
|
5
|
+
'Nullable fields with missing data': 'Must be set to literal `null`, not the string "null".',
|
|
6
6
|
'Optional fields with missing data': 'Omit the key entirely (sparse JSON).',
|
|
7
7
|
}),
|
|
8
8
|
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { type Instructions } from './instructions-formatter.js';
|
|
2
|
+
export type FewShotExample = {
|
|
3
|
+
input: any;
|
|
4
|
+
output: any;
|
|
5
|
+
/** Whether this is a negative example (showing what NOT to do). */
|
|
6
|
+
isNegative?: boolean;
|
|
7
|
+
/** Optional reason explaining why this example is positive or negative. */
|
|
8
|
+
reason?: string;
|
|
9
|
+
};
|
|
10
|
+
/**
|
|
11
|
+
* Creates a prompt addition for few-shot learning.
|
|
12
|
+
* @param examples An array of input/output pairs.
|
|
13
|
+
* @returns A formatted few-shot prompt.
|
|
14
|
+
*/
|
|
15
|
+
export declare function fewShotPrompt(examples: FewShotExample[]): Instructions;
|
|
16
|
+
/**
|
|
17
|
+
* Creates a prompt addition to specify the output language.
|
|
18
|
+
* @param language The desired output language (e.g., 'English', 'German', 'en', 'de').
|
|
19
|
+
* @returns A formatted language prompt.
|
|
20
|
+
*/
|
|
21
|
+
export declare function languagePrompt(language: string): string;
|
|
22
|
+
/**
|
|
23
|
+
* Creates a prompt addition for specific style or steering instructions.
|
|
24
|
+
* @param instructions Style or steering instructions (e.g., "Titles should be prefixed with [DMS]").
|
|
25
|
+
* @returns A formatted style prompt.
|
|
26
|
+
*/
|
|
27
|
+
export declare function stylePrompt(instructions: string): string;
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { fromEntries } from '../../utils/object/object.js';
|
|
2
|
+
import { isDefined, isString } from '../../utils/type-guards.js';
|
|
3
|
+
import { formatInstructions, orderedList, unorderedList } from './instructions-formatter.js';
|
|
4
|
+
function formatExampleValue(value) {
|
|
5
|
+
if (isString(value)) {
|
|
6
|
+
return value;
|
|
7
|
+
}
|
|
8
|
+
return JSON.stringify(value);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Creates a prompt addition for few-shot learning.
|
|
12
|
+
* @param examples An array of input/output pairs.
|
|
13
|
+
* @returns A formatted few-shot prompt.
|
|
14
|
+
*/
|
|
15
|
+
export function fewShotPrompt(examples) {
|
|
16
|
+
if (examples.length == 0) {
|
|
17
|
+
return {};
|
|
18
|
+
}
|
|
19
|
+
const entries = examples
|
|
20
|
+
.map((example, index) => {
|
|
21
|
+
const type = example.isNegative ? 'NEGATIVE' : 'POSITIVE';
|
|
22
|
+
return [
|
|
23
|
+
`Example ${index + 1} (${type})`,
|
|
24
|
+
unorderedList({
|
|
25
|
+
Input: formatExampleValue(example.input),
|
|
26
|
+
Output: formatExampleValue(example.output),
|
|
27
|
+
...(isDefined(example.reason) ? { Reason: example.reason } : {}),
|
|
28
|
+
}),
|
|
29
|
+
];
|
|
30
|
+
});
|
|
31
|
+
return {
|
|
32
|
+
Examples: orderedList('Use the following examples to understand the expected input and output format', fromEntries(entries)),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Creates a prompt addition to specify the output language.
|
|
37
|
+
* @param language The desired output language (e.g., 'English', 'German', 'en', 'de').
|
|
38
|
+
* @returns A formatted language prompt.
|
|
39
|
+
*/
|
|
40
|
+
export function languagePrompt(language) {
|
|
41
|
+
return `IMPORTANT: All generated text content MUST be in ${language}.`.trim();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Creates a prompt addition for specific style or steering instructions.
|
|
45
|
+
* @param instructions Style or steering instructions (e.g., "Titles should be prefixed with [DMS]").
|
|
46
|
+
* @returns A formatted style prompt.
|
|
47
|
+
*/
|
|
48
|
+
export function stylePrompt(instructions) {
|
|
49
|
+
return `
|
|
50
|
+
${formatInstructions({
|
|
51
|
+
'Style & Formatting Instructions': instructions,
|
|
52
|
+
})}
|
|
53
|
+
`.trim();
|
|
54
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { formatInstructions, orderedList, sections, unorderedList } from '../prompts/instructions-formatter.js';
|
|
3
|
+
describe('Instructions Formatter', () => {
|
|
4
|
+
test('should format a simple unordered list of strings', () => {
|
|
5
|
+
const instructions = ['Item 1', 'Item 2'];
|
|
6
|
+
const result = formatInstructions(instructions);
|
|
7
|
+
expect(result).toBe(`- Item 1
|
|
8
|
+
- Item 2`);
|
|
9
|
+
});
|
|
10
|
+
test('should format an object as sections by default', () => {
|
|
11
|
+
const instructions = {
|
|
12
|
+
'Section 1': 'Content 1',
|
|
13
|
+
'Section 2': 'Content 2',
|
|
14
|
+
};
|
|
15
|
+
const result = formatInstructions(instructions);
|
|
16
|
+
expect(result).toBe(`# Section 1
|
|
17
|
+
|
|
18
|
+
Content 1
|
|
19
|
+
|
|
20
|
+
# Section 2
|
|
21
|
+
|
|
22
|
+
Content 2`);
|
|
23
|
+
});
|
|
24
|
+
test('should format nested unordered lists', () => {
|
|
25
|
+
const instructions = unorderedList({
|
|
26
|
+
Parent: unorderedList([
|
|
27
|
+
'Child 1',
|
|
28
|
+
'Child 2',
|
|
29
|
+
]),
|
|
30
|
+
});
|
|
31
|
+
const result = formatInstructions(instructions);
|
|
32
|
+
expect(result).toBe(`- **Parent:**
|
|
33
|
+
- Child 1
|
|
34
|
+
- Child 2`);
|
|
35
|
+
});
|
|
36
|
+
test('should format ordered lists', () => {
|
|
37
|
+
const instructions = orderedList(['First', 'Second']);
|
|
38
|
+
const result = formatInstructions(instructions);
|
|
39
|
+
expect(result).toBe(`1. First
|
|
40
|
+
2. Second`);
|
|
41
|
+
});
|
|
42
|
+
test('should format nested mixed lists', () => {
|
|
43
|
+
const instructions = orderedList({
|
|
44
|
+
'Step 1': unorderedList([
|
|
45
|
+
'Substep A',
|
|
46
|
+
'Substep B',
|
|
47
|
+
]),
|
|
48
|
+
});
|
|
49
|
+
const result = formatInstructions(instructions);
|
|
50
|
+
expect(result).toBe(`1. **Step 1:**
|
|
51
|
+
- Substep A
|
|
52
|
+
- Substep B`);
|
|
53
|
+
});
|
|
54
|
+
test('should handle hanging indents for multi-line strings', () => {
|
|
55
|
+
const instructions = unorderedList([
|
|
56
|
+
`Line 1
|
|
57
|
+
Line 2`,
|
|
58
|
+
]);
|
|
59
|
+
const result = formatInstructions(instructions);
|
|
60
|
+
expect(result).toBe(`- Line 1
|
|
61
|
+
Line 2`);
|
|
62
|
+
});
|
|
63
|
+
test('should handle sections with instructions', () => {
|
|
64
|
+
const instructions = sections('General Info', {
|
|
65
|
+
SubSection: 'Details',
|
|
66
|
+
});
|
|
67
|
+
const result = formatInstructions(instructions);
|
|
68
|
+
expect(result).toBe(`General Info
|
|
69
|
+
|
|
70
|
+
# SubSection
|
|
71
|
+
|
|
72
|
+
Details`);
|
|
73
|
+
});
|
|
74
|
+
test('should handle nested sections (incrementing H level)', () => {
|
|
75
|
+
const instructions = sections({
|
|
76
|
+
'Level 1': sections({
|
|
77
|
+
'Level 2': 'Deep content',
|
|
78
|
+
}),
|
|
79
|
+
});
|
|
80
|
+
const result = formatInstructions(instructions);
|
|
81
|
+
expect(result).toBe(`# Level 1
|
|
82
|
+
|
|
83
|
+
## Level 2
|
|
84
|
+
|
|
85
|
+
Deep content`);
|
|
86
|
+
});
|
|
87
|
+
test('should handle complex nested structures with mixed styles', () => {
|
|
88
|
+
const instructions = sections({
|
|
89
|
+
Task: 'Perform the following actions',
|
|
90
|
+
Steps: orderedList({
|
|
91
|
+
'Step A': 'Do something',
|
|
92
|
+
'Step B': unorderedList([
|
|
93
|
+
'Subtask B1',
|
|
94
|
+
'Subtask B2',
|
|
95
|
+
]),
|
|
96
|
+
}),
|
|
97
|
+
Conclusion: 'All done',
|
|
98
|
+
});
|
|
99
|
+
const expected = `# Task
|
|
100
|
+
|
|
101
|
+
Perform the following actions
|
|
102
|
+
|
|
103
|
+
# Steps
|
|
104
|
+
|
|
105
|
+
1. **Step A:** Do something
|
|
106
|
+
2. **Step B:**
|
|
107
|
+
- Subtask B1
|
|
108
|
+
- Subtask B2
|
|
109
|
+
|
|
110
|
+
# Conclusion
|
|
111
|
+
|
|
112
|
+
All done`;
|
|
113
|
+
expect(formatInstructions(instructions)).toBe(expected);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { describe, expect, test } from 'vitest';
|
|
2
|
+
import { fewShotPrompt, formatInstructions, languagePrompt, stylePrompt } from '../../ai/prompts/index.js';
|
|
3
|
+
describe('ai-prompt-factories', () => {
|
|
4
|
+
test('fewShotPrompt should format positive examples', () => {
|
|
5
|
+
const prompt = formatInstructions(fewShotPrompt([
|
|
6
|
+
{ input: { text: 'hello' }, output: { result: 'world' } },
|
|
7
|
+
]));
|
|
8
|
+
expect(prompt).toContain('Examples');
|
|
9
|
+
expect(prompt).toContain('Example 1 (POSITIVE)');
|
|
10
|
+
expect(prompt).toContain('**Input:** {"text":"hello"}');
|
|
11
|
+
expect(prompt).toContain('**Output:** {"result":"world"}');
|
|
12
|
+
});
|
|
13
|
+
test('fewShotPrompt should format negative examples with reasons', () => {
|
|
14
|
+
const examples = [
|
|
15
|
+
{ input: { text: 'bad' }, output: { result: 'no' }, isNegative: true, reason: 'This is not allowed' },
|
|
16
|
+
];
|
|
17
|
+
const prompt = formatInstructions(fewShotPrompt(examples));
|
|
18
|
+
expect(prompt).toContain('Example 1 (NEGATIVE)');
|
|
19
|
+
expect(prompt).toContain('**Reason:** This is not allowed');
|
|
20
|
+
});
|
|
21
|
+
test('fewShotPrompt should format string examples without quotes', () => {
|
|
22
|
+
const prompt = formatInstructions(fewShotPrompt([
|
|
23
|
+
{ input: 'input string', output: 'output string' },
|
|
24
|
+
]));
|
|
25
|
+
expect(prompt).toContain('**Input:** input string');
|
|
26
|
+
expect(prompt).toContain('**Output:** output string');
|
|
27
|
+
});
|
|
28
|
+
test('languagePrompt should include the language', () => {
|
|
29
|
+
const prompt = languagePrompt('German');
|
|
30
|
+
expect(prompt).toBe('IMPORTANT: All generated text content MUST be in German.');
|
|
31
|
+
});
|
|
32
|
+
test('stylePrompt should include the instructions', () => {
|
|
33
|
+
const prompt = stylePrompt('Use formal tone.');
|
|
34
|
+
expect(prompt).toContain('Style & Formatting Instructions');
|
|
35
|
+
expect(prompt).toContain('Use formal tone.');
|
|
36
|
+
});
|
|
37
|
+
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { CancellationSignal } from '../cancellation/token.js';
|
|
2
|
-
import { type ProvidersItem } from '../injector/injector.js';
|
|
2
|
+
import { Injector, type ProvidersItem } from '../injector/injector.js';
|
|
3
3
|
import { Module } from '../module/index.js';
|
|
4
4
|
import type { OneOrMany, Type } from '../types/index.js';
|
|
5
5
|
export type InitializerFn = () => void | Promise<void>;
|
|
@@ -11,6 +11,7 @@ export declare const APPLICATION_INSTANCE_ID: import("../injector/token.js").Inj
|
|
|
11
11
|
export declare const APPLICATION_NAME: import("../injector/token.js").InjectionToken<string, never>;
|
|
12
12
|
export declare class Application {
|
|
13
13
|
#private;
|
|
14
|
+
get injector(): Injector;
|
|
14
15
|
static create(name: string, providers?: OneOrMany<ProvidersItem>[]): Application;
|
|
15
16
|
static run(name: string, providers?: OneOrMany<ProvidersItem>[]): Application;
|
|
16
17
|
get shutdownSignal(): CancellationSignal;
|
|
@@ -28,6 +28,9 @@ let Application = Application_1 = class Application {
|
|
|
28
28
|
#moduleTypesAndInstances = new Set(injectAll(APPLICATION_MODULE, undefined, { optional: true }));
|
|
29
29
|
#shutdownPromise = new DeferredPromise();
|
|
30
30
|
#shutdownToken = inject(CancellationSignal, undefined, { optional: true })?.createChild() ?? new CancellationToken();
|
|
31
|
+
get injector() {
|
|
32
|
+
return this.#injector;
|
|
33
|
+
}
|
|
31
34
|
static create(name, providers = []) {
|
|
32
35
|
const injector = new Injector(`${name}ApplicationInjector`);
|
|
33
36
|
injector.register(APPLICATION_INSTANCE_ID, { useValue: crypto.randomUUID() });
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ApiClientImplementation } from '../../api/index.js';
|
|
2
|
-
import { Injector } from '../../injector/
|
|
2
|
+
import { Injector } from '../../injector/index.js';
|
|
3
3
|
import type { Type } from '../../types/index.js';
|
|
4
4
|
import type { AuthenticationApiDefinition } from '../authentication.api.js';
|
|
5
5
|
/**
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { HTTP_CLIENT_MIDDLEWARE } from '../../http/client/tokens.js';
|
|
2
|
-
import { getCurrentInjector } from '../../injector/
|
|
3
|
-
import { Injector } from '../../injector/injector.js';
|
|
2
|
+
import { forwardRef, getCurrentInjector, Injector } from '../../injector/index.js';
|
|
4
3
|
import { isDefined } from '../../utils/type-guards.js';
|
|
5
4
|
import { AuthenticationClientService } from './authentication.service.js';
|
|
6
5
|
import { authenticationMiddleware, logoutOnUnauthorizedMiddleware, waitForAuthenticationCredentialsMiddleware } from './http-client.middleware.js';
|
|
@@ -20,19 +19,19 @@ export function configureAuthenticationClient(config, injector = getCurrentInjec
|
|
|
20
19
|
if (config.registerMiddleware == true) {
|
|
21
20
|
(injector ?? Injector).register(HTTP_CLIENT_MIDDLEWARE, {
|
|
22
21
|
useFactory(_, context) {
|
|
23
|
-
const authenticationService = context.resolve(
|
|
22
|
+
const authenticationService = context.resolve(forwardRef(() => AuthenticationClientService, 'object'));
|
|
24
23
|
return waitForAuthenticationCredentialsMiddleware(authenticationService);
|
|
25
24
|
},
|
|
26
25
|
}, { multi: true });
|
|
27
26
|
(injector ?? Injector).register(HTTP_CLIENT_MIDDLEWARE, {
|
|
28
27
|
useFactory(_, context) {
|
|
29
|
-
const authenticationService = context.resolve(
|
|
28
|
+
const authenticationService = context.resolve(forwardRef(() => AuthenticationClientService, 'object'));
|
|
30
29
|
return logoutOnUnauthorizedMiddleware(authenticationService);
|
|
31
30
|
},
|
|
32
31
|
}, { multi: true });
|
|
33
32
|
(injector ?? Injector).register(HTTP_CLIENT_MIDDLEWARE, {
|
|
34
33
|
useFactory(_, context) {
|
|
35
|
-
const authenticationService = context.resolve(
|
|
34
|
+
const authenticationService = context.resolve(forwardRef(() => AuthenticationClientService, 'object'));
|
|
36
35
|
return authenticationMiddleware(authenticationService);
|
|
37
36
|
},
|
|
38
37
|
}, { multi: true });
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { describe, expect, test } from 'vitest';
|
|
2
2
|
import { runInInjectionContext } from '../../injector/index.js';
|
|
3
|
-
import { setupIntegrationTest } from '../../
|
|
3
|
+
import { setupIntegrationTest } from '../../testing/index.js';
|
|
4
4
|
import { DefaultAuthenticationAncillaryService } from './authentication.test-ancillary-service.js';
|
|
5
5
|
describe('AuthenticationAncillaryService', () => {
|
|
6
6
|
test('default implementation should be abstract or have defaults', async () => {
|