@solidxai/core 0.1.10-beta.26 → 0.1.10-beta.28
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/.claude/settings.local.json +15 -0
- package/CLAUDE.md +26 -0
- package/MICROSOFT_ACTIVE_DIRECTORY_OAUTH_FLOW.md +616 -0
- package/ai-interaction-cleanup.sql +53 -0
- package/dist/constants/error-messages.d.ts +1 -0
- package/dist/constants/error-messages.d.ts.map +1 -1
- package/dist/constants/error-messages.js +1 -0
- package/dist/constants/error-messages.js.map +1 -1
- package/dist/controllers/microsoft-active-directory-authentication.controller.d.ts +28 -0
- package/dist/controllers/microsoft-active-directory-authentication.controller.d.ts.map +1 -0
- package/dist/controllers/microsoft-active-directory-authentication.controller.js +122 -0
- package/dist/controllers/microsoft-active-directory-authentication.controller.js.map +1 -0
- package/dist/controllers/service.controller.d.ts +1 -5
- package/dist/controllers/service.controller.d.ts.map +1 -1
- package/dist/controllers/service.controller.js +6 -11
- package/dist/controllers/service.controller.js.map +1 -1
- package/dist/controllers/test.controller.d.ts +1 -6
- package/dist/controllers/test.controller.d.ts.map +1 -1
- package/dist/controllers/test.controller.js +2 -20
- package/dist/controllers/test.controller.js.map +1 -1
- package/dist/dtos/create-permission-metadata.dto.d.ts.map +1 -1
- package/dist/dtos/create-permission-metadata.dto.js +2 -0
- package/dist/dtos/create-permission-metadata.dto.js.map +1 -1
- package/dist/dtos/create-role-metadata.dto.d.ts +2 -0
- package/dist/dtos/create-role-metadata.dto.d.ts.map +1 -1
- package/dist/dtos/create-role-metadata.dto.js +13 -1
- package/dist/dtos/create-role-metadata.dto.js.map +1 -1
- package/dist/dtos/import-instructions.dto.d.ts +2 -0
- package/dist/dtos/import-instructions.dto.d.ts.map +1 -1
- package/dist/dtos/import-instructions.dto.js +15 -1
- package/dist/dtos/import-instructions.dto.js.map +1 -1
- package/dist/dtos/update-permission-metadata.dto.d.ts.map +1 -1
- package/dist/dtos/update-permission-metadata.dto.js +3 -1
- package/dist/dtos/update-permission-metadata.dto.js.map +1 -1
- package/dist/dtos/update-role-metadata.dto.d.ts +2 -0
- package/dist/dtos/update-role-metadata.dto.d.ts.map +1 -1
- package/dist/dtos/update-role-metadata.dto.js +13 -1
- package/dist/dtos/update-role-metadata.dto.js.map +1 -1
- package/dist/entities/action-metadata.entity.d.ts.map +1 -1
- package/dist/entities/action-metadata.entity.js +1 -0
- package/dist/entities/action-metadata.entity.js.map +1 -1
- package/dist/entities/agent-event.entity.d.ts.map +1 -1
- package/dist/entities/agent-event.entity.js +1 -0
- package/dist/entities/agent-event.entity.js.map +1 -1
- package/dist/entities/agent-session.entity.d.ts.map +1 -1
- package/dist/entities/agent-session.entity.js +1 -0
- package/dist/entities/agent-session.entity.js.map +1 -1
- package/dist/entities/chatter-message.entity.d.ts.map +1 -1
- package/dist/entities/chatter-message.entity.js +2 -0
- package/dist/entities/chatter-message.entity.js.map +1 -1
- package/dist/entities/email-template.entity.d.ts.map +1 -1
- package/dist/entities/email-template.entity.js +1 -0
- package/dist/entities/email-template.entity.js.map +1 -1
- package/dist/entities/field-metadata.entity.d.ts.map +1 -1
- package/dist/entities/field-metadata.entity.js +4 -0
- package/dist/entities/field-metadata.entity.js.map +1 -1
- package/dist/entities/list-of-values.entity.d.ts.map +1 -1
- package/dist/entities/list-of-values.entity.js +4 -0
- package/dist/entities/list-of-values.entity.js.map +1 -1
- package/dist/entities/locale.entity.d.ts.map +1 -1
- package/dist/entities/locale.entity.js +1 -0
- package/dist/entities/locale.entity.js.map +1 -1
- package/dist/entities/media.entity.d.ts.map +1 -1
- package/dist/entities/media.entity.js +1 -0
- package/dist/entities/media.entity.js.map +1 -1
- package/dist/entities/menu-item-metadata.entity.d.ts.map +1 -1
- package/dist/entities/menu-item-metadata.entity.js +2 -0
- package/dist/entities/menu-item-metadata.entity.js.map +1 -1
- package/dist/entities/model-metadata.entity.d.ts.map +1 -1
- package/dist/entities/model-metadata.entity.js +3 -0
- package/dist/entities/model-metadata.entity.js.map +1 -1
- package/dist/entities/module-metadata.entity.d.ts.map +1 -1
- package/dist/entities/module-metadata.entity.js +2 -0
- package/dist/entities/module-metadata.entity.js.map +1 -1
- package/dist/entities/permission-metadata.entity.d.ts.map +1 -1
- package/dist/entities/permission-metadata.entity.js.map +1 -1
- package/dist/entities/role-metadata.entity.d.ts +2 -0
- package/dist/entities/role-metadata.entity.d.ts.map +1 -1
- package/dist/entities/role-metadata.entity.js +10 -2
- package/dist/entities/role-metadata.entity.js.map +1 -1
- package/dist/entities/saved-filters.entity.d.ts.map +1 -1
- package/dist/entities/saved-filters.entity.js +3 -0
- package/dist/entities/saved-filters.entity.js.map +1 -1
- package/dist/entities/scheduled-job.entity.d.ts.map +1 -1
- package/dist/entities/scheduled-job.entity.js +2 -0
- package/dist/entities/scheduled-job.entity.js.map +1 -1
- package/dist/entities/security-rule.entity.d.ts.map +1 -1
- package/dist/entities/security-rule.entity.js +1 -0
- package/dist/entities/security-rule.entity.js.map +1 -1
- package/dist/entities/sms-template.entity.d.ts.map +1 -1
- package/dist/entities/sms-template.entity.js +2 -0
- package/dist/entities/sms-template.entity.js.map +1 -1
- package/dist/entities/user-activity-history.entity.d.ts.map +1 -1
- package/dist/entities/user-activity-history.entity.js +1 -0
- package/dist/entities/user-activity-history.entity.js.map +1 -1
- package/dist/entities/user.entity.d.ts +3 -0
- package/dist/entities/user.entity.d.ts.map +1 -1
- package/dist/entities/user.entity.js +15 -1
- package/dist/entities/user.entity.js.map +1 -1
- package/dist/entities/view-metadata.entity.d.ts.map +1 -1
- package/dist/entities/view-metadata.entity.js +2 -0
- package/dist/entities/view-metadata.entity.js.map +1 -1
- package/dist/helpers/microsoft-active-directory-oauth.helper.d.ts +34 -0
- package/dist/helpers/microsoft-active-directory-oauth.helper.d.ts.map +1 -0
- package/dist/helpers/microsoft-active-directory-oauth.helper.js +43 -0
- package/dist/helpers/microsoft-active-directory-oauth.helper.js.map +1 -0
- package/dist/helpers/module.helper.js +0 -5
- package/dist/helpers/module.helper.js.map +1 -1
- package/dist/helpers/user-helper.d.ts.map +1 -1
- package/dist/helpers/user-helper.js +4 -0
- package/dist/helpers/user-helper.js.map +1 -1
- package/dist/index.d.ts +1 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -5
- package/dist/index.js.map +1 -1
- package/dist/interfaces.d.ts +0 -8
- package/dist/interfaces.d.ts.map +1 -1
- package/dist/interfaces.js.map +1 -1
- package/dist/passport-strategies/microsoft-active-directory-oauth.strategy.d.ts +14 -0
- package/dist/passport-strategies/microsoft-active-directory-oauth.strategy.d.ts.map +1 -0
- package/dist/passport-strategies/microsoft-active-directory-oauth.strategy.js +67 -0
- package/dist/passport-strategies/microsoft-active-directory-oauth.strategy.js.map +1 -0
- package/dist/seeders/seed-data/solid-core-metadata.json +317 -814
- package/dist/services/authentication.service.d.ts +12 -0
- package/dist/services/authentication.service.d.ts.map +1 -1
- package/dist/services/authentication.service.js +64 -0
- package/dist/services/authentication.service.js.map +1 -1
- package/dist/services/crud-helper.service.d.ts.map +1 -1
- package/dist/services/crud-helper.service.js +11 -3
- package/dist/services/crud-helper.service.js.map +1 -1
- package/dist/services/import-transaction.service.d.ts.map +1 -1
- package/dist/services/import-transaction.service.js +6 -0
- package/dist/services/import-transaction.service.js.map +1 -1
- package/dist/services/settings/default-settings-provider.service.d.ts +100 -0
- package/dist/services/settings/default-settings-provider.service.d.ts.map +1 -1
- package/dist/services/settings/default-settings-provider.service.js +56 -0
- package/dist/services/settings/default-settings-provider.service.js.map +1 -1
- package/dist/services/user.service.d.ts +2 -0
- package/dist/services/user.service.d.ts.map +1 -1
- package/dist/services/user.service.js +46 -0
- package/dist/services/user.service.js.map +1 -1
- package/dist/solid-core.module.d.ts.map +1 -1
- package/dist/solid-core.module.js +4 -29
- package/dist/solid-core.module.js.map +1 -1
- package/dist/subscribers/scheduled-job.subscriber.js +1 -1
- package/dist/subscribers/scheduled-job.subscriber.js.map +1 -1
- package/dist/subscribers/security-rule.subscriber.js +1 -1
- package/dist/subscribers/security-rule.subscriber.js.map +1 -1
- package/package.json +4 -4
- package/src/constants/error-messages.ts +2 -1
- package/src/controllers/microsoft-active-directory-authentication.controller.ts +104 -0
- package/src/controllers/service.controller.ts +4 -7
- package/src/controllers/test.controller.ts +0 -9
- package/src/dtos/create-permission-metadata.dto.ts +3 -0
- package/src/dtos/create-role-metadata.dto.ts +11 -1
- package/src/dtos/import-instructions.dto.ts +11 -1
- package/src/dtos/update-permission-metadata.dto.ts +4 -1
- package/src/dtos/update-role-metadata.dto.ts +21 -1
- package/src/entities/action-metadata.entity.ts +1 -0
- package/src/entities/agent-event.entity.ts +1 -0
- package/src/entities/agent-session.entity.ts +1 -0
- package/src/entities/chatter-message.entity.ts +2 -0
- package/src/entities/email-template.entity.ts +1 -0
- package/src/entities/field-metadata.entity.ts +4 -1
- package/src/entities/list-of-values.entity.ts +5 -1
- package/src/entities/locale.entity.ts +1 -0
- package/src/entities/media.entity.ts +1 -0
- package/src/entities/menu-item-metadata.entity.ts +2 -0
- package/src/entities/model-metadata.entity.ts +3 -0
- package/src/entities/module-metadata.entity.ts +2 -0
- package/src/entities/permission-metadata.entity.ts +2 -2
- package/src/entities/role-metadata.entity.ts +11 -3
- package/src/entities/saved-filters.entity.ts +3 -0
- package/src/entities/scheduled-job.entity.ts +2 -0
- package/src/entities/security-rule.entity.ts +1 -0
- package/src/entities/sms-template.entity.ts +2 -0
- package/src/entities/user-activity-history.entity.ts +1 -0
- package/src/entities/user.entity.ts +15 -1
- package/src/entities/view-metadata.entity.ts +2 -0
- package/src/helpers/microsoft-active-directory-oauth.helper.ts +83 -0
- package/src/helpers/module.helper.ts +5 -5
- package/src/helpers/user-helper.ts +5 -1
- package/src/index.ts +1 -5
- package/src/interfaces.ts +0 -8
- package/src/passport-strategies/microsoft-active-directory-oauth.strategy.ts +63 -0
- package/src/seeders/seed-data/solid-core-metadata.json +317 -814
- package/src/services/1.js +6 -0
- package/src/services/authentication.service.ts +78 -0
- package/src/services/crud-helper.service.ts +9 -3
- package/src/services/import-transaction.service.ts +11 -1
- package/src/services/settings/default-settings-provider.service.ts +59 -0
- package/src/services/user.service.ts +61 -0
- package/src/solid-core.module.ts +4 -31
- package/src/subscribers/scheduled-job.subscriber.ts +1 -1
- package/src/subscribers/security-rule.subscriber.ts +1 -1
- package/dist/commands/ingest.command.d.ts +0 -16
- package/dist/commands/ingest.command.d.ts.map +0 -1
- package/dist/commands/ingest.command.js +0 -50
- package/dist/commands/ingest.command.js.map +0 -1
- package/dist/controllers/ai-interaction.controller.d.ts +0 -29
- package/dist/controllers/ai-interaction.controller.d.ts.map +0 -1
- package/dist/controllers/ai-interaction.controller.js +0 -218
- package/dist/controllers/ai-interaction.controller.js.map +0 -1
- package/dist/dtos/create-ai-interaction.dto.d.ts +0 -23
- package/dist/dtos/create-ai-interaction.dto.d.ts.map +0 -1
- package/dist/dtos/create-ai-interaction.dto.js +0 -149
- package/dist/dtos/create-ai-interaction.dto.js.map +0 -1
- package/dist/dtos/invoke-ai-prompt.dto.d.ts +0 -5
- package/dist/dtos/invoke-ai-prompt.dto.d.ts.map +0 -1
- package/dist/dtos/invoke-ai-prompt.dto.js +0 -30
- package/dist/dtos/invoke-ai-prompt.dto.js.map +0 -1
- package/dist/dtos/update-ai-interaction.dto.d.ts +0 -24
- package/dist/dtos/update-ai-interaction.dto.d.ts.map +0 -1
- package/dist/dtos/update-ai-interaction.dto.js +0 -150
- package/dist/dtos/update-ai-interaction.dto.js.map +0 -1
- package/dist/entities/ai-interaction.entity.d.ts +0 -24
- package/dist/entities/ai-interaction.entity.d.ts.map +0 -1
- package/dist/entities/ai-interaction.entity.js +0 -116
- package/dist/entities/ai-interaction.entity.js.map +0 -1
- package/dist/jobs/database/trigger-mcp-client-publisher-database.service.d.ts +0 -11
- package/dist/jobs/database/trigger-mcp-client-publisher-database.service.d.ts.map +0 -1
- package/dist/jobs/database/trigger-mcp-client-publisher-database.service.js +0 -39
- package/dist/jobs/database/trigger-mcp-client-publisher-database.service.js.map +0 -1
- package/dist/jobs/database/trigger-mcp-client-queue-options.d.ts +0 -8
- package/dist/jobs/database/trigger-mcp-client-queue-options.d.ts.map +0 -1
- package/dist/jobs/database/trigger-mcp-client-queue-options.js +0 -10
- package/dist/jobs/database/trigger-mcp-client-queue-options.js.map +0 -1
- package/dist/jobs/database/trigger-mcp-client-subscriber-database.service.d.ts +0 -25
- package/dist/jobs/database/trigger-mcp-client-subscriber-database.service.d.ts.map +0 -1
- package/dist/jobs/database/trigger-mcp-client-subscriber-database.service.js +0 -222
- package/dist/jobs/database/trigger-mcp-client-subscriber-database.service.js.map +0 -1
- package/dist/jobs/rabbitmq/trigger-mcp-client-publisher.service.d.ts +0 -11
- package/dist/jobs/rabbitmq/trigger-mcp-client-publisher.service.d.ts.map +0 -1
- package/dist/jobs/rabbitmq/trigger-mcp-client-publisher.service.js +0 -39
- package/dist/jobs/rabbitmq/trigger-mcp-client-publisher.service.js.map +0 -1
- package/dist/jobs/rabbitmq/trigger-mcp-client-queue-options.d.ts +0 -8
- package/dist/jobs/rabbitmq/trigger-mcp-client-queue-options.d.ts.map +0 -1
- package/dist/jobs/rabbitmq/trigger-mcp-client-queue-options.js +0 -10
- package/dist/jobs/rabbitmq/trigger-mcp-client-queue-options.js.map +0 -1
- package/dist/jobs/rabbitmq/trigger-mcp-client-subscriber.service.d.ts +0 -18
- package/dist/jobs/rabbitmq/trigger-mcp-client-subscriber.service.d.ts.map +0 -1
- package/dist/jobs/rabbitmq/trigger-mcp-client-subscriber.service.js +0 -103
- package/dist/jobs/rabbitmq/trigger-mcp-client-subscriber.service.js.map +0 -1
- package/dist/jobs/redis/trigger-mcp-client-publisher-redis.service.d.ts +0 -11
- package/dist/jobs/redis/trigger-mcp-client-publisher-redis.service.d.ts.map +0 -1
- package/dist/jobs/redis/trigger-mcp-client-publisher-redis.service.js +0 -39
- package/dist/jobs/redis/trigger-mcp-client-publisher-redis.service.js.map +0 -1
- package/dist/jobs/redis/trigger-mcp-client-queue-options-redis.d.ts +0 -8
- package/dist/jobs/redis/trigger-mcp-client-queue-options-redis.d.ts.map +0 -1
- package/dist/jobs/redis/trigger-mcp-client-queue-options-redis.js +0 -10
- package/dist/jobs/redis/trigger-mcp-client-queue-options-redis.js.map +0 -1
- package/dist/jobs/redis/trigger-mcp-client-subscriber-redis.service.d.ts +0 -18
- package/dist/jobs/redis/trigger-mcp-client-subscriber-redis.service.d.ts.map +0 -1
- package/dist/jobs/redis/trigger-mcp-client-subscriber-redis.service.js +0 -103
- package/dist/jobs/redis/trigger-mcp-client-subscriber-redis.service.js.map +0 -1
- package/dist/repository/ai-interaction.repository.d.ts +0 -12
- package/dist/repository/ai-interaction.repository.d.ts.map +0 -1
- package/dist/repository/ai-interaction.repository.js +0 -34
- package/dist/repository/ai-interaction.repository.js.map +0 -1
- package/dist/services/ai-interaction.service.d.ts +0 -23
- package/dist/services/ai-interaction.service.d.ts.map +0 -1
- package/dist/services/ai-interaction.service.js +0 -217
- package/dist/services/ai-interaction.service.js.map +0 -1
- package/dist/services/genai/ingest-metadata.service.d.ts +0 -38
- package/dist/services/genai/ingest-metadata.service.d.ts.map +0 -1
- package/dist/services/genai/ingest-metadata.service.js +0 -542
- package/dist/services/genai/ingest-metadata.service.js.map +0 -1
- package/dist/services/genai/mcp-handlers/mcp-handler-factory.service.d.ts +0 -9
- package/dist/services/genai/mcp-handlers/mcp-handler-factory.service.d.ts.map +0 -1
- package/dist/services/genai/mcp-handlers/mcp-handler-factory.service.js +0 -39
- package/dist/services/genai/mcp-handlers/mcp-handler-factory.service.js.map +0 -1
- package/dist/services/genai/r2r-helper.service.d.ts +0 -9
- package/dist/services/genai/r2r-helper.service.d.ts.map +0 -1
- package/dist/services/genai/r2r-helper.service.js +0 -40
- package/dist/services/genai/r2r-helper.service.js.map +0 -1
- package/dist-tests/api/authenticate.spec.js +0 -119
- package/dist-tests/api/authenticate.spec.js.map +0 -1
- package/dist-tests/api/crud-service.findOne.cityMaster.spec.js +0 -97
- package/dist-tests/api/crud-service.findOne.cityMaster.spec.js.map +0 -1
- package/dist-tests/api/ping.spec.js +0 -21
- package/dist-tests/api/ping.spec.js.map +0 -1
- package/dist-tests/helpers/auth.js +0 -41
- package/dist-tests/helpers/auth.js.map +0 -1
- package/dist-tests/helpers/env.js +0 -11
- package/dist-tests/helpers/env.js.map +0 -1
- package/docs/dashboards/AGENTIC_DASHBOARD_IMPLEMENTATION_PLAN.md +0 -438
- package/docs/dashboards/dashboard-curl-smoke-tests.txt +0 -146
- package/docs/dashboards/delete-legacy-dashboard-metadata.sql +0 -172
- package/docs/grouping-enhancements.md +0 -89
- package/docs/java-spring/README.md +0 -3
- package/docs/java-spring/solid-core-module-deep-dive-report.md +0 -1317
- package/docs/module-package-import-handoff.md +0 -691
- package/docs/seed-changes.md +0 -65
- package/docs/test-data-workflow.md +0 -200
- package/docs/type-declaration-import-issue.md +0 -24
- package/src/commands/ingest.command.ts +0 -36
- package/src/controllers/ai-interaction.controller.ts +0 -112
- package/src/dtos/create-ai-interaction.dto.ts +0 -89
- package/src/dtos/invoke-ai-prompt.dto.ts +0 -10
- package/src/dtos/update-ai-interaction.dto.ts +0 -93
- package/src/entities/ai-interaction.entity.ts +0 -71
- package/src/jobs/database/trigger-mcp-client-publisher-database.service.ts +0 -22
- package/src/jobs/database/trigger-mcp-client-queue-options.ts +0 -9
- package/src/jobs/database/trigger-mcp-client-subscriber-database.service.ts +0 -278
- package/src/jobs/rabbitmq/trigger-mcp-client-publisher.service.ts +0 -22
- package/src/jobs/rabbitmq/trigger-mcp-client-queue-options.ts +0 -9
- package/src/jobs/rabbitmq/trigger-mcp-client-subscriber.service.ts +0 -104
- package/src/jobs/redis/trigger-mcp-client-publisher-redis.service.ts +0 -23
- package/src/jobs/redis/trigger-mcp-client-queue-options-redis.ts +0 -9
- package/src/jobs/redis/trigger-mcp-client-subscriber-redis.service.ts +0 -98
- package/src/repository/ai-interaction.repository.ts +0 -17
- package/src/services/ai-interaction.service.ts +0 -239
- package/src/services/genai/ingest-metadata.service.ts +0 -798
- package/src/services/genai/mcp-handlers/mcp-handler-factory.service.ts +0 -33
- package/src/services/genai/r2r-helper.service.ts +0 -37
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ingest-metadata.service.js","sourceRoot":"","sources":["../../../src/services/genai/ingest-metadata.service.ts"],"names":[],"mappings":"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","sourcesContent":["import { Injectable, Logger } from '@nestjs/common';\nimport * as crypto from 'crypto';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nimport { getDynamicModuleNames, getDynamicModuleNamesBasedOnMetadata } from 'src/helpers/module.helper';\nimport { CreateModuleMetadataDto } from 'src/dtos/create-module-metadata.dto';\nimport { R2RHelperService } from './r2r-helper.service';\nimport { r2rClient } from 'r2r-js';\nimport { CreateModelMetadataDto } from 'src/dtos/create-model-metadata.dto';\nimport { CreateFieldMetadataDto } from 'src/dtos/create-field-metadata.dto';\n\nexport type FieldIngestionInfo = {\n fieldName: string;\n fieldChunkId?: string;\n fieldHash?: string;\n};\n\nexport type ModelIngestionInfo = {\n modelName: string;\n modelChunkId?: string;\n modelHash?: string;\n fields: FieldIngestionInfo[];\n};\n\nexport type ModuleRAGIngestionInfo = {\n moduleName?: string;\n collectionId?: string;\n\n // Full json document is also uploaded so we track references...\n documentId?: string;\n documentHash?: string;\n\n // module references\n moduleChunkId?: string;\n // track a hash of module metadata to skip unchanged\n moduleHash?: string;\n\n // model references...\n models: ModelIngestionInfo[];\n};\n\n@Injectable()\nexport class IngestMetadataService {\n private readonly logger = new Logger(IngestMetadataService.name);\n private ragClient: r2rClient;\n\n constructor(\n private readonly r2rService: R2RHelperService,\n ) { }\n\n // Stable stringify so hashes/ids don't flap\n // private stableStringify(obj: any): string {\n // return JSON.stringify(obj, Object.keys(obj).sort(), 2);\n // }\n // private sha256(input: string): string {\n // return crypto.createHash('sha256').update(input).digest('hex');\n // }\n // private hashSchema(obj: any): string {\n // return this.sha256(this.stableStringify(obj));\n // }\n private _sha256OfJson(obj: any): string {\n const s = JSON.stringify(obj);\n return crypto.createHash('sha256').update(s).digest('hex');\n }\n // // Small natural-language one-liners for relations\n // private relationSig(model: any): string[] {\n // const rels: string[] = [];\n // for (const f of model.fields ?? []) {\n // if (f.relation?.targetModel) {\n // rels.push(`${model.singularName}.${f.name} -> ${f.relation.targetModel}(${f.relation.targetField ?? 'id'})`);\n // }\n // }\n // return rels;\n // }\n\n private _oneLineBool(b?: boolean): 'yes' | 'no' {\n return b ? 'yes' : 'no';\n }\n\n private _shortList(arr?: string[] | null, max = 10): string {\n if (!Array.isArray(arr) || arr.length === 0) return 'none';\n const a = arr.slice(0, max);\n return `${a.join(', ')}${arr.length > max ? ', …' : ''}`;\n }\n\n async ingest() {\n // Create a new ragClient...\n this.ragClient = await this.r2rService.getClient();\n\n // const allModuleMetadataJson = [];\n this.logger.debug(`getting dynamics modules`);\n // const enabledModules = getDynamicModuleNames();\n const enabledModules = getDynamicModuleNamesBasedOnMetadata();\n this.logger.log(`ingesting metadata`);\n\n for (let i = 0; i < enabledModules.length; i++) {\n const enabledModule = enabledModules[i];\n const fileName = `${enabledModule}-metadata.json`;\n const enabledModuleSeedFile = `src/${enabledModule}/metadata/${fileName}`;\n const fullPath = path.join(process.cwd(), enabledModuleSeedFile);\n const overallMetadata: any = JSON.parse(fs.readFileSync(fullPath, 'utf-8').toString());\n\n const moduleMetadata: CreateModuleMetadataDto = overallMetadata.moduleMetadata;\n\n // Manage all the ingestion info file paths...\n const enabledModulIngestionInfoFile = `src/${enabledModule}/metadata/genai/${enabledModule}-ingested-info.json`;\n const enabledModulIngestionInfoFullPath = path.join(process.cwd(), enabledModulIngestionInfoFile);\n const ingestionInfo: ModuleRAGIngestionInfo = fs.existsSync(enabledModulIngestionInfoFullPath) ? JSON.parse(fs.readFileSync(enabledModulIngestionInfoFullPath, 'utf-8').toString()) : {};\n const enabledModulIngestionInfoDir = path.dirname(enabledModulIngestionInfoFullPath);\n if (!fs.existsSync(enabledModulIngestionInfoDir)) {\n fs.mkdirSync(enabledModulIngestionInfoDir, { recursive: true });\n }\n\n ingestionInfo.moduleName = enabledModule\n\n // Process module metadata first. \n this.logger.log(`[Start] Processing module metadata for ${moduleMetadata.name}`)\n\n // Create or use an existing collection...\n const collectionId = await this.resolveRagCollectionForModule(ingestionInfo, enabledModule)\n ingestionInfo.collectionId = collectionId;\n\n // Delete and re-insert a document representing the full json...\n // await this.deleteInsertRagDocumentForModuleMetadataJsonFile(ingestionInfo, fullPath, fileName)\n\n // Delete all metadata chunks. \n // const collectionName = `${enabledModule}-rag-collection`;\n // const deleteResult = await this.ragClient.documents.deleteByFilter({\n // filters: {\n // // AND semantics across fields:\n // \"$and\": [\n // { 'metadata.kind': { $eq: 'solidx-metadata' } },\n // { 'metadata.collectionName': { $eq: collectionName } },\n // { 'title': { $like: '%Ingested Chunks%' } },\n // ]\n // },\n // });\n // this.logger.log(`Deleted existing documents for collectionName: ${collectionName}. Got response:`, deleteResult);\n\n // Delete and re-insert a chunk representing the module.\n await this.deleteInsertRagChunkForModule(ingestionInfo, moduleMetadata);\n\n // Delete and re-insert chunks representing each model.\n for (const model of moduleMetadata.models) {\n await this.deleteInsertRagChunkForModel(ingestionInfo, enabledModule, model);\n\n // Disabling this for now...\n // for (const field of model.fields) {\n // await this.deleteInsertRagChunkForField(ingestionInfo, enabledModule, model.singularName, field);\n // }\n }\n\n // TODO: Delete and re-insert chunks representing roles\n\n // TODO: Delete and re-insert chunks representing menus \n\n // TODO: Delete and re-insert chunks representing actions\n\n // TODO: Delete and re-insert chunks representing list views \n\n // TODO: Delete and re-insert chunks representing kanban views \n\n // TODO: Delete and re-insert chunks representing form views\n\n // TODO: Delete and re-insert chunks representing security rules\n\n // TODO: Delete and re-insert chunks representing scheduled jobs\n\n // Save ingestion info to disk...\n fs.writeFileSync(enabledModulIngestionInfoFullPath, JSON.stringify({ ...ingestionInfo }, null, 2), 'utf8');\n }\n }\n\n private async resolveRagCollectionForModule(ingestionInfo: ModuleRAGIngestionInfo, moduleName: string): Promise<string> {\n this.logger.debug(`Resolving RAG collection for module: ${moduleName}`);\n\n const collectionName = `${moduleName}-rag-collection`;\n\n // delete and recreate \n // if (alwaysRecreate === true) {\n const existingCollection = await this.ragClient.collections.retrieveByName({\n name: collectionName\n });\n\n if (existingCollection) {\n try {\n await this.ragClient.collections.delete({ id: existingCollection.results.id });\n } catch (e) {\n this.logger.warn(`[Warn] Failed deleteByFilter for collection': ${String(e)}`);\n }\n }\n // }\n\n // let existingCollection: CollectionResponse = null;\n // if (ingestionInfo.collectionId) {\n // // See if collection already exists... \n // const r = await this.ragClient.collections.list({\n // ids: [\n // ingestionInfo.collectionId\n // ]\n // });\n\n // if (r) {\n // if (r.results.length === 1) {\n // existingCollection = r.results[0];\n // }\n // if (r.results.length > 1) {\n // // TODO: do something that will print a meaningful error on the console...\n // }\n // }\n // }\n\n // if (!existingCollection) {\n const r = await this.ragClient.collections.create({\n name: collectionName,\n description: `Collection created to group all documents, chunks related to module: ${moduleName}`\n });\n\n // TODO: for some reason if we are unable to create a collection then fail with a visible error message in the console...\n return r.results.id;\n // }\n // return existingCollection.id;\n }\n\n private async deleteInsertRagDocumentForModuleMetadataJsonFile(ingestionInfo: ModuleRAGIngestionInfo, fullPath: string, fileName: string): Promise<void> {\n this.logger.debug(`Ingesting file: ${fullPath}`);\n\n // 1) Compute hash of the entire JSON string (as-is)\n const jsonStr = fs.readFileSync(fullPath, 'utf-8');\n const contentHash = this._sha256OfJson(JSON.parse(jsonStr));\n\n // 2) Short-circuit if unchanged and we still have a documentId\n if (ingestionInfo.documentHash === contentHash && ingestionInfo.documentId) {\n this.logger.log(`[Skip] Unchanged: ${fileName} (hash=${contentHash.slice(0, 8)}…)`);\n return;\n // return ingestionInfo.documentId;\n }\n\n // 3) Delete the previous doc if present\n if (ingestionInfo.documentId) {\n try {\n await this.ragClient.documents.delete({ id: ingestionInfo.documentId });\n } catch (e) {\n this.logger.warn(\n `[Warn] Failed deleting prior document ${ingestionInfo.documentId}: ${String(e)}`\n );\n }\n }\n\n // 4) Create a fresh document; attach the hash into metadata for traceability\n const ingestResult = await this.ragClient.documents.create({\n file: {\n path: fullPath,\n name: fileName\n },\n collectionIds: [ingestionInfo.collectionId],\n metadata: {\n contentHash,\n fileName\n },\n });\n // console.log(\"file ingest result:\", JSON.stringify(ingestResult, null, 2));\n\n const newId = ingestResult?.results?.documentId;\n if (!newId) {\n throw new Error(`R2R did not return a documentId for ${fileName}`);\n }\n\n // 5) Persist identifiers + hash on our side\n ingestionInfo.documentId = newId;\n ingestionInfo.documentHash = contentHash;\n\n this.logger.log(`[OK] Ingested ${fileName} → id=${newId}, hash=${contentHash.slice(0, 8)}…`);\n // return newId;\n\n }\n\n private async deleteInsertRagChunkForModule(ingestionInfo: ModuleRAGIngestionInfo, moduleMetadata: CreateModuleMetadataDto): Promise<void> {\n const moduleName: string = moduleMetadata?.name;\n\n // Hash the meaningful parts of the module to detect changes and skip re-ingest.\n const schemaHash = this._sha256OfJson({\n name: moduleMetadata?.name ?? null,\n description: moduleMetadata?.description ?? null,\n\n // Keep model names + brief shape so module-level hash changes when models change.\n models: (moduleMetadata?.models ?? []).map((m: any) => ({\n singularName: m?.singularName ?? null,\n description: m?.description ?? null,\n\n // Include field names to detect field-level changes at module granularity - maybe remove this later?\n // fields: Array.isArray(m?.fields) ? m.fields.map((f: any) => f?.name ?? null) : [],\n })),\n });\n\n // Skip unchanged module\n if (ingestionInfo.moduleHash === schemaHash && ingestionInfo.moduleChunkId) {\n this.logger.log(`[Skip] Module unchanged: ${moduleName}`);\n return;\n // return ingestionInfo.moduleChunkId;\n }\n\n const models: any[] = moduleMetadata?.models ?? [];\n const modelLines = models.map((m) => {\n const name = m?.singularName;\n const desc = m?.description ? `: ${m.description}` : '';\n return `- ${name}${desc}`;\n });\n\n const text = `SolidX Module: ${moduleName}\nPurpose: ${moduleMetadata?.description ?? 'N/A'}\n\nModels (${models.length}):\n${modelLines.join('\\n')}\n\nUsage: Use this chunk to choose the correct model/field chunks for code generation or metadata edits.`;\n\n // metadata has to be concise and queryable\n const metadata = {\n collectionName: `${moduleName}-rag-collection`,\n kind: 'solidx-metadata',\n type: 'module',\n moduleName,\n modelCount: models.length,\n schemaHash,\n models: models.map((m) => m?.singularName).filter(Boolean),\n };\n\n // Delete previous chunk if we have one\n // if (ingestionInfo.moduleChunkId) {\n // try {\n // await this.ragClient.documents.delete({ id: ingestionInfo.moduleChunkId });\n // } catch (e) {\n // this.logger.warn(`[Warn] Failed deleting old module chunk (${ingestionInfo.moduleChunkId}): ${String(e)}`);\n // }\n // }\n\n // We changed the approach to delete and re-create using metadata.\n // delete any existing module records by metadata (idempotent)\n try {\n const deleteResult = await this.ragClient.documents.deleteByFilter({\n filters: {\n // AND semantics across fields:\n \"$and\": [\n { 'metadata.kind': { $eq: 'solidx-metadata' } },\n { 'metadata.type': { $eq: 'module' } },\n { 'metadata.moduleName': { $eq: moduleName } },\n // (optional but nice to constrain tightly if you always set it)\n { 'metadata.collectionName': { $eq: `${moduleName}-rag-collection` } },\n ]\n },\n });\n\n this.logger.log(`Deleted existing module document for moduleName: ${moduleName}. Got response:`, deleteResult);\n\n } catch (e) {\n this.logger.warn(`[Warn] Failed deleteByFilter for module '${moduleName}': ${String(e)}`);\n // Non-fatal: we can still proceed to create; caller’s auth will limit scope anyway\n }\n\n const r = await this.ragClient.documents.create({\n chunks: [text],\n // raw_text: text,\n metadata: metadata,\n collectionIds: [ingestionInfo.collectionId],\n });\n\n const newId = r?.results?.documentId;\n if (!newId) {\n throw new Error(`R2R did not return a documentId while creating module chunk for module name ${moduleName}`);\n }\n\n // Update ingestion info for persistence by the caller\n ingestionInfo.moduleChunkId = r.results?.documentId;\n ingestionInfo.moduleHash = schemaHash;\n\n this.logger.log(`[OK] Ingested module ${moduleName} → id=${newId}, hash=${schemaHash.slice(0, 8)}…`);\n\n }\n\n private async deleteInsertRagChunkForModel(ingestionInfo: ModuleRAGIngestionInfo, moduleName: string, model: CreateModelMetadataDto): Promise<void> {\n const modelName: string = model?.singularName;\n\n // 1) Hash full JSON (as-is) to detect changes and skip re-ingest\n const schemaHash = this._sha256OfJson(model);\n\n // Ensure ingestionInfo.models[] has an entry for this model\n const modelsArr = ingestionInfo.models ?? (ingestionInfo.models = []);\n let modelEntry = modelsArr.find(m => m.modelName === modelName);\n if (!modelEntry) {\n modelEntry = { modelName, fields: [] };\n modelsArr.push(modelEntry);\n }\n\n // 2) Short-circuit if unchanged\n if (modelEntry.modelHash === schemaHash && modelEntry.modelChunkId) {\n this.logger.log(`[Skip] Model unchanged: ${moduleName}.${modelName}`);\n return;\n // return modelEntry.modelChunkId;\n }\n\n // 3) Build retrieval-friendly text (concise)\n const fields: CreateFieldMetadataDto[] = Array.isArray(model?.fields) ? model.fields : [];\n const userkey = fields.find((f: CreateFieldMetadataDto) => f?.isUserKey)?.name ?? 'id';\n const uniques = fields.filter((f: CreateFieldMetadataDto) => f?.unique).map((f: any) => f.name);\n const required = fields.filter((f: CreateFieldMetadataDto) => f?.required).map((f: any) => f.name);\n const rels = fields\n .filter((f: CreateFieldMetadataDto) => f.type === 'relation')\n .map((f: CreateFieldMetadataDto) => `${modelName}.${f.name} -> ${f.relationCoModelSingularName}.${f.relationCoModelColumnName ?? 'id'}`);\n\n const fieldSummaryLines = fields.slice(0, 30).map((f: CreateFieldMetadataDto) => {\n const bits = [\n `${f.name}:${f.type}`,\n f.required ? 'req' : '',\n f.unique ? 'unique' : '',\n f.isUserKey ? 'userkey' : '',\n f.relationCoModelSingularName ? `rel->${f.relationCoModelSingularName}` : '',\n ].filter(Boolean).join('|');\n return `- ${bits}`;\n });\n\n const text =\n `SolidX Model: ${modelName}\nModule: ${moduleName}\nPurpose: ${model?.description ?? 'N/A'}\n\nSignature:\n- Primary: ${userkey}\n- Unique: ${uniques.length ? uniques.join(', ') : 'none'}\n- Required (${required.length}): ${required.slice(0, 12).join(', ')}${required.length > 12 ? '…' : ''}\n\nRelations (${rels.length}):\n${rels.length ? `- ${rels.join('\\n- ')}` : 'None'}\n\nFields (${fields.length}) [name:type|flags]:\n${fieldSummaryLines.join('\\n')}\n\nUsage: Use this chunk to generate DTOs, subscribers, custom service methods, and CRUD handlers for ${modelName}.\n\nFull model metadata json: \n${JSON.stringify(model)}\n\n`;\n\n // 4) Metadata (concise & queryable)\n const metadata = {\n collectionName: `${moduleName}-rag-collection`,\n kind: 'solidx-metadata',\n type: 'model',\n moduleName,\n modelName,\n fieldCount: fields.length,\n requiredCount: required.length,\n relationCount: rels.length,\n userkey: userkey,\n uniqueFields: uniques,\n hasTimestamps: !!fields.find((f: CreateFieldMetadataDto) => ['time', 'date', 'datetime'].includes(f.type)),\n schemaHash,\n };\n\n // 5) Delete previous chunk if present\n // if (modelEntry.modelChunkId) {\n // try {\n // await this.ragClient.documents.delete({ id: modelEntry.modelChunkId });\n // } catch (e) {\n // this.logger.warn(`[Warn] Failed deleting old model chunk (${modelEntry.modelChunkId}): ${String(e)}`);\n // }\n // }\n\n // We changed the approach to delete and re-create using metadata.\n // delete any existing module records by metadata (idempotent)\n try {\n const deleteResult = await this.ragClient.documents.deleteByFilter({\n filters: {\n // AND semantics across fields:\n \"$and\": [\n { 'metadata.kind': { $eq: 'solidx-metadata' } },\n { 'metadata.type': { $eq: 'model' } },\n { 'metadata.moduleName': { $eq: moduleName } },\n { 'metadata.modelName': { $eq: modelName } },\n // (optional but nice to constrain tightly if you always set it)\n { 'metadata.collectionName': { $eq: `${moduleName}-rag-collection` } },\n ]\n },\n });\n\n this.logger.log(`Deleted existing model document for modelName: ${modelName}. Got response:`, deleteResult);\n\n } catch (e) {\n this.logger.warn(`[Warn] Failed deleteByFilter for module '${moduleName}': ${String(e)}`);\n // Non-fatal: we can still proceed to create; caller’s auth will limit scope anyway\n }\n\n // 6) Create new document (R2R auto-generates the ID)\n const r = await this.ragClient.documents.create({\n chunks: [text],\n metadata,\n collectionIds: [ingestionInfo.collectionId],\n });\n\n const newId = r?.results?.documentId;\n if (!newId) {\n throw new Error(`R2R did not return a documentId while creating model chunk for ${moduleName}.${modelName}`);\n }\n\n // 7) Update ingestionInfo for persistence\n modelEntry.modelChunkId = newId;\n modelEntry.modelHash = schemaHash;\n\n this.logger.log(`[OK] Ingested model ${moduleName}.${modelName} → id=${newId}, hash=${schemaHash.slice(0, 8)}…`);\n // return newId;\n }\n\n private _buildFieldTextAndMetadata(moduleName: string, modelName: string, f: CreateFieldMetadataDto) {\n // Identity\n const name = f?.name;\n const displayName = f?.displayName ?? name;\n const description = f?.description ?? 'N/A';\n\n // Types\n const type = f?.type;\n const ormType = f?.ormType ?? null;\n\n // Constraints / validation\n const required = !!f?.required;\n const unique = !!f?.unique;\n const index = !!f?.index;\n const length = f?.length ?? null;\n const min = f?.min ?? null;\n const max = f?.max ?? null;\n const defaultValue = f?.defaultValue ?? null;\n const regex = f?.regexPattern ?? null;\n const regexErr = f?.regexPatternNotMatchingErrorMsg ?? null;\n\n // Relation\n const relationType = f?.relationType ?? null; // e.g., many-to-one, many-to-many, one-to-many\n const relModule = f?.relationModelModuleName ?? null;\n const relModel = f?.relationCoModelSingularName ?? null;\n const relField = f?.relationCoModelFieldName ?? 'id';\n // const relOwner = f?.isRelationManyToManyOwner ?? null;\n // const relJoinTable = f?.relationJoinTableName ?? null;\n // const relCreateInverse = !!f?.relationCreateInverse;\n const relCascade = f?.relationCascade ?? null;\n const relFixedFilter = f?.relationFieldFixedFilter ?? null;\n\n // Selection (dropdowns)\n const selectionDynProvider = f?.selectionDynamicProvider ?? null;\n const selectionDynCtxt = f?.selectionDynamicProviderCtxt ?? null;\n const selectionStatic = Array.isArray(f?.selectionStaticValues) ? f.selectionStaticValues : null;\n const selectionValueType = f?.selectionValueType ?? null;\n const isMultiSelect = !!f?.isMultiSelect;\n\n // Media (uploads)\n const mediaTypes = Array.isArray(f?.mediaTypes) ? f.mediaTypes : null;\n const mediaMaxSizeKb = f?.mediaMaxSizeKb ?? null;\n const mediaStorageProvider = f?.mediaStorageProviderUserKey ?? null; // likely object/id in your JSON\n\n // Computed fields\n const computedProvider = f?.computedFieldValueProvider ?? null;\n const computedProviderCtxt = f?.computedFieldValueProviderCtxt ?? null;\n const computedValueType = f?.computedFieldValueType ?? null;\n const computedTriggerCfg = f?.computedFieldTriggerConfig ?? null;\n\n // Security / privacy / audit\n // const encrypt = !!f?.encrypt;\n // const encryptionType = f?.encryptionType ?? null;\n // const decryptWhen = f?.decryptWhen ?? null;\n const isPrivate = !!f?.private;\n const enableAuditTracking = !!f?.enableAuditTracking;\n\n // Keys / system flags / mapping\n const isUserKey = !!f?.isUserKey;\n const isSystem = !!f?.isSystem;\n const isMarkedForRemoval = !!f?.isMarkedForRemoval;\n const columnName = f?.columnName ?? null;\n const relCoModelColumn = f?.relationCoModelColumnName ?? null;\n const uuid = f?.uuid ?? null;\n\n const relationSummary = (() => {\n if (!relationType || !relModel) return 'none';\n const parts = [\n `type=${relationType}`,\n relModule ? `module=${relModule}` : null,\n `model=${relModel}`,\n relField ? `field=${relField}` : null,\n // relOwner !== null ? `m2mOwner=${relOwner}` : null,\n // relCreateInverse ? 'createInverse=yes' : null,\n relCascade ? `cascade=${relCascade}` : null,\n // relJoinTable ? `joinTable=${relJoinTable}` : null,\n relFixedFilter ? `fixedFilter=${relFixedFilter}` : null,\n ].filter(Boolean);\n return parts.join(', ');\n })();\n\n const selectionSummary = (() => {\n const parts: string[] = [];\n if (selectionDynProvider) parts.push(`dynamicProvider=${selectionDynProvider}`);\n if (selectionDynCtxt) parts.push(`dynamicCtxt=${selectionDynCtxt}`);\n if (selectionStatic?.length) parts.push(`static=[${this._shortList(selectionStatic, 12)}]`);\n if (selectionValueType) parts.push(`valueType=${selectionValueType}`);\n parts.push(`multiSelect=${this._oneLineBool(isMultiSelect)}`);\n return parts.length ? parts.join(', ') : 'none';\n })();\n\n const mediaSummary = (() => {\n const parts: string[] = [];\n if (mediaTypes?.length) parts.push(`types=[${this._shortList(mediaTypes, 12)}]`);\n if (mediaMaxSizeKb) parts.push(`maxSizeKb=${mediaMaxSizeKb}`);\n if (mediaStorageProvider) parts.push(`storageProvider=${typeof mediaStorageProvider === 'string' ? mediaStorageProvider : 'set'}`);\n return parts.length ? parts.join(', ') : 'none';\n })();\n\n const computedSummary = (() => {\n const parts: string[] = [];\n if (computedProvider) parts.push(`provider=${computedProvider}`);\n if (computedProviderCtxt) parts.push(`providerCtxt=${computedProviderCtxt}`);\n if (computedValueType) parts.push(`valueType=${computedValueType}`);\n if (computedTriggerCfg?.length) parts.push(`triggers=${computedTriggerCfg.length}`);\n return parts.length ? parts.join(', ') : 'none';\n })();\n\n const securitySummary = [\n // `encrypt=${this.oneLineBool(encrypt)}`,\n // encryptionType ? `encType=${encryptionType}` : null,\n // decryptWhen ? `decryptWhen=${decryptWhen}` : null,\n `private=${this._oneLineBool(isPrivate)}`,\n `auditTracking=${this._oneLineBool(enableAuditTracking)}`\n ].filter(Boolean).join(', ');\n\n const constraintSummary = [\n `required=${this._oneLineBool(required)}`,\n `unique=${this._oneLineBool(unique)}`,\n `index=${this._oneLineBool(index)}`,\n length !== null ? `length=${length}` : null,\n min !== null ? `min=${min}` : null,\n max !== null ? `max=${max}` : null,\n defaultValue !== null ? `default=${defaultValue}` : null,\n regex ? `regex=${regex}${regexErr ? ` (${regexErr})` : ''}` : null\n ].filter(Boolean).join(', ');\n\n const mappingSummary = [\n columnName ? `column=${columnName}` : null,\n relCoModelColumn ? `relColumn=${relCoModelColumn}` : null,\n uuid ? `uuid=${uuid}` : null,\n `userKey=${this._oneLineBool(isUserKey)}`,\n `system=${this._oneLineBool(isSystem)}`,\n `markedForRemoval=${this._oneLineBool(isMarkedForRemoval)}`\n ].filter(Boolean).join(', ');\n\n const text = [\n `SolidX Field: ${name} (${displayName})`,\n `Model: ${modelName}`,\n `Module: ${moduleName}`,\n ``,\n `Type: ${type}${ormType ? ` (orm=${ormType})` : ''}`,\n `Description: ${description}`,\n ``,\n `Constraints: ${constraintSummary || 'none'}`,\n `Relation: ${relationSummary}`,\n `Selection: ${selectionSummary}`,\n `Media: ${mediaSummary}`,\n `Computed: ${computedSummary}`,\n `Security/Privacy/Audit: ${securitySummary}`,\n `Mapping/Flags: ${mappingSummary || 'none'}`,\n ``,\n `Usage: Use this chunk to generate exact field contracts (DTO, form control, DB column), `,\n `validation rules, relation wiring, and UI widgets (selection/media/computed).`,\n ].join('\\n');\n\n const metadata = {\n kind: 'solidx-metadata',\n type: 'field',\n moduleName,\n modelName,\n fieldName: name,\n displayName,\n description,\n dataType: type,\n ormType,\n required,\n unique,\n index,\n defaultValue,\n length,\n min,\n max,\n regexPattern: regex,\n regexPatternNotMatchingErrorMsg: regexErr,\n\n // relation\n relationType,\n relationModelModuleName: relModule,\n relationCoModelSingularName: relModel,\n relationCoModelFieldName: relField,\n // isRelationManyToManyOwner: relOwner,\n // relationJoinTableName: relJoinTable,\n // relationCreateInverse: relCreateInverse,\n relationCascade: relCascade,\n relationFieldFixedFilter: relFixedFilter,\n\n // selection\n selectionDynProvider,\n selectionDynCtxt,\n selectionStaticValues: selectionStatic,\n selectionValueType,\n isMultiSelect,\n\n // media\n mediaTypes,\n mediaMaxSizeKb,\n mediaStorageProvider: mediaStorageProvider ? (typeof mediaStorageProvider === 'string' ? mediaStorageProvider : 'set') : null,\n\n // computed\n computedFieldValueProvider: computedProvider,\n computedFieldValueProviderCtxt: computedProviderCtxt,\n computedFieldValueType: computedValueType,\n computedFieldTriggerConfigCount: Array.isArray(computedTriggerCfg) ? computedTriggerCfg.length : 0,\n\n // security/privacy/audit\n // encrypt,\n // encryptionType,\n // decryptWhen,\n private: isPrivate,\n enableAuditTracking,\n\n // mapping/flags\n columnName,\n relationCoModelColumnName: relCoModelColumn,\n isUserKey,\n isSystem,\n isMarkedForRemoval,\n };\n\n return { text, metadata };\n }\n\n private async deleteInsertRagChunkForField(ingestionInfo: ModuleRAGIngestionInfo, moduleName: string, modelName: string, field: CreateFieldMetadataDto,): Promise<string> {\n const fieldName: string = field?.name ?? 'unknown_field';\n\n // 1) Full JSON hash (as-is)\n const schemaHash = this._sha256OfJson(field);\n\n // 2) Ensure ingestionInfo entry for the model & field\n const modelsArr = ingestionInfo.models ?? (ingestionInfo.models = []);\n let modelEntry = modelsArr.find(m => m.modelName === modelName);\n if (!modelEntry) {\n modelEntry = { modelName, fields: [] };\n modelsArr.push(modelEntry);\n }\n const fieldsArr = modelEntry.fields ?? (modelEntry.fields = []);\n let fieldEntry = fieldsArr.find(f => f.fieldName === fieldName);\n if (!fieldEntry) {\n fieldEntry = { fieldName };\n fieldsArr.push(fieldEntry);\n }\n\n // 3) Skip if unchanged\n if (fieldEntry.fieldHash === schemaHash && fieldEntry.fieldChunkId) {\n this.logger.log(`[Skip] Field unchanged: ${moduleName}.${modelName}.${fieldName}`);\n return fieldEntry.fieldChunkId;\n }\n\n // 4) Build text + metadata tailored to FieldMetadata\n const { text, metadata } = this._buildFieldTextAndMetadata(moduleName, modelName, field);\n\n // also keep the hash in metadata for audit/debug\n (metadata as any).schemaHash = schemaHash;\n\n // 5) Delete previous chunk if present\n if (fieldEntry.fieldChunkId) {\n try {\n await this.ragClient.documents.delete({ id: fieldEntry.fieldChunkId });\n } catch (e) {\n this.logger.warn(`[Warn] Failed deleting old field chunk (${fieldEntry.fieldChunkId}): ${String(e)}`);\n }\n }\n\n // 6) Create new document (R2R auto-generates the ID)\n const r = await this.ragClient.documents.create({\n raw_text: text,\n metadata,\n collectionIds: [ingestionInfo.collectionId],\n });\n\n const newId = r?.results?.documentId;\n if (!newId) {\n throw new Error(`R2R did not return a documentId while creating field chunk for ${moduleName}.${modelName}.${fieldName}`);\n }\n\n // 7) Update ingestion info\n fieldEntry.fieldChunkId = newId;\n fieldEntry.fieldHash = schemaHash;\n\n this.logger.log(`[OK] Ingested field ${moduleName}.${modelName}.${fieldName} → id=${newId}, hash=${schemaHash.slice(0, 8)}…`);\n return newId;\n }\n}\n"]}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { IMcpToolResponseHandler } from '../../../interfaces';
|
|
2
|
-
import { SolidIntrospectService } from '../../solid-introspect.service';
|
|
3
|
-
export declare class McpHandlerFactory {
|
|
4
|
-
private readonly solidIntrospectionService;
|
|
5
|
-
private readonly logger;
|
|
6
|
-
constructor(solidIntrospectionService: SolidIntrospectService);
|
|
7
|
-
getInstance(toolInvoked: string): IMcpToolResponseHandler;
|
|
8
|
-
}
|
|
9
|
-
//# sourceMappingURL=mcp-handler-factory.service.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-handler-factory.service.d.ts","sourceRoot":"","sources":["../../../../src/services/genai/mcp-handlers/mcp-handler-factory.service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,uBAAuB,EAAE,MAAM,gBAAgB,CAAC;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAC;AAExE,qBACa,iBAAiB;IAItB,OAAO,CAAC,QAAQ,CAAC,yBAAyB;IAH9C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsC;gBAGxC,yBAAyB,EAAE,sBAAsB;IAItE,WAAW,CAAC,WAAW,EAAE,MAAM,GAAG,uBAAuB;CAiB5D"}
|
|
@@ -1,39 +0,0 @@
|
|
|
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
|
-
var McpHandlerFactory_1;
|
|
12
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.McpHandlerFactory = void 0;
|
|
14
|
-
const common_1 = require("@nestjs/common");
|
|
15
|
-
const string_helper_1 = require("../../../helpers/string.helper");
|
|
16
|
-
const solid_introspect_service_1 = require("../../solid-introspect.service");
|
|
17
|
-
let McpHandlerFactory = McpHandlerFactory_1 = class McpHandlerFactory {
|
|
18
|
-
constructor(solidIntrospectionService) {
|
|
19
|
-
this.solidIntrospectionService = solidIntrospectionService;
|
|
20
|
-
this.logger = new common_1.Logger(McpHandlerFactory_1.name);
|
|
21
|
-
}
|
|
22
|
-
getInstance(toolInvoked) {
|
|
23
|
-
toolInvoked = (0, string_helper_1.classify)(toolInvoked);
|
|
24
|
-
let resolvedHandlerName = `${toolInvoked}McpHandler`;
|
|
25
|
-
let actualHandler = this.solidIntrospectionService.getProvider(resolvedHandlerName);
|
|
26
|
-
if (!actualHandler) {
|
|
27
|
-
throw new Error(`Unable to locate mcp tool handler with name ${resolvedHandlerName}`);
|
|
28
|
-
}
|
|
29
|
-
const actualHandlerInstance = actualHandler.instance;
|
|
30
|
-
this.logger.error(`Resolved mcp tool response handler with name ${actualHandler.name}`);
|
|
31
|
-
return actualHandlerInstance;
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
exports.McpHandlerFactory = McpHandlerFactory;
|
|
35
|
-
exports.McpHandlerFactory = McpHandlerFactory = McpHandlerFactory_1 = __decorate([
|
|
36
|
-
(0, common_1.Injectable)(),
|
|
37
|
-
__metadata("design:paramtypes", [solid_introspect_service_1.SolidIntrospectService])
|
|
38
|
-
], McpHandlerFactory);
|
|
39
|
-
//# sourceMappingURL=mcp-handler-factory.service.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-handler-factory.service.js","sourceRoot":"","sources":["../../../../src/services/genai/mcp-handlers/mcp-handler-factory.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAoD;AAEpD,kEAA0D;AAE1D,6EAAwE;AAGjE,IAAM,iBAAiB,yBAAvB,MAAM,iBAAiB;IAG1B,YACqB,yBAAiD;QAAjD,8BAAyB,GAAzB,yBAAyB,CAAwB;QAHrD,WAAM,GAAG,IAAI,eAAM,CAAC,mBAAiB,CAAC,IAAI,CAAC,CAAC;IAK7D,CAAC;IAED,WAAW,CAAC,WAAmB;QAC3B,WAAW,GAAG,IAAA,wBAAQ,EAAC,WAAW,CAAC,CAAC;QAEpC,IAAI,mBAAmB,GAAG,GAAG,WAAW,YAAY,CAAC;QAGrD,IAAI,aAAa,GAAG,IAAI,CAAC,yBAAyB,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC;QACpF,IAAI,CAAC,aAAa,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,+CAA+C,mBAAmB,EAAE,CAAC,CAAC;QAC1F,CAAC;QAGD,MAAM,qBAAqB,GAA4B,aAAa,CAAC,QAAQ,CAAC;QAC9E,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,gDAAgD,aAAa,CAAC,IAAI,EAAE,CAAC,CAAC;QAExF,OAAO,qBAAqB,CAAC;IACjC,CAAC;CACJ,CAAA;AAzBY,8CAAiB;4BAAjB,iBAAiB;IAD7B,IAAA,mBAAU,GAAE;qCAKuC,iDAAsB;GAJ7D,iBAAiB,CAyB7B","sourcesContent":["import { Injectable, Logger } from '@nestjs/common';\n\nimport { classify } from '../../../helpers/string.helper';\nimport { IMcpToolResponseHandler } from 'src/interfaces';\nimport { SolidIntrospectService } from '../../solid-introspect.service';\n\n@Injectable()\nexport class McpHandlerFactory {\n private readonly logger = new Logger(McpHandlerFactory.name);\n\n constructor(\n private readonly solidIntrospectionService: SolidIntrospectService\n ) {\n }\n\n getInstance(toolInvoked: string): IMcpToolResponseHandler {\n toolInvoked = classify(toolInvoked);\n\n let resolvedHandlerName = `${toolInvoked}McpHandler`;\n\n // Get hold of the tool response handler instance using the tool name used. \n let actualHandler = this.solidIntrospectionService.getProvider(resolvedHandlerName);\n if (!actualHandler) {\n throw new Error(`Unable to locate mcp tool handler with name ${resolvedHandlerName}`);\n }\n\n // type safe\n const actualHandlerInstance: IMcpToolResponseHandler = actualHandler.instance;\n this.logger.error(`Resolved mcp tool response handler with name ${actualHandler.name}`);\n\n return actualHandlerInstance;\n }\n}\n"]}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { r2rClient } from 'r2r-js';
|
|
2
|
-
import { SettingService } from '../setting.service';
|
|
3
|
-
export declare class R2RHelperService {
|
|
4
|
-
private readonly settingService;
|
|
5
|
-
private readonly logger;
|
|
6
|
-
constructor(settingService: SettingService);
|
|
7
|
-
getClient(): Promise<r2rClient>;
|
|
8
|
-
}
|
|
9
|
-
//# sourceMappingURL=r2r-helper.service.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"r2r-helper.service.d.ts","sourceRoot":"","sources":["../../../src/services/genai/r2r-helper.service.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACnC,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAIpD,qBACa,gBAAgB;IAGb,OAAO,CAAC,QAAQ,CAAC,cAAc;IAF3C,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqC;gBAE/B,cAAc,EAAE,cAAc;IAErD,SAAS;CAsBlB"}
|
|
@@ -1,40 +0,0 @@
|
|
|
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
|
-
var R2RHelperService_1;
|
|
12
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
-
exports.R2RHelperService = void 0;
|
|
14
|
-
const common_1 = require("@nestjs/common");
|
|
15
|
-
const r2r_js_1 = require("r2r-js");
|
|
16
|
-
const setting_service_1 = require("../setting.service");
|
|
17
|
-
let R2RHelperService = R2RHelperService_1 = class R2RHelperService {
|
|
18
|
-
constructor(settingService) {
|
|
19
|
-
this.settingService = settingService;
|
|
20
|
-
this.logger = new common_1.Logger(R2RHelperService_1.name);
|
|
21
|
-
}
|
|
22
|
-
async getClient() {
|
|
23
|
-
const ragServerUrl = this.settingService.getConfigValue('ragServerUrl');
|
|
24
|
-
this.logger.debug(`Attempting to create RAG client with url: ${ragServerUrl}`);
|
|
25
|
-
const client = new r2r_js_1.r2rClient(ragServerUrl);
|
|
26
|
-
const ragServerLogin = this.settingService.getConfigValue('ragServerLogin');
|
|
27
|
-
this.logger.debug(`Attempting to login to our RAG server with user ${ragServerLogin}`);
|
|
28
|
-
await client.users.login({
|
|
29
|
-
email: ragServerLogin,
|
|
30
|
-
password: this.settingService.getConfigValue('ragServerPassword')
|
|
31
|
-
});
|
|
32
|
-
return client;
|
|
33
|
-
}
|
|
34
|
-
};
|
|
35
|
-
exports.R2RHelperService = R2RHelperService;
|
|
36
|
-
exports.R2RHelperService = R2RHelperService = R2RHelperService_1 = __decorate([
|
|
37
|
-
(0, common_1.Injectable)(),
|
|
38
|
-
__metadata("design:paramtypes", [setting_service_1.SettingService])
|
|
39
|
-
], R2RHelperService);
|
|
40
|
-
//# sourceMappingURL=r2r-helper.service.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"r2r-helper.service.js","sourceRoot":"","sources":["../../../src/services/genai/r2r-helper.service.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAoD;AAGpD,mCAAmC;AACnC,wDAAoD;AAK7C,IAAM,gBAAgB,wBAAtB,MAAM,gBAAgB;IAGzB,YAA6B,cAA8B;QAA9B,mBAAc,GAAd,cAAc,CAAgB;QAF1C,WAAM,GAAG,IAAI,eAAM,CAAC,kBAAgB,CAAC,IAAI,CAAC,CAAC;IAEG,CAAC;IAEhE,KAAK,CAAC,SAAS;QACX,MAAM,YAAY,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAmB,cAAc,CAAC,CAAC;QAC1F,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,6CAA6C,YAAY,EAAE,CAAC,CAAC;QAC/E,MAAM,MAAM,GAAG,IAAI,kBAAS,CAAC,YAAY,CAAC,CAAC;QAE3C,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,CAAC,cAAc,CAAmB,gBAAgB,CAAC,CAAC;QAE9F,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,mDAAmD,cAAc,EAAE,CAAC,CAAA;QACtF,MAAM,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;YACrB,KAAK,EAAE,cAAc;YACrB,QAAQ,EAAE,IAAI,CAAC,cAAc,CAAC,cAAc,CAAmB,mBAAmB,CAAC;SACtF,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC;IAClB,CAAC;CAQJ,CAAA;AA3BY,4CAAgB;2BAAhB,gBAAgB;IAD5B,IAAA,mBAAU,GAAE;qCAIoC,gCAAc;GAHlD,gBAAgB,CA2B5B","sourcesContent":["import { Injectable, Logger } from '@nestjs/common';\nimport type { SolidCoreSetting } from \"src/services/settings/default-settings-provider.service\";\n\nimport { r2rClient } from 'r2r-js';\nimport { SettingService } from '../setting.service';\n\n\n\n@Injectable()\nexport class R2RHelperService {\n private readonly logger = new Logger(R2RHelperService.name);\n\n constructor(private readonly settingService: SettingService) { }\n\n async getClient() {\n const ragServerUrl = this.settingService.getConfigValue<SolidCoreSetting>('ragServerUrl');\n this.logger.debug(`Attempting to create RAG client with url: ${ragServerUrl}`);\n const client = new r2rClient(ragServerUrl);\n\n const ragServerLogin = this.settingService.getConfigValue<SolidCoreSetting>('ragServerLogin');\n // @ts-ignore\n this.logger.debug(`Attempting to login to our RAG server with user ${ragServerLogin}`)\n await client.users.login({\n email: ragServerLogin,\n password: this.settingService.getConfigValue<SolidCoreSetting>('ragServerPassword')\n });\n\n return client;\n }\n\n // async checkHealth() {\n // const client = new r2rClient('http://localhost:7272');\n\n // return await client.health();\n // }\n\n}"]}
|
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const test_1 = require("@playwright/test");
|
|
4
|
-
const env_1 = require("../helpers/env");
|
|
5
|
-
const baseURL = process.env.API_BASE_URL ?? "http://localhost:3000";
|
|
6
|
-
const TEST_USER_EMAIL = (0, env_1.getRequiredEnv)("TEST_USER_EMAIL");
|
|
7
|
-
const TEST_USER_PASSWORD = (0, env_1.getRequiredEnv)("TEST_USER_PASSWORD");
|
|
8
|
-
function base64UrlDecode(input) {
|
|
9
|
-
const normalized = input.replace(/-/g, "+").replace(/_/g, "/");
|
|
10
|
-
const padded = normalized.length % 4 === 0
|
|
11
|
-
? normalized
|
|
12
|
-
: normalized.padEnd(normalized.length + (4 - (normalized.length % 4)), "=");
|
|
13
|
-
return Buffer.from(padded, "base64").toString("utf-8");
|
|
14
|
-
}
|
|
15
|
-
function validateJwt(token) {
|
|
16
|
-
const parts = token.split(".");
|
|
17
|
-
if (parts.length !== 3) {
|
|
18
|
-
throw new Error("JWT must have three dot-separated parts.");
|
|
19
|
-
}
|
|
20
|
-
const headerJson = JSON.parse(base64UrlDecode(parts[0]));
|
|
21
|
-
const payloadJson = JSON.parse(base64UrlDecode(parts[1]));
|
|
22
|
-
if (!headerJson || typeof headerJson !== "object") {
|
|
23
|
-
throw new Error("JWT header must be a JSON object.");
|
|
24
|
-
}
|
|
25
|
-
if (!payloadJson || typeof payloadJson !== "object") {
|
|
26
|
-
throw new Error("JWT payload must be a JSON object.");
|
|
27
|
-
}
|
|
28
|
-
if (typeof payloadJson.exp !== "number") {
|
|
29
|
-
throw new Error("JWT payload.exp must be a number.");
|
|
30
|
-
}
|
|
31
|
-
return payloadJson;
|
|
32
|
-
}
|
|
33
|
-
(0, test_1.test)("API: authenticate succeeds with valid credentials", async () => {
|
|
34
|
-
const api = await test_1.request.newContext({
|
|
35
|
-
baseURL,
|
|
36
|
-
extraHTTPHeaders: {
|
|
37
|
-
accept: "*/*",
|
|
38
|
-
"content-type": "application/json",
|
|
39
|
-
},
|
|
40
|
-
});
|
|
41
|
-
try {
|
|
42
|
-
const res = await api.post("/api/iam/authenticate", {
|
|
43
|
-
data: {
|
|
44
|
-
email: TEST_USER_EMAIL,
|
|
45
|
-
username: "",
|
|
46
|
-
password: TEST_USER_PASSWORD,
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
(0, test_1.expect)(res.status()).toBe(200);
|
|
50
|
-
const json = await res.json();
|
|
51
|
-
(0, test_1.expect)(json.statusCode).toBe(200);
|
|
52
|
-
(0, test_1.expect)(Array.isArray(json.message)).toBe(true);
|
|
53
|
-
(0, test_1.expect)(json.message.length).toBe(0);
|
|
54
|
-
(0, test_1.expect)(json.error).toBe("");
|
|
55
|
-
const user = json.data?.user;
|
|
56
|
-
(0, test_1.expect)(user, "Expected data.user to be an object.").toBeTruthy();
|
|
57
|
-
(0, test_1.expect)(typeof user).toBe("object");
|
|
58
|
-
const email = user?.email;
|
|
59
|
-
(0, test_1.expect)(typeof email).toBe("string");
|
|
60
|
-
if (email === TEST_USER_EMAIL) {
|
|
61
|
-
(0, test_1.expect)(email).toBe(TEST_USER_EMAIL);
|
|
62
|
-
}
|
|
63
|
-
else {
|
|
64
|
-
(0, test_1.expect)(email.length).toBeGreaterThan(0);
|
|
65
|
-
}
|
|
66
|
-
(0, test_1.expect)(typeof user?.mobile).toBe("string");
|
|
67
|
-
(0, test_1.expect)(typeof user?.username).toBe("string");
|
|
68
|
-
(0, test_1.expect)(typeof user?.forcePasswordChange).toBe("boolean");
|
|
69
|
-
(0, test_1.expect)(typeof user?.id).toBe("number");
|
|
70
|
-
const roles = user?.roles;
|
|
71
|
-
(0, test_1.expect)(Array.isArray(roles)).toBe(true);
|
|
72
|
-
if (Array.isArray(roles)) {
|
|
73
|
-
(0, test_1.expect)(roles.every((role) => typeof role === "string")).toBe(true);
|
|
74
|
-
(0, test_1.expect)(roles).toContain("Admin");
|
|
75
|
-
}
|
|
76
|
-
const accessToken = json.data?.accessToken;
|
|
77
|
-
const refreshToken = json.data?.refreshToken;
|
|
78
|
-
(0, test_1.expect)(typeof accessToken).toBe("string");
|
|
79
|
-
(0, test_1.expect)(typeof refreshToken).toBe("string");
|
|
80
|
-
const accessPayload = validateJwt(accessToken);
|
|
81
|
-
const refreshPayload = validateJwt(refreshToken);
|
|
82
|
-
(0, test_1.expect)(typeof accessPayload.exp).toBe("number");
|
|
83
|
-
(0, test_1.expect)(typeof refreshPayload.exp).toBe("number");
|
|
84
|
-
}
|
|
85
|
-
finally {
|
|
86
|
-
await api.dispose();
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
(0, test_1.test)("API: authenticate fails with wrong password", async () => {
|
|
90
|
-
const api = await test_1.request.newContext({
|
|
91
|
-
baseURL,
|
|
92
|
-
extraHTTPHeaders: {
|
|
93
|
-
accept: "*/*",
|
|
94
|
-
"content-type": "application/json",
|
|
95
|
-
},
|
|
96
|
-
});
|
|
97
|
-
try {
|
|
98
|
-
const res = await api.post("/api/iam/authenticate", {
|
|
99
|
-
data: {
|
|
100
|
-
email: TEST_USER_EMAIL,
|
|
101
|
-
username: "",
|
|
102
|
-
password: `${TEST_USER_PASSWORD}__wrong`,
|
|
103
|
-
},
|
|
104
|
-
});
|
|
105
|
-
(0, test_1.expect)(res.status()).toBe(401);
|
|
106
|
-
const json = await res.json();
|
|
107
|
-
(0, test_1.expect)(json.statusCode).toBe(401);
|
|
108
|
-
(0, test_1.expect)(json.statusCodeMessage).toBe("Unauthorized");
|
|
109
|
-
(0, test_1.expect)(json.message).toBe("Invalid credentials");
|
|
110
|
-
(0, test_1.expect)(json.error).toBe("Invalid credentials");
|
|
111
|
-
(0, test_1.expect)(json.data?.statusCode).toBe(401);
|
|
112
|
-
(0, test_1.expect)(json.data?.error).toBe("Unauthorized");
|
|
113
|
-
(0, test_1.expect)(json.data?.message).toBe("Invalid credentials");
|
|
114
|
-
}
|
|
115
|
-
finally {
|
|
116
|
-
await api.dispose();
|
|
117
|
-
}
|
|
118
|
-
});
|
|
119
|
-
//# sourceMappingURL=authenticate.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"authenticate.spec.js","sourceRoot":"","sources":["../../tests/api/authenticate.spec.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, request, test } from \"@playwright/test\";\nimport { getRequiredEnv } from \"../helpers/env\";\n\ntype JwtPayload = {\n exp?: number;\n [key: string]: unknown;\n};\n\nconst baseURL = process.env.API_BASE_URL ?? \"http://localhost:3000\";\nconst TEST_USER_EMAIL = getRequiredEnv(\"TEST_USER_EMAIL\");\nconst TEST_USER_PASSWORD = getRequiredEnv(\"TEST_USER_PASSWORD\");\n\nfunction base64UrlDecode(input: string): string {\n const normalized = input.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const padded =\n normalized.length % 4 === 0\n ? normalized\n : normalized.padEnd(\n normalized.length + (4 - (normalized.length % 4)),\n \"=\"\n );\n return Buffer.from(padded, \"base64\").toString(\"utf-8\");\n}\n\nfunction validateJwt(token: string): JwtPayload {\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n throw new Error(\"JWT must have three dot-separated parts.\");\n }\n\n const headerJson = JSON.parse(base64UrlDecode(parts[0]));\n const payloadJson = JSON.parse(base64UrlDecode(parts[1]));\n\n if (!headerJson || typeof headerJson !== \"object\") {\n throw new Error(\"JWT header must be a JSON object.\");\n }\n\n if (!payloadJson || typeof payloadJson !== \"object\") {\n throw new Error(\"JWT payload must be a JSON object.\");\n }\n\n if (typeof payloadJson.exp !== \"number\") {\n throw new Error(\"JWT payload.exp must be a number.\");\n }\n\n return payloadJson as JwtPayload;\n}\n\ntest(\"API: authenticate succeeds with valid credentials\", async () => {\n const api = await request.newContext({\n baseURL,\n extraHTTPHeaders: {\n accept: \"*/*\",\n \"content-type\": \"application/json\",\n },\n });\n\n try {\n const res = await api.post(\"/api/iam/authenticate\", {\n data: {\n email: TEST_USER_EMAIL,\n username: \"\",\n password: TEST_USER_PASSWORD,\n },\n });\n\n expect(res.status()).toBe(200);\n const json = await res.json();\n\n expect(json.statusCode).toBe(200);\n expect(Array.isArray(json.message)).toBe(true);\n expect(json.message.length).toBe(0);\n expect(json.error).toBe(\"\");\n\n const user = json.data?.user as Record<string, unknown> | undefined;\n expect(user, \"Expected data.user to be an object.\").toBeTruthy();\n expect(typeof user).toBe(\"object\");\n\n const email = user?.email;\n expect(typeof email).toBe(\"string\");\n if (email === TEST_USER_EMAIL) {\n expect(email).toBe(TEST_USER_EMAIL);\n } else {\n // If your API returns a fixed system email, replace this with an exact match.\n expect((email as string).length).toBeGreaterThan(0);\n }\n\n expect(typeof user?.mobile).toBe(\"string\");\n expect(typeof user?.username).toBe(\"string\");\n expect(typeof user?.forcePasswordChange).toBe(\"boolean\");\n expect(typeof user?.id).toBe(\"number\");\n\n const roles = user?.roles;\n expect(Array.isArray(roles)).toBe(true);\n if (Array.isArray(roles)) {\n expect(roles.every((role) => typeof role === \"string\")).toBe(true);\n expect(roles).toContain(\"Admin\");\n }\n\n const accessToken = json.data?.accessToken;\n const refreshToken = json.data?.refreshToken;\n expect(typeof accessToken).toBe(\"string\");\n expect(typeof refreshToken).toBe(\"string\");\n\n const accessPayload = validateJwt(accessToken as string);\n const refreshPayload = validateJwt(refreshToken as string);\n\n expect(typeof accessPayload.exp).toBe(\"number\");\n expect(typeof refreshPayload.exp).toBe(\"number\");\n } finally {\n await api.dispose();\n }\n});\n\ntest(\"API: authenticate fails with wrong password\", async () => {\n const api = await request.newContext({\n baseURL,\n extraHTTPHeaders: {\n accept: \"*/*\",\n \"content-type\": \"application/json\",\n },\n });\n\n try {\n const res = await api.post(\"/api/iam/authenticate\", {\n data: {\n email: TEST_USER_EMAIL,\n username: \"\",\n password: `${TEST_USER_PASSWORD}__wrong`,\n },\n });\n\n expect(res.status()).toBe(401);\n const json = await res.json();\n\n expect(json.statusCode).toBe(401);\n expect(json.statusCodeMessage).toBe(\"Unauthorized\");\n expect(json.message).toBe(\"Invalid credentials\");\n expect(json.error).toBe(\"Invalid credentials\");\n expect(json.data?.statusCode).toBe(401);\n expect(json.data?.error).toBe(\"Unauthorized\");\n expect(json.data?.message).toBe(\"Invalid credentials\");\n } finally {\n await api.dispose();\n }\n});\n"]}
|
|
@@ -1,97 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const test_1 = require("@playwright/test");
|
|
4
|
-
const auth_1 = require("../helpers/auth");
|
|
5
|
-
const baseURL = process.env.API_BASE_URL ?? "http://localhost:3000";
|
|
6
|
-
async function getCityByName(name) {
|
|
7
|
-
const api = await test_1.request.newContext({
|
|
8
|
-
baseURL,
|
|
9
|
-
extraHTTPHeaders: await (0, auth_1.getAuthHeaders)(baseURL),
|
|
10
|
-
});
|
|
11
|
-
try {
|
|
12
|
-
const res = await api.get(`/api/city-master?filters[name][$eq]=${encodeURIComponent(name)}&limit=1&offset=0`);
|
|
13
|
-
(0, test_1.expect)(res.status()).toBe(200);
|
|
14
|
-
const json = await res.json();
|
|
15
|
-
const record = json?.data?.records?.[0];
|
|
16
|
-
(0, test_1.expect)(record, `Expected city '${name}' in testData`).toBeTruthy();
|
|
17
|
-
(0, test_1.expect)(record.id, "Expected record to have id").toBeTruthy();
|
|
18
|
-
return record;
|
|
19
|
-
}
|
|
20
|
-
finally {
|
|
21
|
-
await api.dispose();
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
test_1.test.describe("CRUDService.findOne (cityMaster)", () => {
|
|
25
|
-
(0, test_1.test)("returns a city by id", async () => {
|
|
26
|
-
const city = await getCityByName("Mumbai");
|
|
27
|
-
const api = await test_1.request.newContext({
|
|
28
|
-
baseURL,
|
|
29
|
-
extraHTTPHeaders: await (0, auth_1.getAuthHeaders)(baseURL),
|
|
30
|
-
});
|
|
31
|
-
try {
|
|
32
|
-
const res = await api.get(`/api/city-master/${city.id}`);
|
|
33
|
-
(0, test_1.expect)(res.status()).toBe(200);
|
|
34
|
-
const json = await res.json();
|
|
35
|
-
(0, test_1.expect)(json?.data?.id).toBe(city.id);
|
|
36
|
-
(0, test_1.expect)(json?.data?.name).toBe("Mumbai");
|
|
37
|
-
(0, test_1.expect)(json?.data?.description).toBe("Mumbai city");
|
|
38
|
-
}
|
|
39
|
-
finally {
|
|
40
|
-
await api.dispose();
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
(0, test_1.test)("supports fields[] selection", async () => {
|
|
44
|
-
const city = await getCityByName("Pune");
|
|
45
|
-
const api = await test_1.request.newContext({
|
|
46
|
-
baseURL,
|
|
47
|
-
extraHTTPHeaders: await (0, auth_1.getAuthHeaders)(baseURL),
|
|
48
|
-
});
|
|
49
|
-
try {
|
|
50
|
-
const res = await api.get(`/api/city-master/${city.id}?fields[]=id&fields[]=name`);
|
|
51
|
-
(0, test_1.expect)(res.status()).toBe(200);
|
|
52
|
-
const json = await res.json();
|
|
53
|
-
(0, test_1.expect)(json?.data?.id).toBe(city.id);
|
|
54
|
-
(0, test_1.expect)(json?.data?.name).toBe("Pune");
|
|
55
|
-
(0, test_1.expect)(json?.data?.description).toBeUndefined();
|
|
56
|
-
(0, test_1.expect)(json?.data?.state).toBeUndefined();
|
|
57
|
-
}
|
|
58
|
-
finally {
|
|
59
|
-
await api.dispose();
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
(0, test_1.test)("supports populate=state", async () => {
|
|
63
|
-
const city = await getCityByName("Bengaluru");
|
|
64
|
-
const api = await test_1.request.newContext({
|
|
65
|
-
baseURL,
|
|
66
|
-
extraHTTPHeaders: await (0, auth_1.getAuthHeaders)(baseURL),
|
|
67
|
-
});
|
|
68
|
-
try {
|
|
69
|
-
const res = await api.get(`/api/city-master/${city.id}?populate=state`);
|
|
70
|
-
(0, test_1.expect)(res.status()).toBe(200);
|
|
71
|
-
const json = await res.json();
|
|
72
|
-
(0, test_1.expect)(json?.data?.name).toBe("Bengaluru");
|
|
73
|
-
(0, test_1.expect)(json?.data?.state).toBeTruthy();
|
|
74
|
-
(0, test_1.expect)(json?.data?.state?.name).toBe("Karnataka");
|
|
75
|
-
}
|
|
76
|
-
finally {
|
|
77
|
-
await api.dispose();
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
(0, test_1.test)("returns 404 for missing id", async () => {
|
|
81
|
-
const api = await test_1.request.newContext({
|
|
82
|
-
baseURL,
|
|
83
|
-
extraHTTPHeaders: await (0, auth_1.getAuthHeaders)(baseURL),
|
|
84
|
-
});
|
|
85
|
-
try {
|
|
86
|
-
const res = await api.get(`/api/city-master/99999999`);
|
|
87
|
-
(0, test_1.expect)(res.status()).toBe(404);
|
|
88
|
-
const json = await res.json();
|
|
89
|
-
(0, test_1.expect)(String(json?.message)).toContain("cityMaster");
|
|
90
|
-
(0, test_1.expect)(String(json?.message)).toContain("not found");
|
|
91
|
-
}
|
|
92
|
-
finally {
|
|
93
|
-
await api.dispose();
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
});
|
|
97
|
-
//# sourceMappingURL=crud-service.findOne.cityMaster.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"crud-service.findOne.cityMaster.spec.js","sourceRoot":"","sources":["../../tests/api/crud-service.findOne.cityMaster.spec.ts"],"names":[],"mappings":"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","sourcesContent":["import { expect, request, test } from \"@playwright/test\";\nimport { getAuthHeaders } from \"../helpers/auth\";\n\nconst baseURL = process.env.API_BASE_URL ?? \"http://localhost:3000\";\n\nasync function getCityByName(name: string) {\n const api = await request.newContext({\n baseURL,\n extraHTTPHeaders: await getAuthHeaders(baseURL),\n });\n try {\n const res = await api.get(\n `/api/city-master?filters[name][$eq]=${encodeURIComponent(name)}&limit=1&offset=0`\n );\n expect(res.status()).toBe(200);\n const json = await res.json();\n\n const record = json?.data?.records?.[0];\n expect(record, `Expected city '${name}' in testData`).toBeTruthy();\n expect(record.id, \"Expected record to have id\").toBeTruthy();\n\n return record;\n } finally {\n await api.dispose();\n }\n}\n\ntest.describe(\"CRUDService.findOne (cityMaster)\", () => {\n test(\"returns a city by id\", async () => {\n const city = await getCityByName(\"Mumbai\");\n\n const api = await request.newContext({\n baseURL,\n extraHTTPHeaders: await getAuthHeaders(baseURL),\n });\n try {\n const res = await api.get(`/api/city-master/${city.id}`);\n expect(res.status()).toBe(200);\n\n const json = await res.json();\n expect(json?.data?.id).toBe(city.id);\n expect(json?.data?.name).toBe(\"Mumbai\");\n expect(json?.data?.description).toBe(\"Mumbai city\");\n } finally {\n await api.dispose();\n }\n });\n\n test(\"supports fields[] selection\", async () => {\n const city = await getCityByName(\"Pune\");\n\n const api = await request.newContext({\n baseURL,\n extraHTTPHeaders: await getAuthHeaders(baseURL),\n });\n try {\n const res = await api.get(\n `/api/city-master/${city.id}?fields[]=id&fields[]=name`\n );\n expect(res.status()).toBe(200);\n\n const json = await res.json();\n expect(json?.data?.id).toBe(city.id);\n expect(json?.data?.name).toBe(\"Pune\");\n expect(json?.data?.description).toBeUndefined();\n expect(json?.data?.state).toBeUndefined();\n } finally {\n await api.dispose();\n }\n });\n\n test(\"supports populate=state\", async () => {\n const city = await getCityByName(\"Bengaluru\");\n\n const api = await request.newContext({\n baseURL,\n extraHTTPHeaders: await getAuthHeaders(baseURL),\n });\n try {\n const res = await api.get(`/api/city-master/${city.id}?populate=state`);\n expect(res.status()).toBe(200);\n\n const json = await res.json();\n expect(json?.data?.name).toBe(\"Bengaluru\");\n expect(json?.data?.state).toBeTruthy();\n expect(json?.data?.state?.name).toBe(\"Karnataka\");\n } finally {\n await api.dispose();\n }\n });\n\n test(\"returns 404 for missing id\", async () => {\n const api = await request.newContext({\n baseURL,\n extraHTTPHeaders: await getAuthHeaders(baseURL),\n });\n try {\n const res = await api.get(`/api/city-master/99999999`);\n expect(res.status()).toBe(404);\n\n const json = await res.json();\n expect(String(json?.message)).toContain(\"cityMaster\");\n expect(String(json?.message)).toContain(\"not found\");\n } finally {\n await api.dispose();\n }\n });\n});\n"]}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const test_1 = require("@playwright/test");
|
|
4
|
-
(0, test_1.test)("GET /api/ping returns pong", async () => {
|
|
5
|
-
const baseURL = process.env.BASE_URL || "http://localhost:3000";
|
|
6
|
-
if (!baseURL) {
|
|
7
|
-
throw new Error("baseURL is not configured. Set API_BASE_URL or use the default.");
|
|
8
|
-
}
|
|
9
|
-
const api = await test_1.request.newContext({ baseURL });
|
|
10
|
-
const res = await api.get("/api/ping");
|
|
11
|
-
(0, test_1.expect)(res.status()).toBe(200);
|
|
12
|
-
const body = await res.json();
|
|
13
|
-
(0, test_1.expect)(body).toEqual({
|
|
14
|
-
statusCode: 200,
|
|
15
|
-
message: [],
|
|
16
|
-
error: "",
|
|
17
|
-
data: { pong: "v1.0.2" },
|
|
18
|
-
});
|
|
19
|
-
await api.dispose();
|
|
20
|
-
});
|
|
21
|
-
//# sourceMappingURL=ping.spec.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ping.spec.js","sourceRoot":"","sources":["../../tests/api/ping.spec.ts"],"names":[],"mappings":";;AAAA,2CAAyD;AAEzD,IAAA,WAAI,EAAC,4BAA4B,EAAE,KAAK,IAAI,EAAE;IAC5C,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,QAAQ,IAAI,uBAAuB,CAAC;IAChE,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,iEAAiE,CAAC,CAAC;IACrF,CAAC;IACD,MAAM,GAAG,GAAG,MAAM,cAAO,CAAC,UAAU,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;IAElD,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAEvC,IAAA,aAAM,EAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE/B,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;IAC9B,IAAA,aAAM,EAAC,IAAI,CAAC,CAAC,OAAO,CAAC;QACnB,UAAU,EAAE,GAAG;QACf,OAAO,EAAE,EAAE;QACX,KAAK,EAAE,EAAE;QACT,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;KACzB,CAAC,CAAC;IAEH,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC;AACtB,CAAC,CAAC,CAAC","sourcesContent":["import { expect, request, test } from \"@playwright/test\";\n\ntest(\"GET /api/ping returns pong\", async () => {\n const baseURL = process.env.BASE_URL || \"http://localhost:3000\";\n if (!baseURL) {\n throw new Error(\"baseURL is not configured. Set API_BASE_URL or use the default.\");\n }\n const api = await request.newContext({ baseURL });\n\n const res = await api.get(\"/api/ping\");\n\n expect(res.status()).toBe(200);\n\n const body = await res.json();\n expect(body).toEqual({\n statusCode: 200,\n message: [],\n error: \"\",\n data: { pong: \"v1.0.2\" },\n });\n\n await api.dispose();\n});\n"]}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getAccessToken = getAccessToken;
|
|
4
|
-
exports.getAuthHeaders = getAuthHeaders;
|
|
5
|
-
const test_1 = require("@playwright/test");
|
|
6
|
-
const env_1 = require("./env");
|
|
7
|
-
async function getAccessToken(baseURL) {
|
|
8
|
-
const TEST_USER_EMAIL = (0, env_1.getRequiredEnv)("TEST_USER_EMAIL");
|
|
9
|
-
const TEST_USER_PASSWORD = (0, env_1.getRequiredEnv)("TEST_USER_PASSWORD");
|
|
10
|
-
const api = await test_1.request.newContext({
|
|
11
|
-
baseURL,
|
|
12
|
-
extraHTTPHeaders: {
|
|
13
|
-
accept: "*/*",
|
|
14
|
-
"content-type": "application/json",
|
|
15
|
-
},
|
|
16
|
-
});
|
|
17
|
-
try {
|
|
18
|
-
const res = await api.post("/api/iam/authenticate", {
|
|
19
|
-
data: {
|
|
20
|
-
email: TEST_USER_EMAIL,
|
|
21
|
-
username: "",
|
|
22
|
-
password: TEST_USER_PASSWORD,
|
|
23
|
-
},
|
|
24
|
-
});
|
|
25
|
-
(0, test_1.expect)(res.status()).toBe(200);
|
|
26
|
-
const json = await res.json();
|
|
27
|
-
const token = json?.data?.accessToken;
|
|
28
|
-
(0, test_1.expect)(token, "Expected access token from authenticate endpoint.").toBeTruthy();
|
|
29
|
-
return token;
|
|
30
|
-
}
|
|
31
|
-
finally {
|
|
32
|
-
await api.dispose();
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
async function getAuthHeaders(baseURL) {
|
|
36
|
-
const token = await getAccessToken(baseURL);
|
|
37
|
-
return {
|
|
38
|
-
authorization: `Bearer ${token}`,
|
|
39
|
-
};
|
|
40
|
-
}
|
|
41
|
-
//# sourceMappingURL=auth.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../tests/helpers/auth.ts"],"names":[],"mappings":";;AAGA,wCA6BC;AAED,wCAKC;AAvCD,2CAAmD;AACnD,+BAAuC;AAEhC,KAAK,UAAU,cAAc,CAAC,OAAe;IAClD,MAAM,eAAe,GAAG,IAAA,oBAAc,EAAC,iBAAiB,CAAC,CAAC;IAC1D,MAAM,kBAAkB,GAAG,IAAA,oBAAc,EAAC,oBAAoB,CAAC,CAAC;IAEhE,MAAM,GAAG,GAAG,MAAM,cAAO,CAAC,UAAU,CAAC;QACnC,OAAO;QACP,gBAAgB,EAAE;YAChB,MAAM,EAAE,KAAK;YACb,cAAc,EAAE,kBAAkB;SACnC;KACF,CAAC,CAAC;IAEH,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,GAAG,CAAC,IAAI,CAAC,uBAAuB,EAAE;YAClD,IAAI,EAAE;gBACJ,KAAK,EAAE,eAAe;gBACtB,QAAQ,EAAE,EAAE;gBACZ,QAAQ,EAAE,kBAAkB;aAC7B;SACF,CAAC,CAAC;QAEH,IAAA,aAAM,EAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC/B,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC9B,MAAM,KAAK,GAAG,IAAI,EAAE,IAAI,EAAE,WAAiC,CAAC;QAC5D,IAAA,aAAM,EAAC,KAAK,EAAE,mDAAmD,CAAC,CAAC,UAAU,EAAE,CAAC;QAChF,OAAO,KAAe,CAAC;IACzB,CAAC;YAAS,CAAC;QACT,MAAM,GAAG,CAAC,OAAO,EAAE,CAAC;IACtB,CAAC;AACH,CAAC;AAEM,KAAK,UAAU,cAAc,CAAC,OAAe;IAClD,MAAM,KAAK,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,CAAC;IAC5C,OAAO;QACL,aAAa,EAAE,UAAU,KAAK,EAAE;KACjC,CAAC;AACJ,CAAC","sourcesContent":["import { expect, request } from \"@playwright/test\";\nimport { getRequiredEnv } from \"./env\";\n\nexport async function getAccessToken(baseURL: string) {\n const TEST_USER_EMAIL = getRequiredEnv(\"TEST_USER_EMAIL\");\n const TEST_USER_PASSWORD = getRequiredEnv(\"TEST_USER_PASSWORD\");\n\n const api = await request.newContext({\n baseURL,\n extraHTTPHeaders: {\n accept: \"*/*\",\n \"content-type\": \"application/json\",\n },\n });\n\n try {\n const res = await api.post(\"/api/iam/authenticate\", {\n data: {\n email: TEST_USER_EMAIL,\n username: \"\",\n password: TEST_USER_PASSWORD,\n },\n });\n\n expect(res.status()).toBe(200);\n const json = await res.json();\n const token = json?.data?.accessToken as string | undefined;\n expect(token, \"Expected access token from authenticate endpoint.\").toBeTruthy();\n return token as string;\n } finally {\n await api.dispose();\n }\n}\n\nexport async function getAuthHeaders(baseURL: string) {\n const token = await getAccessToken(baseURL);\n return {\n authorization: `Bearer ${token}`,\n };\n}\n"]}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getRequiredEnv = getRequiredEnv;
|
|
4
|
-
function getRequiredEnv(name) {
|
|
5
|
-
const value = process.env[name];
|
|
6
|
-
if (!value) {
|
|
7
|
-
throw new Error(`Missing required env var: ${name}`);
|
|
8
|
-
}
|
|
9
|
-
return value;
|
|
10
|
-
}
|
|
11
|
-
//# sourceMappingURL=env.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"env.js","sourceRoot":"","sources":["../../tests/helpers/env.ts"],"names":[],"mappings":";;AAAA,wCAMC;AAND,SAAgB,cAAc,CAAC,IAAY;IACzC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC","sourcesContent":["export function getRequiredEnv(name: string): string {\n const value = process.env[name];\n if (!value) {\n throw new Error(`Missing required env var: ${name}`);\n }\n return value;\n}\n"]}
|