@owox/backend 0.36.0 → 0.38.0

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 (139) hide show
  1. package/dist/src/common/search/search.facade.d.ts +1 -0
  2. package/dist/src/data-marts/controllers/spec/data-mart.api.js +5 -5
  3. package/dist/src/data-marts/data-destination-types/ee/email/services/email-credentials-validator.js +1 -3
  4. package/dist/src/data-marts/data-destination-types/ee/google-chat/services/google-chat-credentials-validator.js +1 -3
  5. package/dist/src/data-marts/data-destination-types/google-sheets/services/google-sheets-credentials-validator.js +1 -3
  6. package/dist/src/data-marts/data-destination-types/google-sheets/services/google-sheets-report-writer.d.ts +1 -0
  7. package/dist/src/data-marts/data-destination-types/google-sheets/services/google-sheets-report-writer.js +13 -1
  8. package/dist/src/data-marts/data-destination-types/interfaces/data-destination-credentials-validator.interface.d.ts +2 -0
  9. package/dist/src/data-marts/data-destination-types/interfaces/data-destination-credentials-validator.interface.js +7 -0
  10. package/dist/src/data-marts/data-destination-types/looker-studio-connector/services/looker-studio-connector-credentials-validator.js +1 -3
  11. package/dist/src/data-marts/data-marts.module.js +4 -0
  12. package/dist/src/data-marts/data-storage-types/athena/adapters/athena-api.adapter.js +2 -1
  13. package/dist/src/data-marts/data-storage-types/athena/adapters/s3-api.adapter.js +5 -3
  14. package/dist/src/data-marts/data-storage-types/athena/services/athena-access.validator.js +2 -4
  15. package/dist/src/data-marts/data-storage-types/athena/utils/athena-output-location.util.d.ts +5 -0
  16. package/dist/src/data-marts/data-storage-types/athena/utils/athena-output-location.util.js +13 -0
  17. package/dist/src/data-marts/data-storage-types/bigquery/services/bigquery-access.validator.js +2 -4
  18. package/dist/src/data-marts/data-storage-types/bigquery/services/bigquery-resource-location.util.d.ts +3 -0
  19. package/dist/src/data-marts/data-storage-types/bigquery/services/bigquery-resource-location.util.js +18 -0
  20. package/dist/src/data-marts/data-storage-types/bigquery/services/bigquery-sharded-tables.util.d.ts +1 -0
  21. package/dist/src/data-marts/data-storage-types/bigquery/services/bigquery-sharded-tables.util.js +4 -1
  22. package/dist/src/data-marts/data-storage-types/bigquery/services/bigquery-storage-resource-browser.service.js +12 -5
  23. package/dist/src/data-marts/data-storage-types/databricks/services/databricks-access.validator.js +2 -4
  24. package/dist/src/data-marts/data-storage-types/interfaces/data-storage-access-validator.interface.d.ts +3 -0
  25. package/dist/src/data-marts/data-storage-types/interfaces/data-storage-access-validator.interface.js +7 -0
  26. package/dist/src/data-marts/data-storage-types/interfaces/storage-resource-browser.interface.d.ts +2 -0
  27. package/dist/src/data-marts/data-storage-types/redshift/services/redshift-access.validator.js +2 -6
  28. package/dist/src/data-marts/data-storage-types/snowflake/services/snowflake-access.validator.js +2 -4
  29. package/dist/src/data-marts/dto/domain/create-data-mart.command.d.ts +3 -3
  30. package/dist/src/data-marts/dto/domain/data-mart-list-item.dto.d.ts +3 -3
  31. package/dist/src/data-marts/dto/domain/data-mart.dto.d.ts +3 -3
  32. package/dist/src/data-marts/dto/domain/list-data-marts.command.d.ts +2 -1
  33. package/dist/src/data-marts/dto/domain/list-data-marts.command.js +3 -1
  34. package/dist/src/data-marts/dto/domain/model-canvas.dto.d.ts +2 -2
  35. package/dist/src/data-marts/dto/domain/update-data-mart-icon.command.d.ts +3 -3
  36. package/dist/src/data-marts/dto/presentation/create-data-mart-request-api.dto.d.ts +2 -2
  37. package/dist/src/data-marts/dto/presentation/create-data-mart-request-api.dto.js +6 -3
  38. package/dist/src/data-marts/dto/presentation/custom-connector-response.dto.js +1 -1
  39. package/dist/src/data-marts/dto/presentation/data-mart-list-item-response-api.dto.d.ts +2 -2
  40. package/dist/src/data-marts/dto/presentation/data-mart-list-item-response-api.dto.js +3 -2
  41. package/dist/src/data-marts/dto/presentation/data-mart-response-api.dto.d.ts +2 -2
  42. package/dist/src/data-marts/dto/presentation/data-mart-response-api.dto.js +3 -2
  43. package/dist/src/data-marts/dto/presentation/list-data-marts-query-api.dto.js +1 -1
  44. package/dist/src/data-marts/dto/presentation/model-canvas-response-api.dto.d.ts +2 -2
  45. package/dist/src/data-marts/dto/presentation/model-canvas-response-api.dto.js +3 -2
  46. package/dist/src/data-marts/dto/presentation/sql-dry-run-request-api.dto.js +3 -0
  47. package/dist/src/data-marts/dto/presentation/storage-resources/list-storage-resources-response.dto.d.ts +2 -0
  48. package/dist/src/data-marts/dto/presentation/storage-resources/list-storage-resources-response.dto.js +17 -0
  49. package/dist/src/data-marts/dto/presentation/update-data-mart-icon-api.dto.d.ts +2 -2
  50. package/dist/src/data-marts/dto/presentation/update-data-mart-icon-api.dto.js +6 -3
  51. package/dist/src/data-marts/entities/data-mart.entity.d.ts +2 -2
  52. package/dist/src/data-marts/enums/data-mart-icon.enum.d.ts +6 -0
  53. package/dist/src/data-marts/enums/data-mart-icon.enum.js +6 -1
  54. package/dist/src/data-marts/errors/google-sheets-api-call.error.d.ts +6 -0
  55. package/dist/src/data-marts/errors/google-sheets-api-call.error.js +34 -0
  56. package/dist/src/data-marts/facades/mcp-contexts.facade.d.ts +13 -0
  57. package/dist/src/data-marts/facades/mcp-contexts.facade.impl.d.ts +9 -0
  58. package/dist/src/data-marts/facades/mcp-contexts.facade.impl.js +35 -0
  59. package/dist/src/data-marts/facades/mcp-contexts.facade.js +5 -0
  60. package/dist/src/data-marts/facades/mcp-data-marts.facade.d.ts +9 -0
  61. package/dist/src/data-marts/facades/mcp-data-marts.facade.impl.js +4 -1
  62. package/dist/src/data-marts/mappers/context.mapper.d.ts +4 -0
  63. package/dist/src/data-marts/mappers/context.mapper.js +12 -0
  64. package/dist/src/data-marts/search/engine/advanced-search.service.js +1 -0
  65. package/dist/src/data-marts/search/engine/in-memory-paginated.search.js +17 -1
  66. package/dist/src/data-marts/search/engine/vector-search.port.d.ts +1 -0
  67. package/dist/src/data-marts/services/connector/connector-definition.service.js +4 -2
  68. package/dist/src/data-marts/services/connector/connector-test.service.d.ts +1 -0
  69. package/dist/src/data-marts/services/connector/connector-test.service.js +11 -6
  70. package/dist/src/data-marts/services/connector/declarative-manifest-schemas.js +2 -2
  71. package/dist/src/data-marts/services/context/context-access.service.js +2 -2
  72. package/dist/src/data-marts/services/context/context.service.d.ts +2 -0
  73. package/dist/src/data-marts/services/context/context.service.js +21 -0
  74. package/dist/src/data-marts/services/data-mart.service.d.ts +1 -0
  75. package/dist/src/data-marts/services/data-mart.service.js +3 -0
  76. package/dist/src/data-marts/services/member-ownership-warnings.service.js +1 -1
  77. package/dist/src/data-marts/services/report-access.service.js +1 -1
  78. package/dist/src/data-marts/use-cases/list-data-marts.service.js +1 -0
  79. package/dist/src/data-marts/use-cases/preview-data-mart.service.js +4 -2
  80. package/dist/src/data-marts/use-cases/stream-http-data.service.d.ts +0 -1
  81. package/dist/src/data-marts/use-cases/stream-http-data.service.js +2 -6
  82. package/dist/src/data-marts/use-cases/update-availability.service.js +2 -2
  83. package/dist/src/data-marts/use-cases/update-data-mart-definition.service.js +1 -1
  84. package/dist/src/data-marts/use-cases/update-data-mart-owners.service.js +1 -1
  85. package/dist/src/data-marts/use-cases/update-data-storage.service.js +9 -9
  86. package/dist/src/data-marts/utils/field-errors.utils.d.ts +9 -0
  87. package/dist/src/data-marts/utils/field-errors.utils.js +51 -0
  88. package/dist/src/ee/mcp/instructions/mcp-system-instructions.d.ts +1 -1
  89. package/dist/src/ee/mcp/instructions/mcp-system-instructions.js +6 -3
  90. package/dist/src/ee/mcp/sdk/mcp-output-schema.d.ts +3 -0
  91. package/dist/src/ee/mcp/sdk/mcp-output-schema.js +53 -0
  92. package/dist/src/ee/mcp/sdk/mcp-schema-refresh.d.ts +8 -0
  93. package/dist/src/ee/mcp/sdk/mcp-schema-refresh.js +44 -0
  94. package/dist/src/ee/mcp/sdk/mcp-sdk-server.factory.d.ts +8 -1
  95. package/dist/src/ee/mcp/sdk/mcp-sdk-server.factory.js +35 -4
  96. package/dist/src/ee/mcp/tools/add-report.tool.d.ts +1 -1
  97. package/dist/src/ee/mcp/tools/add-report.tool.js +2 -2
  98. package/dist/src/ee/mcp/tools/context-input.d.ts +6 -0
  99. package/dist/src/ee/mcp/tools/context-input.js +13 -0
  100. package/dist/src/ee/mcp/tools/create-report-run-schedule.tool.js +1 -1
  101. package/dist/src/ee/mcp/tools/data-mart-catalog.tool.d.ts +10 -2
  102. package/dist/src/ee/mcp/tools/data-mart-catalog.tool.js +17 -5
  103. package/dist/src/ee/mcp/tools/data-mart-details.tool.d.ts +5 -1
  104. package/dist/src/ee/mcp/tools/data-mart-details.tool.js +4 -1
  105. package/dist/src/ee/mcp/tools/get-report-output-schema.tool.js +6 -6
  106. package/dist/src/ee/mcp/tools/list-contexts.tool.d.ts +131 -0
  107. package/dist/src/ee/mcp/tools/list-contexts.tool.js +50 -0
  108. package/dist/src/ee/mcp/tools/mcp-getting-started.util.js +2 -2
  109. package/dist/src/ee/mcp/tools/mcp-tool.providers.js +2 -0
  110. package/dist/src/ee/mcp/tools/query-data-mart.tool.js +1 -1
  111. package/dist/src/ee/mcp/tools/run-report.tool.js +1 -1
  112. package/dist/src/ee/mcp/tools/search-data-marts.tool.d.ts +10 -2
  113. package/dist/src/ee/mcp/tools/search-data-marts.tool.js +17 -3
  114. package/dist/src/ee/mcp/tools/update-report-run-schedule.tool.d.ts +1 -1
  115. package/dist/src/ee/mcp/tools/update-report-run-schedule.tool.js +3 -3
  116. package/dist/src/ee/mcp/tools/update-report.tool.js +1 -1
  117. package/dist/src/ee/mcp/transport/mcp-http-entry.service.js +1 -1
  118. package/dist/src/idp/decorators/auth.decorator.js +1 -1
  119. package/dist/src/idp/guards/idp.guard.js +1 -1
  120. package/dist/src/idp/oauth/oauth-project-selection.service.js +1 -1
  121. package/dist/src/migrations/1790830000000-widen-sql-dry-run-trigger-sql-column.d.ts +6 -0
  122. package/dist/src/migrations/1790830000000-widen-sql-dry-run-trigger-sql-column.js +21 -0
  123. package/dist/src/plugin-host/controllers/plugin-gallery.controller.d.ts +5 -1
  124. package/dist/src/plugin-host/controllers/plugin-gallery.controller.js +25 -1
  125. package/dist/src/plugin-host/dto/domain/find-plugin-by-repository.command.d.ts +6 -0
  126. package/dist/src/plugin-host/dto/domain/find-plugin-by-repository.command.js +13 -0
  127. package/dist/src/plugin-host/dto/presentation/plugin-lookup-api.dto.d.ts +3 -0
  128. package/dist/src/plugin-host/dto/presentation/plugin-lookup-api.dto.js +22 -0
  129. package/dist/src/plugin-host/mappers/plugin-presentation.mapper.d.ts +6 -0
  130. package/dist/src/plugin-host/mappers/plugin-presentation.mapper.js +7 -0
  131. package/dist/src/plugin-host/plugin-host.module.js +2 -0
  132. package/dist/src/plugin-host/services/plugin-publication.service.d.ts +2 -0
  133. package/dist/src/plugin-host/services/plugin-publication.service.js +36 -16
  134. package/dist/src/plugin-host/use-cases/find-plugin-by-repository.service.d.ts +9 -0
  135. package/dist/src/plugin-host/use-cases/find-plugin-by-repository.service.js +35 -0
  136. package/dist/src/plugin-host/use-cases/list-installations.service.d.ts +3 -1
  137. package/dist/src/plugin-host/use-cases/list-installations.service.js +14 -3
  138. package/dist/src/plugin-host/utils/github-repo-locator.util.js +1 -1
  139. package/package.json +4 -4
