tychat-contracts 1.6.69 → 1.6.73

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 (28) hide show
  1. package/dist/connections/connections.dto.d.ts +53 -0
  2. package/dist/connections/connections.dto.d.ts.map +1 -0
  3. package/dist/connections/connections.dto.js +376 -0
  4. package/dist/fiscal/enqueue-nfe.dto.d.ts +3 -0
  5. package/dist/fiscal/enqueue-nfe.dto.d.ts.map +1 -1
  6. package/dist/fiscal/enqueue-nfe.dto.js +14 -0
  7. package/dist/tenants/index.d.ts +1 -0
  8. package/dist/tenants/index.d.ts.map +1 -1
  9. package/dist/tenants/index.js +1 -0
  10. package/dist/tenants/tenant-fiscal-profile.dto.d.ts +27 -0
  11. package/dist/tenants/tenant-fiscal-profile.dto.d.ts.map +1 -0
  12. package/dist/tenants/tenant-fiscal-profile.dto.js +128 -0
  13. package/package.json +1 -1
  14. package/src/campaigns/campaign-template-header-media.dto.ts +25 -25
  15. package/src/campaigns/campaign-template.dto.ts +45 -45
  16. package/src/campaigns/create-campaign.dto.ts +80 -80
  17. package/src/fiscal/enqueue-nfe.dto.ts +22 -1
  18. package/src/patients/index.ts +10 -10
  19. package/src/tenants/anamnesis-public-frontend-url.spec.ts +45 -45
  20. package/src/tenants/anamnesis-public-frontend-url.ts +61 -61
  21. package/src/tenants/index.ts +1 -0
  22. package/src/tenants/tenant-fiscal-profile.dto.ts +85 -0
  23. package/dist/anamneses/normalize-anamnesis-access-token.d.ts +0 -9
  24. package/dist/anamneses/normalize-anamnesis-access-token.d.ts.map +0 -1
  25. package/dist/anamneses/normalize-anamnesis-access-token.js +0 -21
  26. package/dist/anamneses/normalize-anamnesis-access-token.spec.d.ts +0 -2
  27. package/dist/anamneses/normalize-anamnesis-access-token.spec.d.ts.map +0 -1
  28. package/dist/anamneses/normalize-anamnesis-access-token.spec.js +0 -18
