@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.
Files changed (65) hide show
  1. package/dist-server/controllers/scenario-controller.d.ts +2 -2
  2. package/dist-server/controllers/scenario-controller.js +19 -8
  3. package/dist-server/controllers/scenario-controller.js.map +1 -1
  4. package/dist-server/engine/analyzer/analyze-integration.js +6 -2
  5. package/dist-server/engine/analyzer/analyze-integration.js.map +1 -1
  6. package/dist-server/engine/connector/operato-connector.js +4 -1
  7. package/dist-server/engine/connector/operato-connector.js.map +1 -1
  8. package/dist-server/engine/scenario-engine.js +7 -2
  9. package/dist-server/engine/scenario-engine.js.map +1 -1
  10. package/dist-server/engine/task/pick-pending-scenario.js +6 -1
  11. package/dist-server/engine/task/pick-pending-scenario.js.map +1 -1
  12. package/dist-server/engine/task/stop-scenario.js +1 -1
  13. package/dist-server/engine/task/stop-scenario.js.map +1 -1
  14. package/dist-server/engine/task/sub-scenario.js +6 -1
  15. package/dist-server/engine/task/sub-scenario.js.map +1 -1
  16. package/dist-server/engine/task/switch-range-scenario.js +6 -1
  17. package/dist-server/engine/task/switch-range-scenario.js.map +1 -1
  18. package/dist-server/engine/task/switch-scenario.js +6 -1
  19. package/dist-server/engine/task/switch-scenario.js.map +1 -1
  20. package/dist-server/routers/scenario-schedule-callback-router.js +4 -1
  21. package/dist-server/routers/scenario-schedule-callback-router.js.map +1 -1
  22. package/dist-server/routers/scenario-view-router.js +4 -3
  23. package/dist-server/routers/scenario-view-router.js.map +1 -1
  24. package/dist-server/service/index.d.ts +4 -1
  25. package/dist-server/service/index.js +4 -1
  26. package/dist-server/service/index.js.map +1 -1
  27. package/dist-server/service/scenario/event-subscriber.d.ts +22 -0
  28. package/dist-server/service/scenario/event-subscriber.js +49 -0
  29. package/dist-server/service/scenario/event-subscriber.js.map +1 -0
  30. package/dist-server/service/scenario/index.d.ts +6 -2
  31. package/dist-server/service/scenario/index.js +7 -3
  32. package/dist-server/service/scenario/index.js.map +1 -1
  33. package/dist-server/service/scenario/resolve-steps.d.ts +43 -0
  34. package/dist-server/service/scenario/resolve-steps.js +101 -0
  35. package/dist-server/service/scenario/resolve-steps.js.map +1 -0
  36. package/dist-server/service/scenario/scenario-history.d.ts +44 -0
  37. package/dist-server/service/scenario/scenario-history.js +167 -0
  38. package/dist-server/service/scenario/scenario-history.js.map +1 -0
  39. package/dist-server/service/scenario/scenario-mutation.d.ts +2 -0
  40. package/dist-server/service/scenario/scenario-mutation.js +150 -36
  41. package/dist-server/service/scenario/scenario-mutation.js.map +1 -1
  42. package/dist-server/service/scenario/scenario-query.js +8 -14
  43. package/dist-server/service/scenario/scenario-query.js.map +1 -1
  44. package/dist-server/service/scenario/scenario-version-diff.d.ts +8 -0
  45. package/dist-server/service/scenario/scenario-version-diff.js +107 -0
  46. package/dist-server/service/scenario/scenario-version-diff.js.map +1 -0
  47. package/dist-server/service/scenario/scenario-version-query.d.ts +11 -0
  48. package/dist-server/service/scenario/scenario-version-query.js +135 -0
  49. package/dist-server/service/scenario/scenario-version-query.js.map +1 -0
  50. package/dist-server/service/scenario/scenario-version-type.d.ts +18 -0
  51. package/dist-server/service/scenario/scenario-version-type.js +79 -0
  52. package/dist-server/service/scenario/scenario-version-type.js.map +1 -0
  53. package/dist-server/service/scenario/scenario.d.ts +23 -0
  54. package/dist-server/service/scenario/scenario.js +18 -3
  55. package/dist-server/service/scenario/scenario.js.map +1 -1
  56. package/dist-server/service/scenario-instance/scenario-instance-mutation.d.ts +2 -2
  57. package/dist-server/service/scenario-instance/scenario-instance-mutation.js +8 -6
  58. package/dist-server/service/scenario-instance/scenario-instance-mutation.js.map +1 -1
  59. package/dist-server/service/step/step-mutation.js +26 -13
  60. package/dist-server/service/step/step-mutation.js.map +1 -1
  61. package/dist-server/tsconfig.tsbuildinfo +1 -1
  62. package/dist-server/utils/version-text-column.d.ts +16 -0
  63. package/dist-server/utils/version-text-column.js +67 -0
  64. package/dist-server/utils/version-text-column.js.map +1 -0
  65. package/package.json +12 -11