@@ -1,3 +1,4 @@
1
+ import { type McpContextsFacade } from '../../../data-marts/facades/mcp-contexts.facade';
1
2
  import { z } from 'zod-v4';
2
3
  import type { McpScope } from '@owox/idp-protocol';
3
4
  import { type SearchFacade } from '../../../common/search/search.facade';
@@ -7,6 +8,7 @@ import { type McpProjectContextFacade } from '../../../idp/facades/mcp-project-c
7
8
  import type { McpAuthContext } from '../auth/mcp-auth-context';
8
9
  import { type McpToolDefinition, type McpToolResult } from './mcp-tool.definition';
9
10
  declare const inputSchema: z.ZodObject<{
11
+ context_ids: z.ZodPipe<z.ZodOptional<z.ZodArray<z.ZodString>>, z.ZodTransform<string[] | undefined, string[] | undefined>>;
10
12
  prompt: z.ZodString;
11
13
  limit: z.ZodOptional<z.ZodNumber>;
12
14
  }, z.core.$strict>;
@@ -16,9 +18,11 @@ export declare class SearchDataMartsTool implements McpToolDefinition<SearchData
16
18
  private readonly publicOriginService;
17
19
  private readonly projectContext;
18
20
  private readonly dataMarts;
21
+ private readonly contexts;
19
22
  readonly name = "get_relevant_data_marts_by_prompt";