@@ -0,0 +1,128 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ 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;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.TenantFiscalProfileResponseDto = exports.UpsertTenantFiscalProfileDto = exports.GetTenantFiscalProfileDto = exports.TenantFiscalProfileDto = exports.TenantFiscalProfileCompanyDto = exports.TENANT_FISCAL_PROFILE_UPSERT = exports.TENANT_FISCAL_PROFILE_GET = void 0;
13
+ const swagger_1 = require("@nestjs/swagger");
14
+ const class_validator_1 = require("class-validator");
15
+ const class_transformer_1 = require("class-transformer");
16
+ exports.TENANT_FISCAL_PROFILE_GET = 'tenant.fiscalProfile.get';
17
+ exports.TENANT_FISCAL_PROFILE_UPSERT = 'tenant.fiscalProfile.upsert';
18
+ class TenantFiscalProfileCompanyDto {
19
+ cpfCnpj;
20
+ razaoSocial;
21
+ nomeFantasia;
22
+ email;
23
+ telefone;
24
+ }
25
+ exports.TenantFiscalProfileCompanyDto = TenantFiscalProfileCompanyDto;
26
+ __decorate([
27
+ (0, swagger_1.ApiPropertyOptional)({ description: 'CPF/CNPJ (somente números)' }),
28
+ (0, class_validator_1.IsOptional)(),
29
+ (0, class_validator_1.IsString)(),
30
+ __metadata("design:type", String)
31
+ ], TenantFiscalProfileCompanyDto.prototype, "cpfCnpj", void 0);
32
+ __decorate([
33
+ (0, swagger_1.ApiPropertyOptional)({ description: 'Razão social' }),
34
+ (0, class_validator_1.IsOptional)(),
35
+ (0, class_validator_1.IsString)(),
36
+ __metadata("design:type", String)
37
+ ], TenantFiscalProfileCompanyDto.prototype, "razaoSocial", void 0);
38
+ __decorate([
39
+ (0, swagger_1.ApiPropertyOptional)({ description: 'Nome fantasia' }),
40
+ (0, class_validator_1.IsOptional)(),
41
+ (0, class_validator_1.IsString)(),
42
+ __metadata("design:type", String)
43
+ ], TenantFiscalProfileCompanyDto.prototype, "nomeFantasia", void 0);
44
+ __decorate([
45
+ (0, swagger_1.ApiPropertyOptional)({ description: 'E-mail' }),
46
+ (0, class_validator_1.IsOptional)(),
47
+ (0, class_validator_1.IsString)(),
48
+ __metadata("design:type", String)
49
+ ], TenantFiscalProfileCompanyDto.prototype, "email", void 0);
50
+ __decorate([
51
+ (0, swagger_1.ApiPropertyOptional)({ description: 'Telefone' }),
52
+ (0, class_validator_1.IsOptional)(),
53
+ (0, class_validator_1.IsString)(),
54
+ __metadata("design:type", String)
55
+ ], TenantFiscalProfileCompanyDto.prototype, "telefone", void 0);
56
+ class TenantFiscalProfileDto {
57
+ company;
58
+ acbrCompanyPayload;
59
+ fiscalDefaults;
60
+ }
61
+ exports.TenantFiscalProfileDto = TenantFiscalProfileDto;
62
+ __decorate([
63
+ (0, swagger_1.ApiPropertyOptional)({ description: 'Dados principais da empresa do tenant (SaaS: 1 tenant = 1 empresa fiscal)' }),
64
+ (0, class_validator_1.IsOptional)(),
65
+ (0, class_validator_1.ValidateNested)(),
66
+ (0, class_transformer_1.Type)(() => TenantFiscalProfileCompanyDto),
67
+ __metadata("design:type", TenantFiscalProfileCompanyDto)
68
+ ], TenantFiscalProfileDto.prototype, "company", void 0);
69
+ __decorate([
70
+ (0, swagger_1.ApiPropertyOptional)({ description: 'Payload bruto compatível com endpoints /empresas (ACBr API)' }),
71
+ (0, class_validator_1.IsOptional)(),
72
+ (0, class_validator_1.IsObject)(),
73
+ __metadata("design:type", Object)
74
+ ], TenantFiscalProfileDto.prototype, "acbrCompanyPayload", void 0);
75
+ __decorate([
76
+ (0, swagger_1.ApiPropertyOptional)({ description: 'Defaults e preferências do módulo fiscal (livre)' }),
77
+ (0, class_validator_1.IsOptional)(),
78
+ (0, class_validator_1.IsObject)(),
79
+ __metadata("design:type", Object)
80
+ ], TenantFiscalProfileDto.prototype, "fiscalDefaults", void 0);
81
+ class GetTenantFiscalProfileDto {
82
+ tenantSlug;
83
+ }
84
+ exports.GetTenantFiscalProfileDto = GetTenantFiscalProfileDto;
85
+ __decorate([
86
+ (0, class_validator_1.IsString)(),
87
+ __metadata("design:type", String)
88
+ ], GetTenantFiscalProfileDto.prototype, "tenantSlug", void 0);
89
+ class UpsertTenantFiscalProfileDto {
90
+ tenantSlug;
91
+ profile;
92
+ }
93
+ exports.UpsertTenantFiscalProfileDto = UpsertTenantFiscalProfileDto;
94
+ __decorate([
95
+ (0, class_validator_1.IsString)(),
96
+ __metadata("design:type", String)
97
+ ], UpsertTenantFiscalProfileDto.prototype, "tenantSlug", void 0);
98
+ __decorate([
99
+ (0, class_validator_1.IsOptional)(),
100
+ (0, class_validator_1.ValidateNested)(),
101
+ (0, class_transformer_1.Type)(() => TenantFiscalProfileDto),
102
+ __metadata("design:type", TenantFiscalProfileDto)
103
+ ], UpsertTenantFiscalProfileDto.prototype, "profile", void 0);
104
+ class TenantFiscalProfileResponseDto {
105
+ tenantId;
106
+ tenantSlug;
107
+ profile;
108
+ }
109
+ exports.TenantFiscalProfileResponseDto = TenantFiscalProfileResponseDto;
110
+ __decorate([
111
+ (0, swagger_1.ApiPropertyOptional)(),
112
+ (0, class_validator_1.IsOptional)(),
113
+ (0, class_validator_1.IsUUID)(),
114
+ __metadata("design:type", String)
115
+ ], TenantFiscalProfileResponseDto.prototype, "tenantId", void 0);
116
+ __decorate([
117
+ (0, swagger_1.ApiPropertyOptional)(),
118
+ (0, class_validator_1.IsOptional)(),
119
+ (0, class_validator_1.IsString)(),
120
+ __metadata("design:type", String)
121
+ ], TenantFiscalProfileResponseDto.prototype, "tenantSlug", void 0);
122
+ __decorate([
123
+ (0, swagger_1.ApiPropertyOptional)(),
124
+ (0, class_validator_1.IsOptional)(),
125
+ (0, class_validator_1.ValidateNested)(),
126
+ (0, class_transformer_1.Type)(() => TenantFiscalProfileDto),
127
+ __metadata("design:type", TenantFiscalProfileDto)
128
+ ], TenantFiscalProfileResponseDto.prototype, "profile", void 0);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tychat-contracts",
3
- "version": "1.6.69",
3
+ "version": "1.6.73",
4
4
  "description": "DTOs compartilhados com class-validator (API e microserviços)",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,25 +1,25 @@
