@things-factory/figure-service 10.1.110 → 10.1.111
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-server/service/figure/event-subscriber.js +4 -1
- package/dist-server/service/figure/event-subscriber.js.map +1 -1
- package/dist-server/service/figure/figure-format.d.ts +5 -3
- package/dist-server/service/figure/figure-format.js +21 -5
- package/dist-server/service/figure/figure-format.js.map +1 -1
- package/dist-server/service/figure/figure-history.d.ts +3 -0
- package/dist-server/service/figure/figure-history.js +22 -0
- package/dist-server/service/figure/figure-history.js.map +1 -1
- package/dist-server/service/figure/figure-mutation.d.ts +10 -0
- package/dist-server/service/figure/figure-mutation.js +54 -1
- package/dist-server/service/figure/figure-mutation.js.map +1 -1
- package/dist-server/service/figure/figure-type.d.ts +1 -0
- package/dist-server/service/figure/figure-type.js +5 -0
- package/dist-server/service/figure/figure-type.js.map +1 -1
- package/dist-server/service/figure/figure.d.ts +3 -0
- package/dist-server/service/figure/figure.js +16 -0
- package/dist-server/service/figure/figure.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/server/service/figure/event-subscriber.ts +4 -1
- package/server/service/figure/figure-deprecation-db.test.ts +107 -0
- package/server/service/figure/figure-format.test.ts +19 -1
- package/server/service/figure/figure-format.ts +27 -8
- package/server/service/figure/figure-history.ts +20 -0
- package/server/service/figure/figure-mutation.ts +45 -1
- package/server/service/figure/figure-release-record-db.test.ts +5 -0
- package/server/service/figure/figure-type.ts +5 -0
- package/server/service/figure/figure.ts +21 -0
- package/translations/en.json +4 -1
- package/translations/ko.json +4 -1
|
@@ -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@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), ...pictureOf(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), ...pictureOf(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 saved = await repository.save({\n ...figure,\n source,\n ...derived,\n state: figure.state ?? 'draft',\n thumbnailUpdatedAt: figure.thumbnail ? new Date() : undefined,\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 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 ...patch,\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 thumbnailUpdatedAt:\n patch.thumbnail !== undefined && patch.thumbnail !== figure.thumbnail\n ? new Date()\n : figure.thumbnailUpdatedAt,\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 } 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-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), ...pictureOf(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), ...pictureOf(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 saved = await repository.save({\n ...figure,\n source,\n ...derived,\n state: figure.state ?? 'draft',\n thumbnailUpdatedAt: figure.thumbnail ? new Date() : undefined,\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\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 ...patch,\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 thumbnailUpdatedAt:\n patch.thumbnail !== undefined && patch.thumbnail !== figure.thumbnail\n ? new Date()\n : figure.thumbnailUpdatedAt,\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"]}
|
|
@@ -4,6 +4,7 @@ exports.FigureInspection = exports.FigureGateFinding = exports.FigureRevertResul
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const figure_replaced_draft_js_1 = require("./figure-replaced-draft.js");
|
|
6
6
|
const type_graphql_1 = require("type-graphql");
|
|
7
|
+
const graphql_scalars_1 = require("graphql-scalars");
|
|
7
8
|
const figure_js_1 = require("./figure.js");
|
|
8
9
|
/**
|
|
9
10
|
* 새 Figure.
|
|
@@ -79,6 +80,10 @@ tslib_1.__decorate([
|
|
|
79
80
|
(0, type_graphql_1.Field)({ nullable: true, description: 'The new description.' }),
|
|
80
81
|
tslib_1.__metadata("design:type", String)
|
|
81
82
|
], FigurePatch.prototype, "description", void 0);
|
|
83
|
+
tslib_1.__decorate([
|
|
84
|
+
(0, type_graphql_1.Field)(type => graphql_scalars_1.GraphQLJSON, { nullable: true, description: 'Display names by language. {} clears them; omitting the field leaves them.' }),
|
|
85
|
+
tslib_1.__metadata("design:type", Object)
|
|
86
|
+
], FigurePatch.prototype, "names", void 0);
|
|
82
87
|
tslib_1.__decorate([
|
|
83
88
|
(0, type_graphql_1.Field)({ nullable: true, description: 'The new classification code.' }),
|
|
84
89
|
tslib_1.__metadata("design:type", String)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figure-type.js","sourceRoot":"","sources":["../../../server/service/figure/figure-type.ts"],"names":[],"mappings":"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","sourcesContent":["import { FigureReplacedDraft } from './figure-replaced-draft.js'\nimport { Field, InputType, Int, ObjectType } from 'type-graphql'\n\nimport { Figure } from './figure.js'\n\n/**\n * 새 Figure.\n *\n * `score`·`triangles`·`groups` 는 **받지 않는다.** 서버가 `source` 에서 계산한다 —\n * 받으면 거짓이 들어오고 목록이 실물과 다른 것을 보여 준다.\n */\n@InputType({ description: 'Input for creating a new figure.' })\nexport class NewFigure {\n @Field({ description: 'Component type name. Immutable once created, unique per domain.' })\n type: string\n\n @Field({ description: 'Display name shown to authors.' })\n name: string\n\n @Field({ nullable: true, description: 'A detailed description for the figure.' })\n description?: string\n\n @Field({ nullable: true, description: 'Classification code used to group figures in the palette.' })\n category?: string\n\n @Field(type => [String], { nullable: true, description: 'Free-form tags. A figure may carry several.' })\n tags?: string[]\n\n @Field({ description: 'The figure asset JSON (figure-asset-1).' })\n source: string\n\n @Field({ nullable: true, description: 'JSON definition of the master-data fields an instance carries.' })\n properties?: string\n\n @Field({ nullable: true, description: \"Lifecycle state — defaults to 'draft'.\" })\n state?: 'draft' | 'released'\n\n @Field({ nullable: true, description: 'A base64 encoded thumbnail image.' })\n thumbnail?: string\n}\n\n/**\n * 수정.\n *\n * `type` 은 **한 번도 발행되지 않은 초안에서만** 바뀐다(ADR-0063 결정 4). 저장되는 식별자라\n * 발행된 뒤에 바꾸면 이미 배치된 보드가 타입을 못 찾아 오류 없이 빈 화면이 된다. 발행 전에는\n * 그 도형을 가리키는 도면이 있을 수 없다 — 도면은 최신 발행판을 그리므로 발행된 적 없는\n * 도형은 그려질 자리가 없다.\n *\n * 닫아 두었더니 저작자가 이름을 한 번도 정하지 못했다. 새 Figure 에는 기계가 지은 이름이\n * 붙고(`FIGURE_MU6RJH47`) 칸에 자물쇠가 걸려서, 그 이름이 그대로 도면에 적히는 이름이 됐다.\n */\n@InputType({ description: 'Input for updating an existing figure. `type` is accepted only while the figure has never been released.' })\nexport class FigurePatch {\n @Field({ nullable: true, description: 'The stored identifier. Accepted only before the first release; rejected once a version exists.' })\n type?: string\n\n @Field({ nullable: true, description: 'The new display name.' })\n name?: string\n\n @Field({ nullable: true, description: 'The new description.' })\n description?: string\n\n @Field({ nullable: true, description: 'The new classification code.' })\n category?: string\n\n /*\n 빈 배열과 안 준 것을 가른다. `undefined` 는 「건드리지 않는다」, `[]` 는 「전부 지운다」다.\n 둘을 뭉개면 태그를 다 지우려는 저작자가 지울 방법을 잃는다.\n */\n @Field(type => [String], { nullable: true, description: 'The new tags. An empty list clears them; omitting the field leaves them.' })\n tags?: string[]\n\n @Field({ nullable: true, description: 'The new figure asset JSON (figure-asset-1).' })\n source?: string\n\n @Field({ nullable: true, description: 'The new master-data field definition.' })\n properties?: string\n\n /*\n `state` 는 여기 없다 — **상태는 저장이 정하지 않는다.**\n\n 발행은 `releaseFigure` 가 한다. 저장으로 상태를 바꿀 수 있게 두면 발행된 판을 덮어쓰면서 같은\n 판 번호로 판본을 또 뜨게 되고(유니크 충돌), 무엇이 약속된 판인지도 흐려진다. board 도 같다.\n */\n\n @Field({ nullable: true, description: 'A base64 encoded thumbnail image.' })\n thumbnail?: string\n}\n\n@ObjectType({ description: 'A paginated list of figures.' })\nexport class FigureList {\n @Field(type => [Figure], { description: 'The figures on this page.' })\n items: Figure[]\n\n @Field(type => Int, { description: 'Total number of figures matching the query.' })\n total: number\n}\n\n/**\n * 검증 결과 한 줄.\n *\n * 정본 형식의 검증은 `@hatiolab/figure-model` 이 두 단계로 나눈다 — `errors` 는\n * 막고, `violations` 는 알린다. 그 경계를 서버가 다시 정하지 않는다.\n */\n@ObjectType({ description: 'One validation finding from figure-model.' })\nexport class FigureFinding {\n @Field({ description: 'Stable code from figure-model (ERROR_CODES / VIOLATION_CODES).' })\n code: string\n\n @Field({ description: 'Human-readable message.' })\n message: string\n\n @Field({ nullable: true, description: 'Path within the source that the finding points at.' })\n at?: string\n}\n\n/**\n * 저장 결과.\n *\n * `violations` 가 있어도 저장은 된다 — 막는 것과 알리는 것을 가른다. 화면이\n * 이것을 그대로 보여 줘야 한다. 조용히 버리면 저작자가 모른다.\n */\n@ObjectType({ description: 'Result of saving a figure, carrying non-blocking violations.' })\nexport class FigureSaveResult {\n @Field(type => Figure, { description: 'The saved figure.' })\n figure: Figure\n\n @Field(type => [FigureFinding], { description: 'Non-blocking findings. The save succeeded despite these.' })\n violations: FigureFinding[]\n}\n\n/** An AI proposal saved into a figure, with the figure's names as they are now (ADR-0097 §5.6 item 5). */\n@ObjectType({ description: 'A figure an AI proposal was saved into.' })\nexport class FigureProposalOutcome {\n @Field({ description: 'The figure it was saved into.' })\n figureId: string\n\n @Field({ nullable: true, description: \"The figure's type name now.\" })\n type?: string\n\n @Field({ nullable: true, description: \"The figure's display name now.\" })\n name?: string\n\n @Field({ nullable: true, description: 'When the save that held it was made.' })\n recordedAt?: Date\n}\n\n/** A revert's outcome: the figure as it now is, and the draft kept for it (ADR-0097 §5.6). */\n@ObjectType({ description: 'The result of a revert, or of an undo of one.' })\nexport class FigureRevertResult {\n @Field(type => Figure, { description: 'The figure, as it now is.' })\n figure: Figure\n\n @Field(type => [FigureFinding], { description: 'Non-blocking findings on the source written.' })\n violations: FigureFinding[]\n\n @Field(type => FigureReplacedDraft, { description: 'The draft kept for this revert -- or, for an undo, the one brought back.' })\n kept: FigureReplacedDraft\n}\n\n/**\n * 발행 판정 한 줄.\n *\n * `FigureFinding` 과 칸이 겹치지만 **`blocking` 이 하나 더 있다.** 저장 쪽 발견은 정의상 막지 않는\n * 것들이라 그 칸이 필요 없었다. 발행 판정은 막는 것과 알리는 것을 함께 내므로, 어느 쪽인지를 값이\n * 스스로 말해야 한다 — 코드를 보고 화면이 다시 분류하면 규칙이 두 벌이 된다.\n */\n@ObjectType({ description: 'One finding from the release gate.' })\nexport class FigureGateFinding {\n @Field({ description: 'Stable code of the gate finding, for example part-outside-occupancy or parts-split-on-resize.' })\n code: string\n\n @Field({ description: 'Human-readable message.' })\n message: string\n\n @Field({ nullable: true, description: 'Why this is a problem — what a person sees when it happens.' })\n why?: string\n\n @Field({ nullable: true, description: 'What to change, naming the part and the value.' })\n how?: string\n\n @Field({ nullable: true, description: 'Where it points: part names that came apart, or a path in the source.' })\n at?: string\n\n @Field({ description: 'True when this finding blocks the release.' })\n blocking: boolean\n}\n\n/**\n * 발행 판정.\n *\n * 화면이 **발행을 누르기 전에** 물어보는 자리다. 눌러 보고 거절당하는 것으로 알게 되면, 무엇을\n * 고쳐야 하는지 모른 채 단추만 두드리게 된다.\n */\n@ObjectType({ description: 'Whether a figure may be released, and why not.' })\nexport class FigureInspection {\n @Field({ description: 'True when at least one finding blocks the release.' })\n blocked: boolean\n\n @Field(type => [FigureGateFinding], { description: 'Findings, blocking and advisory together.' })\n findings: FigureGateFinding[]\n}\n"]}
|
|
1
|
+
{"version":3,"file":"figure-type.js","sourceRoot":"","sources":["../../../server/service/figure/figure-type.ts"],"names":[],"mappings":"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","sourcesContent":["import { FigureReplacedDraft } from './figure-replaced-draft.js'\nimport { Field, InputType, Int, ObjectType } from 'type-graphql'\nimport { GraphQLJSON } from 'graphql-scalars'\n\nimport { Figure } from './figure.js'\n\n/**\n * 새 Figure.\n *\n * `score`·`triangles`·`groups` 는 **받지 않는다.** 서버가 `source` 에서 계산한다 —\n * 받으면 거짓이 들어오고 목록이 실물과 다른 것을 보여 준다.\n */\n@InputType({ description: 'Input for creating a new figure.' })\nexport class NewFigure {\n @Field({ description: 'Component type name. Immutable once created, unique per domain.' })\n type: string\n\n @Field({ description: 'Display name shown to authors.' })\n name: string\n\n @Field({ nullable: true, description: 'A detailed description for the figure.' })\n description?: string\n\n @Field({ nullable: true, description: 'Classification code used to group figures in the palette.' })\n category?: string\n\n @Field(type => [String], { nullable: true, description: 'Free-form tags. A figure may carry several.' })\n tags?: string[]\n\n @Field({ description: 'The figure asset JSON (figure-asset-1).' })\n source: string\n\n @Field({ nullable: true, description: 'JSON definition of the master-data fields an instance carries.' })\n properties?: string\n\n @Field({ nullable: true, description: \"Lifecycle state — defaults to 'draft'.\" })\n state?: 'draft' | 'released'\n\n @Field({ nullable: true, description: 'A base64 encoded thumbnail image.' })\n thumbnail?: string\n}\n\n/**\n * 수정.\n *\n * `type` 은 **한 번도 발행되지 않은 초안에서만** 바뀐다(ADR-0063 결정 4). 저장되는 식별자라\n * 발행된 뒤에 바꾸면 이미 배치된 보드가 타입을 못 찾아 오류 없이 빈 화면이 된다. 발행 전에는\n * 그 도형을 가리키는 도면이 있을 수 없다 — 도면은 최신 발행판을 그리므로 발행된 적 없는\n * 도형은 그려질 자리가 없다.\n *\n * 닫아 두었더니 저작자가 이름을 한 번도 정하지 못했다. 새 Figure 에는 기계가 지은 이름이\n * 붙고(`FIGURE_MU6RJH47`) 칸에 자물쇠가 걸려서, 그 이름이 그대로 도면에 적히는 이름이 됐다.\n */\n@InputType({ description: 'Input for updating an existing figure. `type` is accepted only while the figure has never been released.' })\nexport class FigurePatch {\n @Field({ nullable: true, description: 'The stored identifier. Accepted only before the first release; rejected once a version exists.' })\n type?: string\n\n @Field({ nullable: true, description: 'The new display name.' })\n name?: string\n\n @Field({ nullable: true, description: 'The new description.' })\n description?: string\n\n /* 언어별 표시 이름. 안 준 것은 그대로, `{}` 는 전부 지운다. */\n @Field(type => GraphQLJSON, { nullable: true, description: 'Display names by language. {} clears them; omitting the field leaves them.' })\n names?: Record<string, string>\n\n @Field({ nullable: true, description: 'The new classification code.' })\n category?: string\n\n /*\n 빈 배열과 안 준 것을 가른다. `undefined` 는 「건드리지 않는다」, `[]` 는 「전부 지운다」다.\n 둘을 뭉개면 태그를 다 지우려는 저작자가 지울 방법을 잃는다.\n */\n @Field(type => [String], { nullable: true, description: 'The new tags. An empty list clears them; omitting the field leaves them.' })\n tags?: string[]\n\n @Field({ nullable: true, description: 'The new figure asset JSON (figure-asset-1).' })\n source?: string\n\n @Field({ nullable: true, description: 'The new master-data field definition.' })\n properties?: string\n\n /*\n `state` 는 여기 없다 — **상태는 저장이 정하지 않는다.**\n\n 발행은 `releaseFigure` 가 한다. 저장으로 상태를 바꿀 수 있게 두면 발행된 판을 덮어쓰면서 같은\n 판 번호로 판본을 또 뜨게 되고(유니크 충돌), 무엇이 약속된 판인지도 흐려진다. board 도 같다.\n */\n\n @Field({ nullable: true, description: 'A base64 encoded thumbnail image.' })\n thumbnail?: string\n}\n\n@ObjectType({ description: 'A paginated list of figures.' })\nexport class FigureList {\n @Field(type => [Figure], { description: 'The figures on this page.' })\n items: Figure[]\n\n @Field(type => Int, { description: 'Total number of figures matching the query.' })\n total: number\n}\n\n/**\n * 검증 결과 한 줄.\n *\n * 정본 형식의 검증은 `@hatiolab/figure-model` 이 두 단계로 나눈다 — `errors` 는\n * 막고, `violations` 는 알린다. 그 경계를 서버가 다시 정하지 않는다.\n */\n@ObjectType({ description: 'One validation finding from figure-model.' })\nexport class FigureFinding {\n @Field({ description: 'Stable code from figure-model (ERROR_CODES / VIOLATION_CODES).' })\n code: string\n\n @Field({ description: 'Human-readable message.' })\n message: string\n\n @Field({ nullable: true, description: 'Path within the source that the finding points at.' })\n at?: string\n}\n\n/**\n * 저장 결과.\n *\n * `violations` 가 있어도 저장은 된다 — 막는 것과 알리는 것을 가른다. 화면이\n * 이것을 그대로 보여 줘야 한다. 조용히 버리면 저작자가 모른다.\n */\n@ObjectType({ description: 'Result of saving a figure, carrying non-blocking violations.' })\nexport class FigureSaveResult {\n @Field(type => Figure, { description: 'The saved figure.' })\n figure: Figure\n\n @Field(type => [FigureFinding], { description: 'Non-blocking findings. The save succeeded despite these.' })\n violations: FigureFinding[]\n}\n\n/** An AI proposal saved into a figure, with the figure's names as they are now (ADR-0097 §5.6 item 5). */\n@ObjectType({ description: 'A figure an AI proposal was saved into.' })\nexport class FigureProposalOutcome {\n @Field({ description: 'The figure it was saved into.' })\n figureId: string\n\n @Field({ nullable: true, description: \"The figure's type name now.\" })\n type?: string\n\n @Field({ nullable: true, description: \"The figure's display name now.\" })\n name?: string\n\n @Field({ nullable: true, description: 'When the save that held it was made.' })\n recordedAt?: Date\n}\n\n/** A revert's outcome: the figure as it now is, and the draft kept for it (ADR-0097 §5.6). */\n@ObjectType({ description: 'The result of a revert, or of an undo of one.' })\nexport class FigureRevertResult {\n @Field(type => Figure, { description: 'The figure, as it now is.' })\n figure: Figure\n\n @Field(type => [FigureFinding], { description: 'Non-blocking findings on the source written.' })\n violations: FigureFinding[]\n\n @Field(type => FigureReplacedDraft, { description: 'The draft kept for this revert -- or, for an undo, the one brought back.' })\n kept: FigureReplacedDraft\n}\n\n/**\n * 발행 판정 한 줄.\n *\n * `FigureFinding` 과 칸이 겹치지만 **`blocking` 이 하나 더 있다.** 저장 쪽 발견은 정의상 막지 않는\n * 것들이라 그 칸이 필요 없었다. 발행 판정은 막는 것과 알리는 것을 함께 내므로, 어느 쪽인지를 값이\n * 스스로 말해야 한다 — 코드를 보고 화면이 다시 분류하면 규칙이 두 벌이 된다.\n */\n@ObjectType({ description: 'One finding from the release gate.' })\nexport class FigureGateFinding {\n @Field({ description: 'Stable code of the gate finding, for example part-outside-occupancy or parts-split-on-resize.' })\n code: string\n\n @Field({ description: 'Human-readable message.' })\n message: string\n\n @Field({ nullable: true, description: 'Why this is a problem — what a person sees when it happens.' })\n why?: string\n\n @Field({ nullable: true, description: 'What to change, naming the part and the value.' })\n how?: string\n\n @Field({ nullable: true, description: 'Where it points: part names that came apart, or a path in the source.' })\n at?: string\n\n @Field({ description: 'True when this finding blocks the release.' })\n blocking: boolean\n}\n\n/**\n * 발행 판정.\n *\n * 화면이 **발행을 누르기 전에** 물어보는 자리다. 눌러 보고 거절당하는 것으로 알게 되면, 무엇을\n * 고쳐야 하는지 모른 채 단추만 두드리게 된다.\n */\n@ObjectType({ description: 'Whether a figure may be released, and why not.' })\nexport class FigureInspection {\n @Field({ description: 'True when at least one finding blocks the release.' })\n blocked: boolean\n\n @Field(type => [FigureGateFinding], { description: 'Findings, blocking and advisory together.' })\n findings: FigureGateFinding[]\n}\n"]}
|
|
@@ -4,6 +4,7 @@ exports.Figure = void 0;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const typeorm_1 = require("typeorm");
|
|
6
6
|
const type_graphql_1 = require("type-graphql");
|
|
7
|
+
const graphql_scalars_1 = require("graphql-scalars");
|
|
7
8
|
const auth_base_1 = require("@things-factory/auth-base");
|
|
8
9
|
const shell_1 = require("@things-factory/shell");
|
|
9
10
|
/**
|
|
@@ -72,6 +73,21 @@ tslib_1.__decorate([
|
|
|
72
73
|
(0, type_graphql_1.Field)({ nullable: true, description: 'A detailed description for the figure.' }),
|
|
73
74
|
tslib_1.__metadata("design:type", String)
|
|
74
75
|
], Figure.prototype, "description", void 0);
|
|
76
|
+
tslib_1.__decorate([
|
|
77
|
+
(0, typeorm_1.Column)('simple-json', { nullable: true, default: null }),
|
|
78
|
+
(0, type_graphql_1.Field)(type => graphql_scalars_1.GraphQLJSON, { nullable: true, description: 'Display names by language, e.g. { "en": "...", "ko": "..." }. A language not here shows `name`.' }),
|
|
79
|
+
tslib_1.__metadata("design:type", Object)
|
|
80
|
+
], Figure.prototype, "names", void 0);
|
|
81
|
+
tslib_1.__decorate([
|
|
82
|
+
(0, typeorm_1.Column)({ nullable: true, default: false }),
|
|
83
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'Retired: still released and still served, but not to be chosen for new work.' }),
|
|
84
|
+
tslib_1.__metadata("design:type", Boolean)
|
|
85
|
+
], Figure.prototype, "deprecated", void 0);
|
|
86
|
+
tslib_1.__decorate([
|
|
87
|
+
(0, typeorm_1.Column)({ nullable: true }),
|
|
88
|
+
(0, type_graphql_1.Field)({ nullable: true, description: 'The type to use instead of a retired figure.' }),
|
|
89
|
+
tslib_1.__metadata("design:type", String)
|
|
90
|
+
], Figure.prototype, "supersededBy", void 0);
|
|
75
91
|
tslib_1.__decorate([
|
|
76
92
|
(0, typeorm_1.Column)({ nullable: true }),
|
|
77
93
|
(0, type_graphql_1.Field)({ nullable: true, description: 'Classification code used to group figures in the palette. One per figure.' }),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"figure.js","sourceRoot":"","sources":["../../../server/service/figure/figure.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Column,\n CreateDateColumn,\n DeleteDateColumn,\n Entity,\n Index,\n ManyToOne,\n PrimaryGeneratedColumn,\n RelationId,\n UpdateDateColumn\n} from 'typeorm'\nimport { Field, Float, ID, Int, ObjectType } from 'type-graphql'\n\nimport { User } from '@things-factory/auth-base'\nimport { Domain, longTextColumn } from '@things-factory/shell'\n\n/**\n * Figure — 저작된 3D 컴포넌트 한 종류.\n *\n * `Board` 를 준용한다. 다른 점만 주석으로 적는다.\n *\n * ## 무엇을 담나 — 도형 자산이다, 씬 모델이 아니다\n *\n * 형식은 `@hatiolab/figure-model` 이 정한다(`figure-asset-1`). 씬 컴포넌트 트리를 담지 않는다.\n * 컴파일한 것도 저장하지 않는다 — 원본에서 파생되므로 소비하는 쪽이 커널로 컴파일한다. 저장하면 원본과 갈린다.\n *\n * 그래서 부품·움직임·자리 같은 것을 컬럼으로 두지 않는다 — 전부 `source` 안에 이미 있다. 두 벌이면 갈린다.\n *\n * 설계: `docs/design/figure-modules.md` §2\n */\n@Entity()\n@Index('ix_figure_1', (figure: Figure) => [figure.domain, figure.type], {\n unique: true,\n where: '\"deleted_at\" IS NULL'\n})\n@Index('ix_figure_2', (figure: Figure) => [figure.domain, figure.category])\n@ObjectType({ description: 'An authored 3D component type — its figure asset plus its metadata.' })\nexport class Figure {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { nullable: true, description: 'Unique identifier for the figure.' })\n readonly id?: string\n\n /**\n * 발행된 판의 번호 — **발행할 때만 올라간다.**\n *\n * 저장 횟수가 아니다. 저작 중에는 몇 번을 고쳐 저장하든 그대로이고, `draft` 가 `released` 가\n * 되는 순간에만 하나 오른다. 소비처가 「몇 번째 판을 쓰고 있나」를 이 값으로 말한다.\n *\n * 한 번도 발행되지 않았으면 **0** 이다. 1 로 시작하면 아직 아무에게도 약속하지 않은 초안이\n * 첫 판인 것처럼 보인다.\n */\n @Column({ nullable: true, default: 0 })\n @Field(type => Int, {\n nullable: true,\n description: 'Published version. Raised when the figure is released, not when it is saved. 0 means never released.'\n })\n version?: number = 0\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain this figure belongs to.' })\n domain?: Domain\n\n @RelationId((figure: Figure) => figure.domain)\n domainId?: string\n\n /**\n * 컴포넌트 타입 이름. **저장되는 식별자다.**\n *\n * 배치된 도면이 이 이름으로 타입을 찾는다. 바꾸면 그 도면은 타입을 못 찾아\n * **오류 없이 빈 화면**이 된다. 그래서 만들 때 정하고 잠근다 — 고칠 수 있는 것은\n * 표시 이름(`name`)뿐이다. 수정 리졸버가 이 필드를 받지 않는다.\n *\n * `Board.type`(main/sub/popup)과 뜻이 전혀 다르다. 혼동하지 않는다.\n */\n @Column()\n @Field({ description: 'Component type name. A stored identifier — unique per domain and immutable once created.' })\n type?: string\n\n @Column()\n @Field({ description: 'Display name shown to authors. Safe to rename.' })\n name?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'A detailed description for the figure.' })\n description?: string\n\n /**\n * 분류 하나. **팔레트에서 묶어 보이는 기준이다.**\n *\n * 도형 하나에 하나뿐이다 — 팔레트는 목록을 한 벌로 나눠 보여 주므로, 한 도형이 두 묶음에\n * 동시에 있으면 저작자가 같은 것을 두 번 만난다.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Classification code used to group figures in the palette. One per figure.' })\n category?: string\n\n /**\n * 태그. **여럿 붙는다.**\n *\n * 분류와 다른 일을 한다. 분류는 「이것이 무엇인가」를 한 번 정하는 것이고, 태그는 「어디에\n * 걸리는가」를 여러 갈래로 적는 것이다 — 컨베이어이면서 반출 구역의 것일 수 있다. 그래서\n * 분류로는 못 하는 찾기가 된다.\n *\n * `simple-json` 으로 담는다. 사내 선례가 그것이고(`ops-master` · `organization` ·\n * `personalization`), 드라이버마다 배열 타입이 다른 것을 피한다.\n */\n /* `simple-json` 과 `default: null` 은 사내 선례 그대로다 — board-template · attachment 가 같은 모양이다. */\n @Column('simple-json', { nullable: true, default: null })\n @Field(type => [String], { nullable: true, description: 'Free-form tags. A figure may carry several.' })\n tags?: string[]\n\n @Column({ nullable: true, default: 'draft' })\n @Field({ nullable: true, description: \"Lifecycle state — 'draft' figures do not appear in the board palette.\" })\n state?: 'draft' | 'released'\n\n /**\n * The figure asset JSON (`figure-asset-1`).\n *\n * `Board.model` 자리이지만 이름을 바꿨다 — 「씬 모델이 아니다」를 필드 이름이\n * 드러내야 한다.\n */\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'The figure asset JSON (figure-asset-1) authored by the modeller.' })\n source?: string\n\n // ── 파생값 — 저장하는 이유가 하나뿐이다 ──────────────────────────────────\n //\n // 셋 다 `source` 에서 계산된다. 그런데도 컬럼으로 두는 이유는 **목록 화면이\n // 정렬·필터를 해야** 하기 때문이다. JSON 을 파싱해 정렬할 수는 없다.\n //\n // 저장할 때 `figure-model` 로 계산해 채운다. **클라이언트가 준 값을 받지 않는다** —\n // 받으면 거짓이 들어오고, 목록이 실물과 다른 것을 보여 준다.\n\n /** 재활용 점수 0~100. `scoreOf()` 가 계산한다. */\n @Column({ type: 'float', nullable: true })\n @Field(type => Float, { nullable: true, description: 'Reuse score 0-100, computed from source on save.' })\n score?: number\n\n /** 삼각형 수. `costOf()` 가 계산한다. */\n @Column({ nullable: true })\n @Field(type => Int, { nullable: true, description: 'Triangle count, computed from source on save.' })\n triangles?: number\n\n /** 재질 묶음 수 — 인스턴스당 draw call 의 근거. */\n @Column({ nullable: true })\n @Field(type => Int, { nullable: true, description: 'Material group count — the basis of per-instance draw calls.' })\n groups?: number\n\n /** 기준정보 항목 정의. Figure 를 배치할 때 인스턴스가 채우는 자리. */\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'JSON definition of the master-data fields an instance of this figure carries.' })\n properties?: string\n\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'A base64 encoded thumbnail image of the figure.' })\n thumbnail?: string\n\n /**\n * 썸네일이 **썸네일로서** 마지막으로 갱신된 시각. `updatedAt` 과는 별개 도메인이다 —\n * 이름·설명만 고쳤을 때는 갱신되지 않는다. `Board` 와 같은 방식.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Timestamp of the last thumbnail generation. Separate lifecycle from updatedAt.' })\n thumbnailUpdatedAt?: Date\n\n @Column({ type: 'float', nullable: true, default: 0 })\n @Field(type => Float, { nullable: true, description: 'Sort order within a listing.' })\n sortOrder?: number\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Creation timestamp.' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'Last update timestamp.' })\n updatedAt?: Date\n\n @DeleteDateColumn()\n @Field({ nullable: true, description: 'Soft-delete timestamp.' })\n deletedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who created this figure.' })\n creator?: User\n\n @RelationId((figure: Figure) => figure.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who last updated this figure.' })\n updater?: User\n\n @RelationId((figure: Figure) => figure.updater)\n updaterId?: string\n}\n"]}
|
|
1
|
+
{"version":3,"file":"figure.js","sourceRoot":"","sources":["../../../server/service/figure/figure.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n Column,\n CreateDateColumn,\n DeleteDateColumn,\n Entity,\n Index,\n ManyToOne,\n PrimaryGeneratedColumn,\n RelationId,\n UpdateDateColumn\n} from 'typeorm'\nimport { Field, Float, ID, Int, ObjectType } from 'type-graphql'\nimport { GraphQLJSON } from 'graphql-scalars'\n\nimport { User } from '@things-factory/auth-base'\nimport { Domain, longTextColumn } from '@things-factory/shell'\n\n/**\n * Figure — 저작된 3D 컴포넌트 한 종류.\n *\n * `Board` 를 준용한다. 다른 점만 주석으로 적는다.\n *\n * ## 무엇을 담나 — 도형 자산이다, 씬 모델이 아니다\n *\n * 형식은 `@hatiolab/figure-model` 이 정한다(`figure-asset-1`). 씬 컴포넌트 트리를 담지 않는다.\n * 컴파일한 것도 저장하지 않는다 — 원본에서 파생되므로 소비하는 쪽이 커널로 컴파일한다. 저장하면 원본과 갈린다.\n *\n * 그래서 부품·움직임·자리 같은 것을 컬럼으로 두지 않는다 — 전부 `source` 안에 이미 있다. 두 벌이면 갈린다.\n *\n * 설계: `docs/design/figure-modules.md` §2\n */\n@Entity()\n@Index('ix_figure_1', (figure: Figure) => [figure.domain, figure.type], {\n unique: true,\n where: '\"deleted_at\" IS NULL'\n})\n@Index('ix_figure_2', (figure: Figure) => [figure.domain, figure.category])\n@ObjectType({ description: 'An authored 3D component type — its figure asset plus its metadata.' })\nexport class Figure {\n @PrimaryGeneratedColumn('uuid')\n @Field(type => ID, { nullable: true, description: 'Unique identifier for the figure.' })\n readonly id?: string\n\n /**\n * 발행된 판의 번호 — **발행할 때만 올라간다.**\n *\n * 저장 횟수가 아니다. 저작 중에는 몇 번을 고쳐 저장하든 그대로이고, `draft` 가 `released` 가\n * 되는 순간에만 하나 오른다. 소비처가 「몇 번째 판을 쓰고 있나」를 이 값으로 말한다.\n *\n * 한 번도 발행되지 않았으면 **0** 이다. 1 로 시작하면 아직 아무에게도 약속하지 않은 초안이\n * 첫 판인 것처럼 보인다.\n */\n @Column({ nullable: true, default: 0 })\n @Field(type => Int, {\n nullable: true,\n description: 'Published version. Raised when the figure is released, not when it is saved. 0 means never released.'\n })\n version?: number = 0\n\n @ManyToOne(type => Domain)\n @Field(type => Domain, { nullable: true, description: 'The domain this figure belongs to.' })\n domain?: Domain\n\n @RelationId((figure: Figure) => figure.domain)\n domainId?: string\n\n /**\n * 컴포넌트 타입 이름. **저장되는 식별자다.**\n *\n * 배치된 도면이 이 이름으로 타입을 찾는다. 바꾸면 그 도면은 타입을 못 찾아\n * **오류 없이 빈 화면**이 된다. 그래서 만들 때 정하고 잠근다 — 고칠 수 있는 것은\n * 표시 이름(`name`)뿐이다. 수정 리졸버가 이 필드를 받지 않는다.\n *\n * `Board.type`(main/sub/popup)과 뜻이 전혀 다르다. 혼동하지 않는다.\n */\n @Column()\n @Field({ description: 'Component type name. A stored identifier — unique per domain and immutable once created.' })\n type?: string\n\n @Column()\n @Field({ description: 'Display name shown to authors. Safe to rename.' })\n name?: string\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'A detailed description for the figure.' })\n description?: string\n\n /*\n 언어별 표시 이름(ADR-0104 결정 6). 없는 언어는 `name` 을 보인다. 식별자는 여전히 `type` 이다 — 이름은 몇 번을\n 바꿔도 도면이 가리키는 것이 달라지지 않는다.\n */\n @Column('simple-json', { nullable: true, default: null })\n @Field(type => GraphQLJSON, { nullable: true, description: 'Display names by language, e.g. { \"en\": \"...\", \"ko\": \"...\" }. A language not here shows `name`.' })\n names?: Record<string, string>\n\n /*\n 퇴역(ADR-0104 결정 6). 표시일 뿐이다 — 발행판은 지우지 않고 받는 쪽은 그대로 받는다. 무엇으로 대신하라는지는\n `supersededBy`(그 도메인의 type)가 말한다. 퇴역은 저장이 아니라 `setFigureDeprecation` 이 정하고, 발행을 풀지 않는다.\n */\n @Column({ nullable: true, default: false })\n @Field({ nullable: true, description: 'Retired: still released and still served, but not to be chosen for new work.' })\n deprecated?: boolean\n\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'The type to use instead of a retired figure.' })\n supersededBy?: string\n\n /**\n * 분류 하나. **팔레트에서 묶어 보이는 기준이다.**\n *\n * 도형 하나에 하나뿐이다 — 팔레트는 목록을 한 벌로 나눠 보여 주므로, 한 도형이 두 묶음에\n * 동시에 있으면 저작자가 같은 것을 두 번 만난다.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Classification code used to group figures in the palette. One per figure.' })\n category?: string\n\n /**\n * 태그. **여럿 붙는다.**\n *\n * 분류와 다른 일을 한다. 분류는 「이것이 무엇인가」를 한 번 정하는 것이고, 태그는 「어디에\n * 걸리는가」를 여러 갈래로 적는 것이다 — 컨베이어이면서 반출 구역의 것일 수 있다. 그래서\n * 분류로는 못 하는 찾기가 된다.\n *\n * `simple-json` 으로 담는다. 사내 선례가 그것이고(`ops-master` · `organization` ·\n * `personalization`), 드라이버마다 배열 타입이 다른 것을 피한다.\n */\n /* `simple-json` 과 `default: null` 은 사내 선례 그대로다 — board-template · attachment 가 같은 모양이다. */\n @Column('simple-json', { nullable: true, default: null })\n @Field(type => [String], { nullable: true, description: 'Free-form tags. A figure may carry several.' })\n tags?: string[]\n\n @Column({ nullable: true, default: 'draft' })\n @Field({ nullable: true, description: \"Lifecycle state — 'draft' figures do not appear in the board palette.\" })\n state?: 'draft' | 'released'\n\n /**\n * The figure asset JSON (`figure-asset-1`).\n *\n * `Board.model` 자리이지만 이름을 바꿨다 — 「씬 모델이 아니다」를 필드 이름이\n * 드러내야 한다.\n */\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'The figure asset JSON (figure-asset-1) authored by the modeller.' })\n source?: string\n\n // ── 파생값 — 저장하는 이유가 하나뿐이다 ──────────────────────────────────\n //\n // 셋 다 `source` 에서 계산된다. 그런데도 컬럼으로 두는 이유는 **목록 화면이\n // 정렬·필터를 해야** 하기 때문이다. JSON 을 파싱해 정렬할 수는 없다.\n //\n // 저장할 때 `figure-model` 로 계산해 채운다. **클라이언트가 준 값을 받지 않는다** —\n // 받으면 거짓이 들어오고, 목록이 실물과 다른 것을 보여 준다.\n\n /** 재활용 점수 0~100. `scoreOf()` 가 계산한다. */\n @Column({ type: 'float', nullable: true })\n @Field(type => Float, { nullable: true, description: 'Reuse score 0-100, computed from source on save.' })\n score?: number\n\n /** 삼각형 수. `costOf()` 가 계산한다. */\n @Column({ nullable: true })\n @Field(type => Int, { nullable: true, description: 'Triangle count, computed from source on save.' })\n triangles?: number\n\n /** 재질 묶음 수 — 인스턴스당 draw call 의 근거. */\n @Column({ nullable: true })\n @Field(type => Int, { nullable: true, description: 'Material group count — the basis of per-instance draw calls.' })\n groups?: number\n\n /** 기준정보 항목 정의. Figure 를 배치할 때 인스턴스가 채우는 자리. */\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'JSON definition of the master-data fields an instance of this figure carries.' })\n properties?: string\n\n @Column({ nullable: true, ...longTextColumn() })\n @Field({ nullable: true, description: 'A base64 encoded thumbnail image of the figure.' })\n thumbnail?: string\n\n /**\n * 썸네일이 **썸네일로서** 마지막으로 갱신된 시각. `updatedAt` 과는 별개 도메인이다 —\n * 이름·설명만 고쳤을 때는 갱신되지 않는다. `Board` 와 같은 방식.\n */\n @Column({ nullable: true })\n @Field({ nullable: true, description: 'Timestamp of the last thumbnail generation. Separate lifecycle from updatedAt.' })\n thumbnailUpdatedAt?: Date\n\n @Column({ type: 'float', nullable: true, default: 0 })\n @Field(type => Float, { nullable: true, description: 'Sort order within a listing.' })\n sortOrder?: number\n\n @CreateDateColumn()\n @Field({ nullable: true, description: 'Creation timestamp.' })\n createdAt?: Date\n\n @UpdateDateColumn()\n @Field({ nullable: true, description: 'Last update timestamp.' })\n updatedAt?: Date\n\n @DeleteDateColumn()\n @Field({ nullable: true, description: 'Soft-delete timestamp.' })\n deletedAt?: Date\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who created this figure.' })\n creator?: User\n\n @RelationId((figure: Figure) => figure.creator)\n creatorId?: string\n\n @ManyToOne(type => User, { nullable: true })\n @Field(type => User, { nullable: true, description: 'The user who last updated this figure.' })\n updater?: User\n\n @RelationId((figure: Figure) => figure.updater)\n updaterId?: string\n}\n"]}
|