@things-factory/figure-service 10.1.114 → 10.1.115

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.
@@ -15,7 +15,7 @@ const figure_history_js_1 = require("./figure-history.js");
15
15
  *
16
16
  * 발행 메모는 Figure 의 칸이 아니다. `releaseFigure` 가 저장할 엔티티에 `__releaseComment` 로 얹어
17
17
  * 두면 여기서 판본의 `comment` 로 옮긴다 — 메모는 그 판의 것이지 도형의 것이 아니다. 정본 형식
18
- * (`__releaseFormat`), 직전 판에 견준 변경(`__releaseChanges`), 발행 때 잰 값(`__releaseMetrics`)과
18
+ * (`__releaseFormat`), 잰 커널의 판(`__releaseKernel`, ADR-0109 C1), 직전 판에 견준 변경(`__releaseChanges`), 발행 때 잰 값(`__releaseMetrics`)과
19
19
  * 윗모습(`__releaseTopView`)도 같은 길로 옮긴다(ADR-0104).
20
20
  */
21
21
  /** What `releaseFigure` laid on the entity for this release, moved onto the history row. */
@@ -23,6 +23,7 @@ function releaseRecordOnto(history, entity) {
23
23
  const e = entity;
24
24
  history.comment = e.__releaseComment ?? null;
25
25
  history.assetFormat = e.__releaseFormat ?? null;
26
+ history.kernelVersion = e.__releaseKernel ?? null;
26
27
  /* [] stays "[]" (nothing changed); null stays null (not compared). */
27
28
  history.changes = e.__releaseChanges == null ? null : JSON.stringify(e.__releaseChanges);
28
29
  history.metrics = e.__releaseMetrics == null ? null : JSON.stringify(e.__releaseMetrics);
@@ -1 +1 @@
1
- {"version":3,"file":"event-subscriber.js","sourceRoot":"","sources":["../../../server/service/figure/event-subscriber.ts"],"names":[],"mappings":";;;;AAAA,qCAAyC;AAEzC,8DAAkE;AAElE,2CAAoC;AACpC,2DAAmD;AAEnD;;;;;;;;;;;GAWG;AACH,4FAA4F;AAC5F,SAAS,iBAAiB,CAAC,OAAsB,EAAE,MAAc;IAC/D,MAAM,CAAC,GAAG,MAAa,CACtB;IAAC,OAAe,CAAC,OAAO,GAAG,CAAC,CAAC,gBAAgB,IAAI,IAAI,CAAA;IACtD,OAAO,CAAC,WAAW,GAAG,CAAC,CAAC,eAAe,IAAI,IAAI,CAAA;IAC/C,sEAAsE;IACtE,OAAO,CAAC,OAAO,GAAG,CAAC,CAAC,gBAAgB,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAA;IACxF,OAAO,CAAC,OAAO,GAAG,CAAC,CAAC,gBAAgB,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAA;IACxF,OAAO,CAAC,OAAO,GAAG,CAAC,CAAC,gBAAgB,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAA;IACxF,OAAO,OAAO,CAAA;AAChB,CAAC;AAGM,IAAM,6BAA6B,GAAnC,MAAM,6BAA8B,SAAQ,yCAA8C;IAC/F,IAAW,MAAM;QACf,OAAO,kBAAM,CAAA;IACf,CAAC;IAED,IAAW,aAAa;QACtB,OAAO,iCAAa,CAAA;IACtB,CAAC;IAEM,mBAAmB,CAAC,OAAsB,EAAE,MAAc;QAC/D,OAAO,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IAC3C,CAAC;IAEM,mBAAmB,CAAC,OAAsB,EAAE,MAAc;QAC/D,OAAO,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IAC3C,CAAC;IAEM,KAAK,CAAC,WAAW,CAAC,KAAU;QACjC,IAAI,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,UAAU,EAAE,CAAC;YACtC,MAAM,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;QAChC,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,WAAW,CAAC,KAAU;QACjC,IAAI,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,UAAU,EAAE,CAAC;YACtC,MAAM,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;QAChC,CAAC;IACH,CAAC;CACF,CAAA;AA5BY,sEAA6B;wCAA7B,6BAA6B;IADzC,IAAA,yBAAe,GAAE;GACL,6BAA6B,CA4BzC","sourcesContent":["import { EventSubscriber } from 'typeorm'\n\nimport { HistoryEntitySubscriber } from '@operato/typeorm-history'\n\nimport { Figure } from './figure.js'\nimport { FigureHistory } from './figure-history.js'\n\n/**\n * 판본을 남긴다 — **발행된 저장에만.**\n *\n * `@operato/typeorm-history` 는 원래 모든 저장을 베낀다. 그런데 도형은 저작 중에 수십 번 저장되고,\n * 그 전부를 남기면 판본 목록이 「내가 오늘 몇 번 눌렀나」가 된다. 사람이 판이라고 부르는 것은\n * **발행한 것**이므로 그때만 베낀다. board 가 같은 규칙으로 돈다(`board-service` 의 같은 이름 파일).\n *\n * 발행 메모는 Figure 의 칸이 아니다. `releaseFigure` 가 저장할 엔티티에 `__releaseComment` 로 얹어\n * 두면 여기서 판본의 `comment` 로 옮긴다 — 메모는 그 판의 것이지 도형의 것이 아니다. 정본 형식\n * (`__releaseFormat`), 직전 판에 견준 변경(`__releaseChanges`), 발행 때 잰 값(`__releaseMetrics`)과\n * 윗모습(`__releaseTopView`)도 같은 길로 옮긴다(ADR-0104).\n */\n/** What `releaseFigure` laid on the entity for this release, moved onto the history row. */\nfunction releaseRecordOnto(history: FigureHistory, entity: Figure): FigureHistory {\n const e = entity as any\n ;(history as any).comment = e.__releaseComment ?? null\n history.assetFormat = e.__releaseFormat ?? null\n /* [] stays \"[]\" (nothing changed); null stays null (not compared). */\n history.changes = e.__releaseChanges == null ? null : JSON.stringify(e.__releaseChanges)\n history.metrics = e.__releaseMetrics == null ? null : JSON.stringify(e.__releaseMetrics)\n history.topView = e.__releaseTopView == null ? null : JSON.stringify(e.__releaseTopView)\n return history\n}\n\n@EventSubscriber()\nexport class FigureHistoryEntitySubscriber extends HistoryEntitySubscriber<Figure, FigureHistory> {\n public get entity() {\n return Figure\n }\n\n public get historyEntity() {\n return FigureHistory\n }\n\n public beforeInsertHistory(history: FigureHistory, entity: Figure): FigureHistory {\n return releaseRecordOnto(history, entity)\n }\n\n public beforeUpdateHistory(history: FigureHistory, entity: Figure): FigureHistory {\n return releaseRecordOnto(history, entity)\n }\n\n public async afterInsert(event: any): Promise<void> {\n if (event.entity?.state == 'released') {\n await super.afterInsert(event)\n }\n }\n\n public async afterUpdate(event: any): Promise<void> {\n if (event.entity?.state == 'released') {\n await super.afterUpdate(event)\n }\n }\n}\n"]}
1
+ {"version":3,"file":"event-subscriber.js","sourceRoot":"","sources":["../../../server/service/figure/event-subscriber.ts"],"names":[],"mappings":";;;;AAAA,qCAAyC;AAEzC,8DAAkE;AAElE,2CAAoC;AACpC,2DAAmD;AAEnD;;;;;;;;;;;GAWG;AACH,4FAA4F;AAC5F,SAAS,iBAAiB,CAAC,OAAsB,EAAE,MAAc;IAC/D,MAAM,CAAC,GAAG,MAAa,CACtB;IAAC,OAAe,CAAC,OAAO,GAAG,CAAC,CAAC,gBAAgB,IAAI,IAAI,CAAA;IACtD,OAAO,CAAC,WAAW,GAAG,CAAC,CAAC,eAAe,IAAI,IAAI,CAAA;IAC/C,OAAO,CAAC,aAAa,GAAG,CAAC,CAAC,eAAe,IAAI,IAAI,CAAA;IACjD,sEAAsE;IACtE,OAAO,CAAC,OAAO,GAAG,CAAC,CAAC,gBAAgB,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAA;IACxF,OAAO,CAAC,OAAO,GAAG,CAAC,CAAC,gBAAgB,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAA;IACxF,OAAO,CAAC,OAAO,GAAG,CAAC,CAAC,gBAAgB,IAAI,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAA;IACxF,OAAO,OAAO,CAAA;AAChB,CAAC;AAGM,IAAM,6BAA6B,GAAnC,MAAM,6BAA8B,SAAQ,yCAA8C;IAC/F,IAAW,MAAM;QACf,OAAO,kBAAM,CAAA;IACf,CAAC;IAED,IAAW,aAAa;QACtB,OAAO,iCAAa,CAAA;IACtB,CAAC;IAEM,mBAAmB,CAAC,OAAsB,EAAE,MAAc;QAC/D,OAAO,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IAC3C,CAAC;IAEM,mBAAmB,CAAC,OAAsB,EAAE,MAAc;QAC/D,OAAO,iBAAiB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IAC3C,CAAC;IAEM,KAAK,CAAC,WAAW,CAAC,KAAU;QACjC,IAAI,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,UAAU,EAAE,CAAC;YACtC,MAAM,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;QAChC,CAAC;IACH,CAAC;IAEM,KAAK,CAAC,WAAW,CAAC,KAAU;QACjC,IAAI,KAAK,CAAC,MAAM,EAAE,KAAK,IAAI,UAAU,EAAE,CAAC;YACtC,MAAM,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAA;QAChC,CAAC;IACH,CAAC;CACF,CAAA;AA5BY,sEAA6B;wCAA7B,6BAA6B;IADzC,IAAA,yBAAe,GAAE;GACL,6BAA6B,CA4BzC","sourcesContent":["import { EventSubscriber } from 'typeorm'\n\nimport { HistoryEntitySubscriber } from '@operato/typeorm-history'\n\nimport { Figure } from './figure.js'\nimport { FigureHistory } from './figure-history.js'\n\n/**\n * 판본을 남긴다 — **발행된 저장에만.**\n *\n * `@operato/typeorm-history` 는 원래 모든 저장을 베낀다. 그런데 도형은 저작 중에 수십 번 저장되고,\n * 그 전부를 남기면 판본 목록이 「내가 오늘 몇 번 눌렀나」가 된다. 사람이 판이라고 부르는 것은\n * **발행한 것**이므로 그때만 베낀다. board 가 같은 규칙으로 돈다(`board-service` 의 같은 이름 파일).\n *\n * 발행 메모는 Figure 의 칸이 아니다. `releaseFigure` 가 저장할 엔티티에 `__releaseComment` 로 얹어\n * 두면 여기서 판본의 `comment` 로 옮긴다 — 메모는 그 판의 것이지 도형의 것이 아니다. 정본 형식\n * (`__releaseFormat`), 잰 커널의 판(`__releaseKernel`, ADR-0109 C1), 직전 판에 견준 변경(`__releaseChanges`), 발행 때 잰 값(`__releaseMetrics`)과\n * 윗모습(`__releaseTopView`)도 같은 길로 옮긴다(ADR-0104).\n */\n/** What `releaseFigure` laid on the entity for this release, moved onto the history row. */\nfunction releaseRecordOnto(history: FigureHistory, entity: Figure): FigureHistory {\n const e = entity as any\n ;(history as any).comment = e.__releaseComment ?? null\n history.assetFormat = e.__releaseFormat ?? null\n history.kernelVersion = e.__releaseKernel ?? null\n /* [] stays \"[]\" (nothing changed); null stays null (not compared). */\n history.changes = e.__releaseChanges == null ? null : JSON.stringify(e.__releaseChanges)\n history.metrics = e.__releaseMetrics == null ? null : JSON.stringify(e.__releaseMetrics)\n history.topView = e.__releaseTopView == null ? null : JSON.stringify(e.__releaseTopView)\n return history\n}\n\n@EventSubscriber()\nexport class FigureHistoryEntitySubscriber extends HistoryEntitySubscriber<Figure, FigureHistory> {\n public get entity() {\n return Figure\n }\n\n public get historyEntity() {\n return FigureHistory\n }\n\n public beforeInsertHistory(history: FigureHistory, entity: Figure): FigureHistory {\n return releaseRecordOnto(history, entity)\n }\n\n public beforeUpdateHistory(history: FigureHistory, entity: Figure): FigureHistory {\n return releaseRecordOnto(history, entity)\n }\n\n public async afterInsert(event: any): Promise<void> {\n if (event.entity?.state == 'released') {\n await super.afterInsert(event)\n }\n }\n\n public async afterUpdate(event: any): Promise<void> {\n if (event.entity?.state == 'released') {\n await super.afterUpdate(event)\n }\n }\n}\n"]}
@@ -66,6 +66,7 @@ rowType?: string): Inspection;
66
66
  */