20
- readonly description = "Find relevant non-draft data marts in the current OWOX project from a natural-language prompt, limited to data marts visible to the current MCP user. This is the default discovery step for a concrete analytical question when the data mart has not already been confirmed. Use it when the user asks to find, discover, or search published data marts by title, description, business meaning, schema fields, or metrics. This tool returns only data marts, not data storages or destinations, and it intentionally excludes draft data marts.";
23
+ readonly description = "Find relevant non-draft data marts in the current OWOX project from a natural-language prompt, limited to data marts visible to the current MCP user. This is the default discovery step for a concrete analytical question when the data mart has not already been confirmed. Use it when the user asks to find, discover, or search published data marts by title, description, business meaning, schema fields, or metrics. This tool returns only data marts, not data storages or destinations, and it intentionally excludes draft data marts. Use get_project_context \u2192 list_contexts to discover business goals, then pass context_ids to restrict discovery to any selected context; omission preserves project-wide discovery within your existing access. Responses include all attached context IDs and names.";
21
24
  readonly zodSchema: {
25
+ context_ids: z.ZodPipe<z.ZodOptional<z.ZodArray<z.ZodString>>, z.ZodTransform<string[] | undefined, string[] | undefined>>;
22
26
  prompt: z.ZodString;
23
27
  limit: z.ZodOptional<z.ZodNumber>;
24
28
  };
@@ -31,6 +35,10 @@ export declare class SearchDataMartsTool implements McpToolDefinition<SearchData
31
35
  id: z.ZodString;
32
36
  title: z.ZodString;
33
37
  description: z.ZodString;
38
+ contexts: z.ZodArray<z.ZodObject<{
39
+ id: z.ZodString;
40
+ name: z.ZodString;
41
+ }, z.core.$strip>>;
34
42
  url: z.ZodString;
35
43
  relevance_score: z.ZodNumber;
36
44
  }, z.core.$strip>>;
@@ -59,7 +67,7 @@ export declare class SearchDataMartsTool implements McpToolDefinition<SearchData
59
67
  openWorldHint: boolean;
60
68
  };
61
69
  readonly requiredScopes: McpScope[];
62
- constructor(searchFacade: SearchFacade, publicOriginService: PublicOriginService, projectContext: McpProjectContextFacade, dataMarts: McpDataMartsFacade);
70
+ constructor(searchFacade: SearchFacade, publicOriginService: PublicOriginService, projectContext: McpProjectContextFacade, dataMarts: McpDataMartsFacade, contexts: McpContextsFacade);
63
71
  parseInput(input: unknown): SearchDataMartsInput;
64
72
  handler(input: SearchDataMartsInput, context: McpAuthContext): Promise<McpToolResult>;
65
73
  }
@@ -13,6 +13,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.SearchDataMartsTool = void 0;
16
+ const context_input_1 = require("./context-input");
17
+ const mcp_contexts_facade_1 = require("../../../data-marts/facades/mcp-contexts.facade");
16
18
  const common_1 = require("@nestjs/common");
17
19
  const zod_v4_1 = require("zod-v4");
18
20
  const search_facade_1 = require("../../../common/search/search.facade");
@@ -28,6 +30,7 @@ const DEFAULT_LIMIT = 10;
28
30
  const MAX_LIMIT = 25;
29
31
  const inputSchema = zod_v4_1.z
30
32
  .object({
33
+ context_ids: context_input_1.contextIdsSchema,
31
34
  prompt: zod_v4_1.z.string().trim().min(2).max(256),
32
35
  limit: zod_v4_1.z.number().int().min(1).max(MAX_LIMIT).optional(),
33
36
  })
@@ -37,8 +40,9 @@ let SearchDataMartsTool = class SearchDataMartsTool {
37
40
  publicOriginService;
38
41
  projectContext;
39
42
  dataMarts;
43
+ contexts;
40
44
  name = 'get_relevant_data_marts_by_prompt';
41
- description = 'Find relevant non-draft data marts in the current OWOX project from a natural-language prompt, limited to data marts visible to the current MCP user. This is the default discovery step for a concrete analytical question when the data mart has not already been confirmed. Use it when the user asks to find, discover, or search published data marts by title, description, business meaning, schema fields, or metrics. This tool returns only data marts, not data storages or destinations, and it intentionally excludes draft data marts.';
45
+ description = 'Find relevant non-draft data marts in the current OWOX project from a natural-language prompt, limited to data marts visible to the current MCP user. This is the default discovery step for a concrete analytical question when the data mart has not already been confirmed. Use it when the user asks to find, discover, or search published data marts by title, description, business meaning, schema fields, or metrics. This tool returns only data marts, not data storages or destinations, and it intentionally excludes draft data marts. Use get_project_context → list_contexts to discover business goals, then pass context_ids to restrict discovery to any selected context; omission preserves project-wide discovery within your existing access. Responses include all attached context IDs and names.';
42
46
  zodSchema = inputSchema.shape;
43
47
  outputSchema = {
44
48
  project: zod_v4_1.z.object({ id: zod_v4_1.z.string(), title: zod_v4_1.z.string() }).optional(),
@@ -46,6 +50,7 @@ let SearchDataMartsTool = class SearchDataMartsTool {
46
50
  id: zod_v4_1.z.string(),
47
51
  title: zod_v4_1.z.string(),
48
52
  description: zod_v4_1.z.string(),
53
+ contexts: (0, context_input_1.makeContextSummariesSchema)(),
49
54
  url: zod_v4_1.z.string(),
50
55
  relevance_score: zod_v4_1.z.number(),
51
56
  })),