1
- /** Formato do header de template oficial (Meta Cloud API). */
2
- export type TemplateHeaderFormatDto = 'TEXT' | 'IMAGE' | 'VIDEO' | 'DOCUMENT';
3
-
4
- /** Resposta do upload de mídia para header de template (Meta + storage opcional). */
5
- export interface UploadTemplateHeaderMediaResponseDto {
6
- headerHandle: string;
7
- messagingMediaId: string;
8
- mimeType: string;
9
- sizeBytes: number;
10
- /** URL pública opcional persistida no storage da plataforma. */
11
- previewUrl?: string;
12
- }
13
-
14
- /** URL temporária da Meta (GET /{media-id}) para pré-visualização. */
15
- export interface TemplateHeaderMediaPreviewUrlResponseDto {
16
- mediaId: string;
17
- url: string;
18
- mimeType: string;
19
- }
20
-
21
- /** Bytes da mídia de header para proxy de pré-visualização. */
22
- export interface TemplateHeaderMediaPreviewBinaryResponseDto {
23
- mimeType: string;
24
- fileBase64: string;
25
- }
1
+ /** Formato do header de template oficial (Meta Cloud API). */
2
+ export type TemplateHeaderFormatDto = 'TEXT' | 'IMAGE' | 'VIDEO' | 'DOCUMENT';
3
+
4
+ /** Resposta do upload de mídia para header de template (Meta + storage opcional). */
5
+ export interface UploadTemplateHeaderMediaResponseDto {
6
+ headerHandle: string;
7
+ messagingMediaId: string;
8
+ mimeType: string;
9
+ sizeBytes: number;
10
+ /** URL pública opcional persistida no storage da plataforma. */
11
+ previewUrl?: string;
12
+ }
13
+
14
+ /** URL temporária da Meta (GET /{media-id}) para pré-visualização. */
15
+ export interface TemplateHeaderMediaPreviewUrlResponseDto {
16
+ mediaId: string;
17
+ url: string;
18
+ mimeType: string;
19
+ }
20
+
21
+ /** Bytes da mídia de header para proxy de pré-visualização. */
22
+ export interface TemplateHeaderMediaPreviewBinaryResponseDto {
23
+ mimeType: string;
24
+ fileBase64: string;
25
+ }
@@ -1,45 +1,45 @@
1
- import type { TemplateCategoryDto, TemplateMetaStatusDto } from './campaign-status.dto';
2
- import type { TemplateHeaderFormatDto } from './campaign-template-header-media.dto';
3
-
4
- export type { TemplateHeaderFormatDto };
5
-
6
- export interface CampaignTemplateDto {
7
- id: string;
8
- tenantId: string;
9
- name: string;
10
- languageCode: string;
11
- category: TemplateCategoryDto | null;
12
- metaTemplateName: string | null;
13
- metaTemplateId: string | null;
14
- metaStatus: TemplateMetaStatusDto | null;
15
- headerText: string | null;
16
- headerFormat?: TemplateHeaderFormatDto | null;
17
- headerMediaHandle?: string | null;
18
- headerMediaId?: string | null;
19
- headerMediaPreviewUrl?: string | null;
20
- bodyText: string;
21
- footerText: string | null;
22
- buttons: Record<string, unknown>[] | null;
23
- isOfficial: boolean;
24
- metaSyncedAt: string | null;
25
- createdAt: string;
26
- updatedAt: string;
27
- }
28
-
29
- export interface CampaignTemplateListResponseDto {
30
- items: CampaignTemplateDto[];
31
- }
32
-
33
- export interface TemplateVariablePreviewDto {
34
- variableName: string;
35
- sampleValue: string;
36
- }
37
-
38
- export interface TemplatePreviewRequestDto {
39
- bodyText: string;
40
- variables: TemplateVariablePreviewDto[];
41
- }
42
-
43
- export interface TemplatePreviewResponseDto {
44
- previewText: string;
45
- }
1
+ import type { TemplateCategoryDto, TemplateMetaStatusDto } from './campaign-status.dto';
2
+ import type { TemplateHeaderFormatDto } from './campaign-template-header-media.dto';
3
+
4
+ export type { TemplateHeaderFormatDto };
5
+
6
+ export interface CampaignTemplateDto {
7
+ id: string;
8
+ tenantId: string;
9
+ name: string;
10
+ languageCode: string;
11
+ category: TemplateCategoryDto | null;
12
+ metaTemplateName: string | null;
13
+ metaTemplateId: string | null;
14
+ metaStatus: TemplateMetaStatusDto | null;
15
+ headerText: string | null;
16
+ headerFormat?: TemplateHeaderFormatDto | null;
17
+ headerMediaHandle?: string | null;
18
+ headerMediaId?: string | null;
19
+ headerMediaPreviewUrl?: string | null;
20
+ bodyText: string;
21
+ footerText: string | null;
22
+ buttons: Record<string, unknown>[] | null;
23
+ isOfficial: boolean;
24
+ metaSyncedAt: string | null;
25
+ createdAt: string;
26
+ updatedAt: string;
27
+ }
28
+
29
+ export interface CampaignTemplateListResponseDto {
30
+ items: CampaignTemplateDto[];
31
+ }
32
+
33
+ export interface TemplateVariablePreviewDto {
34
+ variableName: string;
35
+ sampleValue: string;
36
+ }
37
+
38
+ export interface TemplatePreviewRequestDto {
39
+ bodyText: string;
40
+ variables: TemplateVariablePreviewDto[];
41
+ }
42
+
43
+ export interface TemplatePreviewResponseDto {
44
+ previewText: string;
45
+ }
@@ -1,80 +1,80 @@
1
- import type { TemplateCategoryDto } from './campaign-status.dto';
2
- import type { TemplateHeaderFormatDto } from './campaign-template-header-media.dto';
3
-
4
- export type { TemplateHeaderFormatDto };
5
-
6
- export interface CreateCampaignRequestDto {
7
- name: string;
8
- templateId?: string;
9
- isOfficial?: boolean;
10
- audienceFilters?: Record<string, unknown>[];
11
- delayBetweenSendsMs?: number;
12
- scheduledAt?: string;
13
- }
14
-
15
- export interface UpdateCampaignRequestDto {
16
- name?: string;
17
- templateId?: string;
18
- audienceFilters?: Record<string, unknown>[];
19
- delayBetweenSendsMs?: number;
20
- scheduledAt?: string;
21
- }
22
-
23
- export interface CreateCampaignTemplateRequestDto {
24
- name: string;
25
- languageCode?: string;
26
- category?: TemplateCategoryDto;
27
- bodyText: string;
28
- headerText?: string;
29
- headerFormat?: TemplateHeaderFormatDto;
30
- headerMediaHandle?: string;
31
- /** Numeric Meta messaging media id from header upload (required to send media headers). */
32
- headerMediaId?: string;
33
- headerMediaPreviewUrl?: string;
34
- headerMediaMimeType?: string;
35
- headerMediaSizeBytes?: number;
36
- footerText?: string;
37
- isOfficial?: boolean;
38
- buttons?: Record<string, unknown>[];
39
- }
40
-
41
- export interface StartCampaignRequestDto {
42
- campaignId: string;
43
- }
44
-
45
- export interface PauseCampaignRequestDto {
46
- campaignId: string;
47
- }
48
-
49
- export interface ResumeCampaignRequestDto {
50
- campaignId: string;
51
- }
52
-
53
- export interface CancelCampaignRequestDto {
54
- campaignId: string;
55
- reason?: string;
56
- }
57
-
58
- export interface ConfirmCampaignPaymentRequestDto {
59
- campaignId: string;
60
- billingId: string;
61
- }
62
-
63
- export interface PopulateRecipientsRequestDto {
64
- campaignId: string;
65
- }
66
-
67
- export interface PopulateRecipientsResponseDto {
68
- count: number;
69
- }
70
-
71
- export interface CampaignCostEstimateRequestDto {
72
- campaignId: string;
73
- }
74
-
75
- export interface CampaignCostEstimateResponseDto {
76
- totalRecipients: number;
77
- costPerMessageCents: number;
78
- estimatedTotalCents: number;
79
- category: TemplateCategoryDto;
80
- }
1
+ import type { TemplateCategoryDto } from './campaign-status.dto';
2
+ import type { TemplateHeaderFormatDto } from './campaign-template-header-media.dto';
3
+
4
+ export type { TemplateHeaderFormatDto };
5
+
6
+ export interface CreateCampaignRequestDto {
7
+ name: string;
8
+ templateId?: string;
9
+ isOfficial?: boolean;
10
+ audienceFilters?: Record<string, unknown>[];
11
+ delayBetweenSendsMs?: number;
12
+ scheduledAt?: string;
13
+ }
14
+
15
+ export interface UpdateCampaignRequestDto {
16
+ name?: string;
17
+ templateId?: string;
18
+ audienceFilters?: Record<string, unknown>[];
19
+ delayBetweenSendsMs?: number;
20
+ scheduledAt?: string;
21
+ }
22
+
23
+ export interface CreateCampaignTemplateRequestDto {
24
+ name: string;
25
+ languageCode?: string;
26
+ category?: TemplateCategoryDto;
27
+ bodyText: string;
28
+ headerText?: string;
29
+ headerFormat?: TemplateHeaderFormatDto;
30
+ headerMediaHandle?: string;
31
+ /** Numeric Meta messaging media id from header upload (required to send media headers). */
32
+ headerMediaId?: string;
33
+ headerMediaPreviewUrl?: string;
34
+ headerMediaMimeType?: string;
35
+ headerMediaSizeBytes?: number;
36
+ footerText?: string;
37
+ isOfficial?: boolean;
38
+ buttons?: Record<string, unknown>[];
39
+ }
40
+
41
+ export interface StartCampaignRequestDto {
42
+ campaignId: string;
43
+ }
44
+
45
+ export interface PauseCampaignRequestDto {
46
+ campaignId: string;
47
+ }
48
+
49
+ export interface ResumeCampaignRequestDto {
50
+ campaignId: string;
51
+ }
52
+
53
+ export interface CancelCampaignRequestDto {
54
+ campaignId: string;
55
+ reason?: string;
56
+ }
57
+
58
+ export interface ConfirmCampaignPaymentRequestDto {
59
+ campaignId: string;
60
+ billingId: string;
61
+ }
62
+
63
+ export interface PopulateRecipientsRequestDto {
64
+ campaignId: string;
65
+ }
66
+
67
+ export interface PopulateRecipientsResponseDto {
68
+ count: number;
69
+ }
70
+
71
+ export interface CampaignCostEstimateRequestDto {
72
+ campaignId: string;
73
+ }
74
+
75
+ export interface CampaignCostEstimateResponseDto {
76
+ totalRecipients: number;
77
+ costPerMessageCents: number;
78
+ estimatedTotalCents: number;
79
+ category: TemplateCategoryDto;
80
+ }
@@ -1,5 +1,15 @@
1
1
  import { ApiPropertyOptional } from '@nestjs/swagger';