@@ -1 +1 @@
1
- {"version":3,"file":"scenario.js","sourceRoot":"","sources":["../../../server/service/scenario/scenario.ts"],"names":[],"mappings":"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","sourcesContent":["import { Field, ID, InputType, Int, ObjectType } from 'type-graphql'\nimport {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n ManyToOne,\n OneToMany,\n PrimaryGeneratedColumn,\n RelationId,\n UpdateDateColumn\n} from 'typeorm'\n\nimport { PrivilegeObject, Role, User } from '@things-factory/auth-base'\nimport { Domain } from '@things-factory/shell'\n\nimport { ScenarioEngine } from '../../engine'\nimport { Step } from '../step/step-type'\n\n@Entity()\n@Index('ix_scenario_0', (scenario: Scenario) => [scenario.domain, scenario.name], { unique: true })\n@ObjectType({ description: 'Represents a sequence of steps designed to automate a task or process.' })\nexport class Scenario {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier for the scenario.' })\n id?: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { description: 'The domain to which this scenario belongs.' })\n domain?: Domain\n\n @RelationId((scenario: Scenario) => scenario.domain)\n domainId?: string\n\n @Column()\n @Field({ description: 'The name of the scenario.' })\n name?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'A detailed description of the scenario.' })\n description?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The type of the scenario, used for categorization.' })\n type?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Indicates if the scenario is accessible and executable system-wide.' })\n public?: boolean\n\n @Column({ nullable: true })\n @Field({\n nullable: true,\n description: 'Indicates if the scenario should be automatically started when the server starts.'\n })\n active?: boolean\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'A cron-style schedule for running the scenario automatically.' })\n schedule?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The ID of the scheduled job, if any.' })\n scheduleId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The timezone for the schedule.' })\n timezone?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Time-to-live in seconds for scenario instances.' })\n ttl?: number\n\n @Column({ nullable: true, default: 'SELF' })\n @Field({ nullable: true, description: 'Iteration for scenario execution: SELF, CHILDREN, or SELF & CHILDREN.' })\n iteration?: string\n\n @OneToMany(type => Step, step => step.scenario)\n @Field(type => [Step], { nullable: true, description: 'The sequence of steps that make up the scenario.' })\n steps?: Step[]\n\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => PrivilegeObject, { nullable: true, description: 'Privilege required to execute the scenario.' })\n privilege?: PrivilegeObject\n\n @ManyToOne(type => Role)\n @Field(type => Role, { nullable: true, description: 'Role required to execute the scenario.' })\n role?: Role\n\n @RelationId((scenario: Scenario) => scenario.role)\n roleId?: string\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'The timestamp when the scenario was created.' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'The timestamp when the scenario was last updated.' })\n updatedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who created the scenario.' })\n creator?: User\n\n @RelationId((scenario: Scenario) => scenario.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who last updated the scenario.' })\n updater?: User\n\n @RelationId((scenario: Scenario) => scenario.updater)\n updaterId?: string\n\n async start(options?: { instanceName?: string; domain?: Domain; user?: User; variables?: any }) {\n try {\n await ScenarioEngine.loadIteration(options?.instanceName || this.name, this, {\n domain: options?.domain || this.domain,\n user: options?.user || this.updater,\n variables: options?.variables\n })\n } catch (ex) {}\n }\n\n async stop(options?: { instanceName?: string; domain?: Domain; user?: User }) {\n try {\n await ScenarioEngine.unload(options?.domain || this.domain, options?.instanceName || this.name)\n } finally {\n }\n }\n}\n"]}
1
+ {"version":3,"file":"scenario.js","sourceRoot":"","sources":["../../../server/service/scenario/scenario.ts"],"names":[],"mappings":"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","sourcesContent":["import { Field, ID, InputType, Int, ObjectType } from 'type-graphql'\nimport {\n Column,\n CreateDateColumn,\n Entity,\n Index,\n ManyToOne,\n PrimaryGeneratedColumn,\n RelationId,\n UpdateDateColumn\n} from 'typeorm'\n\nimport { PrivilegeObject, Role, User } from '@things-factory/auth-base'\nimport { Domain } from '@things-factory/shell'\n\nimport { ScenarioEngine } from '../../engine'\nimport { Step } from '../step/step-type'\nimport { jsonTextColumn } from '../../utils/version-text-column'\n\n@Entity()\n@Index('ix_scenario_0', (scenario: Scenario) => [scenario.domain, scenario.name], { unique: true })\n@ObjectType({ description: 'Represents a sequence of steps designed to automate a task or process.' })\nexport class Scenario {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier for the scenario.' })\n id?: string\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { description: 'The domain to which this scenario belongs.' })\n domain?: Domain\n\n @RelationId((scenario: Scenario) => scenario.domain)\n domainId?: string\n\n @Column()\n @Field({ description: 'The name of the scenario.' })\n name?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'A detailed description of the scenario.' })\n description?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The type of the scenario, used for categorization.' })\n type?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Indicates if the scenario is accessible and executable system-wide.' })\n public?: boolean\n\n @Column({ nullable: true })\n @Field({\n nullable: true,\n description: 'Indicates if the scenario should be automatically started when the server starts.'\n })\n active?: boolean\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'A cron-style schedule for running the scenario automatically.' })\n schedule?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The ID of the scheduled job, if any.' })\n scheduleId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The timezone for the schedule.' })\n timezone?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Time-to-live in seconds for scenario instances.' })\n ttl?: number\n\n @Column({ nullable: true, default: 'SELF' })\n @Field({ nullable: true, description: 'Iteration for scenario execution: SELF, CHILDREN, or SELF & CHILDREN.' })\n iteration?: string\n\n /**\n * 시나리오의 스텝 배열 — draft 작업본의 정본 저장소.\n *\n * [버전관리 / Option A]\n * 기존에는 별도 Step 테이블(OneToMany)이었으나, 스텝은 항상 배열로 통째로 저장/실행되어\n * 관계형 이점(안정적 행 식별자)을 쓰지 않았다. 버전 스냅샷을 board.model 처럼 단일 JSON 으로\n * 다루기 위해 Scenario 의 임베디드 JSON 컬럼으로 통합한다.\n *\n * [하위 호환]\n * 이 컬럼이 null 이면(=아직 이관되지 않은 기존 시나리오) resolveScenarioSteps() 가\n * 레거시 Step 테이블에서 읽어온다. 저장 시에는 이 컬럼에 기록한다.\n *\n * GraphQL 노출은 ScenarioQuery.steps FieldResolver 가 담당(@Field 없음).\n */\n @Column(jsonTextColumn())\n steps?: Step[]\n\n /**\n * 발행 상태: 'draft'(편집 중, 미발행 변경 있음) 또는 'released'(최신 릴리즈와 일치).\n *\n * version(릴리즈된 적 있는가) 과 draft↔릴리즈 diff(무엇이 바뀌었나) 로도 유도 가능한 파생값이지만,\n * 리스트에서 dirty 여부를 O(1) 로 표시하고 릴리즈 신호(서브스크라이버 게이트)로 쓰기 위해 컬럼으로 둔다.\n * 콘텐츠 편집 경로는 'draft', releaseScenario 는 'released' 로 세팅한다.\n */\n @Column({ nullable: true, default: 'draft' })\n @Field({\n nullable: true,\n description: \"The publish state of the scenario: 'draft' (has unreleased edits) or 'released'.\"\n })\n publishState?: 'draft' | 'released'\n\n @Column({ nullable: true, default: 0 })\n @Field(type => Int, {\n nullable: true,\n description: 'The latest released version number of the scenario (0 if never released).'\n })\n version?: number\n\n @Column({ type: 'simple-json', nullable: true })\n @Field(type => PrivilegeObject, { nullable: true, description: 'Privilege required to execute the scenario.' })\n privilege?: PrivilegeObject\n\n @ManyToOne(type => Role)\n @Field(type => Role, { nullable: true, description: 'Role required to execute the scenario.' })\n role?: Role\n\n @RelationId((scenario: Scenario) => scenario.role)\n roleId?: string\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'The timestamp when the scenario was created.' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'The timestamp when the scenario was last updated.' })\n updatedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who created the scenario.' })\n creator?: User\n\n @RelationId((scenario: Scenario) => scenario.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who last updated the scenario.' })\n updater?: User\n\n @RelationId((scenario: Scenario) => scenario.updater)\n updaterId?: string\n\n async start(options?: { instanceName?: string; domain?: Domain; user?: User; variables?: any }) {\n try {\n await ScenarioEngine.loadIteration(options?.instanceName || this.name, this, {\n domain: options?.domain || this.domain,\n user: options?.user || this.updater,\n variables: options?.variables\n })\n } catch (ex) {}\n }\n\n async stop(options?: { instanceName?: string; domain?: Domain; user?: User }) {\n try {\n await ScenarioEngine.unload(options?.domain || this.domain, options?.instanceName || this.name)\n } finally {\n }\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
1
  import { ScenarioInstance, ScenarioInstanceRunResult, ScenarioInstanceStartResult } from './scenario-instance-type';
2
2
  export declare class ScenarioInstanceMutation {
3
- runScenario(instanceName: string, scenarioName: string, variables: any, context: ResolverContext): Promise<ScenarioInstanceRunResult>;
4
- startScenario(instanceName: string, scenarioName: string, variables: any, context: ResolverContext): Promise<ScenarioInstanceStartResult>;
3
+ runScenario(instanceName: string, scenarioName: string, variables: any, context: ResolverContext, mode?: string): Promise<ScenarioInstanceRunResult>;
4
+ startScenario(instanceName: string, scenarioName: string, variables: any, context: ResolverContext, mode?: string): Promise<ScenarioInstanceStartResult>;
5
5
  stopScenario(instanceName: string, context: ResolverContext): Promise<ScenarioInstance | undefined>;
6
6
  }
@@ -7,11 +7,11 @@ const shell_1 = require("@things-factory/shell");
7
7
  const scenario_instance_type_1 = require("./scenario-instance-type");
8
8
  const scenario_controller_1 = require("../../controllers/scenario-controller");
9
9
  let ScenarioInstanceMutation = class ScenarioInstanceMutation {
10
- async runScenario(instanceName, scenarioName, variables, context) {
11
- return await (0, scenario_controller_1.runScenario)(instanceName, scenarioName, variables, context);
10
+ async runScenario(instanceName, scenarioName, variables, context, mode) {
11
+ return await (0, scenario_controller_1.runScenario)(instanceName, scenarioName, variables, context, mode === 'draft' ? 'draft' : 'released');
12
12
  }
13
- async startScenario(instanceName, scenarioName, variables, context) {
14
- return await (0, scenario_controller_1.startScenario)(instanceName, scenarioName, variables, context);
13
+ async startScenario(instanceName, scenarioName, variables, context, mode) {
14
+ return await (0, scenario_controller_1.startScenario)(instanceName, scenarioName, variables, context, mode === 'draft' ? 'draft' : 'released');
15
15
  }
16
16
  async stopScenario(instanceName, context) {
17
17
  return await (0, scenario_controller_1.stopScenario)(instanceName, context);
@@ -26,8 +26,9 @@ tslib_1.__decorate([
26
26
  tslib_1.__param(1, (0, type_graphql_1.Arg)('scenarioName')),
27
27
  tslib_1.__param(2, (0, type_graphql_1.Arg)('variables', type => shell_1.ScalarObject, { nullable: true })),
28
28
  tslib_1.__param(3, (0, type_graphql_1.Ctx)()),
29
+ tslib_1.__param(4, (0, type_graphql_1.Arg)('mode', { nullable: true, description: "Version to run: 'released' (default) or 'draft' (debugging)." })),
29
30
  tslib_1.__metadata("design:type", Function),
30
- tslib_1.__metadata("design:paramtypes", [String, String, Object, Object]),
31
+ tslib_1.__metadata("design:paramtypes", [String, String, Object, Object, String]),
31
32
  tslib_1.__metadata("design:returntype", Promise)
32
33
  ], ScenarioInstanceMutation.prototype, "runScenario", null);
33
34
  tslib_1.__decorate([
@@ -38,8 +39,9 @@ tslib_1.__decorate([
38
39
  tslib_1.__param(1, (0, type_graphql_1.Arg)('scenarioName')),
39
40
  tslib_1.__param(2, (0, type_graphql_1.Arg)('variables', type => shell_1.ScalarObject, { nullable: true })),
40
41
  tslib_1.__param(3, (0, type_graphql_1.Ctx)()),
42
+ tslib_1.__param(4, (0, type_graphql_1.Arg)('mode', { nullable: true, description: "Version to run: 'released' (default) or 'draft' (debugging)." })),
41
43
  tslib_1.__metadata("design:type", Function),
42
- tslib_1.__metadata("design:paramtypes", [String, String, Object, Object]),
44
+ tslib_1.__metadata("design:paramtypes", [String, String, Object, Object, String]),
43
45
  tslib_1.__metadata("design:returntype", Promise)
44
46
  ], ScenarioInstanceMutation.prototype, "startScenario", null);
45
47
  tslib_1.__decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"scenario-instance-mutation.js","sourceRoot":"","sources":["../../../server/service/scenario-instance/scenario-instance-mutation.ts"],"names":[],"mappings":";;;;AAAA,+CAA2D;AAE3D,iDAAoD;AAEpD,qEAAmH;AAEnH,+EAI8C;AAGvC,IAAM,wBAAwB,GAA9B,MAAM,wBAAwB;IAI7B,AAAN,KAAK,CAAC,WAAW,CAC0B,YAAoB,EACxC,YAAoB,EACmB,SAAc,EACnE,OAAwB;QAE/B,OAAO,MAAM,IAAA,iCAAqB,EAAC,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,CAAC,CAAA;IACpF,CAAC;IAKK,AAAN,KAAK,CAAC,aAAa,CACwB,YAAoB,EACxC,YAAoB,EACmB,SAAc,EACnE,OAAwB;QAE/B,OAAO,MAAM,IAAA,mCAAuB,EAAC,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,CAAC,CAAA;IACtF,CAAC;IAMK,AAAN,KAAK,CAAC,YAAY,CACyB,YAAoB,EACtD,OAAwB;QAE/B,OAAO,MAAM,IAAA,kCAAsB,EAAC,YAAY,EAAE,OAAO,CAAC,CAAA;IAC5D,CAAC;CACF,CAAA;AAnCY,4DAAwB;AAI7B;IAHL,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,kDAAyB,EAAE;QAC9C,WAAW,EAAE,6EAA6E;KAC3F,CAAC;IAEC,mBAAA,IAAA,kBAAG,EAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IACvC,mBAAA,IAAA,kBAAG,EAAC,cAAc,CAAC,CAAA;IACnB,mBAAA,IAAA,kBAAG,EAAC,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IAC1D,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;2DAGP;AAKK;IAHL,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,oDAA2B,EAAE;QAChD,WAAW,EAAE,mEAAmE;KACjF,CAAC;IAEC,mBAAA,IAAA,kBAAG,EAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IACvC,mBAAA,IAAA,kBAAG,EAAC,cAAc,CAAC,CAAA;IACnB,mBAAA,IAAA,kBAAG,EAAC,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IAC1D,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;6DAGP;AAMK;IAJL,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,yCAAgB,EAAE;QACrC,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,gDAAgD;KAC9D,CAAC;IAEC,mBAAA,IAAA,kBAAG,EAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IACvC,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;4DAGP;mCAlCU,wBAAwB;IADpC,IAAA,uBAAQ,EAAC,yCAAgB,CAAC;GACd,wBAAwB,CAmCpC","sourcesContent":["import { Arg, Ctx, Mutation, Resolver } from 'type-graphql'\n\nimport { ScalarObject } from '@things-factory/shell'\n\nimport { ScenarioInstance, ScenarioInstanceRunResult, ScenarioInstanceStartResult } from './scenario-instance-type'\n\nimport {\n runScenario as controllerRunScenario,\n startScenario as controllerStartScenario,\n stopScenario as controllerStopScenario\n} from '../../controllers/scenario-controller'\n\n@Resolver(ScenarioInstance)\nexport class ScenarioInstanceMutation {\n @Mutation(returns => ScenarioInstanceRunResult, {\n description: 'Runs a new scenario instance once and returns the result after it finishes.'\n })\n async runScenario(\n @Arg('instanceName', { nullable: true }) instanceName: string,\n @Arg('scenarioName') scenarioName: string,\n @Arg('variables', type => ScalarObject, { nullable: true }) variables: any,\n @Ctx() context: ResolverContext\n ): Promise<ScenarioInstanceRunResult> {\n return await controllerRunScenario(instanceName, scenarioName, variables, context)\n }\n\n @Mutation(returns => ScenarioInstanceStartResult, {\n description: 'Starts a new scenario instance, which will run in the background.'\n })\n async startScenario(\n @Arg('instanceName', { nullable: true }) instanceName: string,\n @Arg('scenarioName') scenarioName: string,\n @Arg('variables', type => ScalarObject, { nullable: true }) variables: any,\n @Ctx() context: ResolverContext\n ): Promise<ScenarioInstanceStartResult> {\n return await controllerStartScenario(instanceName, scenarioName, variables, context)\n }\n\n @Mutation(returns => ScenarioInstance, {\n nullable: true,\n description: 'Stops a running scenario instance by its name.'\n })\n async stopScenario(\n @Arg('instanceName', { nullable: true }) instanceName: string,\n @Ctx() context: ResolverContext\n ): Promise<ScenarioInstance | undefined> {\n return await controllerStopScenario(instanceName, context)\n }\n}\n"]}
1
+ {"version":3,"file":"scenario-instance-mutation.js","sourceRoot":"","sources":["../../../server/service/scenario-instance/scenario-instance-mutation.ts"],"names":[],"mappings":";;;;AAAA,+CAA2D;AAE3D,iDAAoD;AAEpD,qEAAmH;AAEnH,+EAI8C;AAGvC,IAAM,wBAAwB,GAA9B,MAAM,wBAAwB;IAI7B,AAAN,KAAK,CAAC,WAAW,CAC0B,YAAoB,EACxC,YAAoB,EACmB,SAAc,EACnE,OAAwB,EAE/B,IAAa;QAEb,OAAO,MAAM,IAAA,iCAAqB,EAChC,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,OAAO,EACP,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CACxC,CAAA;IACH,CAAC;IAKK,AAAN,KAAK,CAAC,aAAa,CACwB,YAAoB,EACxC,YAAoB,EACmB,SAAc,EACnE,OAAwB,EAE/B,IAAa;QAEb,OAAO,MAAM,IAAA,mCAAuB,EAClC,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,OAAO,EACP,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CACxC,CAAA;IACH,CAAC;IAMK,AAAN,KAAK,CAAC,YAAY,CACyB,YAAoB,EACtD,OAAwB;QAE/B,OAAO,MAAM,IAAA,kCAAsB,EAAC,YAAY,EAAE,OAAO,CAAC,CAAA;IAC5D,CAAC;CACF,CAAA;AAnDY,4DAAwB;AAI7B;IAHL,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,kDAAyB,EAAE;QAC9C,WAAW,EAAE,6EAA6E;KAC3F,CAAC;IAEC,mBAAA,IAAA,kBAAG,EAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IACvC,mBAAA,IAAA,kBAAG,EAAC,cAAc,CAAC,CAAA;IACnB,mBAAA,IAAA,kBAAG,EAAC,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IAC1D,mBAAA,IAAA,kBAAG,GAAE,CAAA;IACL,mBAAA,IAAA,kBAAG,EAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,8DAA8D,EAAE,CAAC,CAAA;;;;2DAU9G;AAKK;IAHL,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,oDAA2B,EAAE;QAChD,WAAW,EAAE,mEAAmE;KACjF,CAAC;IAEC,mBAAA,IAAA,kBAAG,EAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IACvC,mBAAA,IAAA,kBAAG,EAAC,cAAc,CAAC,CAAA;IACnB,mBAAA,IAAA,kBAAG,EAAC,WAAW,EAAE,IAAI,CAAC,EAAE,CAAC,oBAAY,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IAC1D,mBAAA,IAAA,kBAAG,GAAE,CAAA;IACL,mBAAA,IAAA,kBAAG,EAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,8DAA8D,EAAE,CAAC,CAAA;;;;6DAU9G;AAMK;IAJL,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,yCAAgB,EAAE;QACrC,QAAQ,EAAE,IAAI;QACd,WAAW,EAAE,gDAAgD;KAC9D,CAAC;IAEC,mBAAA,IAAA,kBAAG,EAAC,cAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAA;IACvC,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;4DAGP;mCAlDU,wBAAwB;IADpC,IAAA,uBAAQ,EAAC,yCAAgB,CAAC;GACd,wBAAwB,CAmDpC","sourcesContent":["import { Arg, Ctx, Mutation, Resolver } from 'type-graphql'\n\nimport { ScalarObject } from '@things-factory/shell'\n\nimport { ScenarioInstance, ScenarioInstanceRunResult, ScenarioInstanceStartResult } from './scenario-instance-type'\n\nimport {\n runScenario as controllerRunScenario,\n startScenario as controllerStartScenario,\n stopScenario as controllerStopScenario\n} from '../../controllers/scenario-controller'\n\n@Resolver(ScenarioInstance)\nexport class ScenarioInstanceMutation {\n @Mutation(returns => ScenarioInstanceRunResult, {\n description: 'Runs a new scenario instance once and returns the result after it finishes.'\n })\n async runScenario(\n @Arg('instanceName', { nullable: true }) instanceName: string,\n @Arg('scenarioName') scenarioName: string,\n @Arg('variables', type => ScalarObject, { nullable: true }) variables: any,\n @Ctx() context: ResolverContext,\n @Arg('mode', { nullable: true, description: \"Version to run: 'released' (default) or 'draft' (debugging).\" })\n mode?: string\n ): Promise<ScenarioInstanceRunResult> {\n return await controllerRunScenario(\n instanceName,\n scenarioName,\n variables,\n context,\n mode === 'draft' ? 'draft' : 'released'\n )\n }\n\n @Mutation(returns => ScenarioInstanceStartResult, {\n description: 'Starts a new scenario instance, which will run in the background.'\n })\n async startScenario(\n @Arg('instanceName', { nullable: true }) instanceName: string,\n @Arg('scenarioName') scenarioName: string,\n @Arg('variables', type => ScalarObject, { nullable: true }) variables: any,\n @Ctx() context: ResolverContext,\n @Arg('mode', { nullable: true, description: \"Version to run: 'released' (default) or 'draft' (debugging).\" })\n mode?: string\n ): Promise<ScenarioInstanceStartResult> {\n return await controllerStartScenario(\n instanceName,\n scenarioName,\n variables,\n context,\n mode === 'draft' ? 'draft' : 'released'\n )\n }\n\n @Mutation(returns => ScenarioInstance, {\n nullable: true,\n description: 'Stops a running scenario instance by its name.'\n })\n async stopScenario(\n @Arg('instanceName', { nullable: true }) instanceName: string,\n @Ctx() context: ResolverContext\n ): Promise<ScenarioInstance | undefined> {\n return await controllerStopScenario(instanceName, context)\n }\n}\n"]}
@@ -6,11 +6,12 @@ const type_graphql_1 = require("type-graphql");
6
6
  const typeorm_1 = require("typeorm");
7
7
  const scenario_1 = require("../scenario/scenario");
8
8
  const step_type_1 = require("./step-type");
9
+ const resolve_steps_1 = require("../scenario/resolve-steps");
10
+ const crypto = require('crypto');
9
11
  let StepMutation = class StepMutation {
10
12
  async updateMultipleStep(scenarioId, patches, context) {
11
13
  const { domain, user, tx } = context.state;
12
14
  let results = [];
13
- const stepRepo = tx.getRepository(step_type_1.Step);
14
15
  const scenario = await tx.getRepository(scenario_1.Scenario).findOneBy({ id: scenarioId });
15
16
  if (!scenario) {
16
17
  throw new Error(`Scenario '${scenarioId}' not found`);
@@ -25,18 +26,30 @@ let StepMutation = class StepMutation {
25
26
  `Per-tenant value override 는 useDomainAttribute params + EnvVar 로 가능. ` +
26
27
  `구조 자체를 customize 하려면 copyScenarios 로 이 시나리오를 현재 도메인에 복사한 뒤 수정.`);
27
28
  }
28
- await stepRepo.delete({ domain: { id: domain.id }, scenario: { id: scenarioId } });
29
- for (let i = 0; i < patches.length; i++) {
30
- const result = await stepRepo.save({
31
- ...patches[i],
32
- sequence: i,
33
- scenario,
34
- domain,
35
- creator: user,
36
- updater: user
37
- });
38
- results.push({ ...result, cuFlag: '+' });
39
- }
29
+ // [버전관리 / Option A]
30
+ // steps 를 Scenario.steps(JSON) 컬럼에 통째로 기록한다. 레거시 Step 테이블은 정리(자연 이관).
31
+ // 콘텐츠 편집이므로 publishState='draft' 로 표시 → 재릴리즈 필요.
32
+ const steps = patches.map((patch, i) => ({
33
+ id: patch.id || crypto.randomUUID(),
34
+ name: patch.name,
35
+ description: patch.description,
36
+ sequence: i,
37
+ task: patch.task,
38
+ skip: patch.skip,
39
+ log: patch.log,
40
+ connection: patch.connection,
41
+ params: patch.params,
42
+ result: patch.result
43
+ }));
44
+ await tx.getRepository(scenario_1.Scenario).save({
45
+ ...scenario,
46
+ steps,
47
+ publishState: 'draft',
48
+ updater: user
49
+ });
50
+ // [전환기 dual-write] 구버전 롤백 대비 Step 테이블도 draft 로 동기화.
51
+ await (0, resolve_steps_1.syncLegacyStepTable)(scenario, steps, { domain, user }, tx);
52
+ results = steps.map(step => ({ ...step, cuFlag: '+' }));
40
53
  return results;
41
54
  }
42
55
  async deleteSteps(ids, context) {
@@ -1 +1 @@
1
- {"version":3,"file":"step-mutation.js","sourceRoot":"","sources":["../../../server/service/step/step-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'\nimport { In } from 'typeorm'\n\nimport { Scenario } from '../scenario/scenario'\nimport { Step, StepPatch } from './step-type'\n\n@Resolver(Step)\nexport class StepMutation {\n @Directive('@transaction')\n @Mutation(returns => [Step], {\n description:\n 'Updates multiple steps within a specific scenario. This operation replaces all existing steps for the scenario.'\n })\n async updateMultipleStep(\n @Arg('scenarioId') scenarioId: string,\n @Arg('patches', type => [StepPatch]) patches: StepPatch[],\n @Ctx() context: ResolverContext\n ): Promise<Step[]> {\n const { domain, user, tx } = context.state\n\n let results = []\n const stepRepo = tx.getRepository(Step)\n const scenario = await tx.getRepository(Scenario).findOneBy({ id: scenarioId })\n\n if (!scenario) {\n throw new Error(`Scenario '${scenarioId}' not found`)\n }\n\n // Inheritance read-only 가드 — inherited scenario (다른 도메인 소유) 의 step 직접 수정 차단.\n // 자식 도메인이 patch.id 를 그대로 보내 save 하면 TypeORM upsert 가 부모의 step row 의\n // domain 을 자식으로 변경해 부모·형제 도메인이 step 을 잃는 사고 발생.\n // 자식별 값 변경은 useDomainAttribute params 의 EnvVar override 로, 전체 수정은\n // copyScenarios 로 자식 도메인 사본을 만든 뒤 그것을 수정.\n if (scenario.domainId !== domain.id) {\n throw new Error(\n `Cannot modify steps of inherited scenario '${scenario.name}' (owned by another domain). ` +\n `Per-tenant value override 는 useDomainAttribute params + EnvVar 로 가능. ` +\n `구조 자체를 customize 하려면 copyScenarios 로 이 시나리오를 현재 도메인에 복사한 뒤 수정.`\n )\n }\n\n await stepRepo.delete({ domain: { id: domain.id }, scenario: { id: scenarioId } })\n\n for (let i = 0; i < patches.length; i++) {\n const result = await stepRepo.save({\n ...patches[i],\n sequence: i,\n scenario,\n domain,\n creator: user,\n updater: user\n })\n\n results.push({ ...result, cuFlag: '+' })\n }\n\n return results\n }\n\n @Directive('@transaction')\n @Mutation(returns => Boolean, { description: 'Deletes multiple scenario steps by their IDs.' })\n async deleteSteps(@Arg('ids', type => [String]) ids: string[], @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, tx } = context.state\n\n // Inheritance read-only 가드 — 다른 도메인 소유 step 은 자식이 삭제 불가.\n // domain 필터를 명시 — current domain 의 step 만 삭제. 부모 step 은 영향 없음.\n await tx.getRepository(Step).delete({\n domain: { id: domain.id },\n id: In(ids.filter(Boolean))\n })\n\n return true\n }\n}\n"]}
1
+ {"version":3,"file":"step-mutation.js","sourceRoot":"","sources":["../../../server/service/step/step-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'\nimport { In } from 'typeorm'\n\nimport { Scenario } from '../scenario/scenario'\nimport { Step, StepPatch } from './step-type'\nimport { syncLegacyStepTable } from '../scenario/resolve-steps'\n\nconst crypto = require('crypto')\n\n@Resolver(Step)\nexport class StepMutation {\n @Directive('@transaction')\n @Mutation(returns => [Step], {\n description:\n 'Updates multiple steps within a specific scenario. This operation replaces all existing steps for the scenario.'\n })\n async updateMultipleStep(\n @Arg('scenarioId') scenarioId: string,\n @Arg('patches', type => [StepPatch]) patches: StepPatch[],\n @Ctx() context: ResolverContext\n ): Promise<Step[]> {\n const { domain, user, tx } = context.state\n\n let results = []\n const scenario = await tx.getRepository(Scenario).findOneBy({ id: scenarioId })\n\n if (!scenario) {\n throw new Error(`Scenario '${scenarioId}' not found`)\n }\n\n // Inheritance read-only 가드 — inherited scenario (다른 도메인 소유) 의 step 직접 수정 차단.\n // 자식 도메인이 patch.id 를 그대로 보내 save 하면 TypeORM upsert 가 부모의 step row 의\n // domain 을 자식으로 변경해 부모·형제 도메인이 step 을 잃는 사고 발생.\n // 자식별 값 변경은 useDomainAttribute params 의 EnvVar override 로, 전체 수정은\n // copyScenarios 로 자식 도메인 사본을 만든 뒤 그것을 수정.\n if (scenario.domainId !== domain.id) {\n throw new Error(\n `Cannot modify steps of inherited scenario '${scenario.name}' (owned by another domain). ` +\n `Per-tenant value override 는 useDomainAttribute params + EnvVar 로 가능. ` +\n `구조 자체를 customize 하려면 copyScenarios 로 이 시나리오를 현재 도메인에 복사한 뒤 수정.`\n )\n }\n\n // [버전관리 / Option A]\n // steps 를 Scenario.steps(JSON) 컬럼에 통째로 기록한다. 레거시 Step 테이블은 정리(자연 이관).\n // 콘텐츠 편집이므로 publishState='draft' 로 표시 → 재릴리즈 필요.\n const steps = patches.map((patch, i) => ({\n id: patch.id || crypto.randomUUID(),\n name: patch.name,\n description: patch.description,\n sequence: i,\n task: patch.task,\n skip: patch.skip,\n log: patch.log,\n connection: patch.connection,\n params: patch.params,\n result: patch.result\n }))\n\n await tx.getRepository(Scenario).save({\n ...scenario,\n steps,\n publishState: 'draft',\n updater: user\n } as any)\n\n // [전환기 dual-write] 구버전 롤백 대비 Step 테이블도 draft 로 동기화.\n await syncLegacyStepTable(scenario, steps, { domain, user }, tx)\n\n results = steps.map(step => ({ ...step, cuFlag: '+' }))\n\n return results as any\n }\n\n @Directive('@transaction')\n @Mutation(returns => Boolean, { description: 'Deletes multiple scenario steps by their IDs.' })\n async deleteSteps(@Arg('ids', type => [String]) ids: string[], @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, tx } = context.state\n\n // Inheritance read-only 가드 — 다른 도메인 소유 step 은 자식이 삭제 불가.\n // domain 필터를 명시 — current domain 의 step 만 삭제. 부모 step 은 영향 없음.\n await tx.getRepository(Step).delete({\n domain: { id: domain.id },\n id: In(ids.filter(Boolean))\n })\n\n return true\n }\n}\n"]}