@@ -60,22 +65,26 @@ let SearchDataMartsTool = class SearchDataMartsTool {
60
65
  openWorldHint: false,
61
66
  };
62
67
  requiredScopes = ['mcp:read'];
63
- constructor(searchFacade, publicOriginService, projectContext, dataMarts) {
68
+ constructor(searchFacade, publicOriginService, projectContext, dataMarts, contexts) {
64
69
  this.searchFacade = searchFacade;
65
70
  this.publicOriginService = publicOriginService;
66
71
  this.projectContext = projectContext;
67
72
  this.dataMarts = dataMarts;
73
+ this.contexts = contexts;
68
74
  }
69
75
  parseInput(input) {
70
76
  return inputSchema.parse(input);
71
77
  }
72
78
  async handler(input, context) {
73
79
  const parsed = this.parseInput(input);
80
+ if (parsed.context_ids)
81
+ await this.contexts.validateContextIds(context.projectId, parsed.context_ids);
74
82
  const [results, projectContext] = await Promise.all([
75
83
  this.searchFacade.search(context.projectId, parsed.prompt, {
76
84
  topK: parsed.limit ?? DEFAULT_LIMIT,
77
85
  entityTypes: [search_facade_1.SearchableEntityType.DATA_MART],
78
86
  excludeDrafts: true,
87
+ ...(parsed.context_ids ? { contextIds: parsed.context_ids } : {}),
79
88
  accessScope: {
80
89
  userId: context.userId,
81
90
  roles: context.roles,
@@ -83,6 +92,9 @@ let SearchDataMartsTool = class SearchDataMartsTool {
83
92
  }),
84
93
  (0, mcp_project_summary_util_1.tryGetMcpProjectSummary)(this.projectContext, context),
85
94
  ]);
95
+ const attachedContexts = await this.contexts.getDataMartContexts(context.projectId, results
96
+ .filter(result => result.entityType === search_facade_1.SearchableEntityType.DATA_MART)
97
+ .map(result => result.entityId));
86
98
  const publicOrigin = this.publicOriginService.getPublicOrigin();
87
99
  const dataMarts = results
88
100
  .filter(result => result.entityType === search_facade_1.SearchableEntityType.DATA_MART)
@@ -91,6 +103,7 @@ let SearchDataMartsTool = class SearchDataMartsTool {
91
103
  title: result.title,
92
104
  description: result.description ?? '',
93
105
  url: (0, mcp_public_url_util_1.joinPublicOrigin)(publicOrigin, (0, data_mart_ui_path_1.buildDataMartUiPath)(context.projectId, result.entityId)),
106
+ contexts: attachedContexts[result.entityId] ?? [],
94
107
  relevance_score: result.finalScore,
95
108
  }));
96
109
  const gettingStarted = dataMarts.length === 0
@@ -110,6 +123,7 @@ exports.SearchDataMartsTool = SearchDataMartsTool = __decorate([
110
123
  __param(0, (0, common_1.Inject)(search_facade_1.SEARCH_FACADE)),
111
124
  __param(2, (0, common_1.Inject)(mcp_project_context_facade_1.MCP_PROJECT_CONTEXT_FACADE)),
112
125
  __param(3, (0, common_1.Inject)(mcp_data_marts_facade_1.MCP_DATA_MARTS_FACADE)),
113
- __metadata("design:paramtypes", [Object, public_origin_service_1.PublicOriginService, Object, Object])
126
+ __param(4, (0, common_1.Inject)(mcp_contexts_facade_1.MCP_CONTEXTS_FACADE)),
127
+ __metadata("design:paramtypes", [Object, public_origin_service_1.PublicOriginService, Object, Object, Object])
114
128
  ], SearchDataMartsTool);
115
129
  //# sourceMappingURL=search-data-marts.tool.js.map
@@ -15,7 +15,7 @@ export declare class UpdateReportRunScheduleTool implements McpToolDefinition<Up
15
15
  private readonly facade;
16
16
  private readonly publicOriginService;
17
17
  readonly name = "update_report_run_schedule";
18
- readonly description = "Updates one existing report run schedule identified by trigger_id (get it from list_report_run_schedules). This changes cron_expression, and optionally time_zone and is_active; it does not change the report target and does not create another schedule. To add another schedule for the same report, call create_report_run_schedule instead. time_zone must be a valid IANA timezone (e.g. \"Europe/Kyiv\"); if omitted, the schedule keeps its current timezone. If is_active is omitted, the schedule keeps its current active state.";
18
+ readonly description = "Updates one existing report run schedule identified by trigger_id (get it from list_report_run_schedules). This changes cron_expression, and optionally time_zone and is_active; it does not change the report target and does not create another schedule. Changing or disabling a schedule can skip report deliveries, and missed runs are not replayed when the schedule is restored. To add another schedule for the same report, call create_report_run_schedule instead. time_zone must be a valid IANA timezone (e.g. \"Europe/Kyiv\"); if omitted, the schedule keeps its current timezone. If is_active is omitted, the schedule keeps its current active state.";
19
19
  readonly zodSchema: {
20
20
  trigger_id: z.ZodString;
21
21
  cron_expression: z.ZodString;
@@ -32,7 +32,7 @@ let UpdateReportRunScheduleTool = class UpdateReportRunScheduleTool {
32
32
  facade;
33
33
  publicOriginService;
34
34
  name = 'update_report_run_schedule';
35
- description = 'Updates one existing report run schedule identified by trigger_id (get it from list_report_run_schedules). This changes cron_expression, and optionally time_zone and is_active; it does not change the report target and does not create another schedule. To add another schedule for the same report, call create_report_run_schedule instead. time_zone must be a valid IANA timezone (e.g. "Europe/Kyiv"); if omitted, the schedule keeps its current timezone. If is_active is omitted, the schedule keeps its current active state.';
35
+ description = 'Updates one existing report run schedule identified by trigger_id (get it from list_report_run_schedules). This changes cron_expression, and optionally time_zone and is_active; it does not change the report target and does not create another schedule. Changing or disabling a schedule can skip report deliveries, and missed runs are not replayed when the schedule is restored. To add another schedule for the same report, call create_report_run_schedule instead. time_zone must be a valid IANA timezone (e.g. "Europe/Kyiv"); if omitted, the schedule keeps its current timezone. If is_active is omitted, the schedule keeps its current active state.';
36
36
  zodSchema = inputSchema.shape;
37
37
  outputSchema = {
38
38
  trigger_id: zod_v4_1.z.string(),
@@ -46,8 +46,8 @@ let UpdateReportRunScheduleTool = class UpdateReportRunScheduleTool {
46
46
  annotations = {
47
47
  title: 'Update Report Run Schedule',
48
48
  readOnlyHint: false,
49
- destructiveHint: false,
50
- openWorldHint: false,
49
+ destructiveHint: true,
50
+ openWorldHint: true,
51
51
  };
52
52
  requiredScopes = ['mcp:read', 'mcp:write'];
53
53
  constructor(facade, publicOriginService) {
@@ -127,7 +127,7 @@ let UpdateReportTool = class UpdateReportTool {
127
127
  annotations = {
128
128
  title: 'Update Report',
129
129
  readOnlyHint: false,
130
- destructiveHint: false,
130
+ destructiveHint: true,
131
131
  openWorldHint: true,
132
132
  };
133
133
  requiredScopes = ['mcp:write'];
@@ -49,7 +49,7 @@ let McpHttpEntryService = McpHttpEntryService_1 = class McpHttpEntryService {
49
49
  return;
50
50
  }
51
51
  const express = this.adapterHost.httpAdapter.getInstance();
52
- this.handler = (0, server_1.createMcpHandler)(({ authInfo }) => this.serverFactory.create((0, mcp_auth_middleware_1.toMcpAuthContext)(authInfo), this.instructionsService.getInstructions()), { onerror: error => this.onTransportError(error) });
52
+ this.handler = (0, server_1.createMcpHandler)(({ authInfo, era }) => this.serverFactory.create((0, mcp_auth_middleware_1.toMcpAuthContext)(authInfo), this.instructionsService.getInstructions(), { era, notifyToolsChanged: () => this.handler?.notify.toolsChanged() }), { onerror: error => this.onTransportError(error) });
53
53
  const nodeHandler = (0, node_1.toNodeHandler)(this.handler, {
54
54
  onerror: error => this.onTransportError(error),
55
55
  });
@@ -7,7 +7,7 @@ const idp_guard_1 = require("../guards/idp.guard");
7
7
  const authentication_openapi_1 = require("../openapi/authentication.openapi");
8
8
  const ROLE_DISPLAY_NAMES = {
9
9
  admin: 'Project Admin',
10
- editor: 'Technical User',
10
+ editor: 'Data Owner',
11
11
  viewer: 'Business User',
12
12
  };
13
13
  const Auth = (roleConfig) => {
@@ -185,7 +185,7 @@ let IdpGuard = class IdpGuard {
185
185
  }
186
186
  static ROLE_DISPLAY_NAMES = {
187
187
  admin: 'Project Admin',
188
- editor: 'Technical User',
188
+ editor: 'Data Owner',
189
189
  viewer: 'Business User',
190
190
  };
191
191
  checkRoleAuthorization(request, requiredRole) {
@@ -11,7 +11,7 @@ const common_1 = require("@nestjs/common");
11
11
  const PROJECT_ROLES = ['admin', 'editor', 'viewer'];
12
12
  const PROJECT_ROLE_LABELS = {
13
13
  admin: 'Project Admin',
14
- editor: 'Technical User',
14
+ editor: 'Data Owner',
15
15
  viewer: 'Business User',
16
16
  };
17
17
  let OAuthProjectSelectionService = class OAuthProjectSelectionService {
@@ -0,0 +1,6 @@
1
+ import { MigrationInterface, QueryRunner } from 'typeorm';
2
+ export declare class WidenSqlDryRunTriggerSqlColumn1790830000000 implements MigrationInterface {
3
+ readonly name = "WidenSqlDryRunTriggerSqlColumn1790830000000";
4
+ up(queryRunner: QueryRunner): Promise<void>;
5
+ down(queryRunner: QueryRunner): Promise<void>;
6
+ }
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.WidenSqlDryRunTriggerSqlColumn1790830000000 = void 0;
4
+ class WidenSqlDryRunTriggerSqlColumn1790830000000 {
5
+ name = 'WidenSqlDryRunTriggerSqlColumn1790830000000';
6
+ async up(queryRunner) {
7
+ if (queryRunner.connection.options.type !== 'mysql') {
8
+ return;
9
+ }
10
+ await queryRunner.query('ALTER TABLE `sql_dry_run_triggers` MODIFY `sql` MEDIUMTEXT NOT NULL');
11
+ }
12
+ async down(queryRunner) {
13
+ if (queryRunner.connection.options.type !== 'mysql') {
14
+ return;
15
+ }
16
+ await queryRunner.query('DELETE FROM `sql_dry_run_triggers` WHERE LENGTH(`sql`) > 65535');
17
+ await queryRunner.query('ALTER TABLE `sql_dry_run_triggers` MODIFY `sql` TEXT NOT NULL');
18
+ }
19
+ }
20
+ exports.WidenSqlDryRunTriggerSqlColumn1790830000000 = WidenSqlDryRunTriggerSqlColumn1790830000000;
21
+ //# sourceMappingURL=1790830000000-widen-sql-dry-run-trigger-sql-column.js.map
@@ -1,13 +1,17 @@
1
1
  import { type AuthorizationContext } from '../../idp';
2
2
  import { PluginGalleryEntryApiDto } from '../dto/presentation/plugin-gallery-api.dto';
3
+ import { PluginLookupApiDto } from '../dto/presentation/plugin-lookup-api.dto';
3
4
  import { PluginPresentationMapper } from '../mappers/plugin-presentation.mapper';
5
+ import { FindPluginByRepositoryService } from '../use-cases/find-plugin-by-repository.service';
4
6
  import { GetPluginDetailsService } from '../use-cases/get-plugin-details.service';
5
7
  import { GetPluginGalleryService } from '../use-cases/get-plugin-gallery.service';
6
8
  export declare class PluginGalleryController {
7
9
  private readonly getPluginGalleryService;
8
10
  private readonly getPluginDetailsService;
11
+ private readonly findPluginByRepositoryService;
9
12
  private readonly mapper;
10
- constructor(getPluginGalleryService: GetPluginGalleryService, getPluginDetailsService: GetPluginDetailsService, mapper: PluginPresentationMapper);
13
+ constructor(getPluginGalleryService: GetPluginGalleryService, getPluginDetailsService: GetPluginDetailsService, findPluginByRepositoryService: FindPluginByRepositoryService, mapper: PluginPresentationMapper);
11
14
  gallery(context: AuthorizationContext): Promise<PluginGalleryEntryApiDto[]>;
15
+ lookup(context: AuthorizationContext, repository: string): Promise<PluginLookupApiDto>;
12
16
  details(context: AuthorizationContext, pluginId: string): Promise<PluginGalleryEntryApiDto>;
13
17
  }
@@ -18,23 +18,31 @@ const swagger_1 = require("@nestjs/swagger");
18
18
  const idp_1 = require("../../idp");
19
19
  const role_config_types_1 = require("../../idp/types/role-config.types");
20
20
  const plugin_gallery_api_dto_1 = require("../dto/presentation/plugin-gallery-api.dto");
21
+ const plugin_lookup_api_dto_1 = require("../dto/presentation/plugin-lookup-api.dto");
21
22
  const plugin_host_exception_filter_1 = require("../filters/plugin-host-exception.filter");
22
23
  const plugin_presentation_mapper_1 = require("../mappers/plugin-presentation.mapper");
24
+ const find_plugin_by_repository_service_1 = require("../use-cases/find-plugin-by-repository.service");
23
25
  const get_plugin_details_service_1 = require("../use-cases/get-plugin-details.service");
24
26
  const get_plugin_gallery_service_1 = require("../use-cases/get-plugin-gallery.service");
25
27
  let PluginGalleryController = class PluginGalleryController {
26
28
  getPluginGalleryService;
27
29
  getPluginDetailsService;
30
+ findPluginByRepositoryService;
28
31
  mapper;
29
- constructor(getPluginGalleryService, getPluginDetailsService, mapper) {
32
+ constructor(getPluginGalleryService, getPluginDetailsService, findPluginByRepositoryService, mapper) {
30
33
  this.getPluginGalleryService = getPluginGalleryService;
31
34
  this.getPluginDetailsService = getPluginDetailsService;
35
+ this.findPluginByRepositoryService = findPluginByRepositoryService;
32
36
  this.mapper = mapper;
33
37
  }
34
38
  async gallery(context) {
35
39
  const result = await this.getPluginGalleryService.run(this.mapper.toGetPluginGalleryCommand(context));
36
40
  return this.mapper.toGalleryEntryResponseList(result);
37
41
  }
42
+ async lookup(context, repository) {
43
+ const result = await this.findPluginByRepositoryService.run(this.mapper.toFindPluginByRepositoryCommand(repository ?? '', context));
44
+ return this.mapper.toLookupResponse(result);
45
+ }
38
46
  async details(context, pluginId) {
39
47
  const result = await this.getPluginDetailsService.run(this.mapper.toGetPluginDetailsCommand(pluginId, context));
40
48
  return this.mapper.toGalleryEntryResponse(result);
@@ -54,6 +62,21 @@ __decorate([
54
62
  __metadata("design:paramtypes", [Object]),
55
63
  __metadata("design:returntype", Promise)
56
64
  ], PluginGalleryController.prototype, "gallery", null);
65
+ __decorate([
66
+ (0, idp_1.Auth)(role_config_types_1.Role.viewer(role_config_types_1.Strategy.PARSE)),
67
+ (0, common_1.Get)('lookup'),
68
+ (0, swagger_1.ApiOperation)({
69
+ summary: 'A public plugin by its GitHub repository',
70
+ description: "Resolves owner/name or a GitHub URL to the id of a public plugin whose deployment publication reaches the caller's project: all projects, or a selected audience that includes it. Any other repository, private, unknown or outside the audience, answers 404 alike.",
71
+ }),
72
+ (0, swagger_1.ApiQuery)({ name: 'repository', required: true, example: 'OWOX/odm-usage-stat' }),
73
+ (0, swagger_1.ApiOkResponse)({ type: plugin_lookup_api_dto_1.PluginLookupApiDto }),
74
+ __param(0, (0, idp_1.AuthContext)()),
75
+ __param(1, (0, common_1.Query)('repository')),
76
+ __metadata("design:type", Function),
77
+ __metadata("design:paramtypes", [Object, String]),
78
+ __metadata("design:returntype", Promise)
79
+ ], PluginGalleryController.prototype, "lookup", null);
57
80
  __decorate([
58
81
  (0, idp_1.Auth)(role_config_types_1.Role.viewer(role_config_types_1.Strategy.PARSE)),
59
82
  (0, common_1.Get)(':pluginId'),
@@ -74,6 +97,7 @@ exports.PluginGalleryController = PluginGalleryController = __decorate([
74
97
  (0, common_1.UseFilters)(plugin_host_exception_filter_1.PluginHostExceptionFilter),
75
98
  __metadata("design:paramtypes", [get_plugin_gallery_service_1.GetPluginGalleryService,
76
99
  get_plugin_details_service_1.GetPluginDetailsService,
100
+ find_plugin_by_repository_service_1.FindPluginByRepositoryService,
77
101
  plugin_presentation_mapper_1.PluginPresentationMapper])
78
102
  ], PluginGalleryController);
79
103
  //# sourceMappingURL=plugin-gallery.controller.js.map
@@ -0,0 +1,6 @@
1
+ import { AuthorizationContext } from '../../../idp/types/auth.types';
2
+ export declare class FindPluginByRepositoryCommand {
3
+ readonly repository: string;
4
+ readonly context: AuthorizationContext;
5
+ constructor(repository: string, context: AuthorizationContext);
6
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.FindPluginByRepositoryCommand = void 0;
4
+ class FindPluginByRepositoryCommand {
5
+ repository;
6
+ context;
7
+ constructor(repository, context) {
8
+ this.repository = repository;
9
+ this.context = context;
10
+ }
11
+ }
12
+ exports.FindPluginByRepositoryCommand = FindPluginByRepositoryCommand;
13
+ //# sourceMappingURL=find-plugin-by-repository.command.js.map
@@ -0,0 +1,3 @@
1
+ export declare class PluginLookupApiDto {
2
+ pluginId: string;
3
+ }
@@ -0,0 +1,22 @@
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.PluginLookupApiDto = void 0;
13
+ const swagger_1 = require("@nestjs/swagger");
14
+ class PluginLookupApiDto {
15
+ pluginId;
16
+ }
17
+ exports.PluginLookupApiDto = PluginLookupApiDto;
18
+ __decorate([
19
+ (0, swagger_1.ApiProperty)({ description: 'The plugin id in this deployment.' }),
20
+ __metadata("design:type", String)
21
+ ], PluginLookupApiDto.prototype, "pluginId", void 0);
22
+ //# sourceMappingURL=plugin-lookup-api.dto.js.map
@@ -1,4 +1,5 @@
1
1
  import type { AuthorizationContext } from '../../idp';
2
+ import { FindPluginByRepositoryCommand } from '../dto/domain/find-plugin-by-repository.command';
2
3
  import { GetPluginDetailsCommand } from '../dto/domain/get-plugin-details.command';
3
4
  import { GetPluginGalleryCommand } from '../dto/domain/get-plugin-gallery.command';
4
5
  import { GetPluginInstallationEntryCommand } from '../dto/domain/get-plugin-installation-entry.command';
@@ -14,6 +15,7 @@ import { UninstallPluginCommand } from '../dto/domain/uninstall-plugin.command';
14
15
  import { PluginUpdateResultDto, UpdatePluginCommand } from '../dto/domain/update-plugin.command';
15
16
  import { InstalledPluginApiDto, InstallPluginApiDto, PluginEntryApiDto, PluginInstallationApiDto, PluginUpdateResultApiDto } from '../dto/presentation/plugin-installation-api.dto';
16
17
  import { PluginGalleryEntryApiDto } from '../dto/presentation/plugin-gallery-api.dto';
18
+ import { PluginLookupApiDto } from '../dto/presentation/plugin-lookup-api.dto';
17
19
  import { PluginSuspensionResponseApiDto, SuspendPluginApiDto } from '../dto/presentation/plugin-suspension-api.dto';
18
20
  import { PluginPublisherDiagnosticsApiDto, PublicationResponseApiDto, PublishPluginApiDto, UpdatePluginByRepositoryApiDto } from '../dto/presentation/publication-api.dto';
19
21
  import { PluginVersion } from '../entities/plugin-version.entity';
@@ -31,6 +33,7 @@ export declare class PluginPresentationMapper {
31
33
  toGetPluginGalleryCommand(context: AuthorizationContext): GetPluginGalleryCommand;
32
34
  toGetPluginDetailsCommand(pluginId: string, context: AuthorizationContext): GetPluginDetailsCommand;
33
35
  toListInstallationsCommand(context: AuthorizationContext, includeUninstalled: boolean): ListInstallationsCommand;
36
+ toFindPluginByRepositoryCommand(repository: string, context: AuthorizationContext): FindPluginByRepositoryCommand;
34
37
  toGetPluginInstallationEntryCommand(installationId: string, context: AuthorizationContext): GetPluginInstallationEntryCommand;
35
38
  toInstallCommand(pluginId: string, context: AuthorizationContext, dto: InstallPluginApiDto): InstallPluginCommand;
36
39
  toUpdateCommand(pluginId: string, context: AuthorizationContext): UpdatePluginCommand;
@@ -39,6 +42,9 @@ export declare class PluginPresentationMapper {
39
42
  toSuspendCommand(context: AuthorizationContext, dto: SuspendPluginApiDto): SuspendPluginCommand;
40
43
  toResumeCommand(context: AuthorizationContext, dto: SuspendPluginApiDto): ResumePluginCommand;
41
44
  toMemberDto(plugin: Plugin, version: PluginVersion | null, context: PluginViewContext): PluginGalleryEntryDto;
45
+ toLookupResponse(result: {
46
+ pluginId: string;
47
+ }): PluginLookupApiDto;
42
48
  toGalleryEntryResponse(dto: PluginGalleryEntryDto): PluginGalleryEntryApiDto;
43
49
  toGalleryEntryResponseList(dtos: PluginGalleryEntryDto[]): PluginGalleryEntryApiDto[];
44
50
  toPublicationResponse(dto: PluginPublicationDto): PublicationResponseApiDto;
@@ -8,6 +8,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.PluginPresentationMapper = void 0;
10
10
  const common_1 = require("@nestjs/common");
11
+ const find_plugin_by_repository_command_1 = require("../dto/domain/find-plugin-by-repository.command");
11
12
  const get_plugin_details_command_1 = require("../dto/domain/get-plugin-details.command");
12
13
  const get_plugin_gallery_command_1 = require("../dto/domain/get-plugin-gallery.command");
13
14
  const get_plugin_installation_entry_command_1 = require("../dto/domain/get-plugin-installation-entry.command");
@@ -44,6 +45,9 @@ let PluginPresentationMapper = class PluginPresentationMapper {
44
45
  toListInstallationsCommand(context, includeUninstalled) {
45
46
  return new list_installations_command_1.ListInstallationsCommand(context, includeUninstalled);
46
47
  }
48
+ toFindPluginByRepositoryCommand(repository, context) {
49
+ return new find_plugin_by_repository_command_1.FindPluginByRepositoryCommand(repository, context);
50
+ }
47
51
  toGetPluginInstallationEntryCommand(installationId, context) {
48
52
  return new get_plugin_installation_entry_command_1.GetPluginInstallationEntryCommand(installationId, context);
49
53
  }
@@ -81,6 +85,9 @@ let PluginPresentationMapper = class PluginPresentationMapper {
81
85
  credentialRequirements: version?.credentialRequirements ?? [],
82
86
  };
83
87
  }
88
+ toLookupResponse(result) {
89
+ return { pluginId: result.pluginId };
90
+ }
84
91
  toGalleryEntryResponse(dto) {
85
92
  return {
86
93
  pluginId: dto.pluginId,
@@ -43,6 +43,7 @@ const publication_authorization_service_1 = require("./services/publication-auth
43
43
  const plugin_runtime_authorizer_service_1 = require("./services/plugin-runtime-authorizer.service");
44
44
  const remote_url_validator_service_1 = require("./services/remote-url-validator.service");
45
45
  const plugin_presentation_mapper_1 = require("./mappers/plugin-presentation.mapper");
46
+ const find_plugin_by_repository_service_1 = require("./use-cases/find-plugin-by-repository.service");
46
47
  const get_plugin_details_service_1 = require("./use-cases/get-plugin-details.service");
47
48
  const get_plugin_installation_entry_service_1 = require("./use-cases/get-plugin-installation-entry.service");
48
49
  const install_plugin_service_1 = require("./use-cases/install-plugin.service");
@@ -132,6 +133,7 @@ exports.PluginHostModule = PluginHostModule = __decorate([
132
133
  plugin_presentation_mapper_1.PluginPresentationMapper,
133
134
  get_plugin_gallery_service_1.GetPluginGalleryService,
134
135
  get_plugin_details_service_1.GetPluginDetailsService,
136
+ find_plugin_by_repository_service_1.FindPluginByRepositoryService,
135
137
  suspend_plugin_service_1.SuspendPluginService,
136
138
  resume_plugin_service_1.ResumePluginService,
137
139
  plugin_installation_service_1.PluginInstallationService,
@@ -22,8 +22,10 @@ export declare class PluginPublicationService {
22
22
  addToAudience(publicationId: string, projectIds: string[]): Promise<void>;
23
23
  removeFromAudience(publicationId: string, projectIds?: string[]): Promise<void>;
24
24
  findVisibleTo(projectId: string, userId: string): Promise<PluginPublication[]>;
25
+ findDeploymentPluginIdByRepo(projectId: string, owner: string, name: string): Promise<string | null>;
25
26
  listManageable(scope: PluginPublicationScope, filters: {
26
27
  projectId?: string;
27
28
  userId?: string;
28
29
  }): Promise<PluginPublication[]>;
30
+ private deploymentVisibleToProject;
29
31
  }
@@ -18,6 +18,7 @@ const typeorm_1 = require("@nestjs/typeorm");
18
18
  const typeorm_2 = require("typeorm");
19
19
  const plugin_publication_project_entity_1 = require("../entities/plugin-publication-project.entity");
20
20
  const plugin_publication_entity_1 = require("../entities/plugin-publication.entity");
21
+ const plugin_entity_1 = require("../entities/plugin.entity");
21
22
  const plugin_publication_scope_enum_1 = require("../enums/plugin-publication-scope.enum");
22
23
  let PluginPublicationService = class PluginPublicationService {
23
24
  publications;
@@ -69,22 +70,7 @@ let PluginPublicationService = class PluginPublicationService {
69
70
  .where('publication.isActive = :isActive', { isActive: true })
70
71
  .andWhere(new typeorm_2.Brackets(scopes => {
71
72
  scopes
72
- .where(new typeorm_2.Brackets(deployment => {
73
- deployment
74
- .where('publication.scope = :deploymentScope', {
75
- deploymentScope: plugin_publication_scope_enum_1.PluginPublicationScope.DEPLOYMENT,
76
- })
77
- .andWhere(new typeorm_2.Brackets(audience => {
78
- audience
79
- .where('publication.allProjects = :isActive', { isActive: true })
80
- .orWhere(`EXISTS (
81
- SELECT 1 FROM plugin_publication_project audience_row
82
- WHERE audience_row.publicationId = publication.id
83
- AND audience_row.projectId = :projectId
84
- AND audience_row.isActive = :isActive
85
- )`);
86
- }));
87
- }))
73
+ .where(this.deploymentVisibleToProject(projectId))
88
74
  .orWhere(new typeorm_2.Brackets(project => {
89
75
  project
90
76
  .where('publication.scope = :projectScope', {
@@ -104,6 +90,20 @@ let PluginPublicationService = class PluginPublicationService {
104
90
  .setParameters({ projectId, userId })
105
91
  .getMany();
106
92
  }
93
+ async findDeploymentPluginIdByRepo(projectId, owner, name) {
94
+ const publication = await this.publications
95
+ .createQueryBuilder('publication')
96
+ .innerJoin(plugin_entity_1.Plugin, 'plugin', 'plugin.id = publication.pluginId')
97
+ .where('publication.isActive = :isActive', { isActive: true })
98
+ .andWhere(this.deploymentVisibleToProject(projectId))
99
+ .andWhere('LOWER(plugin.repoOwner) = :owner', { owner: owner.toLowerCase() })
100
+ .andWhere('LOWER(plugin.repoName) = :name', { name: name.toLowerCase() })
101
+ .andWhere('plugin.isPrivateRepo = :isPrivate', { isPrivate: false })
102
+ .orderBy('plugin.modifiedAt', 'DESC')
103
+ .addOrderBy('plugin.id', 'ASC')
104
+ .getOne();
105
+ return publication?.pluginId ?? null;
106
+ }
107
107
  listManageable(scope, filters) {
108
108
  return this.publications.findBy({
109
109
  scope,
@@ -111,6 +111,26 @@ let PluginPublicationService = class PluginPublicationService {
111
111
  ...(filters.userId ? { userId: filters.userId } : {}),
112
112
  });
113
113
  }
114
+ deploymentVisibleToProject(projectId) {
115
+ return new typeorm_2.Brackets(deployment => {
116
+ deployment
117
+ .where('publication.scope = :deploymentScope', {
118
+ deploymentScope: plugin_publication_scope_enum_1.PluginPublicationScope.DEPLOYMENT,
119
+ })
120
+ .andWhere(new typeorm_2.Brackets(audience => {
121
+ audience
122
+ .where('publication.allProjects = :deploymentAllProjects', {
123
+ deploymentAllProjects: true,
124
+ })
125
+ .orWhere(`EXISTS (
126
+ SELECT 1 FROM plugin_publication_project audience_row
127
+ WHERE audience_row.publicationId = publication.id
128
+ AND audience_row.projectId = :deploymentProjectId
129
+ AND audience_row.isActive = :deploymentAudienceActive
130
+ )`, { deploymentProjectId: projectId, deploymentAudienceActive: true });
131
+ }));
132
+ });
133
+ }
114
134
  };
115
135
  exports.PluginPublicationService = PluginPublicationService;
116
136
  exports.PluginPublicationService = PluginPublicationService = __decorate([
@@ -0,0 +1,9 @@
1
+ import { FindPluginByRepositoryCommand } from '../dto/domain/find-plugin-by-repository.command';
2
+ import { PluginPublicationService } from '../services/plugin-publication.service';
3
+ export declare class FindPluginByRepositoryService {
4
+ private readonly publications;
5
+ constructor(publications: PluginPublicationService);
6
+ run(command: FindPluginByRepositoryCommand): Promise<{
7
+ pluginId: string;
8
+ }>;
9
+ }
@@ -0,0 +1,35 @@
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.FindPluginByRepositoryService = void 0;
13
+ const common_1 = require("@nestjs/common");
14
+ const plugin_publication_service_1 = require("../services/plugin-publication.service");
15
+ const github_repo_locator_util_1 = require("../utils/github-repo-locator.util");
16
+ let FindPluginByRepositoryService = class FindPluginByRepositoryService {
17
+ publications;
18
+ constructor(publications) {
19
+ this.publications = publications;
20
+ }
21
+ async run(command) {
22
+ const { owner, name } = (0, github_repo_locator_util_1.parseGithubRepoLocator)(command.repository);
23
+ const pluginId = await this.publications.findDeploymentPluginIdByRepo(command.context.projectId, owner, name);
24
+ if (!pluginId) {
25
+ throw new common_1.NotFoundException('No public plugin is published from this repository');
26
+ }
27
+ return { pluginId };
28
+ }
29
+ };
30
+ exports.FindPluginByRepositoryService = FindPluginByRepositoryService;
31
+ exports.FindPluginByRepositoryService = FindPluginByRepositoryService = __decorate([
32
+ (0, common_1.Injectable)(),
33
+ __metadata("design:paramtypes", [plugin_publication_service_1.PluginPublicationService])
34
+ ], FindPluginByRepositoryService);
35
+ //# sourceMappingURL=find-plugin-by-repository.service.js.map
@@ -2,6 +2,7 @@ import { ListInstallationsCommand } from '../dto/domain/list-installations.comma
2
2
  import { InstalledPluginDto } from '../dto/domain/plugin-installation.dto';
3
3
  import { PluginPresentationMapper } from '../mappers/plugin-presentation.mapper';
4
4
  import { PluginInstallationService } from '../services/plugin-installation.service';
5
+ import { PluginPublicationService } from '../services/plugin-publication.service';
5
6
  import { PluginVersionService } from '../services/plugin-version.service';
6
7
  import { PluginService } from '../services/plugin.service';
7
8
  export declare class ListInstallationsService {
@@ -9,6 +10,7 @@ export declare class ListInstallationsService {
9
10
  private readonly pluginService;
10
11
  private readonly versionService;
11
12
  private readonly mapper;
12
- constructor(installations: PluginInstallationService, pluginService: PluginService, versionService: PluginVersionService, mapper: PluginPresentationMapper);
13
+ private readonly publications;
14
+ constructor(installations: PluginInstallationService, pluginService: PluginService, versionService: PluginVersionService, mapper: PluginPresentationMapper, publications: PluginPublicationService);
13
15
  run(command: ListInstallationsCommand): Promise<InstalledPluginDto[]>;
14
16
  }