2
- import { IsIn, IsInt, IsNotEmpty, IsObject, IsOptional, IsString, Max, Min } from 'class-validator';
2
+ import {
3
+ IsIn,
4
+ IsInt,
5
+ IsNotEmpty,
6
+ IsObject,
7
+ IsOptional,
8
+ IsString,
9
+ IsUUID,
10
+ Max,
11
+ Min,
12
+ } from 'class-validator';
3
13
 
4
14
  export const FISCAL_DOCUMENT_TYPES = ['nfe', 'nfce', 'nfse'] as const;
5
15
  export type FiscalDocumentType = (typeof FISCAL_DOCUMENT_TYPES)[number];
@@ -33,6 +43,11 @@ export class EnqueueNfeDto {
33
43
  @IsString()
34
44
  @IsOptional()
35
45
  referenceId?: string;
46
+
47
+ @ApiPropertyOptional({ description: 'Paciente vinculado (UUID)' })
48
+ @IsOptional()
49
+ @IsUUID()
50
+ patientId?: string;
36
51
  }
37
52
 
38
53
  export class ListFiscalDocumentsQueryDto {
@@ -51,6 +66,11 @@ export class ListFiscalDocumentsQueryDto {
51
66
  @IsString()
52
67
  referenceId?: string;
53
68
 
69
+ @ApiPropertyOptional({ description: 'Busca por paciente (UUID)' })
70
+ @IsOptional()
71
+ @IsUUID()
72
+ patientId?: string;
73
+
54
74
  @ApiPropertyOptional({ description: 'Busca por ACBR ID (parcial ou completo)' })
55
75
  @IsOptional()
56
76
  @IsString()
@@ -85,6 +105,7 @@ export type FiscalDocumentListItemDto = {
85
105
  documentType: FiscalDocumentType;
86
106
  companyCpfCnpj: string;
87
107
  referenceId: string | null;
108
+ patientId: string | null;
88
109
  acbrId: string | null;
89
110
  status: FiscalDocumentStatusDto;
90
111
  lastError: string | null;
@@ -1,10 +1,10 @@
1
- export * from './create-patient.dto';
2
- export * from './update-patient.dto';
3
- export * from './patient-history-entry.dto';
4
- export * from './list-patients-query.dto';
5
- export * from './list-patients-filters.dto';
6
- export * from './upsert-patient-by-phone.dto';
7
- export * from './patient-status.dto';
8
- export * from './patient-document-response.dto';
9
- export * from './update-patient-document.dto';
10
-
1
+ export * from './create-patient.dto';
2
+ export * from './update-patient.dto';
3
+ export * from './patient-history-entry.dto';
4
+ export * from './list-patients-query.dto';
5
+ export * from './list-patients-filters.dto';
6
+ export * from './upsert-patient-by-phone.dto';
7
+ export * from './patient-status.dto';
8
+ export * from './patient-document-response.dto';
9
+ export * from './update-patient-document.dto';
10
+
@@ -1,45 +1,45 @@
1
- import {
2
- hostnameMatchesTenantSlug,
3
- resolveTenantScopedFrontendBaseUrl,
4
- } from './anamnesis-public-frontend-url';
5
-
6
- describe('resolveTenantScopedFrontendBaseUrl', () => {
7
- it('keeps tenant-specific tychat.app host', () => {
8
- expect(
9
- resolveTenantScopedFrontendBaseUrl(
10
- 'clinica_sampaio',
11
- 'https://clinica-sampaio.tychat.app',
12
- ),
13
- ).toBe('https://clinica-sampaio.tychat.app');
14
- });
15
-
16
- it('scopes shared QA host with tenant subdomain', () => {
17
- expect(
18
- resolveTenantScopedFrontendBaseUrl('clinica_sampaio', 'https://qa.tychat.app'),
19
- ).toBe('https://clinica-sampaio.qa.tychat.app');
20
- });
21
-
22
- it('keeps custom domain unchanged', () => {
23
- expect(
24
- resolveTenantScopedFrontendBaseUrl(
25
- 'clinica_sampaio',
26
- 'https://app.minhaclinica.com.br',
27
- ),
28
- ).toBe('https://app.minhaclinica.com.br');
29
- });
30
-
31
- it('uses slug fallback when host is empty', () => {
32
- expect(resolveTenantScopedFrontendBaseUrl('homolog', '')).toBe(
33
- 'https://homolog.tychat.app',
34
- );
35
- });
36
- });
37
-
38
- describe('hostnameMatchesTenantSlug', () => {
39
- it('matches first DNS label to slug segment', () => {
40
- expect(hostnameMatchesTenantSlug('clinica-sampaio.qa.tychat.app', 'clinica_sampaio')).toBe(
41
- true,
42
- );
43
- expect(hostnameMatchesTenantSlug('qa.tychat.app', 'clinica_sampaio')).toBe(false);
44
- });
45
- });
1
+ import {
2
+ hostnameMatchesTenantSlug,
3
+ resolveTenantScopedFrontendBaseUrl,
4
+ } from './anamnesis-public-frontend-url';
5
+
6
+ describe('resolveTenantScopedFrontendBaseUrl', () => {
7
+ it('keeps tenant-specific tychat.app host', () => {
8
+ expect(
9
+ resolveTenantScopedFrontendBaseUrl(
10
+ 'clinica_sampaio',
11
+ 'https://clinica-sampaio.tychat.app',
12
+ ),
13
+ ).toBe('https://clinica-sampaio.tychat.app');
14
+ });
15
+
16
+ it('scopes shared QA host with tenant subdomain', () => {
17
+ expect(
18
+ resolveTenantScopedFrontendBaseUrl('clinica_sampaio', 'https://qa.tychat.app'),
19
+ ).toBe('https://clinica-sampaio.qa.tychat.app');
20
+ });
21
+
22
+ it('keeps custom domain unchanged', () => {
23
+ expect(
24
+ resolveTenantScopedFrontendBaseUrl(
25
+ 'clinica_sampaio',
26
+ 'https://app.minhaclinica.com.br',
27
+ ),
28
+ ).toBe('https://app.minhaclinica.com.br');
29
+ });
30
+
31
+ it('uses slug fallback when host is empty', () => {
32
+ expect(resolveTenantScopedFrontendBaseUrl('homolog', '')).toBe(
33
+ 'https://homolog.tychat.app',
34
+ );
35
+ });
36
+ });
37
+
38
+ describe('hostnameMatchesTenantSlug', () => {
39
+ it('matches first DNS label to slug segment', () => {
40
+ expect(hostnameMatchesTenantSlug('clinica-sampaio.qa.tychat.app', 'clinica_sampaio')).toBe(
41
+ true,
42
+ );
43
+ expect(hostnameMatchesTenantSlug('qa.tychat.app', 'clinica_sampaio')).toBe(false);
44
+ });
45
+ });