67
67
  export declare function releaseRecordOf(sourceJson: string, releasedJson?: string | null): {
68
68
  format: string;
69
+ kernel: string;
69
70
  changes: FigureContractChange[] | null;
70
71
  metrics: FigureReleaseMetrics;
71
72
  topView: FigureTopView;
@@ -421,7 +421,7 @@ function figureContractWording(change, say) {
421
421
  */
422
422
  function releaseRecordOf(sourceJson, releasedJson) {
423
423
  const asset = (0, figure_model_1.parseFigureAsset)(sourceJson);
424
- const measured = { format: asset.version, metrics: (0, figure_model_1.figureReleaseMetricsOf)(asset), topView: (0, figure_model_1.figureTopViewOf)(asset, null) };
424
+ const measured = { format: asset.version, kernel: figure_model_1.FIGURE_KERNEL_VERSION, metrics: (0, figure_model_1.figureReleaseMetricsOf)(asset), topView: (0, figure_model_1.figureTopViewOf)(asset, null) };
425
425
  if (!releasedJson)
426
426
  return { ...measured, changes: [] };
427
427
  let before;
@@ -1 +1 @@
1
- {"version":3,"file":"figure-format.js","sourceRoot":"","sources":["../../../server/service/figure/figure-format.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The doors a stored source goes through: saving (`parseSource`), publishing (`inspectSource`) and handing it to a\n * board (`consumablePayloadOf`). The format is `figure-asset-1`, and the asset says so in its `version`; a source\n * that does not is refused by name, because a source the server cannot identify is one it must not save.\n */\nimport { compileFigureAsset, inspectFigureAsset, isPlaceholderType, parseFigureAsset, serializeFigureAsset, figureContractChanges, figureCostOf, figureOriginCentredOf, figureReleaseMetricsOf, figureScoreOf, figureTopViewOf } from '@hatiolab/figure-model'\nimport type { FigureAsset, FigureContractChange, FigureContractError, FigureReleaseMetrics, FigureTopView, FigureViolation } from '@hatiolab/figure-model'\n\nimport type { FigureFinding } from './figure-type.js'\n\n/** The version the format stamps on its own source. */\nexport const FIGURE_ASSET_VERSION = 'figure-asset-1'\n\n/** A source that passed the save door: what is stored, and the numbers the catalogue shows, computed here. */\nexport interface ParsedSource {\n /** The source to store, as the kernel serializes it. */\n source: string\n /** Computed from the source, never taken from the client -- a client's numbers could lie to the catalogue. */\n derived: { score: number; triangles: number; groups: number }\n /** Findings that do not block the save; the caller returns them with the answer. */\n violations: FigureFinding[]\n}\n\n/** The source breaks the format. It is not stored. */\nexport class FigureSourceError extends Error {\n readonly findings: FigureFinding[]\n\n constructor(findings: FigureFinding[]) {\n super(`정본이 형식을 어겼다 — ${findings.length}건: ${findings.map(f => f.code).join(', ')}`)\n this.name = 'FigureSourceError'\n this.findings = findings\n }\n}\n\n/** One thing the release gate found. `blocking` true means the figure cannot be published. */\nexport interface GateFinding {\n code: string\n message: string\n /** **Why it matters.** A measurement alone leaves the reader at \"so what?\". */\n why?: string\n /** **What to change.** By part name and value. */\n how?: string\n /** Where it points: the parts, or the path in the source. */\n at?: string\n blocking: boolean\n}\n\nexport interface Inspection {\n findings: GateFinding[]\n /** Whether anything blocks. The screen locks the button with this. */\n blocked: boolean\n}\n\n/**\n * That the source is JSON and names the format.\n *\n * @throws {FigureSourceError} when the text is not JSON, or does not carry `version: 'figure-asset-1'`.\n */\nfunction assertFormat(sourceJson: string): void {\n let parsed: unknown\n try {\n parsed = JSON.parse(sourceJson)\n } catch (e) {\n throw new FigureSourceError([\n { code: 'source-not-json', message: `정본이 JSON 이 아니다: ${(e as Error).message}`, at: 'source' }\n ])\n }\n if ((parsed as { version?: unknown } | null)?.version !== FIGURE_ASSET_VERSION)\n throw new FigureSourceError([\n { code: 'source-format-unknown', message: `정본의 판을 알 수 없다 — 도형 자산은 version '${FIGURE_ASSET_VERSION}' 을 적는다`, at: 'version' }\n ])\n}\n\n/**\n * Validates a source and computes what the catalogue shows: the cost from `figureCostOf`, and the score from `figureScoreOf`\n * -- the headroom against placing `LIMITS.screenInstances` of it on one screen (chief architect, 2026-09-24), the\n * same number the modeller's maturity tab shows. An asset that draws nothing has no score, not a full one.\n *\n * @throws {FigureSourceError} when the source breaks the format.\n */\nexport function parseSource(sourceJson: string): ParsedSource {\n assertFormat(sourceJson)\n let asset\n try {\n asset = parseFigureAsset(sourceJson)\n compileFigureAsset(asset)\n } catch (e) {\n const error = e as FigureContractError & { path?: string }\n throw new FigureSourceError([\n { code: error.code ?? 'asset-invalid', message: error.message ?? String(e), at: error.path }\n ])\n }\n const cost = figureCostOf(asset)\n const score = figureScoreOf(asset)\n return {\n source: serializeFigureAsset(asset),\n derived: { score: (score?.score ?? null) as unknown as number, triangles: cost.triangles, groups: cost.groups },\n violations: []\n }\n}\n\n/**\n * Whether this source may be published, and why not.\n *\n * The judgement is `inspectFigureAsset`: every part inside the volume the asset declares, over the whole\n * state range, and the face it says it is mounted on lying in that plane. A verdict reached by sampling is\n * reported as a finding of its own rather than hidden — an author releasing a figure the gate could only\n * sample should be told so, because nothing proved it holds between the states that were checked.\n */\n/** The request's translator. Always called with params — `t(key, undefined)` loses the locale. */\nexport type Translate = (key: string, options?: Record<string, unknown>) => string\n\n/**\n * A finding in the words of the release panel.\n *\n * The gate says what it measured as a code and values (`part`, `axis`, `mm`, `degrees`) and an English `detail`\n * for logs. The sentence an author reads is made here, where the request's language is known (ADR-0054) — not in\n * figure-model, which knows no locale, and not on the screen, which would then have a second account of the same\n * refusal. The English line is the fallback when a key is missing, so a missing translation reads as English\n * rather than as the key printed raw.\n *\n * The words are the modeller's: 「공간 선언」 for the volume a figure takes up and 「장착면」 for the face it stands on\n * (`figure.text.mounting-face-explained`). A fact, then the way out.\n */\nfunction figureWording(violation: FigureViolation, say: Say, hasParts: boolean): Pick<GateFinding, 'message' | 'why' | 'how'> {\n const part = violation.part ?? ''\n const axis = (violation.axis ?? '').toUpperCase()\n const mm = violation.mm ?? 0\n const degrees = violation.degrees ?? 0\n const key = (field: string) => `figure.gate.${violation.code.toLowerCase().replace(/_/g, '-')}.${field}`\n\n switch (violation.code) {\n case 'PART_OUTSIDE_OCCUPANCY':\n return {\n message: say(key('message'), { part, axis, mm }, `'${part}' goes ${mm} mm past the declared space on ${axis}.`),\n why: say(key('why'), {}, 'The declared space sets the scale a figure is placed at. What lies past it is left out of that scale, so on a board this part lands outside the place given to the figure.'),\n how: say(key('how'), { part, axis, mm }, `Use \"fit to parts\" to declare the space from the parts again, or move '${part}' ${mm} mm inward on ${axis}.`)\n }\n case 'OCCUPANCY_UNDECLARED':\n return violation.axis\n ? {\n message: say(`figure.gate.occupancy-empty-axis.message`, { axis }, `The declared space is empty on ${axis}.`),\n why: say(key('why'), {}, 'Without a declared space the scale a figure is placed at cannot be set.'),\n how: say(key('how'), {}, 'Use \"fit to parts\" to declare the space from the parts as they are now.')\n }\n : {\n message: say(key('message'), {}, 'This figure has not declared the space it takes up.'),\n why: say(key('why'), {}, 'Without a declared space the scale a figure is placed at cannot be set.'),\n /*\n A new figure is refused this way before it has a part, and 「fit to parts」 has nothing to measure then —\n the screen does not offer it. Telling the author to press it sent them looking for a button that was not\n there (:3300, 2026-09-24).\n */\n how: hasParts\n ? say(key('how'), {}, 'Use \"fit to parts\" to declare the space from the parts as they are now.')\n : say(key('how-no-parts'), {}, 'Add a shape first, then use \"fit to parts\" to declare the space from it.')\n }\n case 'PARTS_OFF_PLACEMENT_FACE':\n return {\n message: say(key('message'), { part, mm }, `The mounting face of '${part}' is ${mm} mm off the plane the figure stands on.`),\n why: say(key('why'), {}, 'The figure is declared to stand on that face. If the face does not reach the plane, the figure floats on the board by that much, and whatever is placed on it floats too.'),\n how: say(key('how'), { part, mm }, `Move '${part}' ${mm} mm on Y so the face meets the plane, or choose a different mounting face.`)\n }\n case 'PLACEMENT_FACE_TILTED':\n return {\n message: say(key('message'), { part, degrees }, `The mounting face of '${part}' is tilted ${degrees}° from the plane the figure stands on.`),\n why: say(key('why'), {}, 'A tilted face cannot lie on the plane, so how the figure stands is not settled.'),\n how: say(key('how'), { part }, `Choose a mounting face parallel to the plane, or turn '${part}' upright.`)\n }\n case 'PARTS_SPLIT_ON_RESIZE': {\n /*\n What comes off is every piece but the largest — the figure as the author sees it is the big piece, and the\n small ones are what they will see hanging in the air (2026-09-24).\n */\n const resize = violation.resize!\n const pieces = [...resize.pieces].sort((a, b) => b.length - a.length)\n const parts = pieces.slice(1).flat().map(one => `'${one}'`).join(', ')\n const axes = resize.axes.map(one => one.toUpperCase()).join('·')\n const factor = resize.factor\n return {\n message: say(key('message'), { parts, axes, factor }, `At ${factor}x on ${axes}, ${parts} come away from the rest of the figure.`),\n why: say(key('why'), {}, 'A figure placed at another size shows those parts hanging in the air — to a person, it looks broken.'),\n how: say(key('how'), { parts }, `Fasten ${parts} to a face of the part they rest on, or press \"fix here\" under placement, so they stay put when the figure is resized.`)\n }\n }\n case 'SIZING_NOT_UNIFORM': {\n /* The figure declares it grows by one ratio; these parts keep a size or place of their own (ruling 2026-09-24). */\n const resize = violation.resize!\n const parts = (violation.parts ?? []).map(one => `'${one}'`).join(', ')\n const axes = resize.axes.map(one => one.toUpperCase()).join('·')\n const factor = resize.factor\n return {\n message: say(key('message'), { parts, axes, factor }, `The figure grows by one ratio, but at ${factor}x on ${axes} ${parts} do not grow with it.`),\n why: say(key('why'), {}, 'A figure that grows by one ratio keeps its proportions at any size. A part with a size or place of its own comes apart from the rest.'),\n how: say(key('how'), { parts }, `Let ${parts} follow the figure's size (\"in proportion to size\" under size and placement), or remove their own fixed numbers.`)\n }\n }\n }\n}\n\ntype Say = (key: string, params: Record<string, string | number>, english: string) => string\n\n/*\n The sentence is shown as text, never as HTML, so the values go in as they are. i18next escapes interpolated\n values by default, and the screen then showed `'lamp-in'` as `&#39;lamp-in&#39;`.\n*/\nfunction sayerOf(t?: Translate): Say {\n return (key, params, english) =>\n t ? t(key, { ...params, defaultValue: english, interpolation: { escapeValue: false } }) : english\n}\n\nexport function inspectSource(\n sourceJson?: string | null,\n releasedJson?: string | null,\n t?: Translate,\n /** The row's `type` -- the only place the name lives, since the asset carries none. */\n rowType?: string\n): Inspection {\n if (!sourceJson) {\n return { blocked: true, findings: [{ code: 'no-source', message: '저장된 정본이 없다. 저장하면 발행할 수 있다', blocking: true }] }\n }\n try {\n assertFormat(sourceJson)\n } catch (e) {\n const findings = (e as FigureSourceError).findings ?? [{ code: 'source-unreadable', message: String(e) }]\n return { blocked: true, findings: findings.map(f => ({ ...f, blocking: true })) }\n }\n\n let inspection\n let asset: FigureAsset | undefined\n let hasParts = true\n try {\n asset = parseFigureAsset(sourceJson)\n inspection = inspectFigureAsset(asset)\n const cost = figureCostOf(asset)\n hasParts = cost.groups + cost.hidden > 0\n } catch (e) {\n const error = e as FigureContractError & { path?: string }\n return {\n blocked: true,\n findings: [{ code: error.code ?? 'asset-invalid', message: error.message ?? String(e), at: error.path, blocking: true }]\n }\n }\n\n const say = sayerOf(t)\n const findings: GateFinding[] = inspection.violations.map(violation => ({\n code: violation.code.toLowerCase().replace(/_/g, '-'),\n ...figureWording(violation, say, hasParts),\n at: violation.part,\n blocking: true\n }))\n /*\n A machine-made name is refused at release. The asset has no `type`, so the name is read off the row; a new figure\n was once published as `FIGURE_<uuid>` (:3300, 2026-09-24). Publishing freezes the name (ADR-0063 decision 4) and\n boards call a figure by it.\n */\n if (rowType && isPlaceholderType(rowType)) {\n findings.push({\n code: 'type-is-placeholder',\n message: say('figure.gate.type-is-placeholder.message', { type: rowType }, `'${rowType}' is a temporary type given when the figure was first saved.`),\n why: say('figure.gate.type-is-placeholder.why', {}, 'Boards call a figure by its type, and it cannot change once the figure is published.'),\n how: say('figure.gate.type-is-placeholder.how', {}, 'Set the type in the type field, then publish.'),\n blocking: true\n })\n }\n if (inspection.coverage.method === 'sampled') {\n const states = inspection.coverage.states\n findings.push({\n code: 'state-range-sampled',\n /* Sizes as well as motion: the instance size range is swept for every figure (figure-model, designer 2026-09-27). */\n message: say('figure.gate.state-range-sampled.message', { states }, `The whole range of sizes and motion could not be proven, so ${states} combinations of size and pose were checked.`),\n why: say('figure.gate.state-range-sampled.why', {}, 'Between the combinations that were checked, a part may still go past the declared space.'),\n how: say('figure.gate.state-range-sampled.how', {}, 'To cover the whole range, re-author what could not be proven.'),\n /*\n Which motions stopped the proof, by the name a person gave them: the kernel reports each operation it could\n not prove (`j2-shoulder.chain: compose@1 turns …`), and the screen showed that English list as it was. The\n name before the first dot is the joint or part; the operations stay in the logs.\n */\n at: [...new Set((inspection.coverage.unprovable ?? []).map(entry => entry.split(':')[0]!.split('.')[0]!.trim()).filter(Boolean))].join(' · ') || undefined,\n blocking: false\n })\n }\n /*\n Said, never refused (ADR-0104 decision 4): the origin is where the figure is fastened, and a door fastened at its\n hinge is a right model. A drawing that places figures by the middle of their room reads this before it pins one.\n */\n const origin = figureOriginCentredOf(asset!)\n if (origin && !origin.centred) {\n const off = origin.off.map(o => `${o.axis.toUpperCase()} ${o.mm} mm`).join(', ')\n findings.push({\n code: 'origin-off-centre',\n message: say('figure.gate.origin-off-centre.message', { off }, `The origin is off the middle of the declared room: ${off}.`),\n why: say('figure.gate.origin-off-centre.why', {}, 'A drawing that places figures by the middle of their room puts this one that far from where it is drawn.'),\n how: say('figure.gate.origin-off-centre.how', {}, 'Keep it when the figure is fastened there, as a door at its hinge. Move the origin to the middle to place it by its room.'),\n blocking: false\n })\n }\n if (releasedJson) findings.push(...figureContractFindings(asset!, releasedJson, say))\n return { blocked: findings.some(finding => finding.blocking), findings }\n}\n\n/**\n * The last release against this one — what the drawings that already hold this type lean on (ADR-0063 decision 3).\n *\n * figure-model names the changes and whether each blocks (`figureContractChanges`); the sentence is made here. When\n * the last release no longer parses, the gate says so rather than passing in silence: a release that was not checked\n * against the last one is a different fact from one that was checked and found safe.\n */\nfunction figureContractFindings(asset: FigureAsset, releasedJson: string, say: Say): GateFinding[] {\n let before: FigureAsset\n try {\n before = parseFigureAsset(releasedJson)\n } catch (e) {\n return [\n {\n code: 'released-unreadable',\n message: say('figure.gate.released-not-compared.message', { reason: (e as Error).message }, `The last release could not be read, so this release was not compared with it: ${(e as Error).message}`),\n why: say('figure.gate.released-not-compared.why', {}, 'Whether this release breaks the instances already placed has not been checked.'),\n blocking: false\n }\n ]\n }\n return figureContractChanges(before, asset).map(change => ({\n code: change.code,\n ...figureContractWording(change, say),\n at: change.subject,\n blocking: change.blocking\n }))\n}\n\n/** One contract change in the words of the release panel. The English line is the fallback for a missing key. */\nfunction figureContractWording(change: FigureContractChange, say: Say): Pick<GateFinding, 'message' | 'why' | 'how'> {\n const v = change.values\n const key = (field: string) => `figure.gate.contract.${change.code}.${field}`\n const gone = {\n how: say('figure.gate.contract.gone.how', {}, 'Put it back as it was, or publish this as a new figure type so the placed ones keep the old one.')\n }\n switch (change.code) {\n case 'placement-changed':\n return {\n message: say(key('message'), v, `Placement changed from ${v.before} to ${v.after}.`),\n why: say(key('why'), {}, 'Placement sets the height of every placed instance. They all move with it.'),\n ...gone\n }\n case 'size-inputs-gone':\n return {\n message: say(key('message'), v, 'The figure no longer takes its size from the place it is given.'),\n why: say(key('why'), {}, 'Placed instances were sized on the board. After this release they all draw at the authored size.'),\n ...gone\n }\n case 'size-inputs-added':\n return {\n message: say(key('message'), v, 'The figure now takes its size from the place it is given.'),\n why: say(key('why'), {}, 'Placed instances now follow their own size on the board.')\n }\n case 'size-range-narrowed':\n return {\n message: say(key('message'), { ...v, input: change.subject ?? '' }, `The size range of ${change.subject} narrowed from ${v.before} to ${v.after}.`),\n why: say(key('why'), {}, 'An instance placed at a size outside the new range will not draw. Which sizes are placed is not recorded.')\n }\n case 'authored-size-changed':\n return {\n message: say(key('message'), v, `The authored size changed from ${v.before} to ${v.after}.`),\n why: say(key('why'), {}, 'Placed instances keep their own size. An instance with no depth of its own takes its depth from this.')\n }\n case 'state-input-gone':\n return {\n message: say(key('message'), v, `The control '${v.id}' is gone.`),\n why: say(key('why'), {}, 'Placed instances and connectors give values under this name. After this release those values do nothing, and nothing on screen says why.'),\n ...gone\n }\n case 'state-unit-changed':\n return {\n message: say(key('message'), v, `The unit of the control '${v.id}' changed from ${v.before} to ${v.after}.`),\n why: say(key('why'), {}, 'Stored values keep their number. With another unit the same number means something else.'),\n ...gone\n }\n case 'state-range-narrowed':\n return {\n message: say(key('message'), v, `The range of the control '${v.id}' narrowed from ${v.before} to ${v.after}.`),\n why: say(key('why'), {}, 'A value outside the new range may already be stored on a placed instance.')\n }\n case 'state-input-added':\n return {\n message: say(key('message'), v, `The control '${v.id}' is new.`),\n why: say(key('why'), {}, 'Placed instances that give no value stand at its default.')\n }\n case 'clip-gone':\n return {\n message: say(key('message'), v, `The clip '${v.clip}' is gone.`),\n why: say(key('why'), {}, 'Placed instances play clips by name. After this release that one plays nothing.'),\n ...gone\n }\n case 'clip-added':\n return {\n message: say(key('message'), v, `The clip '${v.clip}' is new.`),\n why: say(key('why'), {}, 'It stays still until an instance plays it.')\n }\n case 'binding-gone':\n return {\n message: say(key('message'), v, `The place '${v.binding}' is gone.`),\n why: say(key('why'), {}, 'What sits in it on a placed instance loses its place.'),\n ...gone\n }\n case 'binding-role-changed':\n return {\n message: say(key('message'), v, `The place '${v.binding}' changed from ${v.before} to ${v.after}.`),\n why: say(key('why'), {}, 'What sits in it was placed for the old role.'),\n ...gone\n }\n case 'binding-capacity-reduced':\n return {\n message: say(key('message'), v, `The place '${v.binding}' holds ${v.after} instead of ${v.before}.`),\n why: say(key('why'), {}, 'What sits in the places that went has nowhere to go.'),\n ...gone\n }\n case 'binding-accepts-narrowed':\n return {\n message: say(key('message'), v, `The place '${v.binding}' no longer accepts ${v.types}.`),\n why: say(key('why'), {}, 'What already sits there stays. The next one of that type is refused.')\n }\n case 'binding-added':\n return {\n message: say(key('message'), v, `The place '${v.binding}' is new.`),\n why: say(key('why'), {}, 'Placed instances do not know it yet and stand as they are.')\n }\n case 'capability-gone':\n return {\n message: say(key('message'), v, `The capability '${v.name}' is gone.`),\n why: say(key('why'), {}, 'Scenes attach behaviour by this name. Placed instances lose what it did.'),\n ...gone\n }\n case 'capability-added':\n return {\n message: say(key('message'), v, `The capability '${v.name}' is new.`),\n why: say(key('why'), {}, 'It adds what the figure can do. Placed instances stand as they are.')\n }\n /* Said, never refused (ADR-0104): a consumer that pins a release reads these before it moves to this one. */\n case 'occupancy-changed':\n return {\n message: say(key('message'), v, `The room the figure takes changed from ${v.before || 'none'} to ${v.after || 'none'}.`),\n why: say(key('why'), {}, 'A consumer places the figure by this room. One that moves to this release sees it take the new room.')\n }\n case 'contact-face-changed':\n return {\n message: say(key('message'), v, 'The face the figure is mounted by changed.'),\n why: say(key('why'), {}, 'A consumer that moves to this release sees it stand on the new face.')\n }\n case 'public-input-gone':\n return {\n message: say(key('message'), { ...v, input: change.subject ?? '' }, `'${change.subject}' is no longer set on a board.`),\n why: say(key('why'), {}, 'Values placed instances give it do nothing after this release.')\n }\n case 'public-input-range-narrowed':\n return {\n message: say(key('message'), { ...v, input: change.subject ?? '' }, `The range of '${change.subject}' narrowed from ${v.before} to ${v.after}.`),\n why: say(key('why'), {}, 'An instance may have set a value outside the new range. Which values are placed is not recorded.')\n }\n case 'public-input-added':\n return {\n message: say(key('message'), { ...v, input: change.subject ?? '' }, `'${change.subject}' can now be set on a board.`),\n why: say(key('why'), {}, 'Placed instances that give no value stand at its default.')\n }\n }\n}\n\n/**\n * What a release records about itself (ADR-0104 decision 5): the format its asset is written in, what it measured\n * (its cost at its largest, whether resizing is stretching), its plan from above, and what changed against the previous release -- the kernel's own comparison, kept as it was then so a consumer that pins releases\n * reads it rather than computing it again. `[]` for a first release; `null` when the previous release could not be\n * read, which is a different fact from \"nothing changed\".\n */\nexport function releaseRecordOf(\n sourceJson: string,\n releasedJson?: string | null\n): { format: string; changes: FigureContractChange[] | null; metrics: FigureReleaseMetrics; topView: FigureTopView } {\n const asset = parseFigureAsset(sourceJson)\n const measured = { format: asset.version, metrics: figureReleaseMetricsOf(asset), topView: figureTopViewOf(asset, null) }\n if (!releasedJson) return { ...measured, changes: [] }\n let before: FigureAsset\n try {\n before = parseFigureAsset(releasedJson)\n } catch {\n return { ...measured, changes: null }\n }\n return { ...measured, changes: figureContractChanges(before, asset) }\n}\n\n/**\n * What a consumer is handed for a released figure: the asset itself, because what draws it -- `registerFigure` in\n * things-scene -- takes the asset and compiles it with the kernel.\n */\nexport function consumablePayloadOf(sourceJson: string): { asset: FigureAsset } {\n assertFormat(sourceJson)\n const asset = parseFigureAsset(sourceJson)\n compileFigureAsset(asset)\n return { asset }\n}\n"]}
1
+ {"version":3,"file":"figure-format.js","sourceRoot":"","sources":["../../../server/service/figure/figure-format.ts"],"names":[],"mappings":"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","sourcesContent":["/*\n * The doors a stored source goes through: saving (`parseSource`), publishing (`inspectSource`) and handing it to a\n * board (`consumablePayloadOf`). The format is `figure-asset-1`, and the asset says so in its `version`; a source\n * that does not is refused by name, because a source the server cannot identify is one it must not save.\n */\nimport { FIGURE_KERNEL_VERSION, compileFigureAsset, inspectFigureAsset, isPlaceholderType, parseFigureAsset, serializeFigureAsset, figureContractChanges, figureCostOf, figureOriginCentredOf, figureReleaseMetricsOf, figureScoreOf, figureTopViewOf } from '@hatiolab/figure-model'\nimport type { FigureAsset, FigureContractChange, FigureContractError, FigureReleaseMetrics, FigureTopView, FigureViolation } from '@hatiolab/figure-model'\n\nimport type { FigureFinding } from './figure-type.js'\n\n/** The version the format stamps on its own source. */\nexport const FIGURE_ASSET_VERSION = 'figure-asset-1'\n\n/** A source that passed the save door: what is stored, and the numbers the catalogue shows, computed here. */\nexport interface ParsedSource {\n /** The source to store, as the kernel serializes it. */\n source: string\n /** Computed from the source, never taken from the client -- a client's numbers could lie to the catalogue. */\n derived: { score: number; triangles: number; groups: number }\n /** Findings that do not block the save; the caller returns them with the answer. */\n violations: FigureFinding[]\n}\n\n/** The source breaks the format. It is not stored. */\nexport class FigureSourceError extends Error {\n readonly findings: FigureFinding[]\n\n constructor(findings: FigureFinding[]) {\n super(`정본이 형식을 어겼다 — ${findings.length}건: ${findings.map(f => f.code).join(', ')}`)\n this.name = 'FigureSourceError'\n this.findings = findings\n }\n}\n\n/** One thing the release gate found. `blocking` true means the figure cannot be published. */\nexport interface GateFinding {\n code: string\n message: string\n /** **Why it matters.** A measurement alone leaves the reader at \"so what?\". */\n why?: string\n /** **What to change.** By part name and value. */\n how?: string\n /** Where it points: the parts, or the path in the source. */\n at?: string\n blocking: boolean\n}\n\nexport interface Inspection {\n findings: GateFinding[]\n /** Whether anything blocks. The screen locks the button with this. */\n blocked: boolean\n}\n\n/**\n * That the source is JSON and names the format.\n *\n * @throws {FigureSourceError} when the text is not JSON, or does not carry `version: 'figure-asset-1'`.\n */\nfunction assertFormat(sourceJson: string): void {\n let parsed: unknown\n try {\n parsed = JSON.parse(sourceJson)\n } catch (e) {\n throw new FigureSourceError([\n { code: 'source-not-json', message: `정본이 JSON 이 아니다: ${(e as Error).message}`, at: 'source' }\n ])\n }\n if ((parsed as { version?: unknown } | null)?.version !== FIGURE_ASSET_VERSION)\n throw new FigureSourceError([\n { code: 'source-format-unknown', message: `정본의 판을 알 수 없다 — 도형 자산은 version '${FIGURE_ASSET_VERSION}' 을 적는다`, at: 'version' }\n ])\n}\n\n/**\n * Validates a source and computes what the catalogue shows: the cost from `figureCostOf`, and the score from `figureScoreOf`\n * -- the headroom against placing `LIMITS.screenInstances` of it on one screen (chief architect, 2026-09-24), the\n * same number the modeller's maturity tab shows. An asset that draws nothing has no score, not a full one.\n *\n * @throws {FigureSourceError} when the source breaks the format.\n */\nexport function parseSource(sourceJson: string): ParsedSource {\n assertFormat(sourceJson)\n let asset\n try {\n asset = parseFigureAsset(sourceJson)\n compileFigureAsset(asset)\n } catch (e) {\n const error = e as FigureContractError & { path?: string }\n throw new FigureSourceError([\n { code: error.code ?? 'asset-invalid', message: error.message ?? String(e), at: error.path }\n ])\n }\n const cost = figureCostOf(asset)\n const score = figureScoreOf(asset)\n return {\n source: serializeFigureAsset(asset),\n derived: { score: (score?.score ?? null) as unknown as number, triangles: cost.triangles, groups: cost.groups },\n violations: []\n }\n}\n\n/**\n * Whether this source may be published, and why not.\n *\n * The judgement is `inspectFigureAsset`: every part inside the volume the asset declares, over the whole\n * state range, and the face it says it is mounted on lying in that plane. A verdict reached by sampling is\n * reported as a finding of its own rather than hidden — an author releasing a figure the gate could only\n * sample should be told so, because nothing proved it holds between the states that were checked.\n */\n/** The request's translator. Always called with params — `t(key, undefined)` loses the locale. */\nexport type Translate = (key: string, options?: Record<string, unknown>) => string\n\n/**\n * A finding in the words of the release panel.\n *\n * The gate says what it measured as a code and values (`part`, `axis`, `mm`, `degrees`) and an English `detail`\n * for logs. The sentence an author reads is made here, where the request's language is known (ADR-0054) — not in\n * figure-model, which knows no locale, and not on the screen, which would then have a second account of the same\n * refusal. The English line is the fallback when a key is missing, so a missing translation reads as English\n * rather than as the key printed raw.\n *\n * The words are the modeller's: 「공간 선언」 for the volume a figure takes up and 「장착면」 for the face it stands on\n * (`figure.text.mounting-face-explained`). A fact, then the way out.\n */\nfunction figureWording(violation: FigureViolation, say: Say, hasParts: boolean): Pick<GateFinding, 'message' | 'why' | 'how'> {\n const part = violation.part ?? ''\n const axis = (violation.axis ?? '').toUpperCase()\n const mm = violation.mm ?? 0\n const degrees = violation.degrees ?? 0\n const key = (field: string) => `figure.gate.${violation.code.toLowerCase().replace(/_/g, '-')}.${field}`\n\n switch (violation.code) {\n case 'PART_OUTSIDE_OCCUPANCY':\n return {\n message: say(key('message'), { part, axis, mm }, `'${part}' goes ${mm} mm past the declared space on ${axis}.`),\n why: say(key('why'), {}, 'The declared space sets the scale a figure is placed at. What lies past it is left out of that scale, so on a board this part lands outside the place given to the figure.'),\n how: say(key('how'), { part, axis, mm }, `Use \"fit to parts\" to declare the space from the parts again, or move '${part}' ${mm} mm inward on ${axis}.`)\n }\n case 'OCCUPANCY_UNDECLARED':\n return violation.axis\n ? {\n message: say(`figure.gate.occupancy-empty-axis.message`, { axis }, `The declared space is empty on ${axis}.`),\n why: say(key('why'), {}, 'Without a declared space the scale a figure is placed at cannot be set.'),\n how: say(key('how'), {}, 'Use \"fit to parts\" to declare the space from the parts as they are now.')\n }\n : {\n message: say(key('message'), {}, 'This figure has not declared the space it takes up.'),\n why: say(key('why'), {}, 'Without a declared space the scale a figure is placed at cannot be set.'),\n /*\n A new figure is refused this way before it has a part, and 「fit to parts」 has nothing to measure then —\n the screen does not offer it. Telling the author to press it sent them looking for a button that was not\n there (:3300, 2026-09-24).\n */\n how: hasParts\n ? say(key('how'), {}, 'Use \"fit to parts\" to declare the space from the parts as they are now.')\n : say(key('how-no-parts'), {}, 'Add a shape first, then use \"fit to parts\" to declare the space from it.')\n }\n case 'PARTS_OFF_PLACEMENT_FACE':\n return {\n message: say(key('message'), { part, mm }, `The mounting face of '${part}' is ${mm} mm off the plane the figure stands on.`),\n why: say(key('why'), {}, 'The figure is declared to stand on that face. If the face does not reach the plane, the figure floats on the board by that much, and whatever is placed on it floats too.'),\n how: say(key('how'), { part, mm }, `Move '${part}' ${mm} mm on Y so the face meets the plane, or choose a different mounting face.`)\n }\n case 'PLACEMENT_FACE_TILTED':\n return {\n message: say(key('message'), { part, degrees }, `The mounting face of '${part}' is tilted ${degrees}° from the plane the figure stands on.`),\n why: say(key('why'), {}, 'A tilted face cannot lie on the plane, so how the figure stands is not settled.'),\n how: say(key('how'), { part }, `Choose a mounting face parallel to the plane, or turn '${part}' upright.`)\n }\n case 'PARTS_SPLIT_ON_RESIZE': {\n /*\n What comes off is every piece but the largest — the figure as the author sees it is the big piece, and the\n small ones are what they will see hanging in the air (2026-09-24).\n */\n const resize = violation.resize!\n const pieces = [...resize.pieces].sort((a, b) => b.length - a.length)\n const parts = pieces.slice(1).flat().map(one => `'${one}'`).join(', ')\n const axes = resize.axes.map(one => one.toUpperCase()).join('·')\n const factor = resize.factor\n return {\n message: say(key('message'), { parts, axes, factor }, `At ${factor}x on ${axes}, ${parts} come away from the rest of the figure.`),\n why: say(key('why'), {}, 'A figure placed at another size shows those parts hanging in the air — to a person, it looks broken.'),\n how: say(key('how'), { parts }, `Fasten ${parts} to a face of the part they rest on, or press \"fix here\" under placement, so they stay put when the figure is resized.`)\n }\n }\n case 'SIZING_NOT_UNIFORM': {\n /* The figure declares it grows by one ratio; these parts keep a size or place of their own (ruling 2026-09-24). */\n const resize = violation.resize!\n const parts = (violation.parts ?? []).map(one => `'${one}'`).join(', ')\n const axes = resize.axes.map(one => one.toUpperCase()).join('·')\n const factor = resize.factor\n return {\n message: say(key('message'), { parts, axes, factor }, `The figure grows by one ratio, but at ${factor}x on ${axes} ${parts} do not grow with it.`),\n why: say(key('why'), {}, 'A figure that grows by one ratio keeps its proportions at any size. A part with a size or place of its own comes apart from the rest.'),\n how: say(key('how'), { parts }, `Let ${parts} follow the figure's size (\"in proportion to size\" under size and placement), or remove their own fixed numbers.`)\n }\n }\n }\n}\n\ntype Say = (key: string, params: Record<string, string | number>, english: string) => string\n\n/*\n The sentence is shown as text, never as HTML, so the values go in as they are. i18next escapes interpolated\n values by default, and the screen then showed `'lamp-in'` as `&#39;lamp-in&#39;`.\n*/\nfunction sayerOf(t?: Translate): Say {\n return (key, params, english) =>\n t ? t(key, { ...params, defaultValue: english, interpolation: { escapeValue: false } }) : english\n}\n\nexport function inspectSource(\n sourceJson?: string | null,\n releasedJson?: string | null,\n t?: Translate,\n /** The row's `type` -- the only place the name lives, since the asset carries none. */\n rowType?: string\n): Inspection {\n if (!sourceJson) {\n return { blocked: true, findings: [{ code: 'no-source', message: '저장된 정본이 없다. 저장하면 발행할 수 있다', blocking: true }] }\n }\n try {\n assertFormat(sourceJson)\n } catch (e) {\n const findings = (e as FigureSourceError).findings ?? [{ code: 'source-unreadable', message: String(e) }]\n return { blocked: true, findings: findings.map(f => ({ ...f, blocking: true })) }\n }\n\n let inspection\n let asset: FigureAsset | undefined\n let hasParts = true\n try {\n asset = parseFigureAsset(sourceJson)\n inspection = inspectFigureAsset(asset)\n const cost = figureCostOf(asset)\n hasParts = cost.groups + cost.hidden > 0\n } catch (e) {\n const error = e as FigureContractError & { path?: string }\n return {\n blocked: true,\n findings: [{ code: error.code ?? 'asset-invalid', message: error.message ?? String(e), at: error.path, blocking: true }]\n }\n }\n\n const say = sayerOf(t)\n const findings: GateFinding[] = inspection.violations.map(violation => ({\n code: violation.code.toLowerCase().replace(/_/g, '-'),\n ...figureWording(violation, say, hasParts),\n at: violation.part,\n blocking: true\n }))\n /*\n A machine-made name is refused at release. The asset has no `type`, so the name is read off the row; a new figure\n was once published as `FIGURE_<uuid>` (:3300, 2026-09-24). Publishing freezes the name (ADR-0063 decision 4) and\n boards call a figure by it.\n */\n if (rowType && isPlaceholderType(rowType)) {\n findings.push({\n code: 'type-is-placeholder',\n message: say('figure.gate.type-is-placeholder.message', { type: rowType }, `'${rowType}' is a temporary type given when the figure was first saved.`),\n why: say('figure.gate.type-is-placeholder.why', {}, 'Boards call a figure by its type, and it cannot change once the figure is published.'),\n how: say('figure.gate.type-is-placeholder.how', {}, 'Set the type in the type field, then publish.'),\n blocking: true\n })\n }\n if (inspection.coverage.method === 'sampled') {\n const states = inspection.coverage.states\n findings.push({\n code: 'state-range-sampled',\n /* Sizes as well as motion: the instance size range is swept for every figure (figure-model, designer 2026-09-27). */\n message: say('figure.gate.state-range-sampled.message', { states }, `The whole range of sizes and motion could not be proven, so ${states} combinations of size and pose were checked.`),\n why: say('figure.gate.state-range-sampled.why', {}, 'Between the combinations that were checked, a part may still go past the declared space.'),\n how: say('figure.gate.state-range-sampled.how', {}, 'To cover the whole range, re-author what could not be proven.'),\n /*\n Which motions stopped the proof, by the name a person gave them: the kernel reports each operation it could\n not prove (`j2-shoulder.chain: compose@1 turns …`), and the screen showed that English list as it was. The\n name before the first dot is the joint or part; the operations stay in the logs.\n */\n at: [...new Set((inspection.coverage.unprovable ?? []).map(entry => entry.split(':')[0]!.split('.')[0]!.trim()).filter(Boolean))].join(' · ') || undefined,\n blocking: false\n })\n }\n /*\n Said, never refused (ADR-0104 decision 4): the origin is where the figure is fastened, and a door fastened at its\n hinge is a right model. A drawing that places figures by the middle of their room reads this before it pins one.\n */\n const origin = figureOriginCentredOf(asset!)\n if (origin && !origin.centred) {\n const off = origin.off.map(o => `${o.axis.toUpperCase()} ${o.mm} mm`).join(', ')\n findings.push({\n code: 'origin-off-centre',\n message: say('figure.gate.origin-off-centre.message', { off }, `The origin is off the middle of the declared room: ${off}.`),\n why: say('figure.gate.origin-off-centre.why', {}, 'A drawing that places figures by the middle of their room puts this one that far from where it is drawn.'),\n how: say('figure.gate.origin-off-centre.how', {}, 'Keep it when the figure is fastened there, as a door at its hinge. Move the origin to the middle to place it by its room.'),\n blocking: false\n })\n }\n if (releasedJson) findings.push(...figureContractFindings(asset!, releasedJson, say))\n return { blocked: findings.some(finding => finding.blocking), findings }\n}\n\n/**\n * The last release against this one — what the drawings that already hold this type lean on (ADR-0063 decision 3).\n *\n * figure-model names the changes and whether each blocks (`figureContractChanges`); the sentence is made here. When\n * the last release no longer parses, the gate says so rather than passing in silence: a release that was not checked\n * against the last one is a different fact from one that was checked and found safe.\n */\nfunction figureContractFindings(asset: FigureAsset, releasedJson: string, say: Say): GateFinding[] {\n let before: FigureAsset\n try {\n before = parseFigureAsset(releasedJson)\n } catch (e) {\n return [\n {\n code: 'released-unreadable',\n message: say('figure.gate.released-not-compared.message', { reason: (e as Error).message }, `The last release could not be read, so this release was not compared with it: ${(e as Error).message}`),\n why: say('figure.gate.released-not-compared.why', {}, 'Whether this release breaks the instances already placed has not been checked.'),\n blocking: false\n }\n ]\n }\n return figureContractChanges(before, asset).map(change => ({\n code: change.code,\n ...figureContractWording(change, say),\n at: change.subject,\n blocking: change.blocking\n }))\n}\n\n/** One contract change in the words of the release panel. The English line is the fallback for a missing key. */\nfunction figureContractWording(change: FigureContractChange, say: Say): Pick<GateFinding, 'message' | 'why' | 'how'> {\n const v = change.values\n const key = (field: string) => `figure.gate.contract.${change.code}.${field}`\n const gone = {\n how: say('figure.gate.contract.gone.how', {}, 'Put it back as it was, or publish this as a new figure type so the placed ones keep the old one.')\n }\n switch (change.code) {\n case 'placement-changed':\n return {\n message: say(key('message'), v, `Placement changed from ${v.before} to ${v.after}.`),\n why: say(key('why'), {}, 'Placement sets the height of every placed instance. They all move with it.'),\n ...gone\n }\n case 'size-inputs-gone':\n return {\n message: say(key('message'), v, 'The figure no longer takes its size from the place it is given.'),\n why: say(key('why'), {}, 'Placed instances were sized on the board. After this release they all draw at the authored size.'),\n ...gone\n }\n case 'size-inputs-added':\n return {\n message: say(key('message'), v, 'The figure now takes its size from the place it is given.'),\n why: say(key('why'), {}, 'Placed instances now follow their own size on the board.')\n }\n case 'size-range-narrowed':\n return {\n message: say(key('message'), { ...v, input: change.subject ?? '' }, `The size range of ${change.subject} narrowed from ${v.before} to ${v.after}.`),\n why: say(key('why'), {}, 'An instance placed at a size outside the new range will not draw. Which sizes are placed is not recorded.')\n }\n case 'authored-size-changed':\n return {\n message: say(key('message'), v, `The authored size changed from ${v.before} to ${v.after}.`),\n why: say(key('why'), {}, 'Placed instances keep their own size. An instance with no depth of its own takes its depth from this.')\n }\n case 'state-input-gone':\n return {\n message: say(key('message'), v, `The control '${v.id}' is gone.`),\n why: say(key('why'), {}, 'Placed instances and connectors give values under this name. After this release those values do nothing, and nothing on screen says why.'),\n ...gone\n }\n case 'state-unit-changed':\n return {\n message: say(key('message'), v, `The unit of the control '${v.id}' changed from ${v.before} to ${v.after}.`),\n why: say(key('why'), {}, 'Stored values keep their number. With another unit the same number means something else.'),\n ...gone\n }\n case 'state-range-narrowed':\n return {\n message: say(key('message'), v, `The range of the control '${v.id}' narrowed from ${v.before} to ${v.after}.`),\n why: say(key('why'), {}, 'A value outside the new range may already be stored on a placed instance.')\n }\n case 'state-input-added':\n return {\n message: say(key('message'), v, `The control '${v.id}' is new.`),\n why: say(key('why'), {}, 'Placed instances that give no value stand at its default.')\n }\n case 'clip-gone':\n return {\n message: say(key('message'), v, `The clip '${v.clip}' is gone.`),\n why: say(key('why'), {}, 'Placed instances play clips by name. After this release that one plays nothing.'),\n ...gone\n }\n case 'clip-added':\n return {\n message: say(key('message'), v, `The clip '${v.clip}' is new.`),\n why: say(key('why'), {}, 'It stays still until an instance plays it.')\n }\n case 'binding-gone':\n return {\n message: say(key('message'), v, `The place '${v.binding}' is gone.`),\n why: say(key('why'), {}, 'What sits in it on a placed instance loses its place.'),\n ...gone\n }\n case 'binding-role-changed':\n return {\n message: say(key('message'), v, `The place '${v.binding}' changed from ${v.before} to ${v.after}.`),\n why: say(key('why'), {}, 'What sits in it was placed for the old role.'),\n ...gone\n }\n case 'binding-capacity-reduced':\n return {\n message: say(key('message'), v, `The place '${v.binding}' holds ${v.after} instead of ${v.before}.`),\n why: say(key('why'), {}, 'What sits in the places that went has nowhere to go.'),\n ...gone\n }\n case 'binding-accepts-narrowed':\n return {\n message: say(key('message'), v, `The place '${v.binding}' no longer accepts ${v.types}.`),\n why: say(key('why'), {}, 'What already sits there stays. The next one of that type is refused.')\n }\n case 'binding-added':\n return {\n message: say(key('message'), v, `The place '${v.binding}' is new.`),\n why: say(key('why'), {}, 'Placed instances do not know it yet and stand as they are.')\n }\n case 'capability-gone':\n return {\n message: say(key('message'), v, `The capability '${v.name}' is gone.`),\n why: say(key('why'), {}, 'Scenes attach behaviour by this name. Placed instances lose what it did.'),\n ...gone\n }\n case 'capability-added':\n return {\n message: say(key('message'), v, `The capability '${v.name}' is new.`),\n why: say(key('why'), {}, 'It adds what the figure can do. Placed instances stand as they are.')\n }\n /* Said, never refused (ADR-0104): a consumer that pins a release reads these before it moves to this one. */\n case 'occupancy-changed':\n return {\n message: say(key('message'), v, `The room the figure takes changed from ${v.before || 'none'} to ${v.after || 'none'}.`),\n why: say(key('why'), {}, 'A consumer places the figure by this room. One that moves to this release sees it take the new room.')\n }\n case 'contact-face-changed':\n return {\n message: say(key('message'), v, 'The face the figure is mounted by changed.'),\n why: say(key('why'), {}, 'A consumer that moves to this release sees it stand on the new face.')\n }\n case 'public-input-gone':\n return {\n message: say(key('message'), { ...v, input: change.subject ?? '' }, `'${change.subject}' is no longer set on a board.`),\n why: say(key('why'), {}, 'Values placed instances give it do nothing after this release.')\n }\n case 'public-input-range-narrowed':\n return {\n message: say(key('message'), { ...v, input: change.subject ?? '' }, `The range of '${change.subject}' narrowed from ${v.before} to ${v.after}.`),\n why: say(key('why'), {}, 'An instance may have set a value outside the new range. Which values are placed is not recorded.')\n }\n case 'public-input-added':\n return {\n message: say(key('message'), { ...v, input: change.subject ?? '' }, `'${change.subject}' can now be set on a board.`),\n why: say(key('why'), {}, 'Placed instances that give no value stand at its default.')\n }\n }\n}\n\n/**\n * What a release records about itself (ADR-0104 decision 5): the format its asset is written in, what it measured\n * (its cost at its largest, whether resizing is stretching), its plan from above, and what changed against the previous release -- the kernel's own comparison, kept as it was then so a consumer that pins releases\n * reads it rather than computing it again. `[]` for a first release; `null` when the previous release could not be\n * read, which is a different fact from \"nothing changed\".\n */\nexport function releaseRecordOf(\n sourceJson: string,\n releasedJson?: string | null\n): { format: string; kernel: string; changes: FigureContractChange[] | null; metrics: FigureReleaseMetrics; topView: FigureTopView } {\n const asset = parseFigureAsset(sourceJson)\n const measured = { format: asset.version, kernel: FIGURE_KERNEL_VERSION, metrics: figureReleaseMetricsOf(asset), topView: figureTopViewOf(asset, null) }\n if (!releasedJson) return { ...measured, changes: [] }\n let before: FigureAsset\n try {\n before = parseFigureAsset(releasedJson)\n } catch {\n return { ...measured, changes: null }\n }\n return { ...measured, changes: figureContractChanges(before, asset) }\n}\n\n/**\n * What a consumer is handed for a released figure: the asset itself, because what draws it -- `registerFigure` in\n * things-scene -- takes the asset and compiles it with the kernel.\n */\nexport function consumablePayloadOf(sourceJson: string): { asset: FigureAsset } {\n assertFormat(sourceJson)\n const asset = parseFigureAsset(sourceJson)\n compileFigureAsset(asset)\n return { asset }\n}\n"]}
@@ -35,6 +35,7 @@ export declare class FigureHistory implements HistoryEntityInterface<Figure> {
35
35
  comment?: string;
36
36
  assetFormat?: string;
37
37
  changes?: string;
38
+ kernelVersion?: string;
38
39
  metrics?: string;
39
40
  topView?: string;
40
41
  createdAt?: Date;
@@ -128,6 +128,14 @@ tslib_1.__decorate([
128
128
  }),
129
129
  tslib_1.__metadata("design:type", String)
130
130
  ], FigureHistory.prototype, "changes", void 0);
131
+ tslib_1.__decorate([
132
+ (0, typeorm_1.Column)({ nullable: true }),
133
+ (0, type_graphql_1.Field)({
134
+ nullable: true,
135
+ description: 'The figure-model kernel version that measured this release (score, groups, metrics). null for releases made before releases recorded it.'
136
+ }),
137
+ tslib_1.__metadata("design:type", String)
138
+ ], FigureHistory.prototype, "kernelVersion", void 0);
131
139
  tslib_1.__decorate([
132
140
  (0, typeorm_1.Column)({ nullable: true, ...(0, shell_1.longTextColumn)() }),
133
141
  (0, type_graphql_1.Field)({
@@ -1 +1 @@
1
- {"version":3,"file":"figure-history.js","sourceRoot":"","sources":["../../../server/service/figure/figure-history.ts"],"names":[],"mappings":"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","sourcesContent":["import { Field, ID, ObjectType, Float, Int } from 'type-graphql'\nimport { GraphQLJSON } from 'graphql-scalars'\nimport { Column, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId } from 'typeorm'\n\nimport {\n HistoryActionColumn,\n HistoryActionType,\n HistoryEntityInterface,\n HistoryOriginalIdColumn\n} from '@operato/typeorm-history'\nimport { User } from '@things-factory/auth-base'\nimport { Domain, longTextColumn } from '@things-factory/shell'\n\nimport { Figure } from './figure.js'\n\n/**\n * 발행된 판 하나 — **발행할 때만 남는다.**\n *\n * 저작 중 저장은 여기 오지 않는다. 스냅샷을 뜨는 subscriber 가 `state === 'released'` 인 저장에만\n * 움직인다(`event-subscriber.ts`) — board 가 같은 규칙으로 돈다.\n *\n * ## 왜 통째로 베끼나\n *\n * 판을 되세우려면 그때의 정본만으로는 모자란다. 이름·분류·그림·비용까지 함께 있어야 「그 판이\n * 무엇이었나」를 보여 주고 되돌릴 수 있다. 파생값(점수·삼각형·묶음)도 같이 둔다 — 다시 계산하면\n * 형식이 바뀐 오늘의 값이 나오고, 그것은 그 판의 값이 아니다.\n */\n@Entity()\n@Index('ix_figure_history_0', (history: FigureHistory) => [history.originalId, history.version], { unique: true })\n@ObjectType({ description: 'A released version of a figure — one row per release.' })\nexport class FigureHistory implements HistoryEntityInterface<Figure> {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier for this history record.' })\n readonly id: string\n\n @Column({ nullable: true, default: 1 })\n @Field(type => Int, { nullable: true, description: 'The published version number this record holds.' })\n version?: number = 1\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain the figure belonged to.' })\n domain?: Domain\n\n @RelationId((history: FigureHistory) => history.domain)\n domainId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The stored identifier of the figure. It never changes.' })\n type?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The display name at this version.' })\n name?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The description at this version.' })\n description?: string\n\n @Column('simple-json', { nullable: true, default: null })\n @Field(type => GraphQLJSON, { nullable: true, description: 'Display names by language at this version.' })\n names?: Record<string, string>\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The classification code at this version.' })\n category?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The lifecycle state recorded with this version.' })\n state?: 'draft' | 'released'\n\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'The figure asset JSON (figure-asset-1) at this version.' })\n source?: string\n\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'The master-data field definition at this version.' })\n properties?: string\n\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'The thumbnail as it looked at this version.' })\n thumbnail?: string\n\n /*\n * 그림의 내용 해시(SHA-256). 그림 자체는 attachment-base 가 갖고(refType `figure-thumbnail`, refBy 이 해시),\n * `/figure-thumbnail/:id` 가 권한을 본 뒤 내준다(ADR-0104 결정 6). `thumbnail` 칸은 옛 base64 가 남은 행을\n * 기동 때 옮기기 위한 칸이다 — 옮긴 뒤에는 비어 있고, 새 그림은 그 칸에 쓰지 않는다.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'SHA-256 of the thumbnail picture; the picture is served by /figure-thumbnail/:id.' })\n thumbnailHash?: string\n\n /*\n * 그때의 비용이다. 오늘 다시 계산하면 오늘의 형식으로 나온다 — 그 판을 설명하지 못한다.\n */\n @Column({ type: 'float', nullable: true })\n @Field(type => Float, { nullable: true, description: 'Reuse score as computed at this version.' })\n score?: number\n\n @Column({ nullable: true })\n @Field(type => Int, { nullable: true, description: 'Triangle count at this version.' })\n triangles?: number\n\n @Column({ nullable: true })\n @Field(type => Int, { nullable: true, description: 'Material group count at this version.' })\n groups?: number\n\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'The note left when this version was released.' })\n comment?: string\n\n /*\n * 이 판의 정본 형식(`figure-asset-1`)과, 직전 판에 견준 변경(ADR-0104 결정 5). 발행할 때 한 번 정하고 다시\n * 계산하지 않는다 — 판을 고정해 쓰는 쪽은 다음 판으로 옮기기 전에 이것을 읽는다.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The asset format this version was written in (figure-asset-1).' })\n assetFormat?: string\n\n @Column({ nullable: true, ...longTextColumn() })\n @Field({\n nullable: true,\n description:\n 'What changed against the previous release, as JSON: [{ code, blocking, subject?, values, detail }]. [] for the first release. null when it was not compared: the previous release could not be read, or this release was made before releases recorded it (figure-service 10.1.109).'\n })\n changes?: string\n\n @Column({ nullable: true, ...longTextColumn() })\n @Field({\n nullable: true,\n description:\n 'What this version measured once, as JSON (figure-model figureReleaseMetricsOf): { atLargest?: { size, triangles, groups }, linear?: { scalable, parts, probe } }. Only for a figure that takes its size from the instance; {} otherwise.'\n })\n metrics?: string\n\n @Column({ nullable: true, ...longTextColumn() })\n @Field({\n nullable: true,\n description: 'The plan from above at the authored size, as JSON (figure-model figureTopViewOf): { shapes: [{ id, color, outline, holes, top, transparent }], size }.'\n })\n topView?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When the original figure was created.' })\n createdAt?: Date\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When the figure was saved at this version.' })\n updatedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Who created the original figure.' })\n creator?: User\n\n @RelationId((history: FigureHistory) => history.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Who released this version.' })\n updater?: User\n\n @RelationId((history: FigureHistory) => history.updater)\n updaterId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When the original figure was deleted, if it was.' })\n deletedAt?: Date\n\n @HistoryOriginalIdColumn()\n @Field({ description: 'The id of the figure this version belongs to.' })\n public originalId!: string\n\n @HistoryActionColumn({ nullable: false, type: 'varchar', length: 10 })\n @Field(type => String, { description: 'What produced this record (created · updated · deleted).' })\n public action!: HistoryActionType\n}\n"]}
1
+ {"version":3,"file":"figure-history.js","sourceRoot":"","sources":["../../../server/service/figure/figure-history.ts"],"names":[],"mappings":"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","sourcesContent":["import { Field, ID, ObjectType, Float, Int } from 'type-graphql'\nimport { GraphQLJSON } from 'graphql-scalars'\nimport { Column, Entity, Index, ManyToOne, PrimaryGeneratedColumn, RelationId } from 'typeorm'\n\nimport {\n HistoryActionColumn,\n HistoryActionType,\n HistoryEntityInterface,\n HistoryOriginalIdColumn\n} from '@operato/typeorm-history'\nimport { User } from '@things-factory/auth-base'\nimport { Domain, longTextColumn } from '@things-factory/shell'\n\nimport { Figure } from './figure.js'\n\n/**\n * 발행된 판 하나 — **발행할 때만 남는다.**\n *\n * 저작 중 저장은 여기 오지 않는다. 스냅샷을 뜨는 subscriber 가 `state === 'released'` 인 저장에만\n * 움직인다(`event-subscriber.ts`) — board 가 같은 규칙으로 돈다.\n *\n * ## 왜 통째로 베끼나\n *\n * 판을 되세우려면 그때의 정본만으로는 모자란다. 이름·분류·그림·비용까지 함께 있어야 「그 판이\n * 무엇이었나」를 보여 주고 되돌릴 수 있다. 파생값(점수·삼각형·묶음)도 같이 둔다 — 다시 계산하면\n * 형식이 바뀐 오늘의 값이 나오고, 그것은 그 판의 값이 아니다.\n */\n@Entity()\n@Index('ix_figure_history_0', (history: FigureHistory) => [history.originalId, history.version], { unique: true })\n@ObjectType({ description: 'A released version of a figure — one row per release.' })\nexport class FigureHistory implements HistoryEntityInterface<Figure> {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { description: 'Unique identifier for this history record.' })\n readonly id: string\n\n @Column({ nullable: true, default: 1 })\n @Field(type => Int, { nullable: true, description: 'The published version number this record holds.' })\n version?: number = 1\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain the figure belonged to.' })\n domain?: Domain\n\n @RelationId((history: FigureHistory) => history.domain)\n domainId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The stored identifier of the figure. It never changes.' })\n type?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The display name at this version.' })\n name?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The description at this version.' })\n description?: string\n\n @Column('simple-json', { nullable: true, default: null })\n @Field(type => GraphQLJSON, { nullable: true, description: 'Display names by language at this version.' })\n names?: Record<string, string>\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The classification code at this version.' })\n category?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The lifecycle state recorded with this version.' })\n state?: 'draft' | 'released'\n\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'The figure asset JSON (figure-asset-1) at this version.' })\n source?: string\n\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'The master-data field definition at this version.' })\n properties?: string\n\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'The thumbnail as it looked at this version.' })\n thumbnail?: string\n\n /*\n * 그림의 내용 해시(SHA-256). 그림 자체는 attachment-base 가 갖고(refType `figure-thumbnail`, refBy 이 해시),\n * `/figure-thumbnail/:id` 가 권한을 본 뒤 내준다(ADR-0104 결정 6). `thumbnail` 칸은 옛 base64 가 남은 행을\n * 기동 때 옮기기 위한 칸이다 — 옮긴 뒤에는 비어 있고, 새 그림은 그 칸에 쓰지 않는다.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'SHA-256 of the thumbnail picture; the picture is served by /figure-thumbnail/:id.' })\n thumbnailHash?: string\n\n /*\n * 그때의 비용이다. 오늘 다시 계산하면 오늘의 형식으로 나온다 — 그 판을 설명하지 못한다.\n */\n @Column({ type: 'float', nullable: true })\n @Field(type => Float, { nullable: true, description: 'Reuse score as computed at this version.' })\n score?: number\n\n @Column({ nullable: true })\n @Field(type => Int, { nullable: true, description: 'Triangle count at this version.' })\n triangles?: number\n\n @Column({ nullable: true })\n @Field(type => Int, { nullable: true, description: 'Material group count at this version.' })\n groups?: number\n\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'The note left when this version was released.' })\n comment?: string\n\n /*\n * 이 판의 정본 형식(`figure-asset-1`)과, 직전 판에 견준 변경(ADR-0104 결정 5). 발행할 때 한 번 정하고 다시\n * 계산하지 않는다 — 판을 고정해 쓰는 쪽은 다음 판으로 옮기기 전에 이것을 읽는다.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The asset format this version was written in (figure-asset-1).' })\n assetFormat?: string\n\n @Column({ nullable: true, ...longTextColumn() })\n @Field({\n nullable: true,\n description:\n 'What changed against the previous release, as JSON: [{ code, blocking, subject?, values, detail }]. [] for the first release. null when it was not compared: the previous release could not be read, or this release was made before releases recorded it (figure-service 10.1.109).'\n })\n changes?: string\n\n /*\n * 이 판을 잰 커널의 판(figure-model `FIGURE_KERNEL_VERSION`). 점수 · 묶음 · metrics 는 그 커널의 규칙으로 센 값이다 —\n * 규칙이 바뀌어도 발행된 값을 다시 세서 덮지 않고(ADR-0109 C1), 읽는 쪽은 이 칸으로 「남긴 값」과 「지금 규칙의 값」을\n * 가른다. 이 칸이 생기기 전에 발행된 판은 비어 있다.\n */\n @Column({ nullable: true })\n @Field({\n nullable: true,\n description:\n 'The figure-model kernel version that measured this release (score, groups, metrics). null for releases made before releases recorded it.'\n })\n kernelVersion?: string\n\n @Column({ nullable: true, ...longTextColumn() })\n @Field({\n nullable: true,\n description:\n 'What this version measured once, as JSON (figure-model figureReleaseMetricsOf): { atLargest?: { size, triangles, groups }, linear?: { scalable, parts, probe } }. Only for a figure that takes its size from the instance; {} otherwise.'\n })\n metrics?: string\n\n @Column({ nullable: true, ...longTextColumn() })\n @Field({\n nullable: true,\n description: 'The plan from above at the authored size, as JSON (figure-model figureTopViewOf): { shapes: [{ id, color, outline, holes, top, transparent }], size }.'\n })\n topView?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When the original figure was created.' })\n createdAt?: Date\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When the figure was saved at this version.' })\n updatedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Who created the original figure.' })\n creator?: User\n\n @RelationId((history: FigureHistory) => history.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'Who released this version.' })\n updater?: User\n\n @RelationId((history: FigureHistory) => history.updater)\n updaterId?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'When the original figure was deleted, if it was.' })\n deletedAt?: Date\n\n @HistoryOriginalIdColumn()\n @Field({ description: 'The id of the figure this version belongs to.' })\n public originalId!: string\n\n @HistoryActionColumn({ nullable: false, type: 'varchar', length: 10 })\n @Field(type => String, { description: 'What produced this record (created · updated · deleted).' })\n public action!: HistoryActionType\n}\n"]}
@@ -266,9 +266,10 @@ let FigureMutation = class FigureMutation {
266
266
  version: nextVersion,
267
267
  state: 'released',
268
268
  updater: user,
269
- /* 판본 구독자가 이것들을 판본의 comment · assetFormat · changes 로 옮긴다. Figure 의 칸이 아니다. */
269
+ /* 판본 구독자가 이것들을 판본의 comment · assetFormat · kernelVersion · changes 로 옮긴다. Figure 의 칸이 아니다. */
270
270
  __releaseComment: comment ?? null,
271
271
  __releaseFormat: record.format,
272
+ __releaseKernel: record.kernel,
272
273
  __releaseChanges: record.changes,
273
274
  __releaseMetrics: record.metrics,
274
275
  __releaseTopView: record.topView
@@ -1 +1 @@
1
- {"version":3,"file":"figure-mutation.js","sourceRoot":"","sources":["../../../server/service/figure/figure-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { In } from 'typeorm'\nimport { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'\n\nimport { parseFigureAsset, placeholderType } from '@hatiolab/figure-model'\nimport { getRepository } from '@things-factory/shell'\n\nimport { Figure } from './figure.js'\nimport { FigureHistory } from './figure-history.js'\nimport { FigurePatch, FigureRevertResult, FigureSaveResult, NewFigure } from './figure-type.js'\nimport { FigureReplacedDraft } from './figure-replaced-draft.js'\nimport { revertKeepingDraft, undoRevert } from './figure-revert.js'\nimport { recordProposals } from './figure-proposal.js'\nimport { FigureProposal, ProposeRequest } from './figure-propose-type.js'\nimport { inspectSource, releaseRecordOf } from './figure-format.js'\nimport { renameDraftType, renameFacts } from './figure-rename.js'\nimport { parseSource } from './figure-format.js'\nimport { ProposeFigureFailure, proposeFigureSteps } from './figure-propose-steps.js'\nimport { prepareFigureWrite, compareAndSwapFigure, pictureOf } from './figure-write.js'\n\n/** Display names by language: a language code to a name of 1-128 characters. Refused whole, with the bad entry named. */\nexport function assertNames(names: unknown): asserts names is Record<string, string> {\n if (!names || typeof names !== 'object' || Array.isArray(names)) throw new Error('names 는 { 언어: 이름 } 이어야 한다')\n for (const [lang, name] of Object.entries(names)) {\n if (!/^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$/.test(lang)) throw new Error(`'${lang}' 는 언어 코드가 아니다`)\n if (typeof name !== 'string' || !name.trim() || name.length > 128) throw new Error(`'${lang}' 의 이름은 1~128자 글이어야 한다`)\n }\n}\n\n@Resolver(Figure)\nexport class FigureMutation {\n @Directive('@transaction')\n @Directive('@privilege(category: \"figure\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => Figure, { description: 'Save a asset draft using an exact-source concurrency check.' })\n async saveFigure(\n @Arg('source') source: string,\n @Ctx() context: ResolverContext,\n @Arg('id', { nullable: true }) id?: string,\n @Arg('expectedSource', { nullable: true }) expectedSource?: string,\n @Arg('creationId', { nullable: true }) creationId?: string,\n @Arg('thumbnail', { nullable: true }) thumbnail?: string,\n @Arg('type', { nullable: true, description: 'The type name a new figure is created under. Ignored for an existing one.' })\n type?: string,\n @Arg('proposalKeys', type => [String], {\n nullable: true,\n description: \"Keys of the AI proposals whose steps this source holds: recorded with the save, in its transaction.\"\n })\n proposalKeys?: string[]\n ): Promise<Figure> {\n const saved = await this.writeSource(context, source, id, expectedSource, creationId, thumbnail, type)\n await recordProposals(context.state.tx, context.state.domain, saved.id!, proposalKeys)\n return saved\n }\n\n private async writeSource(\n context: ResolverContext,\n source: string,\n id?: string,\n expectedSource?: string,\n creationId?: string,\n thumbnail?: string,\n type?: string\n ): Promise<Figure> {\n const { domain, user, tx } = context.state\n const repository = tx.getRepository(Figure)\n if (!id) {\n if (!creationId || !/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(creationId))\n throw Error('새 모델 저장에는 생성 요청 식별자가 필요합니다.')\n const prepared = { ...prepareFigureWrite(source), ...(await pictureOf(tx, domain, user, thumbnail)) }\n const previous = await repository.findOne({ where: { id: creationId, domain: { id: domain.id } } })\n if (previous) {\n if (previous.source !== prepared.source) throw Error('이 생성 요청은 이미 다른 내용으로 저장되었습니다. 저장된 모델을 다시 열어 주세요.')\n return previous\n }\n /*\n The temporary name comes from the format's `placeholderType()`, the one rule the release gate and the AI\n tools use to recognise it. This used to build its own (`FIGURE_<32 hex>`), which `isPlaceholderType` does\n not match, so a new figure could be published under a machine name that then froze (ADR-0063 decision 4)\n — seen on :3300, 2026-09-24. A retry is still safe: the row id is the creation id, not the name.\n */\n /*\n The author names it on the first save (2026-09-25): created under that\n name or not at all -- a taken name refuses the save, rather than saving under the temporary one and failing a\n rename after. Without a name (a caller that has none to give) it is the temporary one, renamed later.\n */\n const named = type?.trim()\n if (named) {\n const facts = await renameFacts(\n { figures: repository, histories: tx.getRepository(FigureHistory) },\n { id: creationId },\n domain,\n named\n )\n renameDraftType({ type: named, source: prepared.source }, named, facts)\n }\n // insert, not save: a concurrent retry must never turn into an unchecked overwrite.\n await repository.insert({ ...prepared, id: creationId, type: named || placeholderType(),\n domain, creator: user, updater: user })\n return repository.findOneOrFail({ where: { id: creationId, domain: { id: domain.id } } })\n }\n // Exact tenant ownership: an inherited catalog entry is not writable in the child domain.\n const figure = await repository.findOne({ where: { id, domain: { id: domain.id } } })\n if (!figure) throw Error('편집할 Figure를 찾을 수 없습니다.')\n const prepared = { ...prepareFigureWrite(source, figure, expectedSource), ...(await pictureOf(tx, domain, user, thumbnail, figure)) }\n // Compare-and-swap in the UPDATE itself: supported by SQLite as well as PostgreSQL.\n // A pessimistic row lock is not supported by the product's SQLite deployment.\n await compareAndSwapFigure(criteria => repository.update(criteria, { ...prepared, updater: user }),\n id, domain.id, expectedSource)\n return repository.findOneOrFail({ where: { id, domain: { id: domain.id } } })\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"figure\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => FigureSaveResult, { description: 'Creates a figure. Rejects when the source violates the format.' })\n async createFigure(\n @Arg('figure') figure: NewFigure,\n @Ctx() context: ResolverContext\n ): Promise<FigureSaveResult> {\n const { domain, user, tx } = context.state\n const repository = tx.getRepository(Figure)\n\n // 타입 이름은 도메인 안에서 유일하다. 유니크 인덱스가 있지만 여기서 먼저 본다 —\n // DB 오류 문구는 저작자에게 아무 말도 해 주지 못한다.\n const taken = await repository.findOne({ where: { domain: { id: domain.id }, type: figure.type } })\n if (taken) {\n throw new Error(`타입 이름 '${figure.type}' 은 이미 쓰이고 있다. 만든 뒤에는 고칠 수 없으므로 다른 이름을 고른다`)\n }\n\n // 형식을 어기면 여기서 던진다. 파생값은 서버가 계산한다.\n const { source, derived, violations } = parseSource(figure.source)\n\n const { thumbnail, ...rest } = figure\n const saved = await repository.save({\n ...rest,\n source,\n ...derived,\n state: figure.state ?? 'draft',\n ...(await pictureOf(tx, domain, user, thumbnail)),\n domain,\n creator: user,\n updater: user\n })\n\n return { figure: saved, violations }\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"figure\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => FigureSaveResult, { description: 'Updates a figure. The `type` field cannot be changed.' })\n async updateFigure(\n @Arg('id') id: string,\n @Arg('patch') patch: FigurePatch,\n @Ctx() context: ResolverContext\n ): Promise<FigureSaveResult> {\n const { domain, user, tx } = context.state\n const repository = tx.getRepository(Figure)\n\n const figure = await repository.findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id }\n })\n if (!figure) {\n throw new Error(`Figure ${id} 를 찾을 수 없다`)\n }\n\n // 정본이 바뀌면 파생값도 다시 계산한다. 안 바뀌었으면 손대지 않는다 —\n // 이름만 고쳤는데 점수가 흔들리면 읽는 사람이 원인을 못 찾는다.\n let derived: { score: number; triangles: number; groups: number } | undefined\n let violations = []\n let source = figure.source\n\n if (patch.source !== undefined && patch.source !== figure.source) {\n const parsed = parseSource(patch.source)\n source = parsed.source\n derived = parsed.derived\n violations = parsed.violations\n }\n\n /*\n **타입은 발행 전에만 바뀐다** — ADR-0063 결정 4.\n\n 발행된 뒤에는 이미 배치된 도면이 이 이름을 가리키고, 바꾸면 그 도면이 아무 오류 없이\n 빈 자리가 된다. 발행된 적 없는 도형은 가리키는 도면이 있을 수 없다 — 도면은 최신\n 발행판을 그리므로 그려질 자리가 없다.\n\n 행과 정본 둘 다 고친다. 정본 안에도 `type` 이 있어서 한쪽만 고치면 저장된 JSON 과\n 행이 다른 이름을 말하고, 발행할 때 어느 쪽이 도면에 적히는지가 갈린다.\n */\n if (patch.names !== undefined) assertNames(patch.names)\n /* The picture is kept by its content; the patch's data URL is never written to the row. */\n const { thumbnail: picturePatch, ...patchRest } = patch\n const picture = await pictureOf(tx, domain, user, picturePatch, figure)\n\n let renamed: string | undefined\n if (patch.type !== undefined && patch.type !== figure.type) {\n const change = await this.renameType(figure, domain, patch.type, source, tx)\n renamed = change.type\n source = change.source\n }\n\n /*\n **판 번호는 여기서 손대지 않는다.** 저장은 저작이고, 판은 발행에서 생긴다(`releaseFigure`).\n board 의 `updateBoard` 도 같다 — 저장 경로에는 version 이 없다.\n */\n const saved = await repository.save({\n /*\n `domain` 을 명시로 넣는다 — 읽어 온 엔티티에는 관계가 안 실려 있다.\n\n 판본 스냅샷은 넘겨받은 엔티티를 베끼므로, 여기서 빠지면 판본의 도메인이 비고 그 판은\n 도메인으로 거르는 조회에 **한 줄도 안 걸린다**(실제로 그랬다). board 의 저장들도 같은\n 자리에서 domain 을 함께 넣는다.\n */\n domain,\n ...figure,\n ...patchRest,\n /* 앞뒤 공백을 떼고 겹침까지 본 이름. `patch.type` 을 그대로 두면 다듬기 전 값이 들어간다. */\n ...(renamed !== undefined ? { type: renamed } : {}),\n source,\n /*\n **고치면 발행이 풀린다.**\n\n 발행은 「이 판을 써도 된다」는 약속이고, 그 뒤에 정본이 바뀌면 약속한 것과 배포된 것이\n 달라진다. 그래서 저장은 언제나 초안으로 되돌리고, 다시 내보내려면 발행을 한 번 더 한다\n (판 번호가 하나 오르고 판본이 하나 더 남는다). board 의 `updateBoard` 가 같은 한 줄을 쓴다.\n */\n state: 'draft',\n ...(derived ?? {}),\n // 썸네일이 **썸네일로서** 바뀐 때만 시각을 갱신한다. 이름·설명 변경에는 안 건드린다.\n thumbnail: figure.thumbnail ?? null,\n ...picture,\n updater: user\n })\n\n return { figure: saved, violations }\n }\n\n /**\n * 초안의 타입을 고친다 — 규칙은 `figure-rename.ts`, 여기서는 그 규칙이 볼 **사실만** 읽는다.\n *\n * 겹침은 DB 인덱스(`ix_figure_1`)도 잡지만 먼저 읽어 본다. 인덱스가 던지는 말은 저작자가\n * 읽을 것이 못 되고, 어느 이름이 이미 쓰였는지도 안 알려 준다.\n */\n private async renameType(\n figure: Figure,\n domain: { id: string },\n wanted: string,\n source: string,\n tx: { getRepository: <T>(target: new () => T) => any }\n ): Promise<{ type: string; source: string }> {\n /* 읽어 온 엔티티에는 관계가 안 실려 있다 — 도메인은 문맥에서 온 것을 쓴다. */\n const facts = await renameFacts(\n { figures: tx.getRepository(Figure), histories: tx.getRepository(FigureHistory) },\n figure,\n domain,\n wanted\n )\n\n return renameDraftType({ type: figure.type, source }, wanted, facts)\n }\n\n /**\n * 발행한다 — **판이 생기는 유일한 자리.**\n *\n * ## 무엇이 일어나나\n *\n * `state` 가 `released` 가 되고, 판 번호가 하나 오르고, 그 순간의 도형이 판본으로 남는다\n * (`FigureHistory` — 스냅샷은 구독자가 뜬다). 저작 중 저장은 이 셋 중 아무것도 하지 않는다.\n *\n * ## 왜 이미 발행된 것을 거절하나\n *\n * 발행은 소비처에게 하는 약속이다. 같은 판을 두 번 발행하면 무엇이 약속인지 흐려진다. 고쳐서\n * 다시 내려면 초안으로 되돌린 뒤 발행한다 — board 가 같은 규칙이다.\n *\n * ## 번호는 판본에서 센다\n *\n * 도형의 현재 번호가 아니라 **판본의 최대 번호 + 1** 이다. 되돌리기로 옛 판이 현재가 되어도\n * 다음 발행이 이미 쓴 번호를 다시 쓰지 않는다.\n *\n * ## 게이트를 통과해야 한다\n *\n * 크기를 바꿨을 때 조각이 갈라지는 도형은 발행되지 않는다(`figure-gate.ts`). 소비처는 형상을\n * 늘려 쓰므로 — 그것이 이 형식의 값이다 — 늘려도 견디는지가 약속의 일부다. 화면은 같은 판정을\n * `inspectFigure` 로 미리 물어 이유를 보여 준다.\n */\n @Directive('@transaction')\n @Directive('@privilege(category: \"figure\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => Figure, { description: 'Releases a figure — raises its version and keeps the released state as history.' })\n async releaseFigure(\n @Arg('id') id: string,\n @Arg('comment', { nullable: true }) comment: string,\n @Ctx() context: ResolverContext\n ): Promise<Figure> {\n const { domain, user, tx } = context.state\n const repository = tx.getRepository(Figure)\n const historyRepository = tx.getRepository(FigureHistory)\n\n const figure = await repository.findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id }\n })\n if (!figure) {\n throw new Error(`Figure ${id} 를 찾을 수 없다`)\n }\n\n if (figure.state === 'released') {\n throw new Error(`Figure '${figure.type}' 은 이미 발행되어 있다. 고쳐서 다시 내려면 초안으로 되돌린 뒤 발행한다`)\n }\n\n /*\n ── 게이트는 여기 있어야 한다 ────────────────────────────────────────────\n 화면도 같은 판정을 미리 물어(`inspectFigure`) 이유를 보여 주지만, **막는 자리는 이곳뿐이다.**\n 물어본 뒤 정본이 바뀌었을 수 있고, 화면을 거치지 않는 부름도 있다.\n\n 막는 이유는 사유와 함께 낸다. 「발행할 수 없습니다」로 뭉치면 무엇을 고쳐야 하는지 모른다.\n */\n /*\n 직전 발행판을 먼저 꺼낸다. 판 번호를 세는 데도 쓰고, **약속을 깨는 발행인가**를 견주는 데도\n 쓴다(ADR-0063 결정 3) — 도면은 type 만 적고 늘 최신 발행판을 그리므로, 다시 발행하는 것은\n 그 type 을 놓아 둔 모든 도면에게 같은 약속을 다시 하는 일이다.\n */\n const released = await historyRepository\n .createQueryBuilder('history')\n .where('history.originalId = :id', { id: figure.id })\n .orderBy('history.version', 'DESC')\n .limit(1)\n .getOne()\n\n const inspection = inspectSource(figure.source, released?.source, context.t, figure.type)\n if (inspection.blocked) {\n const reasons = inspection.findings\n .filter(finding => finding.blocking)\n .map(finding => (finding.at ? `${finding.message} (${finding.at})` : finding.message))\n\n throw new Error(`Figure '${figure.type}' 은 아직 발행할 수 없다 — ${reasons.join(' · ')}`)\n }\n\n const nextVersion = released?.version ? Number(released.version) + 1 : 1\n /* What this release records about itself: its format, and what changed against the last one (ADR-0104). */\n const record = releaseRecordOf(figure.source!, released?.source)\n\n return await repository.save({\n /*\n `domain` 을 명시로 넣는다 — 읽어 온 엔티티에는 관계가 안 실려 있다.\n\n 판본 스냅샷은 넘겨받은 엔티티를 베끼므로, 여기서 빠지면 판본의 도메인이 비고 그 판은\n 도메인으로 거르는 조회에 **한 줄도 안 걸린다**(실제로 그랬다). board 의 저장들도 같은\n 자리에서 domain 을 함께 넣는다.\n */\n domain,\n ...figure,\n version: nextVersion,\n state: 'released',\n updater: user,\n /* 판본 구독자가 이것들을 판본의 comment · assetFormat · changes 로 옮긴다. Figure 의 칸이 아니다. */\n __releaseComment: comment ?? null,\n __releaseFormat: record.format,\n __releaseChanges: record.changes,\n __releaseMetrics: record.metrics,\n __releaseTopView: record.topView\n } as any)\n }\n\n /**\n * 옛 판으로 되돌린다.\n *\n * ## 무엇이 돌아오나\n *\n * 그 판의 **정본과 속성 정의, 그리고 그림**이다. 이름·설명·분류는 그대로 둔다 — 그것들은 언제든\n * 바꿔도 안전한 카탈로그의 말이고, 되돌리기가 개명까지 되돌리면 사람이 시키지 않은 일을 한다.\n *\n * ## 되돌려도 발행은 아니다\n *\n * 초안으로 돌아온다. 다시 내보내려면 발행을 한 번 더 하고, 그때 판 번호는 **이미 쓴 번호 다음**을\n * 받는다 — 3판을 되살렸다고 다시 3판이 되지 않는다. board 도 같다.\n *\n * ## 비용은 다시 잰다\n *\n * 판본이 든 점수·삼각형은 **그때의 형식**으로 잰 값이다. 지금 이 도형이 그 내용이 되었으므로\n * 오늘 기준으로 다시 계산한다. 옛 값은 판본에 그대로 남아 있다.\n */\n @Directive('@transaction')\n @Directive('@privilege(category: \"figure\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => FigureRevertResult, {\n description:\n 'Reverts a figure to one of its released versions, keeping the draft it writes over. It comes back as a draft. ' +\n 'The same requestId again answers with the same revert.'\n })\n async revertFigureVersion(\n @Arg('id') id: string,\n @Arg('version') version: number,\n @Arg('requestId', { description: 'A UUID for this revert: a retry sends the same one.' }) requestId: string,\n @Arg('expectedSource', { description: \"The figure's source as the reverter saw it; the revert goes on only while it holds.\" }) expectedSource: string,\n @Ctx() context: ResolverContext\n ): Promise<FigureRevertResult> {\n /* Kept and written over in this transaction, or neither (ADR-0097 §5.6). */\n const { domain, user, tx } = context.state\n const { figure, violations, kept } = await revertKeepingDraft(tx, domain, user, { id, version, requestId, expectedSource })\n return { figure, violations, kept }\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"figure\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => FigureRevertResult, {\n description: \"Brings back a draft a revert kept -- only while the figure still holds what that revert wrote. The same requestId again answers with the same undo.\"\n })\n async undoFigureRevert(\n @Arg('keptId') keptId: string,\n @Arg('requestId', { description: 'A UUID for this undo: a retry sends the same one.' }) requestId: string,\n @Ctx() context: ResolverContext\n ): Promise<FigureRevertResult> {\n const { domain, user, tx } = context.state\n const { figure, kept } = await undoRevert(tx, domain, user, { keptId, requestId })\n return { figure, violations: [], kept: kept as FigureReplacedDraft }\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"figure\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => Boolean, { description: 'Soft-deletes a figure.' })\n async deleteFigure(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, tx } = context.state\n\n // 소프트 삭제다 — 이미 배치된 도면이 이 타입을 참조할 수 있으므로 행을 지우지\n // 않는다. 되살릴 길을 남긴다.\n await tx.getRepository(Figure).softDelete({ domain: { id: domain.id }, id })\n\n return true\n }\n\n /**\n * 퇴역시키거나 되살린다(ADR-0104 결정 6).\n *\n * 표시일 뿐이다. 발행판은 그대로 남고 받는 쪽은 그대로 받는다 — 발행판은 지우지 않는다. 그래서 **발행을 풀지 않는다**:\n * 행을 엔티티로 저장하지 않고 질의로 고친다. 엔티티로 저장하면 발행된 행이라 판본 구독자가 같은 번호로 판본을 또\n * 뜬다. 대신 쓸 것(`supersededBy`)은 같은 도메인(또는 상위)에 있는 다른 type 이어야 한다.\n */\n @Directive('@transaction')\n @Directive('@privilege(category: \"figure\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => Figure, { description: 'Retires a figure or brings it back. It stays released and served; supersededBy names the type to use instead.' })\n async setFigureDeprecation(\n @Arg('id') id: string,\n @Arg('deprecated') deprecated: boolean,\n @Ctx() context: ResolverContext,\n @Arg('supersededBy', { nullable: true }) supersededBy?: string\n ): Promise<Figure> {\n const { domain, tx } = context.state\n const repository = tx.getRepository(Figure)\n const scope = { id: In([domain.id, domain.parentId].filter(Boolean)) }\n const figure = await repository.findOne({ where: { domain: scope, id } })\n if (!figure) throw new Error(`Figure ${id} 를 찾을 수 없다`)\n const instead = deprecated ? supersededBy?.trim() || null : null\n if (instead) {\n if (instead === figure.type) throw new Error(`Figure '${figure.type}' 는 자기 자신으로 대신할 수 없다`)\n const other = await repository.findOne({ where: { domain: scope, type: instead } })\n if (!other) throw new Error(`대신 쓸 Figure '${instead}' 가 이 도메인에 없다`)\n }\n await repository.createQueryBuilder().update(Figure).set({ deprecated, supersededBy: instead }).where('id = :id', { id }).callListeners(false).execute()\n return await repository.findOneOrFail({ where: { id } })\n }\n\n /**\n * 저작 보조에게 제안을 시킨다(ADR-0094).\n *\n * **저장하지 않는다.** 모델러 명령 목록과 그것이 만드는 도형을 돌려줄 뿐이고, 정본이 되는 것은 저작자가 모델러에\n * 적용하고 저장한 뒤다. 커널이 거절한 명령이나 게이트가 잡은 것은 여기까지 오지 않는다 — 제안기가 사유를 모델에\n * 돌려주고 다시 시킨다. 끝내 못 만들면 **사유와 함께 던진다.** 반쯤 만든 것을 돌려주지 않는다.\n */\n @Directive('@privilege(category: \"figure\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => FigureProposal, {\n description: 'Asks the authoring assistant for modeller commands that make or revise a figure. Nothing is saved.'\n })\n async proposeFigure(@Arg('request') request: ProposeRequest): Promise<FigureProposal> {\n // 그림은 메모리로 받는다. 참고용이라 저장하지 않는다 — 남기면 지울 사람이 없다.\n let image\n if (request.image) {\n const file = await request.image\n const chunks: Buffer[] = []\n for await (const chunk of file.createReadStream()) {\n chunks.push(chunk as Buffer)\n }\n image = { data: Buffer.concat(chunks), mediaType: file.mimetype as never }\n }\n\n try {\n const result = await proposeFigureSteps({\n prompt: request.prompt,\n base: request.base ? parseFigureAsset(request.base) : undefined,\n name: request.name,\n image\n })\n\n return {\n steps: JSON.stringify(result.steps),\n source: JSON.stringify(result.source),\n score: result.score ? Math.round(result.score.score) : undefined,\n grade: result.score?.grade,\n triangles: result.cost.triangles,\n attempts: result.attempts\n }\n } catch (e) {\n if (e instanceof ProposeFigureFailure) {\n // 사유를 삼키지 않는다. 저작자가 무엇이 막혔는지 알아야 말을 고쳐 다시 시킨다.\n throw new Error([e.message, ...e.reasons].join('\\n'))\n }\n throw e\n }\n }\n\n}\n"]}
1
+ {"version":3,"file":"figure-mutation.js","sourceRoot":"","sources":["../../../server/service/figure/figure-mutation.ts"],"names":[],"mappings":"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","sourcesContent":["import { In } from 'typeorm'\nimport { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'\n\nimport { parseFigureAsset, placeholderType } from '@hatiolab/figure-model'\nimport { getRepository } from '@things-factory/shell'\n\nimport { Figure } from './figure.js'\nimport { FigureHistory } from './figure-history.js'\nimport { FigurePatch, FigureRevertResult, FigureSaveResult, NewFigure } from './figure-type.js'\nimport { FigureReplacedDraft } from './figure-replaced-draft.js'\nimport { revertKeepingDraft, undoRevert } from './figure-revert.js'\nimport { recordProposals } from './figure-proposal.js'\nimport { FigureProposal, ProposeRequest } from './figure-propose-type.js'\nimport { inspectSource, releaseRecordOf } from './figure-format.js'\nimport { renameDraftType, renameFacts } from './figure-rename.js'\nimport { parseSource } from './figure-format.js'\nimport { ProposeFigureFailure, proposeFigureSteps } from './figure-propose-steps.js'\nimport { prepareFigureWrite, compareAndSwapFigure, pictureOf } from './figure-write.js'\n\n/** Display names by language: a language code to a name of 1-128 characters. Refused whole, with the bad entry named. */\nexport function assertNames(names: unknown): asserts names is Record<string, string> {\n if (!names || typeof names !== 'object' || Array.isArray(names)) throw new Error('names 는 { 언어: 이름 } 이어야 한다')\n for (const [lang, name] of Object.entries(names)) {\n if (!/^[a-z]{2,3}(-[A-Za-z0-9]{2,8})*$/.test(lang)) throw new Error(`'${lang}' 는 언어 코드가 아니다`)\n if (typeof name !== 'string' || !name.trim() || name.length > 128) throw new Error(`'${lang}' 의 이름은 1~128자 글이어야 한다`)\n }\n}\n\n@Resolver(Figure)\nexport class FigureMutation {\n @Directive('@transaction')\n @Directive('@privilege(category: \"figure\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => Figure, { description: 'Save a asset draft using an exact-source concurrency check.' })\n async saveFigure(\n @Arg('source') source: string,\n @Ctx() context: ResolverContext,\n @Arg('id', { nullable: true }) id?: string,\n @Arg('expectedSource', { nullable: true }) expectedSource?: string,\n @Arg('creationId', { nullable: true }) creationId?: string,\n @Arg('thumbnail', { nullable: true }) thumbnail?: string,\n @Arg('type', { nullable: true, description: 'The type name a new figure is created under. Ignored for an existing one.' })\n type?: string,\n @Arg('proposalKeys', type => [String], {\n nullable: true,\n description: \"Keys of the AI proposals whose steps this source holds: recorded with the save, in its transaction.\"\n })\n proposalKeys?: string[]\n ): Promise<Figure> {\n const saved = await this.writeSource(context, source, id, expectedSource, creationId, thumbnail, type)\n await recordProposals(context.state.tx, context.state.domain, saved.id!, proposalKeys)\n return saved\n }\n\n private async writeSource(\n context: ResolverContext,\n source: string,\n id?: string,\n expectedSource?: string,\n creationId?: string,\n thumbnail?: string,\n type?: string\n ): Promise<Figure> {\n const { domain, user, tx } = context.state\n const repository = tx.getRepository(Figure)\n if (!id) {\n if (!creationId || !/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(creationId))\n throw Error('새 모델 저장에는 생성 요청 식별자가 필요합니다.')\n const prepared = { ...prepareFigureWrite(source), ...(await pictureOf(tx, domain, user, thumbnail)) }\n const previous = await repository.findOne({ where: { id: creationId, domain: { id: domain.id } } })\n if (previous) {\n if (previous.source !== prepared.source) throw Error('이 생성 요청은 이미 다른 내용으로 저장되었습니다. 저장된 모델을 다시 열어 주세요.')\n return previous\n }\n /*\n The temporary name comes from the format's `placeholderType()`, the one rule the release gate and the AI\n tools use to recognise it. This used to build its own (`FIGURE_<32 hex>`), which `isPlaceholderType` does\n not match, so a new figure could be published under a machine name that then froze (ADR-0063 decision 4)\n — seen on :3300, 2026-09-24. A retry is still safe: the row id is the creation id, not the name.\n */\n /*\n The author names it on the first save (2026-09-25): created under that\n name or not at all -- a taken name refuses the save, rather than saving under the temporary one and failing a\n rename after. Without a name (a caller that has none to give) it is the temporary one, renamed later.\n */\n const named = type?.trim()\n if (named) {\n const facts = await renameFacts(\n { figures: repository, histories: tx.getRepository(FigureHistory) },\n { id: creationId },\n domain,\n named\n )\n renameDraftType({ type: named, source: prepared.source }, named, facts)\n }\n // insert, not save: a concurrent retry must never turn into an unchecked overwrite.\n await repository.insert({ ...prepared, id: creationId, type: named || placeholderType(),\n domain, creator: user, updater: user })\n return repository.findOneOrFail({ where: { id: creationId, domain: { id: domain.id } } })\n }\n // Exact tenant ownership: an inherited catalog entry is not writable in the child domain.\n const figure = await repository.findOne({ where: { id, domain: { id: domain.id } } })\n if (!figure) throw Error('편집할 Figure를 찾을 수 없습니다.')\n const prepared = { ...prepareFigureWrite(source, figure, expectedSource), ...(await pictureOf(tx, domain, user, thumbnail, figure)) }\n // Compare-and-swap in the UPDATE itself: supported by SQLite as well as PostgreSQL.\n // A pessimistic row lock is not supported by the product's SQLite deployment.\n await compareAndSwapFigure(criteria => repository.update(criteria, { ...prepared, updater: user }),\n id, domain.id, expectedSource)\n return repository.findOneOrFail({ where: { id, domain: { id: domain.id } } })\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"figure\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => FigureSaveResult, { description: 'Creates a figure. Rejects when the source violates the format.' })\n async createFigure(\n @Arg('figure') figure: NewFigure,\n @Ctx() context: ResolverContext\n ): Promise<FigureSaveResult> {\n const { domain, user, tx } = context.state\n const repository = tx.getRepository(Figure)\n\n // 타입 이름은 도메인 안에서 유일하다. 유니크 인덱스가 있지만 여기서 먼저 본다 —\n // DB 오류 문구는 저작자에게 아무 말도 해 주지 못한다.\n const taken = await repository.findOne({ where: { domain: { id: domain.id }, type: figure.type } })\n if (taken) {\n throw new Error(`타입 이름 '${figure.type}' 은 이미 쓰이고 있다. 만든 뒤에는 고칠 수 없으므로 다른 이름을 고른다`)\n }\n\n // 형식을 어기면 여기서 던진다. 파생값은 서버가 계산한다.\n const { source, derived, violations } = parseSource(figure.source)\n\n const { thumbnail, ...rest } = figure\n const saved = await repository.save({\n ...rest,\n source,\n ...derived,\n state: figure.state ?? 'draft',\n ...(await pictureOf(tx, domain, user, thumbnail)),\n domain,\n creator: user,\n updater: user\n })\n\n return { figure: saved, violations }\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"figure\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => FigureSaveResult, { description: 'Updates a figure. The `type` field cannot be changed.' })\n async updateFigure(\n @Arg('id') id: string,\n @Arg('patch') patch: FigurePatch,\n @Ctx() context: ResolverContext\n ): Promise<FigureSaveResult> {\n const { domain, user, tx } = context.state\n const repository = tx.getRepository(Figure)\n\n const figure = await repository.findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id }\n })\n if (!figure) {\n throw new Error(`Figure ${id} 를 찾을 수 없다`)\n }\n\n // 정본이 바뀌면 파생값도 다시 계산한다. 안 바뀌었으면 손대지 않는다 —\n // 이름만 고쳤는데 점수가 흔들리면 읽는 사람이 원인을 못 찾는다.\n let derived: { score: number; triangles: number; groups: number } | undefined\n let violations = []\n let source = figure.source\n\n if (patch.source !== undefined && patch.source !== figure.source) {\n const parsed = parseSource(patch.source)\n source = parsed.source\n derived = parsed.derived\n violations = parsed.violations\n }\n\n /*\n **타입은 발행 전에만 바뀐다** — ADR-0063 결정 4.\n\n 발행된 뒤에는 이미 배치된 도면이 이 이름을 가리키고, 바꾸면 그 도면이 아무 오류 없이\n 빈 자리가 된다. 발행된 적 없는 도형은 가리키는 도면이 있을 수 없다 — 도면은 최신\n 발행판을 그리므로 그려질 자리가 없다.\n\n 행과 정본 둘 다 고친다. 정본 안에도 `type` 이 있어서 한쪽만 고치면 저장된 JSON 과\n 행이 다른 이름을 말하고, 발행할 때 어느 쪽이 도면에 적히는지가 갈린다.\n */\n if (patch.names !== undefined) assertNames(patch.names)\n /* The picture is kept by its content; the patch's data URL is never written to the row. */\n const { thumbnail: picturePatch, ...patchRest } = patch\n const picture = await pictureOf(tx, domain, user, picturePatch, figure)\n\n let renamed: string | undefined\n if (patch.type !== undefined && patch.type !== figure.type) {\n const change = await this.renameType(figure, domain, patch.type, source, tx)\n renamed = change.type\n source = change.source\n }\n\n /*\n **판 번호는 여기서 손대지 않는다.** 저장은 저작이고, 판은 발행에서 생긴다(`releaseFigure`).\n board 의 `updateBoard` 도 같다 — 저장 경로에는 version 이 없다.\n */\n const saved = await repository.save({\n /*\n `domain` 을 명시로 넣는다 — 읽어 온 엔티티에는 관계가 안 실려 있다.\n\n 판본 스냅샷은 넘겨받은 엔티티를 베끼므로, 여기서 빠지면 판본의 도메인이 비고 그 판은\n 도메인으로 거르는 조회에 **한 줄도 안 걸린다**(실제로 그랬다). board 의 저장들도 같은\n 자리에서 domain 을 함께 넣는다.\n */\n domain,\n ...figure,\n ...patchRest,\n /* 앞뒤 공백을 떼고 겹침까지 본 이름. `patch.type` 을 그대로 두면 다듬기 전 값이 들어간다. */\n ...(renamed !== undefined ? { type: renamed } : {}),\n source,\n /*\n **고치면 발행이 풀린다.**\n\n 발행은 「이 판을 써도 된다」는 약속이고, 그 뒤에 정본이 바뀌면 약속한 것과 배포된 것이\n 달라진다. 그래서 저장은 언제나 초안으로 되돌리고, 다시 내보내려면 발행을 한 번 더 한다\n (판 번호가 하나 오르고 판본이 하나 더 남는다). board 의 `updateBoard` 가 같은 한 줄을 쓴다.\n */\n state: 'draft',\n ...(derived ?? {}),\n // 썸네일이 **썸네일로서** 바뀐 때만 시각을 갱신한다. 이름·설명 변경에는 안 건드린다.\n thumbnail: figure.thumbnail ?? null,\n ...picture,\n updater: user\n })\n\n return { figure: saved, violations }\n }\n\n /**\n * 초안의 타입을 고친다 — 규칙은 `figure-rename.ts`, 여기서는 그 규칙이 볼 **사실만** 읽는다.\n *\n * 겹침은 DB 인덱스(`ix_figure_1`)도 잡지만 먼저 읽어 본다. 인덱스가 던지는 말은 저작자가\n * 읽을 것이 못 되고, 어느 이름이 이미 쓰였는지도 안 알려 준다.\n */\n private async renameType(\n figure: Figure,\n domain: { id: string },\n wanted: string,\n source: string,\n tx: { getRepository: <T>(target: new () => T) => any }\n ): Promise<{ type: string; source: string }> {\n /* 읽어 온 엔티티에는 관계가 안 실려 있다 — 도메인은 문맥에서 온 것을 쓴다. */\n const facts = await renameFacts(\n { figures: tx.getRepository(Figure), histories: tx.getRepository(FigureHistory) },\n figure,\n domain,\n wanted\n )\n\n return renameDraftType({ type: figure.type, source }, wanted, facts)\n }\n\n /**\n * 발행한다 — **판이 생기는 유일한 자리.**\n *\n * ## 무엇이 일어나나\n *\n * `state` 가 `released` 가 되고, 판 번호가 하나 오르고, 그 순간의 도형이 판본으로 남는다\n * (`FigureHistory` — 스냅샷은 구독자가 뜬다). 저작 중 저장은 이 셋 중 아무것도 하지 않는다.\n *\n * ## 왜 이미 발행된 것을 거절하나\n *\n * 발행은 소비처에게 하는 약속이다. 같은 판을 두 번 발행하면 무엇이 약속인지 흐려진다. 고쳐서\n * 다시 내려면 초안으로 되돌린 뒤 발행한다 — board 가 같은 규칙이다.\n *\n * ## 번호는 판본에서 센다\n *\n * 도형의 현재 번호가 아니라 **판본의 최대 번호 + 1** 이다. 되돌리기로 옛 판이 현재가 되어도\n * 다음 발행이 이미 쓴 번호를 다시 쓰지 않는다.\n *\n * ## 게이트를 통과해야 한다\n *\n * 크기를 바꿨을 때 조각이 갈라지는 도형은 발행되지 않는다(`figure-gate.ts`). 소비처는 형상을\n * 늘려 쓰므로 — 그것이 이 형식의 값이다 — 늘려도 견디는지가 약속의 일부다. 화면은 같은 판정을\n * `inspectFigure` 로 미리 물어 이유를 보여 준다.\n */\n @Directive('@transaction')\n @Directive('@privilege(category: \"figure\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => Figure, { description: 'Releases a figure — raises its version and keeps the released state as history.' })\n async releaseFigure(\n @Arg('id') id: string,\n @Arg('comment', { nullable: true }) comment: string,\n @Ctx() context: ResolverContext\n ): Promise<Figure> {\n const { domain, user, tx } = context.state\n const repository = tx.getRepository(Figure)\n const historyRepository = tx.getRepository(FigureHistory)\n\n const figure = await repository.findOne({\n where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id }\n })\n if (!figure) {\n throw new Error(`Figure ${id} 를 찾을 수 없다`)\n }\n\n if (figure.state === 'released') {\n throw new Error(`Figure '${figure.type}' 은 이미 발행되어 있다. 고쳐서 다시 내려면 초안으로 되돌린 뒤 발행한다`)\n }\n\n /*\n ── 게이트는 여기 있어야 한다 ────────────────────────────────────────────\n 화면도 같은 판정을 미리 물어(`inspectFigure`) 이유를 보여 주지만, **막는 자리는 이곳뿐이다.**\n 물어본 뒤 정본이 바뀌었을 수 있고, 화면을 거치지 않는 부름도 있다.\n\n 막는 이유는 사유와 함께 낸다. 「발행할 수 없습니다」로 뭉치면 무엇을 고쳐야 하는지 모른다.\n */\n /*\n 직전 발행판을 먼저 꺼낸다. 판 번호를 세는 데도 쓰고, **약속을 깨는 발행인가**를 견주는 데도\n 쓴다(ADR-0063 결정 3) — 도면은 type 만 적고 늘 최신 발행판을 그리므로, 다시 발행하는 것은\n 그 type 을 놓아 둔 모든 도면에게 같은 약속을 다시 하는 일이다.\n */\n const released = await historyRepository\n .createQueryBuilder('history')\n .where('history.originalId = :id', { id: figure.id })\n .orderBy('history.version', 'DESC')\n .limit(1)\n .getOne()\n\n const inspection = inspectSource(figure.source, released?.source, context.t, figure.type)\n if (inspection.blocked) {\n const reasons = inspection.findings\n .filter(finding => finding.blocking)\n .map(finding => (finding.at ? `${finding.message} (${finding.at})` : finding.message))\n\n throw new Error(`Figure '${figure.type}' 은 아직 발행할 수 없다 — ${reasons.join(' · ')}`)\n }\n\n const nextVersion = released?.version ? Number(released.version) + 1 : 1\n /* What this release records about itself: its format, and what changed against the last one (ADR-0104). */\n const record = releaseRecordOf(figure.source!, released?.source)\n\n return await repository.save({\n /*\n `domain` 을 명시로 넣는다 — 읽어 온 엔티티에는 관계가 안 실려 있다.\n\n 판본 스냅샷은 넘겨받은 엔티티를 베끼므로, 여기서 빠지면 판본의 도메인이 비고 그 판은\n 도메인으로 거르는 조회에 **한 줄도 안 걸린다**(실제로 그랬다). board 의 저장들도 같은\n 자리에서 domain 을 함께 넣는다.\n */\n domain,\n ...figure,\n version: nextVersion,\n state: 'released',\n updater: user,\n /* 판본 구독자가 이것들을 판본의 comment · assetFormat · kernelVersion · changes 로 옮긴다. Figure 의 칸이 아니다. */\n __releaseComment: comment ?? null,\n __releaseFormat: record.format,\n __releaseKernel: record.kernel,\n __releaseChanges: record.changes,\n __releaseMetrics: record.metrics,\n __releaseTopView: record.topView\n } as any)\n }\n\n /**\n * 옛 판으로 되돌린다.\n *\n * ## 무엇이 돌아오나\n *\n * 그 판의 **정본과 속성 정의, 그리고 그림**이다. 이름·설명·분류는 그대로 둔다 — 그것들은 언제든\n * 바꿔도 안전한 카탈로그의 말이고, 되돌리기가 개명까지 되돌리면 사람이 시키지 않은 일을 한다.\n *\n * ## 되돌려도 발행은 아니다\n *\n * 초안으로 돌아온다. 다시 내보내려면 발행을 한 번 더 하고, 그때 판 번호는 **이미 쓴 번호 다음**을\n * 받는다 — 3판을 되살렸다고 다시 3판이 되지 않는다. board 도 같다.\n *\n * ## 비용은 다시 잰다\n *\n * 판본이 든 점수·삼각형은 **그때의 형식**으로 잰 값이다. 지금 이 도형이 그 내용이 되었으므로\n * 오늘 기준으로 다시 계산한다. 옛 값은 판본에 그대로 남아 있다.\n */\n @Directive('@transaction')\n @Directive('@privilege(category: \"figure\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => FigureRevertResult, {\n description:\n 'Reverts a figure to one of its released versions, keeping the draft it writes over. It comes back as a draft. ' +\n 'The same requestId again answers with the same revert.'\n })\n async revertFigureVersion(\n @Arg('id') id: string,\n @Arg('version') version: number,\n @Arg('requestId', { description: 'A UUID for this revert: a retry sends the same one.' }) requestId: string,\n @Arg('expectedSource', { description: \"The figure's source as the reverter saw it; the revert goes on only while it holds.\" }) expectedSource: string,\n @Ctx() context: ResolverContext\n ): Promise<FigureRevertResult> {\n /* Kept and written over in this transaction, or neither (ADR-0097 §5.6). */\n const { domain, user, tx } = context.state\n const { figure, violations, kept } = await revertKeepingDraft(tx, domain, user, { id, version, requestId, expectedSource })\n return { figure, violations, kept }\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"figure\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => FigureRevertResult, {\n description: \"Brings back a draft a revert kept -- only while the figure still holds what that revert wrote. The same requestId again answers with the same undo.\"\n })\n async undoFigureRevert(\n @Arg('keptId') keptId: string,\n @Arg('requestId', { description: 'A UUID for this undo: a retry sends the same one.' }) requestId: string,\n @Ctx() context: ResolverContext\n ): Promise<FigureRevertResult> {\n const { domain, user, tx } = context.state\n const { figure, kept } = await undoRevert(tx, domain, user, { keptId, requestId })\n return { figure, violations: [], kept: kept as FigureReplacedDraft }\n }\n\n @Directive('@transaction')\n @Directive('@privilege(category: \"figure\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => Boolean, { description: 'Soft-deletes a figure.' })\n async deleteFigure(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {\n const { domain, tx } = context.state\n\n // 소프트 삭제다 — 이미 배치된 도면이 이 타입을 참조할 수 있으므로 행을 지우지\n // 않는다. 되살릴 길을 남긴다.\n await tx.getRepository(Figure).softDelete({ domain: { id: domain.id }, id })\n\n return true\n }\n\n /**\n * 퇴역시키거나 되살린다(ADR-0104 결정 6).\n *\n * 표시일 뿐이다. 발행판은 그대로 남고 받는 쪽은 그대로 받는다 — 발행판은 지우지 않는다. 그래서 **발행을 풀지 않는다**:\n * 행을 엔티티로 저장하지 않고 질의로 고친다. 엔티티로 저장하면 발행된 행이라 판본 구독자가 같은 번호로 판본을 또\n * 뜬다. 대신 쓸 것(`supersededBy`)은 같은 도메인(또는 상위)에 있는 다른 type 이어야 한다.\n */\n @Directive('@transaction')\n @Directive('@privilege(category: \"figure\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => Figure, { description: 'Retires a figure or brings it back. It stays released and served; supersededBy names the type to use instead.' })\n async setFigureDeprecation(\n @Arg('id') id: string,\n @Arg('deprecated') deprecated: boolean,\n @Ctx() context: ResolverContext,\n @Arg('supersededBy', { nullable: true }) supersededBy?: string\n ): Promise<Figure> {\n const { domain, tx } = context.state\n const repository = tx.getRepository(Figure)\n const scope = { id: In([domain.id, domain.parentId].filter(Boolean)) }\n const figure = await repository.findOne({ where: { domain: scope, id } })\n if (!figure) throw new Error(`Figure ${id} 를 찾을 수 없다`)\n const instead = deprecated ? supersededBy?.trim() || null : null\n if (instead) {\n if (instead === figure.type) throw new Error(`Figure '${figure.type}' 는 자기 자신으로 대신할 수 없다`)\n const other = await repository.findOne({ where: { domain: scope, type: instead } })\n if (!other) throw new Error(`대신 쓸 Figure '${instead}' 가 이 도메인에 없다`)\n }\n await repository.createQueryBuilder().update(Figure).set({ deprecated, supersededBy: instead }).where('id = :id', { id }).callListeners(false).execute()\n return await repository.findOneOrFail({ where: { id } })\n }\n\n /**\n * 저작 보조에게 제안을 시킨다(ADR-0094).\n *\n * **저장하지 않는다.** 모델러 명령 목록과 그것이 만드는 도형을 돌려줄 뿐이고, 정본이 되는 것은 저작자가 모델러에\n * 적용하고 저장한 뒤다. 커널이 거절한 명령이나 게이트가 잡은 것은 여기까지 오지 않는다 — 제안기가 사유를 모델에\n * 돌려주고 다시 시킨다. 끝내 못 만들면 **사유와 함께 던진다.** 반쯤 만든 것을 돌려주지 않는다.\n */\n @Directive('@privilege(category: \"figure\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Mutation(returns => FigureProposal, {\n description: 'Asks the authoring assistant for modeller commands that make or revise a figure. Nothing is saved.'\n })\n async proposeFigure(@Arg('request') request: ProposeRequest): Promise<FigureProposal> {\n // 그림은 메모리로 받는다. 참고용이라 저장하지 않는다 — 남기면 지울 사람이 없다.\n let image\n if (request.image) {\n const file = await request.image\n const chunks: Buffer[] = []\n for await (const chunk of file.createReadStream()) {\n chunks.push(chunk as Buffer)\n }\n image = { data: Buffer.concat(chunks), mediaType: file.mimetype as never }\n }\n\n try {\n const result = await proposeFigureSteps({\n prompt: request.prompt,\n base: request.base ? parseFigureAsset(request.base) : undefined,\n name: request.name,\n image\n })\n\n return {\n steps: JSON.stringify(result.steps),\n source: JSON.stringify(result.source),\n score: result.score ? Math.round(result.score.score) : undefined,\n grade: result.score?.grade,\n triangles: result.cost.triangles,\n attempts: result.attempts\n }\n } catch (e) {\n if (e instanceof ProposeFigureFailure) {\n // 사유를 삼키지 않는다. 저작자가 무엇이 막혔는지 알아야 말을 고쳐 다시 시킨다.\n throw new Error([e.message, ...e.reasons].join('\\n'))\n }\n throw e\n }\n }\n\n}\n"]}