@things-factory/integration-base 10.0.0-zeta.3 → 10.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-server/controllers/scenario-controller.d.ts +2 -2
- package/dist-server/controllers/scenario-controller.js +19 -8
- package/dist-server/controllers/scenario-controller.js.map +1 -1
- package/dist-server/engine/analyzer/analyze-integration.js +6 -2
- package/dist-server/engine/analyzer/analyze-integration.js.map +1 -1
- package/dist-server/engine/connector/operato-connector.js +4 -1
- package/dist-server/engine/connector/operato-connector.js.map +1 -1
- package/dist-server/engine/scenario-engine.js +7 -2
- package/dist-server/engine/scenario-engine.js.map +1 -1
- package/dist-server/engine/task/pick-pending-scenario.js +6 -1
- package/dist-server/engine/task/pick-pending-scenario.js.map +1 -1
- package/dist-server/engine/task/stop-scenario.js +1 -1
- package/dist-server/engine/task/stop-scenario.js.map +1 -1
- package/dist-server/engine/task/sub-scenario.js +6 -1
- package/dist-server/engine/task/sub-scenario.js.map +1 -1
- package/dist-server/engine/task/switch-range-scenario.js +6 -1
- package/dist-server/engine/task/switch-range-scenario.js.map +1 -1
- package/dist-server/engine/task/switch-scenario.js +6 -1
- package/dist-server/engine/task/switch-scenario.js.map +1 -1
- package/dist-server/routers/scenario-schedule-callback-router.js +4 -1
- package/dist-server/routers/scenario-schedule-callback-router.js.map +1 -1
- package/dist-server/routers/scenario-view-router.js +4 -3
- package/dist-server/routers/scenario-view-router.js.map +1 -1
- package/dist-server/service/index.d.ts +4 -1
- package/dist-server/service/index.js +4 -1
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/service/scenario/event-subscriber.d.ts +22 -0
- package/dist-server/service/scenario/event-subscriber.js +49 -0
- package/dist-server/service/scenario/event-subscriber.js.map +1 -0
- package/dist-server/service/scenario/index.d.ts +6 -2
- package/dist-server/service/scenario/index.js +7 -3
- package/dist-server/service/scenario/index.js.map +1 -1
- package/dist-server/service/scenario/resolve-steps.d.ts +43 -0
- package/dist-server/service/scenario/resolve-steps.js +101 -0
- package/dist-server/service/scenario/resolve-steps.js.map +1 -0
- package/dist-server/service/scenario/scenario-history.d.ts +44 -0
- package/dist-server/service/scenario/scenario-history.js +167 -0
- package/dist-server/service/scenario/scenario-history.js.map +1 -0
- package/dist-server/service/scenario/scenario-mutation.d.ts +2 -0
- package/dist-server/service/scenario/scenario-mutation.js +150 -36
- package/dist-server/service/scenario/scenario-mutation.js.map +1 -1
- package/dist-server/service/scenario/scenario-query.js +8 -14
- package/dist-server/service/scenario/scenario-query.js.map +1 -1
- package/dist-server/service/scenario/scenario-version-diff.d.ts +8 -0
- package/dist-server/service/scenario/scenario-version-diff.js +107 -0
- package/dist-server/service/scenario/scenario-version-diff.js.map +1 -0
- package/dist-server/service/scenario/scenario-version-query.d.ts +11 -0
- package/dist-server/service/scenario/scenario-version-query.js +135 -0
- package/dist-server/service/scenario/scenario-version-query.js.map +1 -0
- package/dist-server/service/scenario/scenario-version-type.d.ts +18 -0
- package/dist-server/service/scenario/scenario-version-type.js +79 -0
- package/dist-server/service/scenario/scenario-version-type.js.map +1 -0
- package/dist-server/service/scenario/scenario.d.ts +23 -0
- package/dist-server/service/scenario/scenario.js +18 -3
- package/dist-server/service/scenario/scenario.js.map +1 -1
- package/dist-server/service/scenario-instance/scenario-instance-mutation.d.ts +2 -2
- package/dist-server/service/scenario-instance/scenario-instance-mutation.js +8 -6
- package/dist-server/service/scenario-instance/scenario-instance-mutation.js.map +1 -1
- package/dist-server/service/step/step-mutation.js +26 -13
- package/dist-server/service/step/step-mutation.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/dist-server/utils/version-text-column.d.ts +16 -0
- package/dist-server/utils/version-text-column.js +67 -0
- package/dist-server/utils/version-text-column.js.map +1 -0
- package/package.json +12 -11
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ScenarioQuery = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const type_graphql_1 = require("type-graphql");
|
|
6
|
-
const typeorm_1 = require("typeorm");
|
|
7
6
|
const auth_base_1 = require("@things-factory/auth-base");
|
|
8
7
|
const shell_1 = require("@things-factory/shell");
|
|
9
8
|
const engine_1 = require("../../engine");
|
|
@@ -12,6 +11,7 @@ const step_type_1 = require("../step/step-type");
|
|
|
12
11
|
const scenario_1 = require("./scenario");
|
|
13
12
|
const scenario_type_1 = require("./scenario-type");
|
|
14
13
|
const connection_1 = require("../connection/connection");
|
|
14
|
+
const resolve_steps_1 = require("./resolve-steps");
|
|
15
15
|
const domain_inheritance_1 = require("../../utils/domain-inheritance");
|
|
16
16
|
/**
|
|
17
17
|
* @description Provides GraphQL resolvers for the Scenario entity.
|
|
@@ -51,24 +51,18 @@ let ScenarioQuery = class ScenarioQuery {
|
|
|
51
51
|
return await (0, shell_1.getRepository)(auth_base_1.User).findOneBy({ id: scenario.creatorId });
|
|
52
52
|
}
|
|
53
53
|
async steps(scenario, _context) {
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
return await (0,
|
|
58
|
-
where: { scenario: { id: scenario.id } }
|
|
59
|
-
});
|
|
54
|
+
// [버전관리 / Option A] draft(작업본) 스텝을 반환.
|
|
55
|
+
// - scenario.steps(JSON) 있으면 사용, 없으면 레거시 Step 테이블에서 읽음(하위호환).
|
|
56
|
+
// 에디터는 draft 를 편집하므로 여기서 draft 를 노출한다(운영 실행은 released 스냅샷 사용).
|
|
57
|
+
return await (0, resolve_steps_1.resolveScenarioSteps)(scenario);
|
|
60
58
|
}
|
|
61
59
|
async connectionNames(scenario, _context) {
|
|
62
|
-
const steps = await (0,
|
|
63
|
-
where: { scenario: { id: scenario.id }, connection: (0, typeorm_1.Not)((0, typeorm_1.IsNull)()) }
|
|
64
|
-
});
|
|
60
|
+
const steps = await (0, resolve_steps_1.resolveScenarioSteps)(scenario);
|
|
65
61
|
return steps.map(step => step.connection).filter(Boolean);
|
|
66
62
|
}
|
|
67
63
|
async publishTags(scenario, _context) {
|
|
68
|
-
const steps = await (0,
|
|
69
|
-
|
|
70
|
-
});
|
|
71
|
-
return steps.map(step => step.params?.tag).filter(Boolean);
|
|
64
|
+
const steps = await (0, resolve_steps_1.resolveScenarioSteps)(scenario);
|
|
65
|
+
return steps.filter(step => step.task == 'publish').map(step => step.params?.tag).filter(Boolean);
|
|
72
66
|
}
|
|
73
67
|
async state(scenario, context) {
|
|
74
68
|
const { domain } = context.state;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scenario-query.js","sourceRoot":"","sources":["../../../server/service/scenario/scenario-query.ts"],"names":[],"mappings":";;;;AAAA,+CAA8F;
|
|
1
|
+
{"version":3,"file":"scenario-query.js","sourceRoot":"","sources":["../../../server/service/scenario/scenario-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Args, Ctx, Directive, FieldResolver, Query, Resolver, Root } from 'type-graphql'\n\nimport { User, Role } from '@things-factory/auth-base'\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'\n\nimport { ScenarioEngine } from '../../engine'\nimport { ScenarioInstance, ScenarioInstanceStatus } from '../scenario-instance/scenario-instance-type'\nimport { Step } from '../step/step-type'\nimport { Scenario } from './scenario'\nimport { ScenarioList } from './scenario-type'\nimport { Connection } from '../connection/connection'\nimport { resolveScenarioSteps } from './resolve-steps'\nimport { getDomainIdsWithAncestors } from '../../utils/domain-inheritance'\n\n/**\n * @description Provides GraphQL resolvers for the Scenario entity.\n */\n@Resolver(Scenario)\nexport class ScenarioQuery {\n @Directive('@privilege(category: \"scenario\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => Scenario, { description: 'Fetches a single scenario by its ID.' })\n async scenario(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Scenario> {\n const { domain } = context.state\n const domainIds = await getDomainIdsWithAncestors(domain)\n\n const scenario = await getRepository(Scenario).findOne({ where: { id } })\n if (scenario && domainIds.includes(scenario.domainId)) {\n return scenario\n }\n }\n\n @Directive('@privilege(category: \"scenario\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => ScenarioList, { description: 'Fetches a paginated list of scenarios.' })\n async scenarios(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<ScenarioList> {\n const { domain } = context.state\n const domainIds = await getDomainIdsWithAncestors(domain)\n\n const queryBuilder = getQueryBuilderFromListParams({\n repository: getRepository(Scenario),\n params,\n // 도메인 필터링은 ancestor 기반으로 직접 적용\n domain: undefined,\n searchables: ['name', 'description', 'type']\n })\n\n queryBuilder.andWhere(`${queryBuilder.alias}.domain IN (:...ancestorDomainIds)`, {\n ancestorDomainIds: domainIds\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() scenario: Scenario) {\n return await getRepository(Domain).findOneBy({ id: scenario.domainId })\n }\n\n @FieldResolver(type => User)\n async updater(@Root() scenario: Scenario): Promise<User> {\n return await getRepository(User).findOneBy({ id: scenario.updaterId })\n }\n\n @FieldResolver(type => User)\n async creator(@Root() scenario: Scenario): Promise<User> {\n return await getRepository(User).findOneBy({ id: scenario.creatorId })\n }\n\n @FieldResolver(type => [Step])\n async steps(@Root() scenario: Scenario, @Ctx() _context: ResolverContext): Promise<Step[]> {\n // [버전관리 / Option A] draft(작업본) 스텝을 반환.\n // - scenario.steps(JSON) 있으면 사용, 없으면 레거시 Step 테이블에서 읽음(하위호환).\n // 에디터는 draft 를 편집하므로 여기서 draft 를 노출한다(운영 실행은 released 스냅샷 사용).\n return await resolveScenarioSteps(scenario)\n }\n\n @FieldResolver(type => [Connection])\n async connectionNames(@Root() scenario: Scenario, @Ctx() _context: ResolverContext) {\n const steps = await resolveScenarioSteps(scenario)\n return steps.map(step => step.connection).filter(Boolean)\n }\n\n @FieldResolver(type => [Connection])\n async publishTags(@Root() scenario: Scenario, @Ctx() _context: ResolverContext) {\n const steps = await resolveScenarioSteps(scenario)\n return steps.filter(step => step.task == 'publish').map(step => step.params?.tag).filter(Boolean)\n }\n\n @FieldResolver(type => String, { nullable: true })\n async state(@Root() scenario: Scenario, @Ctx() context: ResolverContext): Promise<string> {\n const { domain } = context.state\n\n var instance = ScenarioEngine.getScenarioInstance(domain, scenario.name)\n return instance && ScenarioInstanceStatus[instance.context?.state]\n }\n\n @FieldResolver(type => [ScenarioInstance], { nullable: true })\n async instances(@Root() scenario: Scenario, @Ctx() context: ResolverContext): Promise<ScenarioInstance[]> {\n const { domain } = context.state\n\n return ScenarioEngine.getScenarioInstances(domain, scenario.name)\n }\n\n @FieldResolver(type => Role)\n async role(@Root() scenario: Scenario) {\n return scenario.roleId && (await getRepository(Role).findOneBy({ id: scenario.roleId }))\n }\n}\n"]}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ScenarioFieldDiff, ScenarioStepDiff } from './scenario-version-type';
|
|
2
|
+
export declare function diffScenarioMeta(base: any, target: any): ScenarioFieldDiff[];
|
|
3
|
+
/**
|
|
4
|
+
* diff 를 사람이 읽을 수 있는 짧은 요약 문자열로 만든다 — 릴리즈 코멘트 자동 초기값용.
|
|
5
|
+
* 기호 중심(언어 중립): `steps +2 −1 ~3 · fields 1`. 변경 없으면 'released'.
|
|
6
|
+
*/
|
|
7
|
+
export declare function summarizeScenarioDiff(fieldDiffs: ScenarioFieldDiff[], stepDiffs: ScenarioStepDiff[]): string;
|
|
8
|
+
export declare function diffScenarioSteps(baseSteps: any[], targetSteps: any[]): ScenarioStepDiff[];
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.diffScenarioMeta = diffScenarioMeta;
|
|
4
|
+
exports.summarizeScenarioDiff = summarizeScenarioDiff;
|
|
5
|
+
exports.diffScenarioSteps = diffScenarioSteps;
|
|
6
|
+
const tslib_1 = require("tslib");
|
|
7
|
+
const isEqual_1 = tslib_1.__importDefault(require("lodash/isEqual"));
|
|
8
|
+
/**
|
|
9
|
+
* 시나리오 버전 diff 순수 로직 (DB 접근 없음 — 단위 테스트 용이).
|
|
10
|
+
*
|
|
11
|
+
* 스텝 identity 는 이름(name) 기준. 이름이 없거나 중복이면 위치 인덱스로 보정.
|
|
12
|
+
* board 의 model diff 와 달리 시나리오는 스텝 배열이므로 항목 단위(added/removed/modified)로 비교한다.
|
|
13
|
+
*/
|
|
14
|
+
// name 포함 — 시나리오 rename 도 버전 변경으로 잡아야 함(이름만 바뀐 릴리즈가 "no difference" 로 나오던 버그).
|
|
15
|
+
const SCENARIO_META_FIELDS = ['name', 'description', 'type', 'schedule', 'timezone', 'ttl', 'iteration'];
|
|
16
|
+
// description 포함 — step 설명 변경도 내용 변경. (domainId/createdAt 등 레거시 잔재는 의도적으로 제외.)
|
|
17
|
+
const STEP_CONTENT_FIELDS = ['description', 'task', 'connection', 'skip', 'log', 'result', 'sequence', 'params'];
|
|
18
|
+
function stepKey(step, index) {
|
|
19
|
+
const name = step?.name;
|
|
20
|
+
return name === undefined || name === null || name === '' ? `#${index}` : String(name);
|
|
21
|
+
}
|
|
22
|
+
/** diff/표시에서 노이즈가 되는 휘발성 필드(id 등) 제거 */
|
|
23
|
+
function cleanStep(step) {
|
|
24
|
+
if (!step)
|
|
25
|
+
return step;
|
|
26
|
+
const { id, ...rest } = step;
|
|
27
|
+
return rest;
|
|
28
|
+
}
|
|
29
|
+
function diffScenarioMeta(base, target) {
|
|
30
|
+
const diffs = [];
|
|
31
|
+
for (const field of SCENARIO_META_FIELDS) {
|
|
32
|
+
const before = base?.[field] ?? null;
|
|
33
|
+
const after = target?.[field] ?? null;
|
|
34
|
+
if (!(0, isEqual_1.default)(before, after)) {
|
|
35
|
+
diffs.push({ field, before, after });
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return diffs;
|
|
39
|
+
}
|
|
40
|
+
function diffStepFields(base, target) {
|
|
41
|
+
const diffs = [];
|
|
42
|
+
for (const field of STEP_CONTENT_FIELDS) {
|
|
43
|
+
const before = base?.[field] ?? null;
|
|
44
|
+
const after = target?.[field] ?? null;
|
|
45
|
+
if (!(0, isEqual_1.default)(before, after)) {
|
|
46
|
+
diffs.push({ field, before, after });
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return diffs;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* diff 를 사람이 읽을 수 있는 짧은 요약 문자열로 만든다 — 릴리즈 코멘트 자동 초기값용.
|
|
53
|
+
* 기호 중심(언어 중립): `steps +2 −1 ~3 · fields 1`. 변경 없으면 'released'.
|
|
54
|
+
*/
|
|
55
|
+
function summarizeScenarioDiff(fieldDiffs, stepDiffs) {
|
|
56
|
+
const added = stepDiffs.filter(d => d.changeType === 'added').length;
|
|
57
|
+
const removed = stepDiffs.filter(d => d.changeType === 'removed').length;
|
|
58
|
+
const modified = stepDiffs.filter(d => d.changeType === 'modified').length;
|
|
59
|
+
const stepBits = [];
|
|
60
|
+
if (added)
|
|
61
|
+
stepBits.push(`+${added}`);
|
|
62
|
+
if (removed)
|
|
63
|
+
stepBits.push(`−${removed}`);
|
|
64
|
+
if (modified)
|
|
65
|
+
stepBits.push(`~${modified}`);
|
|
66
|
+
const parts = [];
|
|
67
|
+
if (stepBits.length)
|
|
68
|
+
parts.push(`steps ${stepBits.join(' ')}`);
|
|
69
|
+
if (fieldDiffs.length)
|
|
70
|
+
parts.push(`fields ${fieldDiffs.length}`);
|
|
71
|
+
return parts.length ? parts.join(' · ') : 'released';
|
|
72
|
+
}
|
|
73
|
+
function diffScenarioSteps(baseSteps, targetSteps) {
|
|
74
|
+
const base = Array.isArray(baseSteps) ? baseSteps : [];
|
|
75
|
+
const target = Array.isArray(targetSteps) ? targetSteps : [];
|
|
76
|
+
const baseMap = new Map();
|
|
77
|
+
base.forEach((s, i) => baseMap.set(stepKey(s, i), s));
|
|
78
|
+
const targetMap = new Map();
|
|
79
|
+
target.forEach((s, i) => targetMap.set(stepKey(s, i), s));
|
|
80
|
+
const diffs = [];
|
|
81
|
+
// removed: base 에 있고 target 에 없음
|
|
82
|
+
for (const [key, step] of baseMap) {
|
|
83
|
+
if (!targetMap.has(key)) {
|
|
84
|
+
diffs.push({ name: step?.name, changeType: 'removed', before: cleanStep(step) });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// added / modified
|
|
88
|
+
for (const [key, step] of targetMap) {
|
|
89
|
+
if (!baseMap.has(key)) {
|
|
90
|
+
diffs.push({ name: step?.name, changeType: 'added', after: cleanStep(step) });
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
const baseStep = baseMap.get(key);
|
|
94
|
+
const fieldDiffs = diffStepFields(baseStep, step);
|
|
95
|
+
if (fieldDiffs.length > 0) {
|
|
96
|
+
diffs.push({
|
|
97
|
+
name: step?.name,
|
|
98
|
+
changeType: 'modified',
|
|
99
|
+
before: cleanStep(baseStep),
|
|
100
|
+
after: cleanStep(step),
|
|
101
|
+
fieldDiffs
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return diffs;
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=scenario-version-diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenario-version-diff.js","sourceRoot":"","sources":["../../../server/service/scenario/scenario-version-diff.ts"],"names":[],"mappings":"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","sourcesContent":["import isEqual from 'lodash/isEqual'\n\nimport { ScenarioFieldDiff, ScenarioStepDiff } from './scenario-version-type'\n\n/**\n * 시나리오 버전 diff 순수 로직 (DB 접근 없음 — 단위 테스트 용이).\n *\n * 스텝 identity 는 이름(name) 기준. 이름이 없거나 중복이면 위치 인덱스로 보정.\n * board 의 model diff 와 달리 시나리오는 스텝 배열이므로 항목 단위(added/removed/modified)로 비교한다.\n */\n\n// name 포함 — 시나리오 rename 도 버전 변경으로 잡아야 함(이름만 바뀐 릴리즈가 \"no difference\" 로 나오던 버그).\nconst SCENARIO_META_FIELDS = ['name', 'description', 'type', 'schedule', 'timezone', 'ttl', 'iteration'] as const\n// description 포함 — step 설명 변경도 내용 변경. (domainId/createdAt 등 레거시 잔재는 의도적으로 제외.)\nconst STEP_CONTENT_FIELDS = ['description', 'task', 'connection', 'skip', 'log', 'result', 'sequence', 'params'] as const\n\nfunction stepKey(step: any, index: number): string {\n const name = step?.name\n return name === undefined || name === null || name === '' ? `#${index}` : String(name)\n}\n\n/** diff/표시에서 노이즈가 되는 휘발성 필드(id 등) 제거 */\nfunction cleanStep(step: any): any {\n if (!step) return step\n const { id, ...rest } = step\n return rest\n}\n\nexport function diffScenarioMeta(base: any, target: any): ScenarioFieldDiff[] {\n const diffs: ScenarioFieldDiff[] = []\n for (const field of SCENARIO_META_FIELDS) {\n const before = base?.[field] ?? null\n const after = target?.[field] ?? null\n if (!isEqual(before, after)) {\n diffs.push({ field, before, after })\n }\n }\n return diffs\n}\n\nfunction diffStepFields(base: any, target: any): ScenarioFieldDiff[] {\n const diffs: ScenarioFieldDiff[] = []\n for (const field of STEP_CONTENT_FIELDS) {\n const before = base?.[field] ?? null\n const after = target?.[field] ?? null\n if (!isEqual(before, after)) {\n diffs.push({ field, before, after })\n }\n }\n return diffs\n}\n\n/**\n * diff 를 사람이 읽을 수 있는 짧은 요약 문자열로 만든다 — 릴리즈 코멘트 자동 초기값용.\n * 기호 중심(언어 중립): `steps +2 −1 ~3 · fields 1`. 변경 없으면 'released'.\n */\nexport function summarizeScenarioDiff(fieldDiffs: ScenarioFieldDiff[], stepDiffs: ScenarioStepDiff[]): string {\n const added = stepDiffs.filter(d => d.changeType === 'added').length\n const removed = stepDiffs.filter(d => d.changeType === 'removed').length\n const modified = stepDiffs.filter(d => d.changeType === 'modified').length\n\n const stepBits: string[] = []\n if (added) stepBits.push(`+${added}`)\n if (removed) stepBits.push(`−${removed}`)\n if (modified) stepBits.push(`~${modified}`)\n\n const parts: string[] = []\n if (stepBits.length) parts.push(`steps ${stepBits.join(' ')}`)\n if (fieldDiffs.length) parts.push(`fields ${fieldDiffs.length}`)\n\n return parts.length ? parts.join(' · ') : 'released'\n}\n\nexport function diffScenarioSteps(baseSteps: any[], targetSteps: any[]): ScenarioStepDiff[] {\n const base = Array.isArray(baseSteps) ? baseSteps : []\n const target = Array.isArray(targetSteps) ? targetSteps : []\n\n const baseMap = new Map<string, any>()\n base.forEach((s, i) => baseMap.set(stepKey(s, i), s))\n const targetMap = new Map<string, any>()\n target.forEach((s, i) => targetMap.set(stepKey(s, i), s))\n\n const diffs: ScenarioStepDiff[] = []\n\n // removed: base 에 있고 target 에 없음\n for (const [key, step] of baseMap) {\n if (!targetMap.has(key)) {\n diffs.push({ name: step?.name, changeType: 'removed', before: cleanStep(step) })\n }\n }\n\n // added / modified\n for (const [key, step] of targetMap) {\n if (!baseMap.has(key)) {\n diffs.push({ name: step?.name, changeType: 'added', after: cleanStep(step) })\n continue\n }\n const baseStep = baseMap.get(key)\n const fieldDiffs = diffStepFields(baseStep, step)\n if (fieldDiffs.length > 0) {\n diffs.push({\n name: step?.name,\n changeType: 'modified',\n before: cleanStep(baseStep),\n after: cleanStep(step),\n fieldDiffs\n })\n }\n }\n\n return diffs\n}\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ScenarioHistory } from './scenario-history';
|
|
2
|
+
import { ScenarioVersionDiff } from './scenario-version-type';
|
|
3
|
+
/**
|
|
4
|
+
* 시나리오 버전(릴리즈 스냅샷) 조회 및 diff 리졸버.
|
|
5
|
+
*/
|
|
6
|
+
export declare class ScenarioVersionQuery {
|
|
7
|
+
scenarioVersions(id: string, context: ResolverContext): Promise<ScenarioHistory[]>;
|
|
8
|
+
scenarioPublished(id: string, context: ResolverContext): Promise<ScenarioHistory | null>;
|
|
9
|
+
scenarioVersion(id: string, version: number, context: ResolverContext): Promise<ScenarioHistory | null>;
|
|
10
|
+
scenarioVersionDiff(id: string, version: number, context: ResolverContext, toVersion?: number): Promise<ScenarioVersionDiff>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ScenarioVersionQuery = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const type_graphql_1 = require("type-graphql");
|
|
6
|
+
const typeorm_1 = require("typeorm");
|
|
7
|
+
const shell_1 = require("@things-factory/shell");
|
|
8
|
+
const domain_inheritance_1 = require("../../utils/domain-inheritance");
|
|
9
|
+
const scenario_1 = require("./scenario");
|
|
10
|
+
const scenario_history_1 = require("./scenario-history");
|
|
11
|
+
const resolve_steps_1 = require("./resolve-steps");
|
|
12
|
+
const scenario_version_type_1 = require("./scenario-version-type");
|
|
13
|
+
const scenario_version_diff_1 = require("./scenario-version-diff");
|
|
14
|
+
/**
|
|
15
|
+
* 시나리오 버전(릴리즈 스냅샷) 조회 및 diff 리졸버.
|
|
16
|
+
*/
|
|
17
|
+
let ScenarioVersionQuery = class ScenarioVersionQuery {
|
|
18
|
+
async scenarioVersions(id, context) {
|
|
19
|
+
const { domain } = context.state;
|
|
20
|
+
const domainIds = await (0, domain_inheritance_1.getDomainIdsWithAncestors)(domain);
|
|
21
|
+
return await (0, shell_1.getRepository)(scenario_history_1.ScenarioHistory).find({
|
|
22
|
+
where: { originalId: id, domain: { id: (0, typeorm_1.In)(domainIds) } },
|
|
23
|
+
relations: ['updater', 'creator'],
|
|
24
|
+
order: { version: 'DESC' },
|
|
25
|
+
take: 20
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
async scenarioPublished(id, context) {
|
|
29
|
+
const { domain } = context.state;
|
|
30
|
+
const domainIds = await (0, domain_inheritance_1.getDomainIdsWithAncestors)(domain);
|
|
31
|
+
return await (0, shell_1.getRepository)(scenario_history_1.ScenarioHistory).findOne({
|
|
32
|
+
where: { originalId: id, domain: { id: (0, typeorm_1.In)(domainIds) } },
|
|
33
|
+
relations: ['updater', 'creator'],
|
|
34
|
+
order: { version: 'DESC' }
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
async scenarioVersion(id, version, context) {
|
|
38
|
+
const { domain } = context.state;
|
|
39
|
+
const domainIds = await (0, domain_inheritance_1.getDomainIdsWithAncestors)(domain);
|
|
40
|
+
return await (0, shell_1.getRepository)(scenario_history_1.ScenarioHistory).findOne({
|
|
41
|
+
where: { originalId: id, version, domain: { id: (0, typeorm_1.In)(domainIds) } },
|
|
42
|
+
relations: ['updater', 'creator']
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
async scenarioVersionDiff(id, version, context, toVersion) {
|
|
46
|
+
const { domain } = context.state;
|
|
47
|
+
const domainIds = await (0, domain_inheritance_1.getDomainIdsWithAncestors)(domain);
|
|
48
|
+
const historyRepo = (0, shell_1.getRepository)(scenario_history_1.ScenarioHistory);
|
|
49
|
+
const base = await historyRepo.findOne({
|
|
50
|
+
where: { originalId: id, version, domain: { id: (0, typeorm_1.In)(domainIds) } }
|
|
51
|
+
});
|
|
52
|
+
if (!base) {
|
|
53
|
+
throw new Error(`Scenario version (${id}:${version}) is not found`);
|
|
54
|
+
}
|
|
55
|
+
let target;
|
|
56
|
+
if (toVersion !== undefined && toVersion !== null) {
|
|
57
|
+
target = await historyRepo.findOne({
|
|
58
|
+
where: { originalId: id, version: toVersion, domain: { id: (0, typeorm_1.In)(domainIds) } }
|
|
59
|
+
});
|
|
60
|
+
if (!target) {
|
|
61
|
+
throw new Error(`Scenario version (${id}:${toVersion}) is not found`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// 현재 draft 와 비교
|
|
66
|
+
const scenario = await (0, shell_1.getRepository)(scenario_1.Scenario).findOne({ where: { id } });
|
|
67
|
+
if (!scenario || !domainIds.includes(scenario.domainId)) {
|
|
68
|
+
throw new Error(`Scenario (${id}) is not found`);
|
|
69
|
+
}
|
|
70
|
+
const draftSteps = await (0, resolve_steps_1.resolveScenarioSteps)(scenario);
|
|
71
|
+
target = { ...scenario, steps: draftSteps };
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
fromVersion: version,
|
|
75
|
+
toVersion: toVersion ?? null,
|
|
76
|
+
fieldDiffs: (0, scenario_version_diff_1.diffScenarioMeta)(base, target),
|
|
77
|
+
stepDiffs: (0, scenario_version_diff_1.diffScenarioSteps)(base.steps, target.steps)
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
exports.ScenarioVersionQuery = ScenarioVersionQuery;
|
|
82
|
+
tslib_1.__decorate([
|
|
83
|
+
(0, type_graphql_1.Directive)('@privilege(category: "scenario", privilege: "query", domainOwnerGranted: true)'),
|
|
84
|
+
(0, type_graphql_1.Query)(returns => [scenario_history_1.ScenarioHistory], {
|
|
85
|
+
description: 'Fetches recent released versions (snapshots) of a scenario, newest first.'
|
|
86
|
+
}),
|
|
87
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
|
|
88
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
89
|
+
tslib_1.__metadata("design:type", Function),
|
|
90
|
+
tslib_1.__metadata("design:paramtypes", [String, Object]),
|
|
91
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
92
|
+
], ScenarioVersionQuery.prototype, "scenarioVersions", null);
|
|
93
|
+
tslib_1.__decorate([
|
|
94
|
+
(0, type_graphql_1.Directive)('@privilege(category: "scenario", privilege: "query", domainOwnerGranted: true)'),
|
|
95
|
+
(0, type_graphql_1.Query)(returns => scenario_history_1.ScenarioHistory, {
|
|
96
|
+
nullable: true,
|
|
97
|
+
description: 'Fetches the most recently released version (snapshot) of a scenario.'
|
|
98
|
+
}),
|
|
99
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
|
|
100
|
+
tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
|
|
101
|
+
tslib_1.__metadata("design:type", Function),
|
|
102
|
+
tslib_1.__metadata("design:paramtypes", [String, Object]),
|
|
103
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
104
|
+
], ScenarioVersionQuery.prototype, "scenarioPublished", null);
|
|
105
|
+
tslib_1.__decorate([
|
|
106
|
+
(0, type_graphql_1.Directive)('@privilege(category: "scenario", privilege: "query", domainOwnerGranted: true)'),
|
|
107
|
+
(0, type_graphql_1.Query)(returns => scenario_history_1.ScenarioHistory, {
|
|
108
|
+
nullable: true,
|
|
109
|
+
description: 'Fetches a specific released version (snapshot) of a scenario by version number.'
|
|
110
|
+
}),
|
|
111
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
|
|
112
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('version', type => type_graphql_1.Int)),
|
|
113
|
+
tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
|
|
114
|
+
tslib_1.__metadata("design:type", Function),
|
|
115
|
+
tslib_1.__metadata("design:paramtypes", [String, Number, Object]),
|
|
116
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
117
|
+
], ScenarioVersionQuery.prototype, "scenarioVersion", null);
|
|
118
|
+
tslib_1.__decorate([
|
|
119
|
+
(0, type_graphql_1.Directive)('@privilege(category: "scenario", privilege: "query", domainOwnerGranted: true)'),
|
|
120
|
+
(0, type_graphql_1.Query)(returns => scenario_version_type_1.ScenarioVersionDiff, {
|
|
121
|
+
description: 'Computes the difference between a released version and either another released version or the current draft. ' +
|
|
122
|
+
'Omit toVersion to diff the base version against the current draft.'
|
|
123
|
+
}),
|
|
124
|
+
tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
|
|
125
|
+
tslib_1.__param(1, (0, type_graphql_1.Arg)('version', type => type_graphql_1.Int)),
|
|
126
|
+
tslib_1.__param(2, (0, type_graphql_1.Ctx)()),
|
|
127
|
+
tslib_1.__param(3, (0, type_graphql_1.Arg)('toVersion', type => type_graphql_1.Int, { nullable: true })),
|
|
128
|
+
tslib_1.__metadata("design:type", Function),
|
|
129
|
+
tslib_1.__metadata("design:paramtypes", [String, Number, Object, Number]),
|
|
130
|
+
tslib_1.__metadata("design:returntype", Promise)
|
|
131
|
+
], ScenarioVersionQuery.prototype, "scenarioVersionDiff", null);
|
|
132
|
+
exports.ScenarioVersionQuery = ScenarioVersionQuery = tslib_1.__decorate([
|
|
133
|
+
(0, type_graphql_1.Resolver)()
|
|
134
|
+
], ScenarioVersionQuery);
|
|
135
|
+
//# sourceMappingURL=scenario-version-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenario-version-query.js","sourceRoot":"","sources":["../../../server/service/scenario/scenario-version-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Directive, Int, Query, Resolver } from 'type-graphql'\nimport { In } from 'typeorm'\n\nimport { getRepository } from '@things-factory/shell'\n\nimport { getDomainIdsWithAncestors } from '../../utils/domain-inheritance'\nimport { Scenario } from './scenario'\nimport { ScenarioHistory } from './scenario-history'\nimport { resolveScenarioSteps } from './resolve-steps'\nimport { ScenarioVersionDiff } from './scenario-version-type'\nimport { diffScenarioMeta, diffScenarioSteps } from './scenario-version-diff'\n\n/**\n * 시나리오 버전(릴리즈 스냅샷) 조회 및 diff 리졸버.\n */\n@Resolver()\nexport class ScenarioVersionQuery {\n @Directive('@privilege(category: \"scenario\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => [ScenarioHistory], {\n description: 'Fetches recent released versions (snapshots) of a scenario, newest first.'\n })\n async scenarioVersions(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<ScenarioHistory[]> {\n const { domain } = context.state\n const domainIds = await getDomainIdsWithAncestors(domain)\n\n return await getRepository(ScenarioHistory).find({\n where: { originalId: id, domain: { id: In(domainIds) } },\n relations: ['updater', 'creator'],\n order: { version: 'DESC' },\n take: 20\n })\n }\n\n @Directive('@privilege(category: \"scenario\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => ScenarioHistory, {\n nullable: true,\n description: 'Fetches the most recently released version (snapshot) of a scenario.'\n })\n async scenarioPublished(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<ScenarioHistory | null> {\n const { domain } = context.state\n const domainIds = await getDomainIdsWithAncestors(domain)\n\n return await getRepository(ScenarioHistory).findOne({\n where: { originalId: id, domain: { id: In(domainIds) } },\n relations: ['updater', 'creator'],\n order: { version: 'DESC' }\n })\n }\n\n @Directive('@privilege(category: \"scenario\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => ScenarioHistory, {\n nullable: true,\n description: 'Fetches a specific released version (snapshot) of a scenario by version number.'\n })\n async scenarioVersion(\n @Arg('id') id: string,\n @Arg('version', type => Int) version: number,\n @Ctx() context: ResolverContext\n ): Promise<ScenarioHistory | null> {\n const { domain } = context.state\n const domainIds = await getDomainIdsWithAncestors(domain)\n\n return await getRepository(ScenarioHistory).findOne({\n where: { originalId: id, version, domain: { id: In(domainIds) } },\n relations: ['updater', 'creator']\n })\n }\n\n @Directive('@privilege(category: \"scenario\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => ScenarioVersionDiff, {\n description:\n 'Computes the difference between a released version and either another released version or the current draft. ' +\n 'Omit toVersion to diff the base version against the current draft.'\n })\n async scenarioVersionDiff(\n @Arg('id') id: string,\n @Arg('version', type => Int) version: number,\n @Ctx() context: ResolverContext,\n @Arg('toVersion', type => Int, { nullable: true }) toVersion?: number\n ): Promise<ScenarioVersionDiff> {\n const { domain } = context.state\n const domainIds = await getDomainIdsWithAncestors(domain)\n const historyRepo = getRepository(ScenarioHistory)\n\n const base = await historyRepo.findOne({\n where: { originalId: id, version, domain: { id: In(domainIds) } }\n })\n if (!base) {\n throw new Error(`Scenario version (${id}:${version}) is not found`)\n }\n\n let target: any\n if (toVersion !== undefined && toVersion !== null) {\n target = await historyRepo.findOne({\n where: { originalId: id, version: toVersion, domain: { id: In(domainIds) } }\n })\n if (!target) {\n throw new Error(`Scenario version (${id}:${toVersion}) is not found`)\n }\n } else {\n // 현재 draft 와 비교\n const scenario = await getRepository(Scenario).findOne({ where: { id } })\n if (!scenario || !domainIds.includes(scenario.domainId)) {\n throw new Error(`Scenario (${id}) is not found`)\n }\n const draftSteps = await resolveScenarioSteps(scenario)\n target = { ...scenario, steps: draftSteps }\n }\n\n return {\n fromVersion: version,\n toVersion: toVersion ?? null,\n fieldDiffs: diffScenarioMeta(base, target),\n stepDiffs: diffScenarioSteps(base.steps as any[], target.steps as any[])\n }\n }\n}\n"]}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare class ScenarioFieldDiff {
|
|
2
|
+
field: string;
|
|
3
|
+
before?: any;
|
|
4
|
+
after?: any;
|
|
5
|
+
}
|
|
6
|
+
export declare class ScenarioStepDiff {
|
|
7
|
+
name?: string;
|
|
8
|
+
changeType: 'added' | 'removed' | 'modified';
|
|
9
|
+
before?: any;
|
|
10
|
+
after?: any;
|
|
11
|
+
fieldDiffs?: ScenarioFieldDiff[];
|
|
12
|
+
}
|
|
13
|
+
export declare class ScenarioVersionDiff {
|
|
14
|
+
fromVersion: number;
|
|
15
|
+
toVersion?: number;
|
|
16
|
+
fieldDiffs: ScenarioFieldDiff[];
|
|
17
|
+
stepDiffs: ScenarioStepDiff[];
|
|
18
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ScenarioVersionDiff = exports.ScenarioStepDiff = exports.ScenarioFieldDiff = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const type_graphql_1 = require("type-graphql");
|
|
6
|
+
const shell_1 = require("@things-factory/shell");
|
|
7
|
+
let ScenarioFieldDiff = class ScenarioFieldDiff {
|
|
8
|
+
};
|
|
9
|
+
exports.ScenarioFieldDiff = ScenarioFieldDiff;
|
|
10
|
+
tslib_1.__decorate([
|
|
11
|
+
(0, type_graphql_1.Field)({ description: 'The name of the field that changed (e.g. description, schedule, steps).' }),
|
|
12
|
+
tslib_1.__metadata("design:type", String)
|
|
13
|
+
], ScenarioFieldDiff.prototype, "field", void 0);
|
|
14
|
+
tslib_1.__decorate([
|
|
15
|
+
(0, type_graphql_1.Field)(type => shell_1.ScalarObject, { nullable: true, description: 'The value before (in the base version).' }),
|
|
16
|
+
tslib_1.__metadata("design:type", Object)
|
|
17
|
+
], ScenarioFieldDiff.prototype, "before", void 0);
|
|
18
|
+
tslib_1.__decorate([
|
|
19
|
+
(0, type_graphql_1.Field)(type => shell_1.ScalarObject, { nullable: true, description: 'The value after (in the target version/draft).' }),
|
|
20
|
+
tslib_1.__metadata("design:type", Object)
|
|
21
|
+
], ScenarioFieldDiff.prototype, "after", void 0);
|
|
22
|
+
exports.ScenarioFieldDiff = ScenarioFieldDiff = tslib_1.__decorate([
|
|
23
|
+
(0, type_graphql_1.ObjectType)({ description: 'A single scenario field difference between two versions.' })
|
|
24
|
+
], ScenarioFieldDiff);
|
|
25
|
+
let ScenarioStepDiff = class ScenarioStepDiff {
|
|
26
|
+
};
|
|
27
|
+
exports.ScenarioStepDiff = ScenarioStepDiff;
|
|
28
|
+
tslib_1.__decorate([
|
|
29
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'The step name (identity used for diffing).' }),
|
|
30
|
+
tslib_1.__metadata("design:type", String)
|
|
31
|
+
], ScenarioStepDiff.prototype, "name", void 0);
|
|
32
|
+
tslib_1.__decorate([
|
|
33
|
+
(0, type_graphql_1.Field)({ description: "The kind of change: 'added', 'removed', or 'modified'." }),
|
|
34
|
+
tslib_1.__metadata("design:type", String)
|
|
35
|
+
], ScenarioStepDiff.prototype, "changeType", void 0);
|
|
36
|
+
tslib_1.__decorate([
|
|
37
|
+
(0, type_graphql_1.Field)(type => shell_1.ScalarObject, { nullable: true, description: 'The step as it was in the base version.' }),
|
|
38
|
+
tslib_1.__metadata("design:type", Object)
|
|
39
|
+
], ScenarioStepDiff.prototype, "before", void 0);
|
|
40
|
+
tslib_1.__decorate([
|
|
41
|
+
(0, type_graphql_1.Field)(type => shell_1.ScalarObject, { nullable: true, description: 'The step as it is in the target version/draft.' }),
|
|
42
|
+
tslib_1.__metadata("design:type", Object)
|
|
43
|
+
], ScenarioStepDiff.prototype, "after", void 0);
|
|
44
|
+
tslib_1.__decorate([
|
|
45
|
+
(0, type_graphql_1.Field)(type => [ScenarioFieldDiff], {
|
|
46
|
+
nullable: true,
|
|
47
|
+
description: 'Field-level changes within a modified step (task, connection, params, ...).'
|
|
48
|
+
}),
|
|
49
|
+
tslib_1.__metadata("design:type", Array)
|
|
50
|
+
], ScenarioStepDiff.prototype, "fieldDiffs", void 0);
|
|
51
|
+
exports.ScenarioStepDiff = ScenarioStepDiff = tslib_1.__decorate([
|
|
52
|
+
(0, type_graphql_1.ObjectType)({ description: 'A single step difference between two scenario versions, keyed by step name.' })
|
|
53
|
+
], ScenarioStepDiff);
|
|
54
|
+
let ScenarioVersionDiff = class ScenarioVersionDiff {
|
|
55
|
+
};
|
|
56
|
+
exports.ScenarioVersionDiff = ScenarioVersionDiff;
|
|
57
|
+
tslib_1.__decorate([
|
|
58
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.Int, { description: 'The base version number being compared from.' }),
|
|
59
|
+
tslib_1.__metadata("design:type", Number)
|
|
60
|
+
], ScenarioVersionDiff.prototype, "fromVersion", void 0);
|
|
61
|
+
tslib_1.__decorate([
|
|
62
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.Int, {
|
|
63
|
+
nullable: true,
|
|
64
|
+
description: 'The target version number being compared to. Null means the current draft.'
|
|
65
|
+
}),
|
|
66
|
+
tslib_1.__metadata("design:type", Number)
|
|
67
|
+
], ScenarioVersionDiff.prototype, "toVersion", void 0);
|
|
68
|
+
tslib_1.__decorate([
|
|
69
|
+
(0, type_graphql_1.Field)(type => [ScenarioFieldDiff], { description: 'Scenario-level field changes.' }),
|
|
70
|
+
tslib_1.__metadata("design:type", Array)
|
|
71
|
+
], ScenarioVersionDiff.prototype, "fieldDiffs", void 0);
|
|
72
|
+
tslib_1.__decorate([
|
|
73
|
+
(0, type_graphql_1.Field)(type => [ScenarioStepDiff], { description: 'Step-level changes keyed by step name.' }),
|
|
74
|
+
tslib_1.__metadata("design:type", Array)
|
|
75
|
+
], ScenarioVersionDiff.prototype, "stepDiffs", void 0);
|
|
76
|
+
exports.ScenarioVersionDiff = ScenarioVersionDiff = tslib_1.__decorate([
|
|
77
|
+
(0, type_graphql_1.ObjectType)({ description: 'The difference between two scenario versions (or a version and the current draft).' })
|
|
78
|
+
], ScenarioVersionDiff);
|
|
79
|
+
//# sourceMappingURL=scenario-version-type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scenario-version-type.js","sourceRoot":"","sources":["../../../server/service/scenario/scenario-version-type.ts"],"names":[],"mappings":";;;;AAAA,+CAAqD;AAErD,iDAAoD;AAG7C,IAAM,iBAAiB,GAAvB,MAAM,iBAAiB;CAS7B,CAAA;AATY,8CAAiB;AAE5B;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,yEAAyE,EAAE,CAAC;;gDACrF;AAGb;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,yCAAyC,EAAE,CAAC;;iDAC5F;AAGZ;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,gDAAgD,EAAE,CAAC;;gDACpG;4BARA,iBAAiB;IAD7B,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,0DAA0D,EAAE,CAAC;GAC3E,iBAAiB,CAS7B;AAGM,IAAM,gBAAgB,GAAtB,MAAM,gBAAgB;CAkB5B,CAAA;AAlBY,4CAAgB;AAE3B;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,4CAA4C,EAAE,CAAC;;8CACxE;AAGb;IADC,IAAA,oBAAK,EAAC,EAAE,WAAW,EAAE,wDAAwD,EAAE,CAAC;;oDACrC;AAG5C;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,yCAAyC,EAAE,CAAC;;gDAC5F;AAGZ;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,gDAAgD,EAAE,CAAC;;+CACpG;AAMX;IAJC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,iBAAiB,CAAC,EAAE;QAClC,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,6EAA6E;KAC3F,CAAC;;oDAC8B;2BAjBrB,gBAAgB;IAD5B,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,6EAA6E,EAAE,CAAC;GAC9F,gBAAgB,CAkB5B;AAGM,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;CAe/B,CAAA;AAfY,kDAAmB;AAE9B;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE,EAAE,WAAW,EAAE,8CAA8C,EAAE,CAAC;;wDACjE;AAMnB;IAJC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,EAAE;QAClB,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,4EAA4E;KAC1F,CAAC;;sDACgB;AAGlB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,iBAAiB,CAAC,EAAE,EAAE,WAAW,EAAE,+BAA+B,EAAE,CAAC;;uDACtD;AAG/B;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,gBAAgB,CAAC,EAAE,EAAE,WAAW,EAAE,wCAAwC,EAAE,CAAC;;sDAChE;8BAdlB,mBAAmB;IAD/B,IAAA,yBAAU,EAAC,EAAE,WAAW,EAAE,oFAAoF,EAAE,CAAC;GACrG,mBAAmB,CAe/B","sourcesContent":["import { Field, Int, ObjectType } from 'type-graphql'\n\nimport { ScalarObject } from '@things-factory/shell'\n\n@ObjectType({ description: 'A single scenario field difference between two versions.' })\nexport class ScenarioFieldDiff {\n @Field({ description: 'The name of the field that changed (e.g. description, schedule, steps).' })\n field: string\n\n @Field(type => ScalarObject, { nullable: true, description: 'The value before (in the base version).' })\n before?: any\n\n @Field(type => ScalarObject, { nullable: true, description: 'The value after (in the target version/draft).' })\n after?: any\n}\n\n@ObjectType({ description: 'A single step difference between two scenario versions, keyed by step name.' })\nexport class ScenarioStepDiff {\n @Field({ nullable: true, description: 'The step name (identity used for diffing).' })\n name?: string\n\n @Field({ description: \"The kind of change: 'added', 'removed', or 'modified'.\" })\n changeType: 'added' | 'removed' | 'modified'\n\n @Field(type => ScalarObject, { nullable: true, description: 'The step as it was in the base version.' })\n before?: any\n\n @Field(type => ScalarObject, { nullable: true, description: 'The step as it is in the target version/draft.' })\n after?: any\n\n @Field(type => [ScenarioFieldDiff], {\n nullable: true,\n description: 'Field-level changes within a modified step (task, connection, params, ...).'\n })\n fieldDiffs?: ScenarioFieldDiff[]\n}\n\n@ObjectType({ description: 'The difference between two scenario versions (or a version and the current draft).' })\nexport class ScenarioVersionDiff {\n @Field(type => Int, { description: 'The base version number being compared from.' })\n fromVersion: number\n\n @Field(type => Int, {\n nullable: true,\n description: 'The target version number being compared to. Null means the current draft.'\n })\n toVersion?: number\n\n @Field(type => [ScenarioFieldDiff], { description: 'Scenario-level field changes.' })\n fieldDiffs: ScenarioFieldDiff[]\n\n @Field(type => [ScenarioStepDiff], { description: 'Step-level changes keyed by step name.' })\n stepDiffs: ScenarioStepDiff[]\n}\n"]}
|
|
@@ -15,7 +15,30 @@ export declare class Scenario {
|
|
|
15
15
|
timezone?: string;
|
|
16
16
|
ttl?: number;
|
|
17
17
|
iteration?: string;
|
|
18
|
+
/**
|
|
19
|
+
* 시나리오의 스텝 배열 — draft 작업본의 정본 저장소.
|
|
20
|
+
*
|
|
21
|
+
* [버전관리 / Option A]
|
|
22
|
+
* 기존에는 별도 Step 테이블(OneToMany)이었으나, 스텝은 항상 배열로 통째로 저장/실행되어
|
|
23
|
+
* 관계형 이점(안정적 행 식별자)을 쓰지 않았다. 버전 스냅샷을 board.model 처럼 단일 JSON 으로
|
|
24
|
+
* 다루기 위해 Scenario 의 임베디드 JSON 컬럼으로 통합한다.
|
|
25
|
+
*
|
|
26
|
+
* [하위 호환]
|
|
27
|
+
* 이 컬럼이 null 이면(=아직 이관되지 않은 기존 시나리오) resolveScenarioSteps() 가
|
|
28
|
+
* 레거시 Step 테이블에서 읽어온다. 저장 시에는 이 컬럼에 기록한다.
|
|
29
|
+
*
|
|
30
|
+
* GraphQL 노출은 ScenarioQuery.steps FieldResolver 가 담당(@Field 없음).
|
|
31
|
+
*/
|
|
18
32
|
steps?: Step[];
|
|
33
|
+
/**
|
|
34
|
+
* 발행 상태: 'draft'(편집 중, 미발행 변경 있음) 또는 'released'(최신 릴리즈와 일치).
|
|
35
|
+
*
|
|
36
|
+
* version(릴리즈된 적 있는가) 과 draft↔릴리즈 diff(무엇이 바뀌었나) 로도 유도 가능한 파생값이지만,
|
|
37
|
+
* 리스트에서 dirty 여부를 O(1) 로 표시하고 릴리즈 신호(서브스크라이버 게이트)로 쓰기 위해 컬럼으로 둔다.
|
|
38
|
+
* 콘텐츠 편집 경로는 'draft', releaseScenario 는 'released' 로 세팅한다.
|
|
39
|
+
*/
|
|
40
|
+
publishState?: 'draft' | 'released';
|
|
41
|
+
version?: number;
|
|
19
42
|
privilege?: PrivilegeObject;
|
|
20
43
|
role?: Role;
|
|
21
44
|
roleId?: string;
|
|
@@ -7,7 +7,7 @@ const typeorm_1 = require("typeorm");
|
|
|
7
7
|
const auth_base_1 = require("@things-factory/auth-base");
|
|
8
8
|
const shell_1 = require("@things-factory/shell");
|
|
9
9
|
const engine_1 = require("../../engine");
|
|
10
|
-
const
|
|
10
|
+
const version_text_column_1 = require("../../utils/version-text-column");
|
|
11
11
|
let Scenario = class Scenario {
|
|
12
12
|
async start(options) {
|
|
13
13
|
try {
|
|
@@ -96,10 +96,25 @@ tslib_1.__decorate([
|
|
|
96
96
|
tslib_1.__metadata("design:type", String)
|
|
97
97
|
], Scenario.prototype, "iteration", void 0);
|
|
98
98
|
tslib_1.__decorate([
|
|
99
|
-
(0, typeorm_1.
|
|
100
|
-
(0, type_graphql_1.Field)(type => [step_type_1.Step], { nullable: true, description: 'The sequence of steps that make up the scenario.' }),
|
|
99
|
+
(0, typeorm_1.Column)((0, version_text_column_1.jsonTextColumn)()),
|
|
101
100
|
tslib_1.__metadata("design:type", Array)
|
|
102
101
|
], Scenario.prototype, "steps", void 0);
|
|
102
|
+
tslib_1.__decorate([
|
|
103
|
+
(0, typeorm_1.Column)({ nullable: true, default: 'draft' }),
|
|
104
|
+
(0, type_graphql_1.Field)({
|
|
105
|
+
nullable: true,
|
|
106
|
+
description: "The publish state of the scenario: 'draft' (has unreleased edits) or 'released'."
|
|
107
|
+
}),
|
|
108
|
+
tslib_1.__metadata("design:type", String)
|
|
109
|
+
], Scenario.prototype, "publishState", void 0);
|
|
110
|
+
tslib_1.__decorate([
|
|
111
|
+
(0, typeorm_1.Column)({ nullable: true, default: 0 }),
|
|
112
|
+
(0, type_graphql_1.Field)(type => type_graphql_1.Int, {
|
|
113
|
+
nullable: true,
|
|
114
|
+
description: 'The latest released version number of the scenario (0 if never released).'
|
|
115
|
+
}),
|
|
116
|
+
tslib_1.__metadata("design:type", Number)
|
|
117
|
+
], Scenario.prototype, "version", void 0);
|
|
103
118
|
tslib_1.__decorate([
|
|
104
119
|
(0, typeorm_1.Column)({ type: 'simple-json', nullable: true }),
|
|
105
120
|
(0, type_graphql_1.Field)(type => auth_base_1.PrivilegeObject, { nullable: true, description: 'Privilege required to execute the scenario.' }),
|