@things-factory/integration-base 10.1.154 → 10.1.155
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/dist-server/controllers/scenario-controller.js +1 -2
- package/dist-server/controllers/scenario-controller.js.map +1 -1
- package/dist-server/engine/connection-manager.js +1 -2
- package/dist-server/engine/connection-manager.js.map +1 -1
- package/dist-server/engine/index.d.ts +0 -1
- package/dist-server/engine/index.js +1 -3
- package/dist-server/engine/index.js.map +1 -1
- package/dist-server/service/connection/connection-mutation.js +2 -3
- package/dist-server/service/connection/connection-mutation.js.map +1 -1
- package/dist-server/service/connection/connection-query.js +2 -3
- package/dist-server/service/connection/connection-query.js.map +1 -1
- package/dist-server/service/connection/connection-secrets.js +1 -2
- package/dist-server/service/connection/connection-secrets.js.map +1 -1
- package/dist-server/service/connection/connection-subscription.js +1 -2
- package/dist-server/service/connection/connection-subscription.js.map +1 -1
- package/dist-server/service/connection/connection.js +1 -2
- package/dist-server/service/connection/connection.js.map +1 -1
- package/dist-server/service/domain-attribute/domain-attribute-query.js +2 -4
- package/dist-server/service/domain-attribute/domain-attribute-query.js.map +1 -1
- package/dist-server/service/scenario/scenario-query.js +2 -3
- package/dist-server/service/scenario/scenario-query.js.map +1 -1
- package/dist-server/service/scenario/scenario-version-query.js +4 -5
- package/dist-server/service/scenario/scenario-version-query.js.map +1 -1
- package/dist-server/service/scenario-instance/scenario-instance-type.js +2 -3
- package/dist-server/service/scenario-instance/scenario-instance-type.js.map +1 -1
- package/dist-server/service/secret-hint.d.ts +0 -12
- package/dist-server/service/secret-hint.js +0 -26
- package/dist-server/service/secret-hint.js.map +1 -1
- package/dist-server/service/step/step-query.js +2 -3
- package/dist-server/service/step/step-query.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/dist-server/utils/domain-inheritance.d.ts +0 -29
- package/dist-server/utils/domain-inheritance.js +0 -98
- package/dist-server/utils/domain-inheritance.js.map +0 -1
|
@@ -9,7 +9,6 @@ const auth_base_1 = require("@things-factory/auth-base");
|
|
|
9
9
|
const cache_service_1 = require("@things-factory/cache-service");
|
|
10
10
|
const scenario_engine_1 = require("../engine/scenario-engine");
|
|
11
11
|
const scenario_1 = require("../service/scenario/scenario");
|
|
12
|
-
const domain_inheritance_1 = require("../utils/domain-inheritance");
|
|
13
12
|
const resolve_steps_1 = require("../service/scenario/resolve-steps");
|
|
14
13
|
const debug = require('debug')('things-factory:integration-base:controller:run-scenario');
|
|
15
14
|
/**
|
|
@@ -22,7 +21,7 @@ const debug = require('debug')('things-factory:integration-base:controller:run-s
|
|
|
22
21
|
async function findScenario(scenarioName, domain, mode = 'released') {
|
|
23
22
|
var repository = (0, shell_1.getRepository)(scenario_1.Scenario);
|
|
24
23
|
// ancestor 도메인을 closest-first 로 순회하여 first hit 사용
|
|
25
|
-
const domainIds = await (0,
|
|
24
|
+
const domainIds = await (0, shell_1.getDomainIdsWithAncestors)(domain);
|
|
26
25
|
var scenario = null;
|
|
27
26
|
for (const did of domainIds) {
|
|
28
27
|
scenario = await repository.findOne({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scenario-controller.js","sourceRoot":"","sources":["../../server/controllers/scenario-controller.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"scenario-controller.js","sourceRoot":"","sources":["../../server/controllers/scenario-controller.ts"],"names":[],"mappings":"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","sourcesContent":["import { getRepository, Domain, GraphqlLocalClient, getDomainIdsWithAncestors } from '@things-factory/shell'\nimport { checkUserHasRole } from '@things-factory/auth-base'\nimport { cacheService } from '@things-factory/cache-service'\n\nimport { ScenarioEngine } from '../engine/scenario-engine'\nimport { Scenario } from '../service/scenario/scenario'\nimport { resolveRunnableSteps } from '../service/scenario/resolve-steps'\nimport {\n ScenarioInstance,\n ScenarioInstanceRunResult,\n ScenarioInstanceStartResult\n} from '../service/scenario-instance/scenario-instance-type'\nimport { Step } from '../service/step/step-type'\n\nconst debug = require('debug')('things-factory:integration-base:controller:run-scenario')\n\n/**\n * 실행할 시나리오를 찾아 실행 대상 steps 를 주입한다.\n *\n * [버전관리] 기본 mode='released' — 운영 실행은 최신 릴리즈 스냅샷을 사용한다.\n * 릴리즈된 버전이 없으면 draft 로 폴백(resolveRunnableSteps 내부 처리).\n * mode='draft' 는 디버깅 실행(편집 중 draft 를 그대로 실행) 용.\n */\nasync function findScenario(\n scenarioName: string,\n domain: Domain,\n mode: 'released' | 'draft' = 'released'\n): Promise<{\n id: string\n ttl: number\n name: string\n steps: Step[]\n domain: Domain\n}> {\n var repository = getRepository(Scenario)\n\n // ancestor 도메인을 closest-first 로 순회하여 first hit 사용\n const domainIds = await getDomainIdsWithAncestors(domain)\n var scenario: Scenario | null = null\n for (const did of domainIds) {\n scenario = await repository.findOne({\n where: { domain: { id: did }, name: scenarioName },\n relations: ['domain', 'role', 'creator', 'updater']\n })\n if (scenario) break\n }\n\n if (scenario) {\n scenario.steps = await resolveRunnableSteps(scenario, { mode })\n }\n\n return scenario as any\n}\n\nexport async function checkHasRole(scenario: Partial<Scenario>, context: ResolverContext): Promise<void> {\n const { domain, user } = context.state\n if (!(await checkUserHasRole(scenario.roleId, domain, user))) {\n throw new Error(\n context.t('error.scenario run unauthorized', {\n scenario: scenario.name\n })\n )\n }\n}\n\nexport async function runScenario(\n instanceName: string,\n scenarioName: string,\n variables: any,\n context: ResolverContext,\n mode: 'released' | 'draft' = 'released'\n): Promise<ScenarioInstanceRunResult> {\n const { domain, user, lng } = context.state\n\n debug('runScenario', scenarioName, instanceName, variables, mode)\n\n var scenario = await findScenario(scenarioName, domain, mode)\n\n if (!scenario) {\n throw new Error(\n context.t('error.scenario not found', {\n scenario: scenarioName\n })\n )\n }\n\n await checkHasRole(scenario, context)\n\n if (scenario.ttl > 0) {\n const cachedValue = await cacheService.getFromCache(scenario.id, { domain: domain.id, variables: variables || {} })\n if (cachedValue) {\n return cachedValue.value\n }\n }\n\n /* 시나리오 인스턴스를 생성한다. */\n instanceName = instanceName || scenarioName + '-' + String(Date.now())\n\n try {\n return await ScenarioEngine.run(instanceName, scenario, { domain, user, lng, variables })\n } catch (err) {\n console.error(err)\n\n throw new Error(\n context.t('error.scenario run error', {\n scenario: scenarioName\n })\n )\n }\n}\n\nexport async function startScenario(\n instanceName: string,\n scenarioName: string,\n variables: any,\n context: ResolverContext,\n mode: 'released' | 'draft' = 'released'\n): Promise<ScenarioInstanceStartResult> {\n const { domain, user, lng } = context.state\n\n debug('startScenario', instanceName, scenarioName, variables, mode)\n\n var scenario = await findScenario(scenarioName, domain, mode)\n\n if (!scenario) {\n throw new Error(\n context.t('error.scenario not found', {\n scenario: scenarioName\n })\n )\n }\n\n await checkHasRole(scenario, context)\n\n instanceName = instanceName || scenarioName\n return await ScenarioEngine.loadIteration(instanceName, scenario, { domain, user, lng, variables })\n}\n\nexport async function stopScenario(\n instanceName: string,\n context: ResolverContext\n): Promise<ScenarioInstance | undefined> {\n const { domain, user, unsafeIP, prohibitedPrivileges } = context.state\n\n debug('stopScenario', instanceName)\n\n var scenarioInstance = ScenarioEngine.getScenarioInstance(domain, instanceName)\n\n if (!scenarioInstance) {\n debug('stopScenario', `ScenarioInstance(${instanceName}) Not Found.`)\n throw new Error(\n context.t('error.scenario instance not found', {\n instance: instanceName\n })\n )\n }\n\n var scenario = await findScenario(scenarioInstance.scenarioName, domain)\n\n await checkHasRole(scenario, context)\n\n await ScenarioEngine.unload(domain, instanceName)\n\n return scenarioInstance\n}\n"]}
|
|
@@ -6,7 +6,6 @@ const moment_timezone_1 = tslib_1.__importDefault(require("moment-timezone"));
|
|
|
6
6
|
const winston_1 = require("winston");
|
|
7
7
|
const shell_1 = require("@things-factory/shell");
|
|
8
8
|
const service_1 = require("../service");
|
|
9
|
-
const domain_inheritance_1 = require("../utils/domain-inheritance");
|
|
10
9
|
const proxy_connector_1 = require("./connector/proxy-connector");
|
|
11
10
|
const { combine, splat, printf, errors } = winston_1.format;
|
|
12
11
|
const debug = require('debug')('things-factory:integration-base:connections');
|
|
@@ -276,7 +275,7 @@ class ConnectionManager {
|
|
|
276
275
|
//
|
|
277
276
|
// 호환성: inheritanceMode 미지정(NULL) → connector default → 폴백 ISOLATE.
|
|
278
277
|
// 기존 모든 Connection 은 이 column 추가 전 만들어졌으므로 NULL → ISOLATE = 기존 거동.
|
|
279
|
-
const ancestorIds = await (0,
|
|
278
|
+
const ancestorIds = await (0, shell_1.getDomainIdsWithAncestors)(domain);
|
|
280
279
|
// ancestorIds[0] = domain.id (이미 위 분기에서 시도), skip
|
|
281
280
|
const searchedAncestors = [];
|
|
282
281
|
for (let i = 1; i < ancestorIds.length; i++) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-manager.js","sourceRoot":"","sources":["../../server/engine/connection-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import moment from 'moment-timezone'\nimport { createLogger, format, transports } from 'winston'\n\nimport { Domain, getRepository, pubsub, PubSubLogTransport } from '@things-factory/shell'\n\nimport { Connection, ConnectionInheritanceMode, ConnectionStatus } from '../service'\nimport { getDomainIdsWithAncestors } from '../utils/domain-inheritance'\nimport { Connector } from './types'\nimport { ProxyConnector } from './connector/proxy-connector'\n\nconst { combine, splat, printf, errors } = format\nconst debug = require('debug')('things-factory:integration-base:connections')\n\nfunction getSystemTimeZone() {\n try {\n const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone\n if (!timeZone) {\n throw new Error('Unable to resolve timeZone')\n }\n return timeZone\n } catch (e) {\n console.warn('Failed to get system timeZone, falling back to UTC.', e)\n return 'UTC'\n }\n}\n\nconst SYSTEM_TZ = getSystemTimeZone()\nconst systemTimestamp = format((info, opts: { tz?: string }) => {\n if (opts.tz) info.timestamp = moment().tz(opts.tz).format()\n return info\n})\n\nexport class ConnectionManager {\n private static connectors: { [propName: string]: Connector } = {}\n private static connections: { [domainId: string]: { [name: string]: any } } = {}\n private static entities = {}\n /**\n * Session 직렬화 mutex — connection name 단위 (도메인 무관 글로벌).\n * sessionExclusive connector 의 acquireSessionPage 동시 호출이 외부 세션을 서로\n * invalidate 하지 않도록 큐잉. release 호출 시 다음 대기자가 진행.\n */\n private static sessionLocks: Map<string, Promise<void>> = new Map()\n private static logFormat = printf(({ level, message, timestamp, stack }) => {\n return `${timestamp} ${level}: ${stack || message}`\n })\n\n public static logger = createLogger({\n format: combine(errors({ stack: true }), systemTimestamp({ tz: SYSTEM_TZ }), splat(), ConnectionManager.logFormat),\n transports: [\n new (transports as any).DailyRotateFile({\n filename: `logs/connections-%DATE%.log`,\n datePattern: 'YYYY-MM-DD-HH',\n zippedArchive: false,\n maxSize: '20m',\n maxFiles: '14d',\n level: 'info'\n }),\n new PubSubLogTransport({\n topic: 'connection-log'\n })\n ]\n })\n\n static async ready() {\n const CONNECTIONS = await Promise.all(\n (\n await getRepository(Connection).find({\n where: { active: true },\n relations: ['domain', 'edge', 'creator', 'updater']\n })\n ).map(async connection => {\n // 🔐 해결된 파라미터 사용\n const resolvedParams = await connection.getResolvedParameters()\n\n return {\n ...connection,\n params: resolvedParams\n }\n })\n )\n\n ConnectionManager.logger.info('Initializing ConnectionManager...')\n\n return await Promise.all(\n [...Object.keys(ConnectionManager.connectors), 'proxy-connector'].map(type => {\n const connector = type == 'proxy-connector' ? ProxyConnector.instance : ConnectionManager.getConnector(type)\n\n ConnectionManager.logger.info(`Connector '${type}' started to ready`)\n\n return connector\n .ready(\n CONNECTIONS.filter(connection => {\n if (type == 'proxy-connector') {\n return !!connection.edge\n } else {\n /* a connector that connects when first asked is not connected at boot */\n return !connection.edge && connection.type == type && !ConnectionManager.getConnector(type)?.connectsOnDemand\n }\n }) as any\n )\n .catch(error => {\n ConnectionManager.logger.error(error)\n })\n .then(() => {\n ConnectionManager.logger.info(`All connector for '${type}' ready`)\n })\n })\n ).then(() => {\n ConnectionManager.logger.info('ConnectionManager initialization done:')\n Object.keys(ConnectionManager.connections).forEach(key => {\n var connections = ConnectionManager.connections[key]\n ConnectionManager.logger.info('For domain(%s) : %s', key, JSON.stringify(Object.keys(connections)))\n })\n })\n }\n\n static registerConnector(type: string, connector: Connector) {\n ConnectionManager.connectors[type] = connector\n }\n\n static getConnector(type: string): Connector {\n return ConnectionManager.connectors[type]\n }\n\n static getConnectors(): { [connectorName: string]: Connector } {\n return {\n ...ConnectionManager.connectors\n }\n }\n\n static unregisterConnector(type: string) {\n delete ConnectionManager.connectors[type]\n }\n\n static getConnections() {\n return ConnectionManager.connections\n }\n\n static getEntities() {\n return ConnectionManager.entities\n }\n\n static getConnectionInstance(connection: Connection): any {\n const { domain, name } = connection\n return ConnectionManager.connections[domain.id]?.[name]\n }\n\n /**\n * 세션 사용 패턴 (RAII).\n *\n * connector 가 sessionExclusive=true 로 선언한 경우 connection.name 단위 mutex 로\n * 직렬화. 호출자는 acquireSessionPage / releasePage 의 lifecycle 을 신경 쓸 필요 없이\n * `withSession(connection, async page => { ... })` 형태로 사용하면 됨.\n *\n * stateless connector (sessionExclusive=false) 는 mutex 없이 즉시 진행.\n *\n * @param connection 도메인 instance (connection.type 에서 connector 조회)\n * @param fn page 를 받아 데이터 작업하는 async 함수\n */\n static async withSession<T>(connection: any, fn: (page: any) => Promise<T>): Promise<T> {\n const connector = ConnectionManager.getConnector(connection.type)\n const exclusive = !!connector?.sessionExclusive\n\n const run = async (): Promise<T> => {\n const page = await connection.acquireSessionPage()\n try {\n return await fn(page)\n } finally {\n // releasePage 가 page 인자를 받음 — 누락 시 내부의 page.close() 와\n // browser 풀 반환이 스킵되어 브라우저가 leak. 풀 고갈 → 정상 종료 hang 으로 이어짐.\n try {\n await connection.releasePage?.(page)\n } catch (e) {\n ConnectionManager.logger.warn(`releasePage failed for '${connection.name}':`, e as any)\n }\n }\n }\n\n if (!exclusive) return await run()\n\n // mutex: connection name 단위로 직렬화 (도메인 무관, 같은 외부 계정 중복 로그인 방지)\n const lockKey = connection.name\n const wasQueued = ConnectionManager.sessionLocks.has(lockKey)\n const prev = ConnectionManager.sessionLocks.get(lockKey) || Promise.resolve()\n let release!: () => void\n const next = new Promise<void>(r => (release = r))\n // chain: 이전 작업이 끝난 뒤 next 가 끝날 때까지 pending — 다음 대기자가 이 chain 으로 await\n const chain = prev.then(() => next)\n ConnectionManager.sessionLocks.set(lockKey, chain)\n\n // 큐 대기 진단 — 운영 중 \"왜 작업이 stall 되는가\" 추적용\n const waitStartedAt = wasQueued ? Date.now() : 0\n if (wasQueued) {\n ConnectionManager.logger.info(\n `[withSession] '${lockKey}' queued behind existing lock — waiting (domain='${connection.domain?.subdomain || connection.domainId}')`\n )\n }\n await prev\n if (wasQueued) {\n const waited = Date.now() - waitStartedAt\n ConnectionManager.logger.info(\n `[withSession] '${lockKey}' lock acquired after ${waited}ms wait`\n )\n }\n\n try {\n return await run()\n } finally {\n release()\n // 내가 latest 면 (이 chain 뒤로 새로 들어온 대기자 없음) cleanup\n if (ConnectionManager.sessionLocks.get(lockKey) === chain) {\n ConnectionManager.sessionLocks.delete(lockKey)\n }\n }\n }\n\n static async getConnectionInstanceByName(domain: Domain, name: string) {\n const connections = ConnectionManager.connections[domain.id]\n const connection = connections?.[name]\n\n if (!connection) {\n // 자식 도메인에 instance 가 없을 때의 세 가지 자동 처리 분기:\n //\n // (a) entity.__sharedFrom 있음 — SHARE 모드 inheritance\n // → 부모 도메인의 instance 를 그대로 lookup 해서 반환. 자식 도메인에는 instance 등록 안 함.\n // 같은 instance 가 부모·자식 모두에게 서비스 됨.\n //\n // (b) entity.__inheritedFrom 있음 — ISOLATE 모드 inheritance\n // → 자식 도메인 키 아래 새 instance 자동 생성. cookies/세션 격리.\n //\n // (c) entity.onDemand=true — 명시적 lazy 생성 (자식 자체 record 인 경우에도 적용)\n // → 자식 도메인 키 아래 새 instance 생성.\n //\n // 나머지: 자식 record 도 없고 inherit 도 안 되는 경우 → throw.\n try {\n const connectionEntity = await ConnectionManager.getConnectionEntityByName(domain, name)\n\n if (connectionEntity?.__sharedFrom) {\n // SHARE: 부모 instance 직접 사용\n const parentInstance = ConnectionManager.connections[connectionEntity.__sharedFrom]?.[name]\n if (parentInstance) return parentInstance\n throw `SHARE mode: parent instance for '${name}' (domain id '${connectionEntity.__sharedFrom}') not registered yet — startup ready() may have failed for parent`\n }\n\n const connectsOnDemand = !!(connectionEntity && ConnectionManager.connectors[connectionEntity.type]?.connectsOnDemand)\n if (connectionEntity?.onDemand || connectionEntity?.__inheritedFrom || connectsOnDemand) {\n const instance = await ConnectionManager.createOnDemandConnection(connectionEntity!)\n return instance\n } else if (connectionEntity) {\n // entity 는 찾았는데 instance 생성 trigger (onDemand/inherit) 없음 — 운영자가 record 자체 점검 필요\n throw `Connection '${name}' record exists but instance is not registered and no auto-create trigger (onDemand=false, no inheritance marker). Check whether parent record's active=true and ready() succeeded at startup.`\n } else {\n // entity 자체 못 찾음 — 도메인 트리 어디에도 record 없음\n throw `Connection '${name}' not found in domain '${domain.subdomain || domain.id}' or any ancestor — verify the Connection record exists at the running domain or any of its ancestors.`\n }\n } catch (error) {\n /* A connector that refused to connect (an on-demand connect) says why by its own error — it passes as it is,\n so the task above can name it. Only the lookup's own findings are worded here. */\n if (typeof error !== 'string') throw error\n throw `The connection with the given name(${name}) cannot be found: ${error}`\n }\n }\n\n return connection\n }\n\n static async getConnectionEntityByName(domain: Domain, name: string): Promise<Connection | null> {\n // 1. 현재 도메인에서 메모리 조회 (우선)\n const cachedEntity = ConnectionManager.entities[domain.id]?.[name]\n if (cachedEntity) {\n return cachedEntity\n }\n\n // 2. 현재 도메인에서 데이터베이스 조회 (우선)\n try {\n let connection = await getRepository(Connection).findOne({\n where: {\n domain: { id: domain.id },\n name: name\n },\n relations: ['domain', 'edge', 'creator', 'updater']\n })\n\n if (connection) {\n const resolvedParams = await connection.getResolvedParameters()\n connection.params = resolvedParams\n return connection\n }\n\n // 3. 현재 도메인에서 못 찾으면 부모 도메인에서 메모리 조회 - 안된다. connection정보를 수정해야 하므로 사용할 수 없다.\n // if (domain.parentId) {\n // const parentCachedEntity = ConnectionManager.entities[domain.parentId]?.[name]\n // if (parentCachedEntity) {\n // return parentCachedEntity\n // }\n // }\n\n // 4. ancestor 도메인 트리 fallback (closest-first walk)\n //\n // EnvVar inheritance 와 일관되게 모든 조상 도메인을 closest-first 로 탐색.\n // 예: SYSTEM → 시공사 → 프로젝트 트리에서 시나리오가 프로젝트 도메인에서 실행될 때\n // Connection record 가 SYSTEM 또는 시공사 어디에 있어도 찾아냄.\n //\n // 매칭된 ancestor 의 inheritanceMode 에 따라 두 갈래:\n // ISOLATE (default): 자식 도메인용 clone 생성. cookies/세션 격리, 자식 컨텍스트에서\n // EnvVar override 해소. __inheritedFrom marker 로 후속 자동 instance.\n // SHARE: 부모 entity 그대로 반환. params·세션·인스턴스 모두 부모 것 공유.\n // __sharedFrom marker 로 instance lookup 이 부모 도메인을 가리키게 함.\n //\n // 호환성: inheritanceMode 미지정(NULL) → connector default → 폴백 ISOLATE.\n // 기존 모든 Connection 은 이 column 추가 전 만들어졌으므로 NULL → ISOLATE = 기존 거동.\n const ancestorIds = await getDomainIdsWithAncestors(domain)\n // ancestorIds[0] = domain.id (이미 위 분기에서 시도), skip\n const searchedAncestors: string[] = []\n for (let i = 1; i < ancestorIds.length; i++) {\n const ancestorId = ancestorIds[i]\n searchedAncestors.push(ancestorId)\n const parentConn = await getRepository(Connection).findOne({\n where: {\n domain: { id: ancestorId },\n name: name\n },\n relations: ['domain', 'edge', 'creator', 'updater']\n })\n\n if (!parentConn) continue // 이 ancestor 에 없으면 다음 ancestor\n\n ConnectionManager.logger.info(\n `[inheritance] '${name}' inherited by domain '${domain.subdomain || domain.id}' ` +\n `from ancestor '${parentConn.domain?.subdomain || ancestorId}' ` +\n `(walked ${i} ancestor(s))`\n )\n\n const connectorDefault = ConnectionManager.connectors[parentConn.type]?.inheritanceMode\n const effectiveMode =\n parentConn.inheritanceMode || connectorDefault || ConnectionInheritanceMode.ISOLATE\n\n if (effectiveMode === ConnectionInheritanceMode.SHARE) {\n // SHARE — 부모 entity 그대로 반환 (mutation 최소화).\n const shared: any = parentConn\n shared.__sharedFrom = parentConn.domainId\n shared.params = await parentConn.getResolvedParameters()\n return shared\n }\n\n // ISOLATE (default) — clone + marker\n const inherited: any = Object.assign(\n Object.create(Object.getPrototypeOf(parentConn)),\n parentConn,\n {\n domain,\n domainId: domain.id,\n cookies: undefined,\n __inheritedFrom: parentConn.domainId\n }\n )\n inherited.params = await inherited.getResolvedParameters()\n return inherited\n }\n\n // 어느 ancestor 에서도 못 찾음 — 운영자가 어디까지 찾았는지 알 수 있도록 진단 로그\n if (searchedAncestors.length > 0) {\n ConnectionManager.logger.warn(\n `[inheritance] '${name}' not found at any ancestor of domain '${domain.subdomain || domain.id}' ` +\n `— searched: [${searchedAncestors.join(', ')}]`\n )\n }\n return null\n } catch (error) {\n ConnectionManager.logger.error(`Failed to get connection entity '${name}' from database:`, error)\n return null\n }\n }\n\n static getConnectionInstanceEntityByName(domain: Domain, name: string): any {\n const connection = ConnectionManager.entities[domain.id]?.[name]\n if (connection) {\n return connection\n }\n\n if (domain.parentId) {\n return ConnectionManager.entities[domain.parentId]?.[name]\n }\n }\n\n /**\n * Creates a connection on-demand and returns the instance.\n * @param connection - The connection entity to create\n * @returns The connection instance\n */\n static async createOnDemandConnection(connection: Connection): Promise<any> {\n try {\n // 커넥션 생성\n await connection.connect()\n\n ConnectionManager.logger.info(`On-demand connection '${connection.name}' created successfully`)\n return ConnectionManager.getConnectionInstance(connection)\n } catch (error) {\n ConnectionManager.logger.error(`Failed to create on-demand connection '${connection.name}':`, error)\n throw error\n }\n }\n\n /**\n * Disconnects an on-demand connection.\n * @param connection - The connection entity to disconnect\n */\n static async disconnectOnDemandConnection(connection: Connection): Promise<void> {\n try {\n await connection.disconnect()\n // ConnectionManager.removeConnectionInstance(connection)\n ConnectionManager.logger.info(`On-demand connection '${connection.name}' disconnected successfully`)\n } catch (error) {\n ConnectionManager.logger.error(`Failed to disconnect on-demand connection '${connection.name}':`, error)\n }\n }\n\n static getConnectionInstances(domain: Domain): { [connectionName: string]: any } {\n const connections = ConnectionManager.connections[domain.id]\n const parentConnections = domain.parentId && ConnectionManager.connections[domain.parentId]\n\n return {\n ...parentConnections,\n ...connections\n }\n }\n\n static getConnectionInstanceEntities(domain: Domain): { [connectionName: string]: any } {\n const connections = ConnectionManager.entities[domain.id]\n\n return {\n ...connections\n }\n }\n\n static addConnectionInstance(connection: Connection, instance: any) {\n const { domain, name } = connection\n\n var connections = ConnectionManager.connections[domain.id]\n if (!connections) {\n connections = ConnectionManager.connections[domain.id] = {}\n }\n\n var entities = ConnectionManager.entities[domain.id]\n if (!entities) {\n entities = ConnectionManager.entities[domain.id] = {}\n }\n\n connections[name] = instance\n entities[name] = connection\n\n ConnectionManager.publishState(connection, ConnectionStatus.CONNECTED)\n debug('add-connection', domain.subdomain, name)\n }\n\n static removeConnectionInstance(connection: Connection): any {\n const { domain, name } = connection\n var connections = ConnectionManager.connections[domain.id]\n var entities = ConnectionManager.entities[domain.id]\n\n var instance = connections?.[name]\n\n if (!connections || !instance) {\n debug('remove-connection', `'${name}' connection not found in domain '${domain.subdomain}'`)\n return\n }\n\n delete connections[name]\n delete entities[name]\n\n ConnectionManager.publishState(connection, ConnectionStatus.DISCONNECTED)\n debug('remove-connection', `'${name}' connection is removed from domain '${domain.subdomain}'`)\n\n return instance\n }\n\n private static async publishState(connection: Connection, state) {\n const { domain, id, name, description, type, edge } = connection\n\n pubsub.publish('connection-state', {\n connectionState: {\n domain,\n id,\n name,\n description,\n type,\n edge,\n state,\n timestamp: new Date()\n }\n })\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"connection-manager.js","sourceRoot":"","sources":["../../server/engine/connection-manager.ts"],"names":[],"mappings":"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","sourcesContent":["import moment from 'moment-timezone'\nimport { createLogger, format, transports } from 'winston'\n\nimport { Domain, getRepository, pubsub, PubSubLogTransport, getDomainIdsWithAncestors } from '@things-factory/shell'\n\nimport { Connection, ConnectionInheritanceMode, ConnectionStatus } from '../service'\nimport { Connector } from './types'\nimport { ProxyConnector } from './connector/proxy-connector'\n\nconst { combine, splat, printf, errors } = format\nconst debug = require('debug')('things-factory:integration-base:connections')\n\nfunction getSystemTimeZone() {\n try {\n const timeZone = Intl.DateTimeFormat().resolvedOptions().timeZone\n if (!timeZone) {\n throw new Error('Unable to resolve timeZone')\n }\n return timeZone\n } catch (e) {\n console.warn('Failed to get system timeZone, falling back to UTC.', e)\n return 'UTC'\n }\n}\n\nconst SYSTEM_TZ = getSystemTimeZone()\nconst systemTimestamp = format((info, opts: { tz?: string }) => {\n if (opts.tz) info.timestamp = moment().tz(opts.tz).format()\n return info\n})\n\nexport class ConnectionManager {\n private static connectors: { [propName: string]: Connector } = {}\n private static connections: { [domainId: string]: { [name: string]: any } } = {}\n private static entities = {}\n /**\n * Session 직렬화 mutex — connection name 단위 (도메인 무관 글로벌).\n * sessionExclusive connector 의 acquireSessionPage 동시 호출이 외부 세션을 서로\n * invalidate 하지 않도록 큐잉. release 호출 시 다음 대기자가 진행.\n */\n private static sessionLocks: Map<string, Promise<void>> = new Map()\n private static logFormat = printf(({ level, message, timestamp, stack }) => {\n return `${timestamp} ${level}: ${stack || message}`\n })\n\n public static logger = createLogger({\n format: combine(errors({ stack: true }), systemTimestamp({ tz: SYSTEM_TZ }), splat(), ConnectionManager.logFormat),\n transports: [\n new (transports as any).DailyRotateFile({\n filename: `logs/connections-%DATE%.log`,\n datePattern: 'YYYY-MM-DD-HH',\n zippedArchive: false,\n maxSize: '20m',\n maxFiles: '14d',\n level: 'info'\n }),\n new PubSubLogTransport({\n topic: 'connection-log'\n })\n ]\n })\n\n static async ready() {\n const CONNECTIONS = await Promise.all(\n (\n await getRepository(Connection).find({\n where: { active: true },\n relations: ['domain', 'edge', 'creator', 'updater']\n })\n ).map(async connection => {\n // 🔐 해결된 파라미터 사용\n const resolvedParams = await connection.getResolvedParameters()\n\n return {\n ...connection,\n params: resolvedParams\n }\n })\n )\n\n ConnectionManager.logger.info('Initializing ConnectionManager...')\n\n return await Promise.all(\n [...Object.keys(ConnectionManager.connectors), 'proxy-connector'].map(type => {\n const connector = type == 'proxy-connector' ? ProxyConnector.instance : ConnectionManager.getConnector(type)\n\n ConnectionManager.logger.info(`Connector '${type}' started to ready`)\n\n return connector\n .ready(\n CONNECTIONS.filter(connection => {\n if (type == 'proxy-connector') {\n return !!connection.edge\n } else {\n /* a connector that connects when first asked is not connected at boot */\n return !connection.edge && connection.type == type && !ConnectionManager.getConnector(type)?.connectsOnDemand\n }\n }) as any\n )\n .catch(error => {\n ConnectionManager.logger.error(error)\n })\n .then(() => {\n ConnectionManager.logger.info(`All connector for '${type}' ready`)\n })\n })\n ).then(() => {\n ConnectionManager.logger.info('ConnectionManager initialization done:')\n Object.keys(ConnectionManager.connections).forEach(key => {\n var connections = ConnectionManager.connections[key]\n ConnectionManager.logger.info('For domain(%s) : %s', key, JSON.stringify(Object.keys(connections)))\n })\n })\n }\n\n static registerConnector(type: string, connector: Connector) {\n ConnectionManager.connectors[type] = connector\n }\n\n static getConnector(type: string): Connector {\n return ConnectionManager.connectors[type]\n }\n\n static getConnectors(): { [connectorName: string]: Connector } {\n return {\n ...ConnectionManager.connectors\n }\n }\n\n static unregisterConnector(type: string) {\n delete ConnectionManager.connectors[type]\n }\n\n static getConnections() {\n return ConnectionManager.connections\n }\n\n static getEntities() {\n return ConnectionManager.entities\n }\n\n static getConnectionInstance(connection: Connection): any {\n const { domain, name } = connection\n return ConnectionManager.connections[domain.id]?.[name]\n }\n\n /**\n * 세션 사용 패턴 (RAII).\n *\n * connector 가 sessionExclusive=true 로 선언한 경우 connection.name 단위 mutex 로\n * 직렬화. 호출자는 acquireSessionPage / releasePage 의 lifecycle 을 신경 쓸 필요 없이\n * `withSession(connection, async page => { ... })` 형태로 사용하면 됨.\n *\n * stateless connector (sessionExclusive=false) 는 mutex 없이 즉시 진행.\n *\n * @param connection 도메인 instance (connection.type 에서 connector 조회)\n * @param fn page 를 받아 데이터 작업하는 async 함수\n */\n static async withSession<T>(connection: any, fn: (page: any) => Promise<T>): Promise<T> {\n const connector = ConnectionManager.getConnector(connection.type)\n const exclusive = !!connector?.sessionExclusive\n\n const run = async (): Promise<T> => {\n const page = await connection.acquireSessionPage()\n try {\n return await fn(page)\n } finally {\n // releasePage 가 page 인자를 받음 — 누락 시 내부의 page.close() 와\n // browser 풀 반환이 스킵되어 브라우저가 leak. 풀 고갈 → 정상 종료 hang 으로 이어짐.\n try {\n await connection.releasePage?.(page)\n } catch (e) {\n ConnectionManager.logger.warn(`releasePage failed for '${connection.name}':`, e as any)\n }\n }\n }\n\n if (!exclusive) return await run()\n\n // mutex: connection name 단위로 직렬화 (도메인 무관, 같은 외부 계정 중복 로그인 방지)\n const lockKey = connection.name\n const wasQueued = ConnectionManager.sessionLocks.has(lockKey)\n const prev = ConnectionManager.sessionLocks.get(lockKey) || Promise.resolve()\n let release!: () => void\n const next = new Promise<void>(r => (release = r))\n // chain: 이전 작업이 끝난 뒤 next 가 끝날 때까지 pending — 다음 대기자가 이 chain 으로 await\n const chain = prev.then(() => next)\n ConnectionManager.sessionLocks.set(lockKey, chain)\n\n // 큐 대기 진단 — 운영 중 \"왜 작업이 stall 되는가\" 추적용\n const waitStartedAt = wasQueued ? Date.now() : 0\n if (wasQueued) {\n ConnectionManager.logger.info(\n `[withSession] '${lockKey}' queued behind existing lock — waiting (domain='${connection.domain?.subdomain || connection.domainId}')`\n )\n }\n await prev\n if (wasQueued) {\n const waited = Date.now() - waitStartedAt\n ConnectionManager.logger.info(\n `[withSession] '${lockKey}' lock acquired after ${waited}ms wait`\n )\n }\n\n try {\n return await run()\n } finally {\n release()\n // 내가 latest 면 (이 chain 뒤로 새로 들어온 대기자 없음) cleanup\n if (ConnectionManager.sessionLocks.get(lockKey) === chain) {\n ConnectionManager.sessionLocks.delete(lockKey)\n }\n }\n }\n\n static async getConnectionInstanceByName(domain: Domain, name: string) {\n const connections = ConnectionManager.connections[domain.id]\n const connection = connections?.[name]\n\n if (!connection) {\n // 자식 도메인에 instance 가 없을 때의 세 가지 자동 처리 분기:\n //\n // (a) entity.__sharedFrom 있음 — SHARE 모드 inheritance\n // → 부모 도메인의 instance 를 그대로 lookup 해서 반환. 자식 도메인에는 instance 등록 안 함.\n // 같은 instance 가 부모·자식 모두에게 서비스 됨.\n //\n // (b) entity.__inheritedFrom 있음 — ISOLATE 모드 inheritance\n // → 자식 도메인 키 아래 새 instance 자동 생성. cookies/세션 격리.\n //\n // (c) entity.onDemand=true — 명시적 lazy 생성 (자식 자체 record 인 경우에도 적용)\n // → 자식 도메인 키 아래 새 instance 생성.\n //\n // 나머지: 자식 record 도 없고 inherit 도 안 되는 경우 → throw.\n try {\n const connectionEntity = await ConnectionManager.getConnectionEntityByName(domain, name)\n\n if (connectionEntity?.__sharedFrom) {\n // SHARE: 부모 instance 직접 사용\n const parentInstance = ConnectionManager.connections[connectionEntity.__sharedFrom]?.[name]\n if (parentInstance) return parentInstance\n throw `SHARE mode: parent instance for '${name}' (domain id '${connectionEntity.__sharedFrom}') not registered yet — startup ready() may have failed for parent`\n }\n\n const connectsOnDemand = !!(connectionEntity && ConnectionManager.connectors[connectionEntity.type]?.connectsOnDemand)\n if (connectionEntity?.onDemand || connectionEntity?.__inheritedFrom || connectsOnDemand) {\n const instance = await ConnectionManager.createOnDemandConnection(connectionEntity!)\n return instance\n } else if (connectionEntity) {\n // entity 는 찾았는데 instance 생성 trigger (onDemand/inherit) 없음 — 운영자가 record 자체 점검 필요\n throw `Connection '${name}' record exists but instance is not registered and no auto-create trigger (onDemand=false, no inheritance marker). Check whether parent record's active=true and ready() succeeded at startup.`\n } else {\n // entity 자체 못 찾음 — 도메인 트리 어디에도 record 없음\n throw `Connection '${name}' not found in domain '${domain.subdomain || domain.id}' or any ancestor — verify the Connection record exists at the running domain or any of its ancestors.`\n }\n } catch (error) {\n /* A connector that refused to connect (an on-demand connect) says why by its own error — it passes as it is,\n so the task above can name it. Only the lookup's own findings are worded here. */\n if (typeof error !== 'string') throw error\n throw `The connection with the given name(${name}) cannot be found: ${error}`\n }\n }\n\n return connection\n }\n\n static async getConnectionEntityByName(domain: Domain, name: string): Promise<Connection | null> {\n // 1. 현재 도메인에서 메모리 조회 (우선)\n const cachedEntity = ConnectionManager.entities[domain.id]?.[name]\n if (cachedEntity) {\n return cachedEntity\n }\n\n // 2. 현재 도메인에서 데이터베이스 조회 (우선)\n try {\n let connection = await getRepository(Connection).findOne({\n where: {\n domain: { id: domain.id },\n name: name\n },\n relations: ['domain', 'edge', 'creator', 'updater']\n })\n\n if (connection) {\n const resolvedParams = await connection.getResolvedParameters()\n connection.params = resolvedParams\n return connection\n }\n\n // 3. 현재 도메인에서 못 찾으면 부모 도메인에서 메모리 조회 - 안된다. connection정보를 수정해야 하므로 사용할 수 없다.\n // if (domain.parentId) {\n // const parentCachedEntity = ConnectionManager.entities[domain.parentId]?.[name]\n // if (parentCachedEntity) {\n // return parentCachedEntity\n // }\n // }\n\n // 4. ancestor 도메인 트리 fallback (closest-first walk)\n //\n // EnvVar inheritance 와 일관되게 모든 조상 도메인을 closest-first 로 탐색.\n // 예: SYSTEM → 시공사 → 프로젝트 트리에서 시나리오가 프로젝트 도메인에서 실행될 때\n // Connection record 가 SYSTEM 또는 시공사 어디에 있어도 찾아냄.\n //\n // 매칭된 ancestor 의 inheritanceMode 에 따라 두 갈래:\n // ISOLATE (default): 자식 도메인용 clone 생성. cookies/세션 격리, 자식 컨텍스트에서\n // EnvVar override 해소. __inheritedFrom marker 로 후속 자동 instance.\n // SHARE: 부모 entity 그대로 반환. params·세션·인스턴스 모두 부모 것 공유.\n // __sharedFrom marker 로 instance lookup 이 부모 도메인을 가리키게 함.\n //\n // 호환성: inheritanceMode 미지정(NULL) → connector default → 폴백 ISOLATE.\n // 기존 모든 Connection 은 이 column 추가 전 만들어졌으므로 NULL → ISOLATE = 기존 거동.\n const ancestorIds = await getDomainIdsWithAncestors(domain)\n // ancestorIds[0] = domain.id (이미 위 분기에서 시도), skip\n const searchedAncestors: string[] = []\n for (let i = 1; i < ancestorIds.length; i++) {\n const ancestorId = ancestorIds[i]\n searchedAncestors.push(ancestorId)\n const parentConn = await getRepository(Connection).findOne({\n where: {\n domain: { id: ancestorId },\n name: name\n },\n relations: ['domain', 'edge', 'creator', 'updater']\n })\n\n if (!parentConn) continue // 이 ancestor 에 없으면 다음 ancestor\n\n ConnectionManager.logger.info(\n `[inheritance] '${name}' inherited by domain '${domain.subdomain || domain.id}' ` +\n `from ancestor '${parentConn.domain?.subdomain || ancestorId}' ` +\n `(walked ${i} ancestor(s))`\n )\n\n const connectorDefault = ConnectionManager.connectors[parentConn.type]?.inheritanceMode\n const effectiveMode =\n parentConn.inheritanceMode || connectorDefault || ConnectionInheritanceMode.ISOLATE\n\n if (effectiveMode === ConnectionInheritanceMode.SHARE) {\n // SHARE — 부모 entity 그대로 반환 (mutation 최소화).\n const shared: any = parentConn\n shared.__sharedFrom = parentConn.domainId\n shared.params = await parentConn.getResolvedParameters()\n return shared\n }\n\n // ISOLATE (default) — clone + marker\n const inherited: any = Object.assign(\n Object.create(Object.getPrototypeOf(parentConn)),\n parentConn,\n {\n domain,\n domainId: domain.id,\n cookies: undefined,\n __inheritedFrom: parentConn.domainId\n }\n )\n inherited.params = await inherited.getResolvedParameters()\n return inherited\n }\n\n // 어느 ancestor 에서도 못 찾음 — 운영자가 어디까지 찾았는지 알 수 있도록 진단 로그\n if (searchedAncestors.length > 0) {\n ConnectionManager.logger.warn(\n `[inheritance] '${name}' not found at any ancestor of domain '${domain.subdomain || domain.id}' ` +\n `— searched: [${searchedAncestors.join(', ')}]`\n )\n }\n return null\n } catch (error) {\n ConnectionManager.logger.error(`Failed to get connection entity '${name}' from database:`, error)\n return null\n }\n }\n\n static getConnectionInstanceEntityByName(domain: Domain, name: string): any {\n const connection = ConnectionManager.entities[domain.id]?.[name]\n if (connection) {\n return connection\n }\n\n if (domain.parentId) {\n return ConnectionManager.entities[domain.parentId]?.[name]\n }\n }\n\n /**\n * Creates a connection on-demand and returns the instance.\n * @param connection - The connection entity to create\n * @returns The connection instance\n */\n static async createOnDemandConnection(connection: Connection): Promise<any> {\n try {\n // 커넥션 생성\n await connection.connect()\n\n ConnectionManager.logger.info(`On-demand connection '${connection.name}' created successfully`)\n return ConnectionManager.getConnectionInstance(connection)\n } catch (error) {\n ConnectionManager.logger.error(`Failed to create on-demand connection '${connection.name}':`, error)\n throw error\n }\n }\n\n /**\n * Disconnects an on-demand connection.\n * @param connection - The connection entity to disconnect\n */\n static async disconnectOnDemandConnection(connection: Connection): Promise<void> {\n try {\n await connection.disconnect()\n // ConnectionManager.removeConnectionInstance(connection)\n ConnectionManager.logger.info(`On-demand connection '${connection.name}' disconnected successfully`)\n } catch (error) {\n ConnectionManager.logger.error(`Failed to disconnect on-demand connection '${connection.name}':`, error)\n }\n }\n\n static getConnectionInstances(domain: Domain): { [connectionName: string]: any } {\n const connections = ConnectionManager.connections[domain.id]\n const parentConnections = domain.parentId && ConnectionManager.connections[domain.parentId]\n\n return {\n ...parentConnections,\n ...connections\n }\n }\n\n static getConnectionInstanceEntities(domain: Domain): { [connectionName: string]: any } {\n const connections = ConnectionManager.entities[domain.id]\n\n return {\n ...connections\n }\n }\n\n static addConnectionInstance(connection: Connection, instance: any) {\n const { domain, name } = connection\n\n var connections = ConnectionManager.connections[domain.id]\n if (!connections) {\n connections = ConnectionManager.connections[domain.id] = {}\n }\n\n var entities = ConnectionManager.entities[domain.id]\n if (!entities) {\n entities = ConnectionManager.entities[domain.id] = {}\n }\n\n connections[name] = instance\n entities[name] = connection\n\n ConnectionManager.publishState(connection, ConnectionStatus.CONNECTED)\n debug('add-connection', domain.subdomain, name)\n }\n\n static removeConnectionInstance(connection: Connection): any {\n const { domain, name } = connection\n var connections = ConnectionManager.connections[domain.id]\n var entities = ConnectionManager.entities[domain.id]\n\n var instance = connections?.[name]\n\n if (!connections || !instance) {\n debug('remove-connection', `'${name}' connection not found in domain '${domain.subdomain}'`)\n return\n }\n\n delete connections[name]\n delete entities[name]\n\n ConnectionManager.publishState(connection, ConnectionStatus.DISCONNECTED)\n debug('remove-connection', `'${name}' connection is removed from domain '${domain.subdomain}'`)\n\n return instance\n }\n\n private static async publishState(connection: Connection, state) {\n const { domain, id, name, description, type, edge } = connection\n\n pubsub.publish('connection-state', {\n connectionState: {\n domain,\n id,\n name,\n description,\n type,\n edge,\n state,\n timestamp: new Date()\n }\n })\n }\n}\n"]}
|
|
@@ -8,5 +8,4 @@ export * from './analyzer/analyze-integration';
|
|
|
8
8
|
export * from './edge-client';
|
|
9
9
|
export * from './resource-pool';
|
|
10
10
|
export { HeadlessConnector } from './connector/headless-connector';
|
|
11
|
-
export { lookupDomainEnvVar } from '../utils/domain-inheritance';
|
|
12
11
|
export { Connector, Context, TaskHandler } from './types';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.HeadlessConnector = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
require("./connector/index.js");
|
|
6
6
|
require("./task/index.js");
|
|
@@ -13,6 +13,4 @@ tslib_1.__exportStar(require("./edge-client"), exports);
|
|
|
13
13
|
tslib_1.__exportStar(require("./resource-pool"), exports);
|
|
14
14
|
var headless_connector_1 = require("./connector/headless-connector");
|
|
15
15
|
Object.defineProperty(exports, "HeadlessConnector", { enumerable: true, get: function () { return headless_connector_1.HeadlessConnector; } });
|
|
16
|
-
var domain_inheritance_1 = require("../utils/domain-inheritance");
|
|
17
|
-
Object.defineProperty(exports, "lookupDomainEnvVar", { enumerable: true, get: function () { return domain_inheritance_1.lookupDomainEnvVar; } });
|
|
18
16
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/engine/index.ts"],"names":[],"mappings":";;;;AAAA,gCAA6B;AAC7B,2BAAwB;AAExB,+DAAoC;AACpC,8DAAmC;AACnC,4DAAiC;AACjC,0DAA+B;AAC/B,yEAA8C;AAC9C,wDAA6B;AAC7B,0DAA+B;AAC/B,qEAAkE;AAAzD,uHAAA,iBAAiB,OAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../server/engine/index.ts"],"names":[],"mappings":";;;;AAAA,gCAA6B;AAC7B,2BAAwB;AAExB,+DAAoC;AACpC,8DAAmC;AACnC,4DAAiC;AACjC,0DAA+B;AAC/B,yEAA8C;AAC9C,wDAA6B;AAC7B,0DAA+B;AAC/B,qEAAkE;AAAzD,uHAAA,iBAAiB,OAAA","sourcesContent":["import './connector/index.js'\nimport './task/index.js'\n\nexport * from './connection-manager'\nexport * from './evaluate-template'\nexport * from './scenario-engine'\nexport * from './task-registry'\nexport * from './analyzer/analyze-integration'\nexport * from './edge-client'\nexport * from './resource-pool'\nexport { HeadlessConnector } from './connector/headless-connector'\n\nexport { Connector, Context, TaskHandler } from './types'\n"]}
|
|
@@ -8,7 +8,6 @@ const shell_1 = require("@things-factory/shell");
|
|
|
8
8
|
const connection_manager_1 = require("../../engine/connection-manager");
|
|
9
9
|
const connection_1 = require("./connection");
|
|
10
10
|
const connection_type_1 = require("./connection-type");
|
|
11
|
-
const domain_inheritance_1 = require("../../utils/domain-inheritance");
|
|
12
11
|
const connection_secrets_1 = require("./connection-secrets");
|
|
13
12
|
const connection_env_vars_1 = require("./connection-env-vars");
|
|
14
13
|
/**
|
|
@@ -128,7 +127,7 @@ let ConnectionMutation = class ConnectionMutation {
|
|
|
128
127
|
const { domain } = context.state;
|
|
129
128
|
var repository = (0, shell_1.getRepository)(connection_1.Connection);
|
|
130
129
|
// ancestor 도메인을 closest-first 로 순회하여 first hit 사용
|
|
131
|
-
const domainIds = await (0,
|
|
130
|
+
const domainIds = await (0, shell_1.getDomainIdsWithAncestors)(domain);
|
|
132
131
|
var connection = null;
|
|
133
132
|
for (const did of domainIds) {
|
|
134
133
|
connection = await repository.findOne({
|
|
@@ -162,7 +161,7 @@ let ConnectionMutation = class ConnectionMutation {
|
|
|
162
161
|
const { domain } = context.state;
|
|
163
162
|
var repository = (0, shell_1.getRepository)(connection_1.Connection);
|
|
164
163
|
// ancestor 도메인을 closest-first 로 순회하여 first hit 사용
|
|
165
|
-
const domainIds = await (0,
|
|
164
|
+
const domainIds = await (0, shell_1.getDomainIdsWithAncestors)(domain);
|
|
166
165
|
var connection = null;
|
|
167
166
|
for (const did of domainIds) {
|
|
168
167
|
connection = await repository.findOne({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-mutation.js","sourceRoot":"","sources":["../../../server/service/connection/connection-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Directive, Mutation, Resolver, UseMiddleware } from 'type-graphql'\nimport { In } from 'typeorm'\n\nimport { getRepository, Refusal, SpeakRefusals } from '@things-factory/shell'\n\nimport { ConnectionManager } from '../../engine/connection-manager'\nimport { Connection, ConnectionStatus } from './connection'\nimport { ConnectionPatch, NewConnection } from './connection-type'\nimport { getDomainIdsWithAncestors } from '../../utils/domain-inheritance'\nimport { keepStoredSecrets, refuseSecretParams, withoutSecretsOf } from './connection-secrets'\nimport { carryConnectionEnvVars } from './connection-env-vars'\n\n/**\n * The params a write stores (ADR-0112): a secret the caller sends is refused, a secret the caller\n * leaves out is kept from the stored row.\n *\n * A write that changes the connector type keeps none of the old type's secrets. They were secrets\n * under the old type's spec; the new type may not declare them, and then reading would show them.\n * When the old type is not registered here nobody can say which were secret, so none of its params\n * are carried over.\n */\nfunction paramsToStore(written: Partial<Connection>, stored?: Connection) {\n const type = written.type ?? stored?.type\n const name = written.name ?? stored?.name\n const typeChanged = Boolean(stored && written.type && written.type !== stored.type)\n\n if (written.params === undefined) {\n return typeChanged ? { params: withoutSecretsOf(stored.type, stored.params) } : {}\n }\n\n refuseSecretParams(type, name, written.params)\n return { params: typeChanged ? written.params : keepStoredSecrets(type, written.params, stored?.params) }\n}\n\n/**\n * A write names an existing row only through this: the row of that id or name **in the request's\n * domain**. `save` writes by primary key, so an id from another domain left in the object would\n * overwrite that domain's row - the lookup alone does not stop it.\n */\nfunction notInThisDomain(connection: string) {\n return new Refusal(\n 'connection-not-in-domain',\n { connection },\n `There is no connection \"${connection}\" in this domain.`\n )\n}\n\n@Resolver(Connection)\n@UseMiddleware(SpeakRefusals)\nexport class ConnectionMutation {\n @Directive('@transaction')\n @Directive(\n '@privilege(category: \"connection\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)'\n )\n @Mutation(returns => Connection, { description: 'Creates a new connection.' })\n async createConnection(\n @Arg('connection') connection: NewConnection,\n @Ctx() context: ResolverContext\n ): Promise<Connection> {\n const { domain, user, tx } = context.state\n\n return await tx.getRepository(Connection).save({\n ...connection,\n ...paramsToStore(connection),\n domain,\n creator: user,\n updater: user\n })\n }\n\n @Directive('@transaction')\n @Directive(\n '@privilege(category: \"connection\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)'\n )\n @Mutation(returns => Connection, { description: 'Updates an existing connection.' })\n async updateConnection(\n @Arg('name') name: string,\n @Arg('patch') patch: ConnectionPatch,\n @Ctx() context: ResolverContext\n ): Promise<Connection> {\n const { domain, user, tx } = context.state\n\n const repository = tx.getRepository(Connection)\n const connection = await repository.findOne({\n where: { domain: { id: domain.id }, name }\n })\n\n if (!connection) {\n throw notInThisDomain(name)\n }\n\n if (patch.name && patch.name !== connection.name) {\n await carryConnectionEnvVars(tx, domain, connection.name, patch.name)\n }\n\n return await repository.save({\n ...connection,\n ...patch,\n ...paramsToStore(patch, connection),\n id: connection.id,\n updater: user\n })\n }\n\n @Directive('@transaction')\n @Directive(\n '@privilege(category: \"connection\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)'\n )\n @Mutation(returns => [Connection], { description: 'Updates multiple connections at once.' })\n async updateMultipleConnection(\n @Arg('patches', type => [ConnectionPatch]) patches: ConnectionPatch[],\n @Ctx() context: ResolverContext\n ): Promise<Connection[]> {\n const { domain, user, tx } = context.state\n\n let results = []\n const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')\n const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')\n const connectionRepo = tx.getRepository(Connection)\n\n if (_createRecords.length > 0) {\n for (let i = 0; i < _createRecords.length; i++) {\n /* A new row: an id it carries would make `save` overwrite the row of that id, wherever it is. */\n const { id, ...newRecord } = _createRecords[i]\n\n const result = await connectionRepo.save({\n ...newRecord,\n ...paramsToStore(newRecord),\n domain,\n creator: user,\n updater: user\n })\n\n results.push({ ...result, cuFlag: '+' })\n }\n }\n\n if (_updateRecords.length > 0) {\n for (let i = 0; i < _updateRecords.length; i++) {\n const newRecord = _updateRecords[i]\n const connection = await connectionRepo.findOneBy({ id: newRecord.id, domain: { id: domain.id } })\n\n if (!connection) {\n throw notInThisDomain(newRecord.name || newRecord.id)\n }\n\n if (newRecord.name && newRecord.name !== connection.name) {\n await carryConnectionEnvVars(tx, domain, connection.name, newRecord.name)\n }\n\n const result = await connectionRepo.save({\n ...connection,\n ...newRecord,\n ...paramsToStore(newRecord, connection),\n id: connection.id,\n updater: user\n })\n\n results.push({ ...result, cuFlag: 'M' })\n }\n }\n\n return results\n }\n\n @Directive('@transaction')\n @Directive(\n '@privilege(category: \"connection\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)'\n )\n @Mutation(returns => Boolean, { description: 'Deletes a single connection by its name.' })\n async deleteConnection(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, tx } = context.state\n\n await tx.getRepository(Connection).delete({ domain: { id: domain.id }, name })\n return true\n }\n\n @Directive('@transaction')\n @Directive(\n '@privilege(category: \"connection\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)'\n )\n @Mutation(returns => Boolean, { description: 'Deletes multiple connections by their names.' })\n async deleteConnections(\n @Arg('names', type => [String]) names: string[],\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, tx } = context.state\n\n await tx.getRepository(Connection).delete({\n domain: { id: domain.id },\n name: In(names)\n })\n\n return true\n }\n\n @Directive('@transaction')\n @Directive(\n '@privilege(category: \"connection\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)'\n )\n @Mutation(returns => Connection, { description: 'Establishes a live connection to a configured endpoint.' })\n async connectConnection(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<Connection> {\n const { domain } = context.state\n var repository = getRepository(Connection)\n\n // ancestor 도메인을 closest-first 로 순회하여 first hit 사용\n const domainIds = await getDomainIdsWithAncestors(domain)\n var connection: Connection | null = null\n for (const did of domainIds) {\n connection = await repository.findOne({\n where: { domain: { id: did }, name },\n relations: ['domain', 'edge']\n })\n if (connection) break\n }\n\n if (!connection) {\n throw new Error(`Connection with name '${name}' not found`)\n }\n\n /* 상속 및 on-demand 연결에서 connection.domain 과 다를 수 있음 */\n if (connection.domain.id !== domain.id) {\n connection.domain = domain\n await connection.connect()\n /* on-demand 연결인 경우에 connection을 저장하지 말아야 한다. */\n } else {\n await connection.connect()\n await repository.save(connection)\n }\n\n return {\n ...connection,\n state: ConnectionManager.getConnectionInstance(connection)\n ? ConnectionStatus.CONNECTED\n : ConnectionStatus.DISCONNECTED\n } as Connection\n }\n\n @Directive('@transaction')\n @Directive(\n '@privilege(category: \"connection\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)'\n )\n @Mutation(returns => Connection, { description: 'Terminates a live connection.' })\n async disconnectConnection(@Arg('name') name: string, @Ctx() context: ResolverContext) {\n const { domain } = context.state\n\n var repository = getRepository(Connection)\n\n // ancestor 도메인을 closest-first 로 순회하여 first hit 사용\n const domainIds = await getDomainIdsWithAncestors(domain)\n var connection: Connection | null = null\n for (const did of domainIds) {\n connection = await repository.findOne({\n where: { domain: { id: did }, name },\n relations: ['domain', 'edge']\n })\n if (connection) break\n }\n\n if (!connection) {\n throw new Error(`Connection with name '${name}' not found`)\n }\n\n /* 상속 및 on-demand 연결에서 connection.domain 과 다를 수 있음 */\n\n /* 상속 및 on-demand 연결에서 connection.domain 과 다를 수 있음 */\n if (connection.domain.id !== domain.id) {\n connection.domain = domain\n await connection.disconnect()\n\n /* on-demand 연결인 경우에 connection을 저장하지 말아야 한다. */\n } else {\n await connection.disconnect()\n await repository.save(connection)\n }\n\n return {\n ...connection,\n state: ConnectionManager.getConnectionInstance(connection)\n ? ConnectionStatus.CONNECTED\n : ConnectionStatus.DISCONNECTED\n }\n }\n\n @Directive('@transaction')\n @Directive(\n '@privilege(category: \"connection\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)'\n )\n @Mutation(returns => Boolean, {\n description: 'Imports multiple connections. Can overwrite existing connections if IDs or names match.'\n })\n async importConnections(\n @Arg('connections', type => [ConnectionPatch]) connections: Connection[],\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { tx, domain, user } = context.state\n\n const repository = tx.getRepository(Connection)\n\n await Promise.all(\n connections.map(async (connection: Connection) => {\n const { id, name } = connection\n\n if (id) {\n const sameId = await repository.findOneBy({ id })\n\n if (sameId) {\n if (sameId.domainId != domain.id) {\n throw `Connection with id '${id}:${name}' is already taken by another domain`\n }\n\n const sameName = await repository.findOneBy({ domain: { id: domain.id }, name })\n if (sameName && sameName.id != id) {\n throw `Connection with name '${name}' is already taken by another connection`\n }\n\n await repository.save({\n ...sameId,\n ...connection,\n ...paramsToStore(connection, sameId),\n domain,\n updater: user\n })\n\n return\n }\n }\n\n await repository.save({\n ...connection,\n ...paramsToStore(connection),\n domain,\n updater: user,\n creator: user\n })\n })\n )\n\n return true\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"connection-mutation.js","sourceRoot":"","sources":["../../../server/service/connection/connection-mutation.ts"],"names":[],"mappings":";;;;AAAA,+CAAqF;AACrF,qCAA4B;AAE5B,iDAAwG;AAExG,wEAAmE;AACnE,6CAA2D;AAC3D,uDAAkE;AAClE,6DAA8F;AAC9F,+DAA8D;AAE9D;;;;;;;;GAQG;AACH,SAAS,aAAa,CAAC,OAA4B,EAAE,MAAmB;IACtE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,MAAM,EAAE,IAAI,CAAA;IACzC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,MAAM,EAAE,IAAI,CAAA;IACzC,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,CAAC,CAAA;IAEnF,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QACjC,OAAO,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,IAAA,qCAAgB,EAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;IACpF,CAAC;IAED,IAAA,uCAAkB,EAAC,IAAI,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAA;IAC9C,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAA,sCAAiB,EAAC,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAA;AAC3G,CAAC;AAED;;;;GAIG;AACH,SAAS,eAAe,CAAC,UAAkB;IACzC,OAAO,IAAI,eAAO,CAChB,0BAA0B,EAC1B,EAAE,UAAU,EAAE,EACd,2BAA2B,UAAU,mBAAmB,CACzD,CAAA;AACH,CAAC;AAIM,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAMvB,AAAN,KAAK,CAAC,gBAAgB,CACD,UAAyB,EACrC,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAE1C,OAAO,MAAM,EAAE,CAAC,aAAa,CAAC,uBAAU,CAAC,CAAC,IAAI,CAAC;YAC7C,GAAG,UAAU;YACb,GAAG,aAAa,CAAC,UAAU,CAAC;YAC5B,MAAM;YACN,OAAO,EAAE,IAAI;YACb,OAAO,EAAE,IAAI;SACd,CAAC,CAAA;IACJ,CAAC;IAOK,AAAN,KAAK,CAAC,gBAAgB,CACP,IAAY,EACX,KAAsB,EAC7B,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAE1C,MAAM,UAAU,GAAG,EAAE,CAAC,aAAa,CAAC,uBAAU,CAAC,CAAA;QAC/C,MAAM,UAAU,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC;YAC1C,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE;SAC3C,CAAC,CAAA;QAEF,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,eAAe,CAAC,IAAI,CAAC,CAAA;QAC7B,CAAC;QAED,IAAI,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI,EAAE,CAAC;YACjD,MAAM,IAAA,4CAAsB,EAAC,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAA;QACvE,CAAC;QAED,OAAO,MAAM,UAAU,CAAC,IAAI,CAAC;YAC3B,GAAG,UAAU;YACb,GAAG,KAAK;YACR,GAAG,aAAa,CAAC,KAAK,EAAE,UAAU,CAAC;YACnC,EAAE,EAAE,UAAU,CAAC,EAAE;YACjB,OAAO,EAAE,IAAI;SACd,CAAC,CAAA;IACJ,CAAC;IAOK,AAAN,KAAK,CAAC,wBAAwB,CACe,OAA0B,EAC9D,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAE1C,IAAI,OAAO,GAAG,EAAE,CAAA;QAChB,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAU,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,CAAA;QACzF,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,KAAU,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,GAAG,CAAC,CAAA;QACzF,MAAM,cAAc,GAAG,EAAE,CAAC,aAAa,CAAC,uBAAU,CAAC,CAAA;QAEnD,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC/C,iGAAiG;gBACjG,MAAM,EAAE,EAAE,EAAE,GAAG,SAAS,EAAE,GAAG,cAAc,CAAC,CAAC,CAAC,CAAA;gBAE9C,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC;oBACvC,GAAG,SAAS;oBACZ,GAAG,aAAa,CAAC,SAAS,CAAC;oBAC3B,MAAM;oBACN,OAAO,EAAE,IAAI;oBACb,OAAO,EAAE,IAAI;iBACd,CAAC,CAAA;gBAEF,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;YAC1C,CAAC;QACH,CAAC;QAED,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC/C,MAAM,SAAS,GAAG,cAAc,CAAC,CAAC,CAAC,CAAA;gBACnC,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;gBAElG,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,MAAM,eAAe,CAAC,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC,EAAE,CAAC,CAAA;gBACvD,CAAC;gBAED,IAAI,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI,EAAE,CAAC;oBACzD,MAAM,IAAA,4CAAsB,EAAC,EAAE,EAAE,MAAM,EAAE,UAAU,CAAC,IAAI,EAAE,SAAS,CAAC,IAAI,CAAC,CAAA;gBAC3E,CAAC;gBAED,MAAM,MAAM,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC;oBACvC,GAAG,UAAU;oBACb,GAAG,SAAS;oBACZ,GAAG,aAAa,CAAC,SAAS,EAAE,UAAU,CAAC;oBACvC,EAAE,EAAE,UAAU,CAAC,EAAE;oBACjB,OAAO,EAAE,IAAI;iBACd,CAAC,CAAA;gBAEF,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAA;YAC1C,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAA;IAChB,CAAC;IAOK,AAAN,KAAK,CAAC,gBAAgB,CAAc,IAAY,EAAS,OAAwB;QAC/E,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAEpC,MAAM,EAAE,CAAC,aAAa,CAAC,uBAAU,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;QAC9E,OAAO,IAAI,CAAA;IACb,CAAC;IAOK,AAAN,KAAK,CAAC,iBAAiB,CACW,KAAe,EACxC,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAEpC,MAAM,EAAE,CAAC,aAAa,CAAC,uBAAU,CAAC,CAAC,MAAM,CAAC;YACxC,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE;YACzB,IAAI,EAAE,IAAA,YAAE,EAAC,KAAK,CAAC;SAChB,CAAC,CAAA;QAEF,OAAO,IAAI,CAAA;IACb,CAAC;IAOK,AAAN,KAAK,CAAC,iBAAiB,CAAc,IAAY,EAAS,OAAwB;QAChF,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAChC,IAAI,UAAU,GAAG,IAAA,qBAAa,EAAC,uBAAU,CAAC,CAAA;QAE1C,kDAAkD;QAClD,MAAM,SAAS,GAAG,MAAM,IAAA,iCAAyB,EAAC,MAAM,CAAC,CAAA;QACzD,IAAI,UAAU,GAAsB,IAAI,CAAA;QACxC,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;YAC5B,UAAU,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC;gBACpC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE;gBACpC,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC;aAC9B,CAAC,CAAA;YACF,IAAI,UAAU;gBAAE,MAAK;QACvB,CAAC;QAED,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,aAAa,CAAC,CAAA;QAC7D,CAAC;QAED,qDAAqD;QACrD,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,EAAE,CAAC;YACvC,UAAU,CAAC,MAAM,GAAG,MAAM,CAAA;YAC1B,MAAM,UAAU,CAAC,OAAO,EAAE,CAAA;YAC1B,gDAAgD;QAClD,CAAC;aAAM,CAAC;YACN,MAAM,UAAU,CAAC,OAAO,EAAE,CAAA;YAC1B,MAAM,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QACnC,CAAC;QAED,OAAO;YACL,GAAG,UAAU;YACb,KAAK,EAAE,sCAAiB,CAAC,qBAAqB,CAAC,UAAU,CAAC;gBACxD,CAAC,CAAC,6BAAgB,CAAC,SAAS;gBAC5B,CAAC,CAAC,6BAAgB,CAAC,YAAY;SACpB,CAAA;IACjB,CAAC;IAOK,AAAN,KAAK,CAAC,oBAAoB,CAAc,IAAY,EAAS,OAAwB;QACnF,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAEhC,IAAI,UAAU,GAAG,IAAA,qBAAa,EAAC,uBAAU,CAAC,CAAA;QAE1C,kDAAkD;QAClD,MAAM,SAAS,GAAG,MAAM,IAAA,iCAAyB,EAAC,MAAM,CAAC,CAAA;QACzD,IAAI,UAAU,GAAsB,IAAI,CAAA;QACxC,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;YAC5B,UAAU,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC;gBACpC,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE;gBACpC,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,CAAC;aAC9B,CAAC,CAAA;YACF,IAAI,UAAU;gBAAE,MAAK;QACvB,CAAC;QAED,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,MAAM,IAAI,KAAK,CAAC,yBAAyB,IAAI,aAAa,CAAC,CAAA;QAC7D,CAAC;QAED,qDAAqD;QAErD,qDAAqD;QACrD,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE,KAAK,MAAM,CAAC,EAAE,EAAE,CAAC;YACvC,UAAU,CAAC,MAAM,GAAG,MAAM,CAAA;YAC1B,MAAM,UAAU,CAAC,UAAU,EAAE,CAAA;YAE7B,gDAAgD;QAClD,CAAC;aAAM,CAAC;YACN,MAAM,UAAU,CAAC,UAAU,EAAE,CAAA;YAC7B,MAAM,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;QACnC,CAAC;QAED,OAAO;YACL,GAAG,UAAU;YACb,KAAK,EAAE,sCAAiB,CAAC,qBAAqB,CAAC,UAAU,CAAC;gBACxD,CAAC,CAAC,6BAAgB,CAAC,SAAS;gBAC5B,CAAC,CAAC,6BAAgB,CAAC,YAAY;SAClC,CAAA;IACH,CAAC;IASK,AAAN,KAAK,CAAC,iBAAiB,CAC0B,WAAyB,EACjE,OAAwB;QAE/B,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAE1C,MAAM,UAAU,GAAG,EAAE,CAAC,aAAa,CAAC,uBAAU,CAAC,CAAA;QAE/C,MAAM,OAAO,CAAC,GAAG,CACf,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,UAAsB,EAAE,EAAE;YAC/C,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,UAAU,CAAA;YAE/B,IAAI,EAAE,EAAE,CAAC;gBACP,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;gBAEjD,IAAI,MAAM,EAAE,CAAC;oBACX,IAAI,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,EAAE,EAAE,CAAC;wBACjC,MAAM,uBAAuB,EAAE,IAAI,IAAI,sCAAsC,CAAA;oBAC/E,CAAC;oBAED,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;oBAChF,IAAI,QAAQ,IAAI,QAAQ,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC;wBAClC,MAAM,yBAAyB,IAAI,0CAA0C,CAAA;oBAC/E,CAAC;oBAED,MAAM,UAAU,CAAC,IAAI,CAAC;wBACpB,GAAG,MAAM;wBACT,GAAG,UAAU;wBACb,GAAG,aAAa,CAAC,UAAU,EAAE,MAAM,CAAC;wBACpC,MAAM;wBACN,OAAO,EAAE,IAAI;qBACd,CAAC,CAAA;oBAEF,OAAM;gBACR,CAAC;YACH,CAAC;YAED,MAAM,UAAU,CAAC,IAAI,CAAC;gBACpB,GAAG,UAAU;gBACb,GAAG,aAAa,CAAC,UAAU,CAAC;gBAC5B,MAAM;gBACN,OAAO,EAAE,IAAI;gBACb,OAAO,EAAE,IAAI;aACd,CAAC,CAAA;QACJ,CAAC,CAAC,CACH,CAAA;QAED,OAAO,IAAI,CAAA;IACb,CAAC;CACF,CAAA;AAnSY,gDAAkB;AAMvB;IALL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EACR,6GAA6G,CAC9G;IACA,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,uBAAU,EAAE,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC;IAE3E,mBAAA,IAAA,kBAAG,EAAC,YAAY,CAAC,CAAA;IACjB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CADyB,+BAAa;;0DAY7C;AAOK;IALL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EACR,6GAA6G,CAC9G;IACA,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,uBAAU,EAAE,EAAE,WAAW,EAAE,iCAAiC,EAAE,CAAC;IAEjF,mBAAA,IAAA,kBAAG,EAAC,MAAM,CAAC,CAAA;IACX,mBAAA,IAAA,kBAAG,EAAC,OAAO,CAAC,CAAA;IACZ,mBAAA,IAAA,kBAAG,GAAE,CAAA;;qDADe,iCAAe;;0DAyBrC;AAOK;IALL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EACR,6GAA6G,CAC9G;IACA,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,CAAC,uBAAU,CAAC,EAAE,EAAE,WAAW,EAAE,uCAAuC,EAAE,CAAC;IAEzF,mBAAA,IAAA,kBAAG,EAAC,SAAS,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,iCAAe,CAAC,CAAC,CAAA;IACzC,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;kEAoDP;AAOK;IALL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EACR,6GAA6G,CAC9G;IACA,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,0CAA0C,EAAE,CAAC;IAClE,mBAAA,IAAA,kBAAG,EAAC,MAAM,CAAC,CAAA;IAAgB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;0DAKvD;AAOK;IALL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EACR,6GAA6G,CAC9G;IACA,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,8CAA8C,EAAE,CAAC;IAE3F,mBAAA,IAAA,kBAAG,EAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;IAC9B,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;2DAUP;AAOK;IALL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EACR,6GAA6G,CAC9G;IACA,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,uBAAU,EAAE,EAAE,WAAW,EAAE,yDAAyD,EAAE,CAAC;IACnF,mBAAA,IAAA,kBAAG,EAAC,MAAM,CAAC,CAAA;IAAgB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;2DAmCxD;AAOK;IALL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EACR,6GAA6G,CAC9G;IACA,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,uBAAU,EAAE,EAAE,WAAW,EAAE,+BAA+B,EAAE,CAAC;IACtD,mBAAA,IAAA,kBAAG,EAAC,MAAM,CAAC,CAAA;IAAgB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;8DAuC3D;AASK;IAPL,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,wBAAS,EACR,6GAA6G,CAC9G;IACA,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE;QAC5B,WAAW,EAAE,yFAAyF;KACvG,CAAC;IAEC,mBAAA,IAAA,kBAAG,EAAC,aAAa,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,iCAAe,CAAC,CAAC,CAAA;IAC7C,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;2DA8CP;6BAlSU,kBAAkB;IAF9B,IAAA,uBAAQ,EAAC,uBAAU,CAAC;IACpB,IAAA,4BAAa,EAAC,qBAAa,CAAC;GAChB,kBAAkB,CAmS9B","sourcesContent":["import { Arg, Ctx, Directive, Mutation, Resolver, UseMiddleware } from 'type-graphql'\nimport { In } from 'typeorm'\n\nimport { getRepository, Refusal, SpeakRefusals, getDomainIdsWithAncestors } from '@things-factory/shell'\n\nimport { ConnectionManager } from '../../engine/connection-manager'\nimport { Connection, ConnectionStatus } from './connection'\nimport { ConnectionPatch, NewConnection } from './connection-type'\nimport { keepStoredSecrets, refuseSecretParams, withoutSecretsOf } from './connection-secrets'\nimport { carryConnectionEnvVars } from './connection-env-vars'\n\n/**\n * The params a write stores (ADR-0112): a secret the caller sends is refused, a secret the caller\n * leaves out is kept from the stored row.\n *\n * A write that changes the connector type keeps none of the old type's secrets. They were secrets\n * under the old type's spec; the new type may not declare them, and then reading would show them.\n * When the old type is not registered here nobody can say which were secret, so none of its params\n * are carried over.\n */\nfunction paramsToStore(written: Partial<Connection>, stored?: Connection) {\n const type = written.type ?? stored?.type\n const name = written.name ?? stored?.name\n const typeChanged = Boolean(stored && written.type && written.type !== stored.type)\n\n if (written.params === undefined) {\n return typeChanged ? { params: withoutSecretsOf(stored.type, stored.params) } : {}\n }\n\n refuseSecretParams(type, name, written.params)\n return { params: typeChanged ? written.params : keepStoredSecrets(type, written.params, stored?.params) }\n}\n\n/**\n * A write names an existing row only through this: the row of that id or name **in the request's\n * domain**. `save` writes by primary key, so an id from another domain left in the object would\n * overwrite that domain's row - the lookup alone does not stop it.\n */\nfunction notInThisDomain(connection: string) {\n return new Refusal(\n 'connection-not-in-domain',\n { connection },\n `There is no connection \"${connection}\" in this domain.`\n )\n}\n\n@Resolver(Connection)\n@UseMiddleware(SpeakRefusals)\nexport class ConnectionMutation {\n @Directive('@transaction')\n @Directive(\n '@privilege(category: \"connection\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)'\n )\n @Mutation(returns => Connection, { description: 'Creates a new connection.' })\n async createConnection(\n @Arg('connection') connection: NewConnection,\n @Ctx() context: ResolverContext\n ): Promise<Connection> {\n const { domain, user, tx } = context.state\n\n return await tx.getRepository(Connection).save({\n ...connection,\n ...paramsToStore(connection),\n domain,\n creator: user,\n updater: user\n })\n }\n\n @Directive('@transaction')\n @Directive(\n '@privilege(category: \"connection\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)'\n )\n @Mutation(returns => Connection, { description: 'Updates an existing connection.' })\n async updateConnection(\n @Arg('name') name: string,\n @Arg('patch') patch: ConnectionPatch,\n @Ctx() context: ResolverContext\n ): Promise<Connection> {\n const { domain, user, tx } = context.state\n\n const repository = tx.getRepository(Connection)\n const connection = await repository.findOne({\n where: { domain: { id: domain.id }, name }\n })\n\n if (!connection) {\n throw notInThisDomain(name)\n }\n\n if (patch.name && patch.name !== connection.name) {\n await carryConnectionEnvVars(tx, domain, connection.name, patch.name)\n }\n\n return await repository.save({\n ...connection,\n ...patch,\n ...paramsToStore(patch, connection),\n id: connection.id,\n updater: user\n })\n }\n\n @Directive('@transaction')\n @Directive(\n '@privilege(category: \"connection\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)'\n )\n @Mutation(returns => [Connection], { description: 'Updates multiple connections at once.' })\n async updateMultipleConnection(\n @Arg('patches', type => [ConnectionPatch]) patches: ConnectionPatch[],\n @Ctx() context: ResolverContext\n ): Promise<Connection[]> {\n const { domain, user, tx } = context.state\n\n let results = []\n const _createRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === '+')\n const _updateRecords = patches.filter((patch: any) => patch.cuFlag.toUpperCase() === 'M')\n const connectionRepo = tx.getRepository(Connection)\n\n if (_createRecords.length > 0) {\n for (let i = 0; i < _createRecords.length; i++) {\n /* A new row: an id it carries would make `save` overwrite the row of that id, wherever it is. */\n const { id, ...newRecord } = _createRecords[i]\n\n const result = await connectionRepo.save({\n ...newRecord,\n ...paramsToStore(newRecord),\n domain,\n creator: user,\n updater: user\n })\n\n results.push({ ...result, cuFlag: '+' })\n }\n }\n\n if (_updateRecords.length > 0) {\n for (let i = 0; i < _updateRecords.length; i++) {\n const newRecord = _updateRecords[i]\n const connection = await connectionRepo.findOneBy({ id: newRecord.id, domain: { id: domain.id } })\n\n if (!connection) {\n throw notInThisDomain(newRecord.name || newRecord.id)\n }\n\n if (newRecord.name && newRecord.name !== connection.name) {\n await carryConnectionEnvVars(tx, domain, connection.name, newRecord.name)\n }\n\n const result = await connectionRepo.save({\n ...connection,\n ...newRecord,\n ...paramsToStore(newRecord, connection),\n id: connection.id,\n updater: user\n })\n\n results.push({ ...result, cuFlag: 'M' })\n }\n }\n\n return results\n }\n\n @Directive('@transaction')\n @Directive(\n '@privilege(category: \"connection\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)'\n )\n @Mutation(returns => Boolean, { description: 'Deletes a single connection by its name.' })\n async deleteConnection(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, tx } = context.state\n\n await tx.getRepository(Connection).delete({ domain: { id: domain.id }, name })\n return true\n }\n\n @Directive('@transaction')\n @Directive(\n '@privilege(category: \"connection\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)'\n )\n @Mutation(returns => Boolean, { description: 'Deletes multiple connections by their names.' })\n async deleteConnections(\n @Arg('names', type => [String]) names: string[],\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { domain, tx } = context.state\n\n await tx.getRepository(Connection).delete({\n domain: { id: domain.id },\n name: In(names)\n })\n\n return true\n }\n\n @Directive('@transaction')\n @Directive(\n '@privilege(category: \"connection\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)'\n )\n @Mutation(returns => Connection, { description: 'Establishes a live connection to a configured endpoint.' })\n async connectConnection(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<Connection> {\n const { domain } = context.state\n var repository = getRepository(Connection)\n\n // ancestor 도메인을 closest-first 로 순회하여 first hit 사용\n const domainIds = await getDomainIdsWithAncestors(domain)\n var connection: Connection | null = null\n for (const did of domainIds) {\n connection = await repository.findOne({\n where: { domain: { id: did }, name },\n relations: ['domain', 'edge']\n })\n if (connection) break\n }\n\n if (!connection) {\n throw new Error(`Connection with name '${name}' not found`)\n }\n\n /* 상속 및 on-demand 연결에서 connection.domain 과 다를 수 있음 */\n if (connection.domain.id !== domain.id) {\n connection.domain = domain\n await connection.connect()\n /* on-demand 연결인 경우에 connection을 저장하지 말아야 한다. */\n } else {\n await connection.connect()\n await repository.save(connection)\n }\n\n return {\n ...connection,\n state: ConnectionManager.getConnectionInstance(connection)\n ? ConnectionStatus.CONNECTED\n : ConnectionStatus.DISCONNECTED\n } as Connection\n }\n\n @Directive('@transaction')\n @Directive(\n '@privilege(category: \"connection\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)'\n )\n @Mutation(returns => Connection, { description: 'Terminates a live connection.' })\n async disconnectConnection(@Arg('name') name: string, @Ctx() context: ResolverContext) {\n const { domain } = context.state\n\n var repository = getRepository(Connection)\n\n // ancestor 도메인을 closest-first 로 순회하여 first hit 사용\n const domainIds = await getDomainIdsWithAncestors(domain)\n var connection: Connection | null = null\n for (const did of domainIds) {\n connection = await repository.findOne({\n where: { domain: { id: did }, name },\n relations: ['domain', 'edge']\n })\n if (connection) break\n }\n\n if (!connection) {\n throw new Error(`Connection with name '${name}' not found`)\n }\n\n /* 상속 및 on-demand 연결에서 connection.domain 과 다를 수 있음 */\n\n /* 상속 및 on-demand 연결에서 connection.domain 과 다를 수 있음 */\n if (connection.domain.id !== domain.id) {\n connection.domain = domain\n await connection.disconnect()\n\n /* on-demand 연결인 경우에 connection을 저장하지 말아야 한다. */\n } else {\n await connection.disconnect()\n await repository.save(connection)\n }\n\n return {\n ...connection,\n state: ConnectionManager.getConnectionInstance(connection)\n ? ConnectionStatus.CONNECTED\n : ConnectionStatus.DISCONNECTED\n }\n }\n\n @Directive('@transaction')\n @Directive(\n '@privilege(category: \"connection\", privilege: \"mutation\", domainOwnerGranted: true, superUserGranted: true)'\n )\n @Mutation(returns => Boolean, {\n description: 'Imports multiple connections. Can overwrite existing connections if IDs or names match.'\n })\n async importConnections(\n @Arg('connections', type => [ConnectionPatch]) connections: Connection[],\n @Ctx() context: ResolverContext\n ): Promise<boolean> {\n const { tx, domain, user } = context.state\n\n const repository = tx.getRepository(Connection)\n\n await Promise.all(\n connections.map(async (connection: Connection) => {\n const { id, name } = connection\n\n if (id) {\n const sameId = await repository.findOneBy({ id })\n\n if (sameId) {\n if (sameId.domainId != domain.id) {\n throw `Connection with id '${id}:${name}' is already taken by another domain`\n }\n\n const sameName = await repository.findOneBy({ domain: { id: domain.id }, name })\n if (sameName && sameName.id != id) {\n throw `Connection with name '${name}' is already taken by another connection`\n }\n\n await repository.save({\n ...sameId,\n ...connection,\n ...paramsToStore(connection, sameId),\n domain,\n updater: user\n })\n\n return\n }\n }\n\n await repository.save({\n ...connection,\n ...paramsToStore(connection),\n domain,\n updater: user,\n creator: user\n })\n })\n )\n\n return true\n }\n}\n"]}
|
|
@@ -9,7 +9,6 @@ const shell_1 = require("@things-factory/shell");
|
|
|
9
9
|
const connection_manager_1 = require("../../engine/connection-manager");
|
|
10
10
|
const connection_1 = require("./connection");
|
|
11
11
|
const connection_type_1 = require("./connection-type");
|
|
12
|
-
const domain_inheritance_1 = require("../../utils/domain-inheritance");
|
|
13
12
|
const connection_secrets_1 = require("./connection-secrets");
|
|
14
13
|
/**
|
|
15
14
|
* @description Provides GraphQL resolvers for the Connection entity.
|
|
@@ -17,7 +16,7 @@ const connection_secrets_1 = require("./connection-secrets");
|
|
|
17
16
|
let ConnectionQuery = class ConnectionQuery {
|
|
18
17
|
async connection(name, context) {
|
|
19
18
|
const { domain } = context.state;
|
|
20
|
-
const domainIds = await (0,
|
|
19
|
+
const domainIds = await (0, shell_1.getDomainIdsWithAncestors)(domain);
|
|
21
20
|
// 동일 name 이 여러 ancestor 도메인에 존재할 수 있음 → closest-first 우선 선택.
|
|
22
21
|
const connections = await (0, shell_1.getRepository)(connection_1.Connection).find({
|
|
23
22
|
where: { domain: { id: (0, typeorm_1.In)(domainIds) }, name },
|
|
@@ -33,7 +32,7 @@ let ConnectionQuery = class ConnectionQuery {
|
|
|
33
32
|
}
|
|
34
33
|
async connections(params, context) {
|
|
35
34
|
const { domain } = context.state;
|
|
36
|
-
const domainIds = await (0,
|
|
35
|
+
const domainIds = await (0, shell_1.getDomainIdsWithAncestors)(domain);
|
|
37
36
|
const queryBuilder = (0, shell_1.getQueryBuilderFromListParams)({
|
|
38
37
|
repository: (0, shell_1.getRepository)(connection_1.Connection),
|
|
39
38
|
params,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-query.js","sourceRoot":"","sources":["../../../server/service/connection/connection-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Args, Ctx, Directive, FieldResolver, Query, Resolver, Root } from 'type-graphql'\nimport { In } from 'typeorm'\n\nimport { Appliance, User } from '@things-factory/auth-base'\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam, ScalarObject } from '@things-factory/shell'\n\nimport { ConnectionManager } from '../../engine/connection-manager'\nimport { Connection, ConnectionStatus } from './connection'\nimport { ConnectionList, ConnectionState } from './connection-type'\nimport { getDomainIdsWithAncestors } from '../../utils/domain-inheritance'\nimport { paramsVisibleTo, secretHintsOf } from './connection-secrets'\n\n/**\n * @description Provides GraphQL resolvers for the Connection entity.\n */\n@Resolver(Connection)\nexport class ConnectionQuery {\n @Directive('@privilege(category: \"connection\", privilege: \"query\", domainOwnerGranted: true, superUserGranted: true)')\n @Query(returns => Connection, {\n description: 'Fetches a single connection by its name, including its current state.'\n })\n async connection(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<Connection> {\n const { domain } = context.state\n const domainIds = await getDomainIdsWithAncestors(domain)\n\n // 동일 name 이 여러 ancestor 도메인에 존재할 수 있음 → closest-first 우선 선택.\n const connections = await getRepository(Connection).find({\n where: { domain: { id: In(domainIds) }, name },\n relations: ['domain']\n })\n\n var connection = connections.sort(\n (a, b) => domainIds.indexOf(a.domainId) - domainIds.indexOf(b.domainId)\n )[0]\n\n return {\n ...connection,\n state: ConnectionManager.getConnectionInstance(connection)\n ? ConnectionStatus.CONNECTED\n : ConnectionStatus.DISCONNECTED\n } as Connection\n }\n\n @Directive('@privilege(category: \"connection\", privilege: \"query\", domainOwnerGranted: true, superUserGranted: true)')\n @Query(returns => ConnectionList, {\n description: 'Fetches a paginated list of connections, including their current states.'\n })\n async connections(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ConnectionList> {\n const { domain } = context.state\n const domainIds = await getDomainIdsWithAncestors(domain)\n\n const queryBuilder = getQueryBuilderFromListParams({\n repository: getRepository(Connection),\n params,\n // 도메인 필터링은 ancestor 기반으로 직접 적용 (shell helper 는 single-parent 만 지원)\n domain: undefined,\n alias: 'connection',\n searchables: ['name', 'description', 'type', 'endpoint']\n })\n\n queryBuilder.andWhere(`connection.domain IN (:...ancestorDomainIds)`, { ancestorDomainIds: domainIds })\n\n const [items, total] = await queryBuilder.leftJoinAndSelect('connection.domain', 'domain').getManyAndCount()\n\n items.forEach(connection => {\n connection['state'] = ConnectionManager.getConnectionInstance(connection)\n ? ConnectionStatus.CONNECTED\n : ConnectionStatus.DISCONNECTED\n })\n\n return { items, total }\n }\n\n @Directive('@privilege(category: \"connection\", privilege: \"query\", domainOwnerGranted: true, superUserGranted: true)')\n @Query(returns => ConnectionState, { description: 'Fetches the current state of a single connection by its name.' })\n fetchConnectionState(@Arg('name') name: string, @Ctx() context: ResolverContext): ConnectionState {\n const { domain } = context.state\n\n const connection = ConnectionManager.getConnectionInstanceEntityByName(domain, name)\n\n return {\n ...connection,\n state: connection ? ConnectionStatus.CONNECTED : ConnectionStatus.DISCONNECTED\n }\n }\n\n /**\n * Every read of `Connection.params` passes here — the queries, the mutations' answers and the edge\n * subscriptions alike. Secrets are left out unless the reader is the edge appliance the connection\n * is assigned to (ADR-0112).\n */\n @FieldResolver(type => ScalarObject, {\n nullable: true,\n description:\n \"The connection's parameters. Secret parameters are left out except for the edge appliance the connection is assigned to (ADR-0112).\"\n })\n params(@Root() connection: Connection, @Ctx() context: ResolverContext) {\n return paramsVisibleTo(connection, context?.state?.user)\n }\n\n @FieldResolver(type => ScalarObject, {\n nullable: true,\n description:\n 'For each secret parameter still stored in params, the part of its value that may be shown (ADR-0112). Null when there is none.'\n })\n secretHints(@Root() connection: Connection, @Ctx() context: ResolverContext) {\n return secretHintsOf(connection, context?.state?.user)\n }\n\n @FieldResolver(type => Domain)\n async edge(@Root() connection: Connection) {\n return connection.edgeId && (await getRepository(Appliance).findOneBy({ id: connection.edgeId }))\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() connection: Connection) {\n return (\n connection.domain || (connection.domainId && (await getRepository(Domain).findOneBy({ id: connection.domainId })))\n )\n }\n\n @FieldResolver(type => User)\n async updater(@Root() connection: Connection): Promise<User> {\n return connection.updaterId && (await getRepository(User).findOneBy({ id: connection.updaterId }))\n }\n\n @FieldResolver(type => User)\n async creator(@Root() connection: Connection): Promise<User> {\n return connection.creatorId && (await getRepository(User).findOneBy({ id: connection.creatorId }))\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"connection-query.js","sourceRoot":"","sources":["../../../server/service/connection/connection-query.ts"],"names":[],"mappings":";;;;AAAA,+CAA8F;AAC9F,qCAA4B;AAE5B,yDAA2D;AAC3D,iDAO8B;AAE9B,wEAAmE;AACnE,6CAA2D;AAC3D,uDAAmE;AACnE,6DAAqE;AAErE;;GAEG;AAEI,IAAM,eAAe,GAArB,MAAM,eAAe;IAKpB,AAAN,KAAK,CAAC,UAAU,CAAc,IAAY,EAAS,OAAwB;QACzE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAChC,MAAM,SAAS,GAAG,MAAM,IAAA,iCAAyB,EAAC,MAAM,CAAC,CAAA;QAEzD,6DAA6D;QAC7D,MAAM,WAAW,GAAG,MAAM,IAAA,qBAAa,EAAC,uBAAU,CAAC,CAAC,IAAI,CAAC;YACvD,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,IAAA,YAAE,EAAC,SAAS,CAAC,EAAE,EAAE,IAAI,EAAE;YAC9C,SAAS,EAAE,CAAC,QAAQ,CAAC;SACtB,CAAC,CAAA;QAEF,IAAI,UAAU,GAAG,WAAW,CAAC,IAAI,CAC/B,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CACxE,CAAC,CAAC,CAAC,CAAA;QAEJ,OAAO;YACL,GAAG,UAAU;YACb,KAAK,EAAE,sCAAiB,CAAC,qBAAqB,CAAC,UAAU,CAAC;gBACxD,CAAC,CAAC,6BAAgB,CAAC,SAAS;gBAC5B,CAAC,CAAC,6BAAgB,CAAC,YAAY;SACpB,CAAA;IACjB,CAAC;IAMK,AAAN,KAAK,CAAC,WAAW,CACU,MAAiB,EACnC,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAChC,MAAM,SAAS,GAAG,MAAM,IAAA,iCAAyB,EAAC,MAAM,CAAC,CAAA;QAEzD,MAAM,YAAY,GAAG,IAAA,qCAA6B,EAAC;YACjD,UAAU,EAAE,IAAA,qBAAa,EAAC,uBAAU,CAAC;YACrC,MAAM;YACN,mEAAmE;YACnE,MAAM,EAAE,SAAS;YACjB,KAAK,EAAE,YAAY;YACnB,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,UAAU,CAAC;SACzD,CAAC,CAAA;QAEF,YAAY,CAAC,QAAQ,CAAC,8CAA8C,EAAE,EAAE,iBAAiB,EAAE,SAAS,EAAE,CAAC,CAAA;QAEvG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,YAAY,CAAC,iBAAiB,CAAC,mBAAmB,EAAE,QAAQ,CAAC,CAAC,eAAe,EAAE,CAAA;QAE5G,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE;YACzB,UAAU,CAAC,OAAO,CAAC,GAAG,sCAAiB,CAAC,qBAAqB,CAAC,UAAU,CAAC;gBACvE,CAAC,CAAC,6BAAgB,CAAC,SAAS;gBAC5B,CAAC,CAAC,6BAAgB,CAAC,YAAY,CAAA;QACnC,CAAC,CAAC,CAAA;QAEF,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;IACzB,CAAC;IAID,oBAAoB,CAAc,IAAY,EAAS,OAAwB;QAC7E,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAEhC,MAAM,UAAU,GAAG,sCAAiB,CAAC,iCAAiC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;QAEpF,OAAO;YACL,GAAG,UAAU;YACb,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,6BAAgB,CAAC,SAAS,CAAC,CAAC,CAAC,6BAAgB,CAAC,YAAY;SAC/E,CAAA;IACH,CAAC;IAED;;;;OAIG;IAMH,MAAM,CAAS,UAAsB,EAAS,OAAwB;QACpE,OAAO,IAAA,oCAAe,EAAC,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;IAC1D,CAAC;IAOD,WAAW,CAAS,UAAsB,EAAS,OAAwB;QACzE,OAAO,IAAA,kCAAa,EAAC,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;IACxD,CAAC;IAGK,AAAN,KAAK,CAAC,IAAI,CAAS,UAAsB;QACvC,OAAO,UAAU,CAAC,MAAM,IAAI,CAAC,MAAM,IAAA,qBAAa,EAAC,qBAAS,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IACnG,CAAC;IAGK,AAAN,KAAK,CAAC,MAAM,CAAS,UAAsB;QACzC,OAAO,CACL,UAAU,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,QAAQ,IAAI,CAAC,MAAM,IAAA,qBAAa,EAAC,cAAM,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CACnH,CAAA;IACH,CAAC;IAGK,AAAN,KAAK,CAAC,OAAO,CAAS,UAAsB;QAC1C,OAAO,UAAU,CAAC,SAAS,IAAI,CAAC,MAAM,IAAA,qBAAa,EAAC,gBAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;IACpG,CAAC;IAGK,AAAN,KAAK,CAAC,OAAO,CAAS,UAAsB;QAC1C,OAAO,UAAU,CAAC,SAAS,IAAI,CAAC,MAAM,IAAA,qBAAa,EAAC,gBAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;IACpG,CAAC;CACF,CAAA;AArHY,0CAAe;AAKpB;IAJL,IAAA,wBAAS,EAAC,0GAA0G,CAAC;IACrH,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,uBAAU,EAAE;QAC5B,WAAW,EAAE,uEAAuE;KACrF,CAAC;IACgB,mBAAA,IAAA,kBAAG,EAAC,MAAM,CAAC,CAAA;IAAgB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;iDAoBjD;AAMK;IAJL,IAAA,wBAAS,EAAC,0GAA0G,CAAC;IACrH,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,gCAAc,EAAE;QAChC,WAAW,EAAE,0EAA0E;KACxF,CAAC;IAEC,mBAAA,IAAA,mBAAI,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAS,CAAC,CAAA;IACvB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAD2B,iBAAS;;kDA0B3C;AAID;IAFC,IAAA,wBAAS,EAAC,0GAA0G,CAAC;IACrH,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,iCAAe,EAAE,EAAE,WAAW,EAAE,+DAA+D,EAAE,CAAC;IAC9F,mBAAA,IAAA,kBAAG,EAAC,MAAM,CAAC,CAAA;IAAgB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;4CAA4B,iCAAe;2DAShG;AAYD;IALC,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE;QACnC,QAAQ,EAAE,IAAI;QACd,WAAW,EACT,qIAAqI;KACxI,CAAC;IACM,mBAAA,IAAA,mBAAI,GAAE,CAAA;IAA0B,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAAlB,uBAAU;;6CAEpC;AAOD;IALC,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE;QACnC,QAAQ,EAAE,IAAI;QACd,WAAW,EACT,gIAAgI;KACnI,CAAC;IACW,mBAAA,IAAA,mBAAI,GAAE,CAAA;IAA0B,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAAlB,uBAAU;;kDAEzC;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,CAAC;IAClB,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAa,uBAAU;;2CAExC;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,CAAC;IAChB,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAa,uBAAU;;6CAI1C;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,CAAC;IACb,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAa,uBAAU;;8CAE3C;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,CAAC;IACb,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAa,uBAAU;;8CAE3C;0BApHU,eAAe;IAD3B,IAAA,uBAAQ,EAAC,uBAAU,CAAC;GACR,eAAe,CAqH3B","sourcesContent":["import { Arg, Args, Ctx, Directive, FieldResolver, Query, Resolver, Root } from 'type-graphql'\nimport { In } from 'typeorm'\n\nimport { Appliance, User } from '@things-factory/auth-base'\nimport {\n Domain,\n getQueryBuilderFromListParams,\n getRepository,\n ListParam,\n ScalarObject,\n getDomainIdsWithAncestors\n} from '@things-factory/shell'\n\nimport { ConnectionManager } from '../../engine/connection-manager'\nimport { Connection, ConnectionStatus } from './connection'\nimport { ConnectionList, ConnectionState } from './connection-type'\nimport { paramsVisibleTo, secretHintsOf } from './connection-secrets'\n\n/**\n * @description Provides GraphQL resolvers for the Connection entity.\n */\n@Resolver(Connection)\nexport class ConnectionQuery {\n @Directive('@privilege(category: \"connection\", privilege: \"query\", domainOwnerGranted: true, superUserGranted: true)')\n @Query(returns => Connection, {\n description: 'Fetches a single connection by its name, including its current state.'\n })\n async connection(@Arg('name') name: string, @Ctx() context: ResolverContext): Promise<Connection> {\n const { domain } = context.state\n const domainIds = await getDomainIdsWithAncestors(domain)\n\n // 동일 name 이 여러 ancestor 도메인에 존재할 수 있음 → closest-first 우선 선택.\n const connections = await getRepository(Connection).find({\n where: { domain: { id: In(domainIds) }, name },\n relations: ['domain']\n })\n\n var connection = connections.sort(\n (a, b) => domainIds.indexOf(a.domainId) - domainIds.indexOf(b.domainId)\n )[0]\n\n return {\n ...connection,\n state: ConnectionManager.getConnectionInstance(connection)\n ? ConnectionStatus.CONNECTED\n : ConnectionStatus.DISCONNECTED\n } as Connection\n }\n\n @Directive('@privilege(category: \"connection\", privilege: \"query\", domainOwnerGranted: true, superUserGranted: true)')\n @Query(returns => ConnectionList, {\n description: 'Fetches a paginated list of connections, including their current states.'\n })\n async connections(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ConnectionList> {\n const { domain } = context.state\n const domainIds = await getDomainIdsWithAncestors(domain)\n\n const queryBuilder = getQueryBuilderFromListParams({\n repository: getRepository(Connection),\n params,\n // 도메인 필터링은 ancestor 기반으로 직접 적용 (shell helper 는 single-parent 만 지원)\n domain: undefined,\n alias: 'connection',\n searchables: ['name', 'description', 'type', 'endpoint']\n })\n\n queryBuilder.andWhere(`connection.domain IN (:...ancestorDomainIds)`, { ancestorDomainIds: domainIds })\n\n const [items, total] = await queryBuilder.leftJoinAndSelect('connection.domain', 'domain').getManyAndCount()\n\n items.forEach(connection => {\n connection['state'] = ConnectionManager.getConnectionInstance(connection)\n ? ConnectionStatus.CONNECTED\n : ConnectionStatus.DISCONNECTED\n })\n\n return { items, total }\n }\n\n @Directive('@privilege(category: \"connection\", privilege: \"query\", domainOwnerGranted: true, superUserGranted: true)')\n @Query(returns => ConnectionState, { description: 'Fetches the current state of a single connection by its name.' })\n fetchConnectionState(@Arg('name') name: string, @Ctx() context: ResolverContext): ConnectionState {\n const { domain } = context.state\n\n const connection = ConnectionManager.getConnectionInstanceEntityByName(domain, name)\n\n return {\n ...connection,\n state: connection ? ConnectionStatus.CONNECTED : ConnectionStatus.DISCONNECTED\n }\n }\n\n /**\n * Every read of `Connection.params` passes here — the queries, the mutations' answers and the edge\n * subscriptions alike. Secrets are left out unless the reader is the edge appliance the connection\n * is assigned to (ADR-0112).\n */\n @FieldResolver(type => ScalarObject, {\n nullable: true,\n description:\n \"The connection's parameters. Secret parameters are left out except for the edge appliance the connection is assigned to (ADR-0112).\"\n })\n params(@Root() connection: Connection, @Ctx() context: ResolverContext) {\n return paramsVisibleTo(connection, context?.state?.user)\n }\n\n @FieldResolver(type => ScalarObject, {\n nullable: true,\n description:\n 'For each secret parameter still stored in params, the part of its value that may be shown (ADR-0112). Null when there is none.'\n })\n secretHints(@Root() connection: Connection, @Ctx() context: ResolverContext) {\n return secretHintsOf(connection, context?.state?.user)\n }\n\n @FieldResolver(type => Domain)\n async edge(@Root() connection: Connection) {\n return connection.edgeId && (await getRepository(Appliance).findOneBy({ id: connection.edgeId }))\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() connection: Connection) {\n return (\n connection.domain || (connection.domainId && (await getRepository(Domain).findOneBy({ id: connection.domainId })))\n )\n }\n\n @FieldResolver(type => User)\n async updater(@Root() connection: Connection): Promise<User> {\n return connection.updaterId && (await getRepository(User).findOneBy({ id: connection.updaterId }))\n }\n\n @FieldResolver(type => User)\n async creator(@Root() connection: Connection): Promise<User> {\n return connection.creatorId && (await getRepository(User).findOneBy({ id: connection.creatorId }))\n }\n}\n"]}
|
|
@@ -10,7 +10,6 @@ exports.paramsVisibleTo = paramsVisibleTo;
|
|
|
10
10
|
exports.secretHintsOf = secretHintsOf;
|
|
11
11
|
const shell_1 = require("@things-factory/shell");
|
|
12
12
|
const connection_manager_1 = require("../../engine/connection-manager");
|
|
13
|
-
const secret_hint_1 = require("../secret-hint");
|
|
14
13
|
/**
|
|
15
14
|
* **A connection's secrets live in EnvVar, never in `params`** (ADR-0112).
|
|
16
15
|
*
|
|
@@ -178,7 +177,7 @@ function secretHintsOf(connection, reader) {
|
|
|
178
177
|
}
|
|
179
178
|
const hints = {};
|
|
180
179
|
for (const param of secretParamNames(connection.type) || []) {
|
|
181
|
-
const hint = present(params[param]) ? (0,
|
|
180
|
+
const hint = present(params[param]) ? (0, shell_1.secretHint)(String(params[param])) : undefined;
|
|
182
181
|
if (hint) {
|
|
183
182
|
hints[param] = hint;
|
|
184
183
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"connection-secrets.js","sourceRoot":"","sources":["../../../server/service/connection/connection-secrets.ts"],"names":[],"mappings":"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","sourcesContent":["import { Refusal } from '@things-factory/shell'\n\nimport { ConnectionManager } from '../../engine/connection-manager'\nimport { secretHint } from '../secret-hint'\n\n/**\n * **A connection's secrets live in EnvVar, never in `params`** (ADR-0112).\n *\n * ── What was wrong ────────────────────────────────────────────────────────\n * `Connection.params` is plain JSON in the database. A password typed into it was kept as it was,\n * handed back by `connections { items { params } }` to anyone who may read connections, and written\n * into the screen's export file. EnvVar already had the right shape — always encrypted at rest\n * (`encryptTransformer`), resolved closest-domain-first by `Connection.getParameter` — but nothing\n * stopped a secret from going into `params` instead.\n *\n * ── Which parameter is a secret ───────────────────────────────────────────\n * One marker: the connector's `parameterSpec` says `type: 'secret'`. Not the name — a name rule\n * catches `keepalive` and `sshKeyPath` and misses `pass`. A test walks every registered connector so a\n * secret written as `string` turns red, and so does a secret without `useDomainAttribute` (it would\n * have nowhere left to go).\n *\n * ── Three things this file does ───────────────────────────────────────────\n * refuse a write that carries a value for a secret parameter is refused, naming the EnvVar key\n * keep a write that leaves a secret out keeps what the row already holds — rows written\n * before this rule still connect, and the masked value a screen read back cannot erase it\n * mask reading `params` leaves secrets out, except for the edge appliance the connection is\n * assigned to, which has to receive them to connect\n */\n\n/**\n * The names of the secret parameters of a connector, or `null` when the connector is not registered\n * here. `null` is \"cannot tell\", not \"none\": a caller must not read it as \"nothing to hide\".\n */\nexport function secretParamNames(type: string): string[] | null {\n const connector = type ? ConnectionManager.getConnector(type) : null\n if (!connector) {\n return null\n }\n\n return (connector.parameterSpec || []).filter(spec => spec?.type === 'secret').map(spec => spec.name)\n}\n\nexport function envVarKeyOf(connectionName: string, param: string): string {\n return `Connection::${connectionName}::${param}`\n}\n\nfunction present(value: any): boolean {\n return value !== null && value !== undefined && value !== ''\n}\n\n/**\n * Refuses a write whose `params` hold a value for a secret parameter.\n *\n * Only what the caller sends is checked. A row that already holds a secret is read as before\n * (decision 1 of ADR-0112 - no flag day); it changes when someone writes it.\n */\nexport function refuseSecretParams(type: string, connectionName: string, params: { [key: string]: any } | null) {\n if (!params || typeof params !== 'object') {\n return\n }\n\n for (const param of secretParamNames(type) || []) {\n if (present(params[param])) {\n const envVar = envVarKeyOf(connectionName, param)\n\n throw new Refusal(\n 'connection-secret-in-params',\n { connection: connectionName, param, envVar },\n `\"${param}\" of connection \"${connectionName}\" is a secret and is not stored in the connection. ` +\n `Set it as the environment variable \"${envVar}\".`\n )\n }\n }\n}\n\n/**\n * The `params` to store for a write: what the caller sent, with each secret it left out taken from\n * the stored row.\n *\n * A screen reads `params` with the secrets removed, so saving that object back must not erase a\n * secret a row written before ADR-0112 still holds - that connection would stop on its next connect.\n */\nexport function keepStoredSecrets(\n type: string,\n incoming: { [key: string]: any } | null | undefined,\n stored: { [key: string]: any } | null | undefined\n): { [key: string]: any } | null | undefined {\n if (!incoming || typeof incoming !== 'object' || !stored || typeof stored !== 'object') {\n return incoming\n }\n\n const kept = { ...incoming }\n for (const param of secretParamNames(type) || []) {\n if (!present(kept[param]) && present(stored[param])) {\n kept[param] = stored[param]\n }\n }\n\n return kept\n}\n\n/**\n * `params` with the secrets of `type` removed - what may outlive a change of connector type.\n * `null` when `type` is not registered here: nothing can be told apart, so nothing is kept.\n */\nexport function withoutSecretsOf(type: string, params: { [key: string]: any } | null | undefined) {\n const secrets = secretParamNames(type)\n if (!secrets) {\n return null\n }\n if (!params || typeof params !== 'object') {\n return params\n }\n\n const kept = { ...params }\n for (const param of secrets) {\n delete kept[param]\n }\n return kept\n}\n\ntype Reader = { userType?: string; reference?: string } | null | undefined\n\n/**\n * Whether this reader is the edge appliance the connection is assigned to.\n *\n * Decided by the authenticated principal only (ADR-0112 condition 3): the appliance's shadow user\n * carries the appliance id in `reference`, and the connection names its appliance in `edgeId`.\n * Nothing the request says about itself takes part.\n */\nexport function isAssignedEdge(connection: { edgeId?: string } | null | undefined, reader: Reader): boolean {\n return Boolean(\n reader?.userType === 'appliance' && reader.reference && connection?.edgeId && connection.edgeId === reader.reference\n )\n}\n\n/**\n * `params` as this reader may see them.\n *\n * The edge subscriptions hand `params` over as a JSON string, so a string comes back a string.\n * A connector that is not registered here cannot say which parameters are secret, so nothing of its\n * `params` is shown - an unknown is not read as \"nothing secret\".\n */\nexport function paramsVisibleTo(\n connection: { type?: string; edgeId?: string; params?: any } | null | undefined,\n reader: Reader\n): any {\n const params = connection?.params\n if (params === null || params === undefined || isAssignedEdge(connection, reader)) {\n return params\n }\n\n const secrets = secretParamNames(connection.type)\n if (!secrets) {\n return null\n }\n\n const asString = typeof params === 'string'\n let object: any = params\n if (asString) {\n try {\n object = JSON.parse(params)\n } catch (e) {\n return null\n }\n }\n\n if (!object || typeof object !== 'object') {\n return asString ? params : object\n }\n\n const visible = { ...object }\n for (const param of secrets) {\n delete visible[param]\n }\n\n return asString ? JSON.stringify(visible) : visible\n}\n\n/**\n * For each secret still held in `params` - written before ADR-0112 - the part that may be shown.\n *\n * Reading `params` leaves those secrets out, so the field on the screen is empty while the connection\n * keeps connecting with the old value. The screen shows these as the field's placeholder: the person\n * sees that a value is in use, and saving the form sends nothing back - a placeholder is not a value.\n *\n * `null` when there is none, and for a reader who receives `params` whole (the assigned edge).\n */\nexport function secretHintsOf(\n connection: { type?: string; edgeId?: string; params?: any } | null | undefined,\n reader: Reader\n): { [param: string]: string } | null {\n if (!connection?.params || isAssignedEdge(connection, reader)) {\n return null\n }\n\n let params: any = connection.params\n if (typeof params === 'string') {\n try {\n params = JSON.parse(params)\n } catch (e) {\n return null\n }\n }\n if (!params || typeof params !== 'object') {\n return null\n }\n\n const hints: { [param: string]: string } = {}\n for (const param of secretParamNames(connection.type) || []) {\n const hint = present(params[param]) ? secretHint(String(params[param])) : undefined\n if (hint) {\n hints[param] = hint\n }\n }\n\n return Object.keys(hints).length > 0 ? hints : null\n}\n"]}
|
|
1
|
+
{"version":3,"file":"connection-secrets.js","sourceRoot":"","sources":["../../../server/service/connection/connection-secrets.ts"],"names":[],"mappings":"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","sourcesContent":["import { Refusal, secretHint } from '@things-factory/shell'\n\nimport { ConnectionManager } from '../../engine/connection-manager'\n\n/**\n * **A connection's secrets live in EnvVar, never in `params`** (ADR-0112).\n *\n * ── What was wrong ────────────────────────────────────────────────────────\n * `Connection.params` is plain JSON in the database. A password typed into it was kept as it was,\n * handed back by `connections { items { params } }` to anyone who may read connections, and written\n * into the screen's export file. EnvVar already had the right shape — always encrypted at rest\n * (`encryptTransformer`), resolved closest-domain-first by `Connection.getParameter` — but nothing\n * stopped a secret from going into `params` instead.\n *\n * ── Which parameter is a secret ───────────────────────────────────────────\n * One marker: the connector's `parameterSpec` says `type: 'secret'`. Not the name — a name rule\n * catches `keepalive` and `sshKeyPath` and misses `pass`. A test walks every registered connector so a\n * secret written as `string` turns red, and so does a secret without `useDomainAttribute` (it would\n * have nowhere left to go).\n *\n * ── Three things this file does ───────────────────────────────────────────\n * refuse a write that carries a value for a secret parameter is refused, naming the EnvVar key\n * keep a write that leaves a secret out keeps what the row already holds — rows written\n * before this rule still connect, and the masked value a screen read back cannot erase it\n * mask reading `params` leaves secrets out, except for the edge appliance the connection is\n * assigned to, which has to receive them to connect\n */\n\n/**\n * The names of the secret parameters of a connector, or `null` when the connector is not registered\n * here. `null` is \"cannot tell\", not \"none\": a caller must not read it as \"nothing to hide\".\n */\nexport function secretParamNames(type: string): string[] | null {\n const connector = type ? ConnectionManager.getConnector(type) : null\n if (!connector) {\n return null\n }\n\n return (connector.parameterSpec || []).filter(spec => spec?.type === 'secret').map(spec => spec.name)\n}\n\nexport function envVarKeyOf(connectionName: string, param: string): string {\n return `Connection::${connectionName}::${param}`\n}\n\nfunction present(value: any): boolean {\n return value !== null && value !== undefined && value !== ''\n}\n\n/**\n * Refuses a write whose `params` hold a value for a secret parameter.\n *\n * Only what the caller sends is checked. A row that already holds a secret is read as before\n * (decision 1 of ADR-0112 - no flag day); it changes when someone writes it.\n */\nexport function refuseSecretParams(type: string, connectionName: string, params: { [key: string]: any } | null) {\n if (!params || typeof params !== 'object') {\n return\n }\n\n for (const param of secretParamNames(type) || []) {\n if (present(params[param])) {\n const envVar = envVarKeyOf(connectionName, param)\n\n throw new Refusal(\n 'connection-secret-in-params',\n { connection: connectionName, param, envVar },\n `\"${param}\" of connection \"${connectionName}\" is a secret and is not stored in the connection. ` +\n `Set it as the environment variable \"${envVar}\".`\n )\n }\n }\n}\n\n/**\n * The `params` to store for a write: what the caller sent, with each secret it left out taken from\n * the stored row.\n *\n * A screen reads `params` with the secrets removed, so saving that object back must not erase a\n * secret a row written before ADR-0112 still holds - that connection would stop on its next connect.\n */\nexport function keepStoredSecrets(\n type: string,\n incoming: { [key: string]: any } | null | undefined,\n stored: { [key: string]: any } | null | undefined\n): { [key: string]: any } | null | undefined {\n if (!incoming || typeof incoming !== 'object' || !stored || typeof stored !== 'object') {\n return incoming\n }\n\n const kept = { ...incoming }\n for (const param of secretParamNames(type) || []) {\n if (!present(kept[param]) && present(stored[param])) {\n kept[param] = stored[param]\n }\n }\n\n return kept\n}\n\n/**\n * `params` with the secrets of `type` removed - what may outlive a change of connector type.\n * `null` when `type` is not registered here: nothing can be told apart, so nothing is kept.\n */\nexport function withoutSecretsOf(type: string, params: { [key: string]: any } | null | undefined) {\n const secrets = secretParamNames(type)\n if (!secrets) {\n return null\n }\n if (!params || typeof params !== 'object') {\n return params\n }\n\n const kept = { ...params }\n for (const param of secrets) {\n delete kept[param]\n }\n return kept\n}\n\ntype Reader = { userType?: string; reference?: string } | null | undefined\n\n/**\n * Whether this reader is the edge appliance the connection is assigned to.\n *\n * Decided by the authenticated principal only (ADR-0112 condition 3): the appliance's shadow user\n * carries the appliance id in `reference`, and the connection names its appliance in `edgeId`.\n * Nothing the request says about itself takes part.\n */\nexport function isAssignedEdge(connection: { edgeId?: string } | null | undefined, reader: Reader): boolean {\n return Boolean(\n reader?.userType === 'appliance' && reader.reference && connection?.edgeId && connection.edgeId === reader.reference\n )\n}\n\n/**\n * `params` as this reader may see them.\n *\n * The edge subscriptions hand `params` over as a JSON string, so a string comes back a string.\n * A connector that is not registered here cannot say which parameters are secret, so nothing of its\n * `params` is shown - an unknown is not read as \"nothing secret\".\n */\nexport function paramsVisibleTo(\n connection: { type?: string; edgeId?: string; params?: any } | null | undefined,\n reader: Reader\n): any {\n const params = connection?.params\n if (params === null || params === undefined || isAssignedEdge(connection, reader)) {\n return params\n }\n\n const secrets = secretParamNames(connection.type)\n if (!secrets) {\n return null\n }\n\n const asString = typeof params === 'string'\n let object: any = params\n if (asString) {\n try {\n object = JSON.parse(params)\n } catch (e) {\n return null\n }\n }\n\n if (!object || typeof object !== 'object') {\n return asString ? params : object\n }\n\n const visible = { ...object }\n for (const param of secrets) {\n delete visible[param]\n }\n\n return asString ? JSON.stringify(visible) : visible\n}\n\n/**\n * For each secret still held in `params` - written before ADR-0112 - the part that may be shown.\n *\n * Reading `params` leaves those secrets out, so the field on the screen is empty while the connection\n * keeps connecting with the old value. The screen shows these as the field's placeholder: the person\n * sees that a value is in use, and saving the form sends nothing back - a placeholder is not a value.\n *\n * `null` when there is none, and for a reader who receives `params` whole (the assigned edge).\n */\nexport function secretHintsOf(\n connection: { type?: string; edgeId?: string; params?: any } | null | undefined,\n reader: Reader\n): { [param: string]: string } | null {\n if (!connection?.params || isAssignedEdge(connection, reader)) {\n return null\n }\n\n let params: any = connection.params\n if (typeof params === 'string') {\n try {\n params = JSON.parse(params)\n } catch (e) {\n return null\n }\n }\n if (!params || typeof params !== 'object') {\n return null\n }\n\n const hints: { [param: string]: string } = {}\n for (const param of secretParamNames(connection.type) || []) {\n const hint = present(params[param]) ? secretHint(String(params[param])) : undefined\n if (hint) {\n hints[param] = hint\n }\n }\n\n return Object.keys(hints).length > 0 ? hints : null\n}\n"]}
|
|
@@ -9,7 +9,6 @@ const shell_1 = require("@things-factory/shell");
|
|
|
9
9
|
const connection_manager_1 = require("../../engine/connection-manager");
|
|
10
10
|
const connection_1 = require("./connection");
|
|
11
11
|
const connection_type_1 = require("./connection-type");
|
|
12
|
-
const domain_inheritance_1 = require("../../utils/domain-inheritance");
|
|
13
12
|
const debug = require('debug')('things-factory:integration:connection-subscription');
|
|
14
13
|
let ConnectionSubscription = class ConnectionSubscription {
|
|
15
14
|
connectionState(payload, name) {
|
|
@@ -36,7 +35,7 @@ tslib_1.__decorate([
|
|
|
36
35
|
}
|
|
37
36
|
// ancestor 도메인 ids 를 한 번만 계산하여 재사용 (subscribe 는 sync 라 lazy memoize)
|
|
38
37
|
let ancestorIdsPromise = null;
|
|
39
|
-
const resolveAncestorIds = () => (ancestorIdsPromise ||= (0,
|
|
38
|
+
const resolveAncestorIds = () => (ancestorIdsPromise ||= (0, shell_1.getDomainIdsWithAncestors)(domain));
|
|
40
39
|
process.nextTick(async () => {
|
|
41
40
|
const domainIds = await resolveAncestorIds();
|
|
42
41
|
var where = { domain: { id: (0, typeorm_1.In)(domainIds) } };
|