@things-factory/figure-service 10.1.224 → 10.1.227

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/dist-server/routers/figure-thumbnail-router.js +1 -1
  2. package/dist-server/routers/figure-thumbnail-router.js.map +1 -1
  3. package/dist-server/service/figure/event-subscriber.js +5 -5
  4. package/dist-server/service/figure/event-subscriber.js.map +1 -1
  5. package/dist-server/service/figure/figure-format.js +3 -3
  6. package/dist-server/service/figure/figure-format.js.map +1 -1
  7. package/dist-server/service/figure/figure-history.d.ts +3 -3
  8. package/dist-server/service/figure/figure-history.js +3 -3
  9. package/dist-server/service/figure/figure-history.js.map +1 -1
  10. package/dist-server/service/figure/figure-mutation.d.ts +13 -13
  11. package/dist-server/service/figure/figure-mutation.js +23 -23
  12. package/dist-server/service/figure/figure-mutation.js.map +1 -1
  13. package/dist-server/service/figure/figure-query.d.ts +6 -6
  14. package/dist-server/service/figure/figure-query.js +7 -7
  15. package/dist-server/service/figure/figure-query.js.map +1 -1
  16. package/dist-server/service/figure/figure-rename.d.ts +6 -6
  17. package/dist-server/service/figure/figure-rename.js +2 -2
  18. package/dist-server/service/figure/figure-rename.js.map +1 -1
  19. package/dist-server/service/figure/figure-revert.js +1 -1
  20. package/dist-server/service/figure/figure-revert.js.map +1 -1
  21. package/dist-server/service/figure/figure-tools.js +2 -2
  22. package/dist-server/service/figure/figure-tools.js.map +1 -1
  23. package/dist-server/service/figure/figure-type.d.ts +1 -1
  24. package/dist-server/service/figure/figure-type.js +1 -1
  25. package/dist-server/service/figure/figure-type.js.map +1 -1
  26. package/dist-server/service/figure/figure.d.ts +3 -3
  27. package/dist-server/service/figure/figure.js +3 -3
  28. package/dist-server/service/figure/figure.js.map +1 -1
  29. package/dist-server/service/index.js +1 -1
  30. package/dist-server/service/index.js.map +1 -1
  31. package/dist-server/tsconfig.tsbuildinfo +1 -1
  32. package/package.json +8 -8
  33. package/server/routers/figure-thumbnail-router.ts +1 -1
  34. package/server/service/figure/event-subscriber.ts +5 -5
  35. package/server/service/figure/figure-blueprint-query.test.ts +3 -3
  36. package/server/service/figure/figure-format.test.ts +4 -4
  37. package/server/service/figure/figure-format.ts +3 -3
  38. package/server/service/figure/figure-history.ts +8 -8
  39. package/server/service/figure/figure-mutation.ts +23 -23
  40. package/server/service/figure/figure-query.ts +7 -7
  41. package/server/service/figure/figure-rename-db.test.ts +3 -3
  42. package/server/service/figure/figure-rename.test.ts +2 -2
  43. package/server/service/figure/figure-rename.ts +7 -7
  44. package/server/service/figure/figure-revert.ts +1 -1
  45. package/server/service/figure/figure-tools.test.ts +9 -9
  46. package/server/service/figure/figure-tools.ts +2 -2
  47. package/server/service/figure/figure-type.ts +3 -3
  48. package/server/service/figure/figure.ts +4 -4
  49. package/server/service/index.ts +1 -1
  50. package/translations/en.json +2 -2
  51. package/translations/ko.json +22 -22
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/figure-service",
3
- "version": "10.1.224",
3
+ "version": "10.1.227",
4
4
  "publishConfig": {
5
5
  "access": "public",
6
6
  "@things-factory:registry": "https://registry.npmjs.org"
@@ -25,18 +25,18 @@
25
25
  "test:templates": "node --test scripts/templates.test.mts"
26
26
  },
27
27
  "dependencies": {
28
- "@hatiolab/figure-model": "^0.12.0",
28
+ "@hatiolab/figure-model": "^0.12.1",
29
29
  "@operato/typeorm-history": "^10.0.0",
30
- "@things-factory/ai-client-base": "^10.1.223",
31
- "@things-factory/attachment-base": "^10.1.223",
32
- "@things-factory/auth-base": "^10.1.223",
30
+ "@things-factory/ai-client-base": "^10.1.227",
31
+ "@things-factory/attachment-base": "^10.1.227",
32
+ "@things-factory/auth-base": "^10.1.227",
33
33
  "@things-factory/env": "^10.1.149",
34
- "@things-factory/setting-base": "^10.1.223",
35
- "@things-factory/shell": "^10.1.208",
34
+ "@things-factory/setting-base": "^10.1.227",
35
+ "@things-factory/shell": "^10.1.227",
36
36
  "graphql-scalars": "^1.22.4",
37
37
  "graphql-upload": "^15.0.2",
38
38
  "jszip": "^3.10.1",
39
39
  "koa-router": "^7.4.0"
40
40
  },
41
- "gitHead": "7edcdca6fc9862973e99048812e22f2aa9b2f9c9"
41
+ "gitHead": "f66591e3864aab08a6fb93fb1fcf1c9de6b546ac"
42
42
  }
@@ -101,7 +101,7 @@ export async function sendFigureThumbnail(
101
101
  /*
102
102
  **개인 캐시만 허락한다.** 이 그림은 권한을 본 뒤에 내주는 것이므로 공용 캐시(프록시)에 남으면 안 된다 —
103
103
  attachment 의 공개 경로가 쓰는 `public` 을 따라 쓰지 않는다(판정 조건 1). 같은 내용은 같은 해시이므로 ETag 가
104
- 곧 내용이다. 부르는 쪽이 `?v=` 로 판을 가리므로 오래 두어도 낡은 그림이 남지 않는다.
104
+ 곧 내용이다. 부르는 쪽이 `?v=` 로 버전을 가리므로 오래 두어도 낡은 그림이 남지 않는다.
105
105
  */
106
106
  const ours = () => {
107
107
  context.type = picture.mimetype
@@ -6,17 +6,17 @@ import { Figure } from './figure.js'
6
6
  import { FigureHistory } from './figure-history.js'
7
7
 
8
8
  /**
9
- * 판본을 남긴다 — **발행된 저장에만.**
9
+ * 버전을 남긴다 — **발행된 저장에만.**
10
10
  *
11
11
  * `@operato/typeorm-history` 는 원래 모든 저장을 베낀다. 그런데 피규어는 저작 중에 수십 번 저장되고,
12
- * 그 전부를 남기면 판본 목록이 「내가 오늘 몇 번 눌렀나」가 된다. 사람이 판이라고 부르는 것은
12
+ * 그 전부를 남기면 버전 목록이 「내가 오늘 몇 번 눌렀나」가 된다. 사람이 버전이라고 부르는 것은
13
13
  * **발행한 것**이므로 그때만 베낀다. board 가 같은 규칙으로 돈다(`board-service` 의 같은 이름 파일).
14
14
  *
15
- * 발행판의 정본(`__releaseSource`)은 크기 범위를 적은 발행판 사본이다 — Figure 행에는 작성자가 좁힌 끝만 남는다.
15
+ * 발행 버전의 정본(`__releaseSource`)은 크기 범위를 적은 발행 버전 사본이다 — Figure 행에는 작성자가 좁힌 끝만 남는다.
16
16
  *
17
17
  * 발행 메모는 Figure 의 칸이 아니다. `releaseFigure` 가 저장할 엔티티에 `__releaseComment` 로 얹어
18
- * 두면 여기서 판본의 `comment` 로 옮긴다 — 메모는 그 판의 것이지 피규어의 것이 아니다. 정본 형식
19
- * (`__releaseFormat`), 잰 커널의 판(`__releaseKernel`, ADR-0109 C1), 직전 판에 견준 변경(`__releaseChanges`), 발행 때 잰 값(`__releaseMetrics`)과
18
+ * 두면 여기서 버전의 `comment` 로 옮긴다 — 메모는 그 버전의 것이지 피규어의 것이 아니다. 정본 형식
19
+ * (`__releaseFormat`), 잰 커널의 버전(`__releaseKernel`, ADR-0109 C1), 직전 버전에 견준 변경(`__releaseChanges`), 발행 때 잰 값(`__releaseMetrics`)과
20
20
  * 윗모습(`__releaseTopView`)도 같은 길로 옮긴다(ADR-0104).
21
21
  */
22
22
  /** What `releaseFigure` laid on the entity for this release, moved onto the history row. */
@@ -131,7 +131,7 @@ describe('figureBlueprint 질의 — 소비처(board, twin, things-scene)에 발
131
131
  expect(partsOf(result)).toEqual(['box-1'])
132
132
  })
133
133
 
134
- it('현재 저작 중(draft)이더라도 과거 발행판(FigureHistory)이 있으면 최신 발행판을 반환한다', async () => {
134
+ it('현재 저작 중(draft)이더라도 과거 발행 버전(FigureHistory)이 있으면 최신 발행 버전을 반환한다', async () => {
135
135
  const repo = dataSource!.getRepository(Figure)
136
136
  const historyRepo = dataSource!.getRepository(FigureHistory)
137
137
 
@@ -152,7 +152,7 @@ describe('figureBlueprint 질의 — 소비처(board, twin, things-scene)에 발
152
152
  domain: testDomain,
153
153
  originalId: figure.id,
154
154
  type: 'UPDATING_FIGURE',
155
- name: 'v1 발행판',
155
+ name: 'v1 발행 버전',
156
156
  state: 'released',
157
157
  version: 1,
158
158
  source: v1Source
@@ -162,7 +162,7 @@ describe('figureBlueprint 질의 — 소비처(board, twin, things-scene)에 발
162
162
  const result = await query.figureBlueprint('UPDATING_FIGURE', makeContext())
163
163
 
164
164
  expect(result).not.toBeNull()
165
- // 소비처는 수정 중인 초안(box-modified, size 200)이 아니라 기발행된 판(box-1, size 100)을 본다!
165
+ // 소비처는 수정 중인 초안(box-modified, size 200)이 아니라 기발행된 버전(box-1, size 100)을 본다!
166
166
  expect(partsOf(result)).toEqual(['box-1'])
167
167
  expect(widthOf(result, 'box-1')).toBe(100)
168
168
  })
@@ -20,9 +20,9 @@ function figureAsset(): FigureAsset {
20
20
  }
21
21
  const figureSource = () => serializeFigureAsset(figureAsset())
22
22
 
23
- describe('figure-format — 판을 알아보는 문', () => {
24
- describe('판은 자산이 적는다', () => {
25
- it('판을 안 적은 정본은 거절한다 — 생김새로 짐작하지 않는다', () => {
23
+ describe('figure-format — 버전을 알아보는 문', () => {
24
+ describe('버전은 자산이 적는다', () => {
25
+ it('버전을 안 적은 정본은 거절한다 — 생김새로 짐작하지 않는다', () => {
26
26
  for (const text of [JSON.stringify({ type: 'MIXER', parts: [] }), JSON.stringify({ version: 2, type: 'MIXER', parts: [] })]) {
27
27
  expect(() => parseSource(text)).toThrow(FigureSourceError)
28
28
  try {
@@ -280,7 +280,7 @@ describe('figure-format — 판을 알아보는 문', () => {
280
280
  })
281
281
 
282
282
  /* ADR-0104 decision 5: a release records its format and what changed against the last one, once, as it was then. */
283
- describe('발행이 스스로 남기는 것 — 형식과 직전 판에 견준 변경', () => {
283
+ describe('발행이 스스로 남기는 것 — 형식과 직전 버전에 견준 변경', () => {
284
284
  const wider = () => {
285
285
  let asset = createFigureAsset('Mixer')
286
286
  asset = addFigureBox(asset, { id: 'body', size: { x: 300, y: 100, z: 100 }, position: { x: 0, y: 50, z: 0 } })
@@ -107,7 +107,7 @@ function assertFormat(sourceJson: string): void {
107
107
  }
108
108
  if ((parsed as { version?: unknown } | null)?.version !== FIGURE_ASSET_VERSION)
109
109
  throw new FigureSourceError([
110
- { code: 'source-format-unknown', message: `정본의 판을 알 수 없다 — 피규어 자산은 version '${FIGURE_ASSET_VERSION}' 을 적는다`, at: 'version' }
110
+ { code: 'source-format-unknown', message: `정본의 버전을 알 수 없다 — 피규어 자산은 version '${FIGURE_ASSET_VERSION}' 을 적는다`, at: 'version' }
111
111
  ])
112
112
  }
113
113
 
@@ -195,7 +195,7 @@ function figureWording(violation: FigureViolation, say: Say): Pick<GateFinding,
195
195
  return {
196
196
  message: say(key('message'), { parts, axes, factor }, `At ${factor}x on ${axes}, ${parts} come away from the rest of the figure.`),
197
197
  why: say(key('why'), {}, 'A figure placed at another size shows those parts hanging in the air — to a person, it looks broken.'),
198
- how: say(key('how'), { parts }, `Fasten ${parts} to a face of the part they rest on, or press "fix here" under position in the responsive tab, so they stay put when the figure is resized.`)
198
+ how: say(key('how'), { parts }, `Fasten ${parts} to a face of the part they rest on, or press "fix here" under position in the size tab, so they stay put when the figure is resized.`)
199
199
  }
200
200
  }
201
201
  case 'SIZING_NOT_UNIFORM': {
@@ -207,7 +207,7 @@ function figureWording(violation: FigureViolation, say: Say): Pick<GateFinding,
207
207
  return {
208
208
  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.`),
209
209
  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.'),
210
- how: say(key('how'), { parts }, `Let ${parts} follow the figure's size ("in proportion" under position in the responsive tab), or remove their own fixed numbers.`)
210
+ how: say(key('how'), { parts }, `Let ${parts} follow the figure's size ("in proportion" under position in the size tab), or remove their own fixed numbers.`)
211
211
  }
212
212
  }
213
213
  }
@@ -14,16 +14,16 @@ import { Domain, longTextColumn } from '@things-factory/shell'
14
14
  import { Figure } from './figure.js'
15
15
 
16
16
  /**
17
- * 발행된 판 하나 — **발행할 때만 남는다.**
17
+ * 발행된 버전 하나 — **발행할 때만 남는다.**
18
18
  *
19
19
  * 저작 중 저장은 여기 오지 않는다. 스냅샷을 뜨는 subscriber 가 `state === 'released'` 인 저장에만
20
20
  * 움직인다(`event-subscriber.ts`) — board 가 같은 규칙으로 돈다.
21
21
  *
22
22
  * ## 왜 통째로 베끼나
23
23
  *
24
- * 판을 되세우려면 그때의 정본만으로는 모자란다. 이름·분류·그림·비용까지 함께 있어야 「그 판이
24
+ * 버전을 되세우려면 그때의 정본만으로는 모자란다. 이름·분류·그림·비용까지 함께 있어야 「그 버전이
25
25
  * 무엇이었나」를 보여 주고 되돌릴 수 있다. 파생값(점수·삼각형·묶음)도 같이 둔다 — 다시 계산하면
26
- * 형식이 바뀐 오늘의 값이 나오고, 그것은 그 판의 값이 아니다.
26
+ * 형식이 바뀐 오늘의 값이 나오고, 그것은 그 버전의 값이 아니다.
27
27
  */
28
28
  @Entity()
29
29
  @Index('ix_figure_history_0', (history: FigureHistory) => [history.originalId, history.version], { unique: true })
@@ -94,7 +94,7 @@ export class FigureHistory implements HistoryEntityInterface<Figure> {
94
94
  thumbnailHash?: string
95
95
 
96
96
  /*
97
- * 그때의 비용이다. 오늘 다시 계산하면 오늘의 형식으로 나온다 — 그 판을 설명하지 못한다.
97
+ * 그때의 비용이다. 오늘 다시 계산하면 오늘의 형식으로 나온다 — 그 버전을 설명하지 못한다.
98
98
  */
99
99
  @Column({ type: 'float', nullable: true })
100
100
  @Field(type => Float, { nullable: true, description: 'Reuse score as computed at this version.' })
@@ -113,8 +113,8 @@ export class FigureHistory implements HistoryEntityInterface<Figure> {
113
113
  comment?: string
114
114
 
115
115
  /*
116
- * 이 판의 정본 형식(`figure-asset-1`)과, 직전 판에 견준 변경(ADR-0104 결정 5). 발행할 때 한 번 정하고 다시
117
- * 계산하지 않는다 — 판을 고정해 쓰는 쪽은 다음 판으로 옮기기 전에 이것을 읽는다.
116
+ * 이 버전의 정본 형식(`figure-asset-1`)과, 직전 버전에 견준 변경(ADR-0104 결정 5). 발행할 때 한 번 정하고 다시
117
+ * 계산하지 않는다 — 버전을 고정해 쓰는 쪽은 다음 버전으로 옮기기 전에 이것을 읽는다.
118
118
  */
119
119
  @Column({ nullable: true })
120
120
  @Field({ nullable: true, description: 'The asset format this version was written in (figure-asset-1).' })
@@ -129,9 +129,9 @@ export class FigureHistory implements HistoryEntityInterface<Figure> {
129
129
  changes?: string
130
130
 
131
131
  /*
132
- * 이 판을 잰 커널의 판(figure-model `FIGURE_KERNEL_VERSION`). 점수 · 묶음 · metrics 는 그 커널의 규칙으로 센 값이다 —
132
+ * 이 버전을 잰 커널의 버전(figure-model `FIGURE_KERNEL_VERSION`). 점수 · 묶음 · metrics 는 그 커널의 규칙으로 센 값이다 —
133
133
  * 규칙이 바뀌어도 발행된 값을 다시 세서 덮지 않고(ADR-0109 C1), 읽는 쪽은 이 칸으로 「남긴 값」과 「지금 규칙의 값」을
134
- * 가른다. 이 칸이 생기기 전에 발행된 판은 비어 있다.
134
+ * 가른다. 이 칸이 생기기 전에 발행된 버전은 비어 있다.
135
135
  */
136
136
  @Column({ nullable: true })
137
137
  @Field({
@@ -245,7 +245,7 @@ export class FigureMutation {
245
245
  /*
246
246
  **그림만 바꾸면 발행이 풀리지 않는다.** 미리보기에서 사람이 돌려 놓은 각도로 찍은 그림이 그렇게 온다.
247
247
  그림은 발행이 약속하는 것이 아니다 — 발행본은 제 그림을 따로 갖고, 다음 발행이 이 그림을 가져간다.
248
- 판본 구독자를 거치지 않는다: 발행된 행의 저장을 판으로 베끼는데, 이것은 판이 아니다.
248
+ 버전 구독자를 거치지 않는다: 발행된 행의 저장을 버전으로 베끼는데, 이것은 버전이 아니다.
249
249
  */
250
250
  if (patch.thumbnail !== undefined && Object.keys(patch).every(key => key === 'thumbnail' || (patch as any)[key] === undefined)) {
251
251
  const picture = await pictureOf(tx, domain, user, patch.thumbnail, figure)
@@ -274,7 +274,7 @@ export class FigureMutation {
274
274
 
275
275
  발행된 뒤에는 이미 배치된 도면이 이 이름을 가리키고, 바꾸면 그 도면이 아무 오류 없이
276
276
  빈 자리가 된다. 발행된 적 없는 피규어는 가리키는 도면이 있을 수 없다 — 도면은 최신
277
- 발행판을 그리므로 그려질 자리가 없다.
277
+ 발행 버전을 그리므로 그려질 자리가 없다.
278
278
 
279
279
  행과 정본 둘 다 고친다. 정본 안에도 `type` 이 있어서 한쪽만 고치면 저장된 JSON 과
280
280
  행이 다른 이름을 말하고, 발행할 때 어느 쪽이 도면에 적히는지가 갈린다.
@@ -294,14 +294,14 @@ export class FigureMutation {
294
294
  }
295
295
 
296
296
  /*
297
- **판 번호는 여기서 손대지 않는다.** 저장은 저작이고, 판은 발행에서 생긴다(`releaseFigure`).
297
+ **버전 번호는 여기서 손대지 않는다.** 저장은 저작이고, 버전은 발행에서 생긴다(`releaseFigure`).
298
298
  board 의 `updateBoard` 도 같다 — 저장 경로에는 version 이 없다.
299
299
  */
300
300
  const saved = await repository.save({
301
301
  /*
302
302
  `domain` 을 명시로 넣는다 — 읽어 온 엔티티에는 관계가 안 실려 있다.
303
303
 
304
- 판본 스냅샷은 넘겨받은 엔티티를 베끼므로, 여기서 빠지면 판본의 도메인이 비고 그 판은
304
+ 버전 스냅샷은 넘겨받은 엔티티를 베끼므로, 여기서 빠지면 버전의 도메인이 비고 그 버전은
305
305
  도메인으로 거르는 조회에 **한 줄도 안 걸린다**(실제로 그랬다). board 의 저장들도 같은
306
306
  자리에서 domain 을 함께 넣는다.
307
307
  */
@@ -314,9 +314,9 @@ export class FigureMutation {
314
314
  /*
315
315
  **고치면 발행이 풀린다.**
316
316
 
317
- 발행은 「이 판을 써도 된다」는 약속이고, 그 뒤에 정본이 바뀌면 약속한 것과 배포된 것이
317
+ 발행은 「이 버전을 써도 된다」는 약속이고, 그 뒤에 정본이 바뀌면 약속한 것과 배포된 것이
318
318
  달라진다. 그래서 저장은 언제나 초안으로 되돌리고, 다시 내보내려면 발행을 한 번 더 한다
319
- (판 번호가 하나 오르고 판본이 하나 더 남는다). board 의 `updateBoard` 가 같은 한 줄을 쓴다.
319
+ (버전 번호가 하나 오르고 버전이 하나 더 남는다). board 의 `updateBoard` 가 같은 한 줄을 쓴다.
320
320
  */
321
321
  state: 'draft',
322
322
  ...(derived ?? {}),
@@ -354,21 +354,21 @@ export class FigureMutation {
354
354
  }
355
355
 
356
356
  /**
357
- * 발행한다 — **판이 생기는 유일한 자리.**
357
+ * 발행한다 — **버전이 생기는 유일한 자리.**
358
358
  *
359
359
  * ## 무엇이 일어나나
360
360
  *
361
- * `state` 가 `released` 가 되고, 판 번호가 하나 오르고, 그 순간의 피규어가 판본으로 남는다
361
+ * `state` 가 `released` 가 되고, 버전 번호가 하나 오르고, 그 순간의 피규어가 버전으로 남는다
362
362
  * (`FigureHistory` — 스냅샷은 구독자가 뜬다). 저작 중 저장은 이 셋 중 아무것도 하지 않는다.
363
363
  *
364
364
  * ## 왜 이미 발행된 것을 거절하나
365
365
  *
366
- * 발행은 소비처에게 하는 약속이다. 같은 판을 두 번 발행하면 무엇이 약속인지 흐려진다. 고쳐서
366
+ * 발행은 소비처에게 하는 약속이다. 같은 버전을 두 번 발행하면 무엇이 약속인지 흐려진다. 고쳐서
367
367
  * 다시 내려면 초안으로 되돌린 뒤 발행한다 — board 가 같은 규칙이다.
368
368
  *
369
- * ## 번호는 판본에서 센다
369
+ * ## 번호는 버전에서 센다
370
370
  *
371
- * 피규어의 현재 번호가 아니라 **판본의 최대 번호 + 1** 이다. 되돌리기로 옛 판이 현재가 되어도
371
+ * 피규어의 현재 번호가 아니라 **버전의 최대 번호 + 1** 이다. 되돌리기로 옛 버전이 현재가 되어도
372
372
  * 다음 발행이 이미 쓴 번호를 다시 쓰지 않는다.
373
373
  *
374
374
  * ## 게이트를 통과해야 한다
@@ -409,8 +409,8 @@ export class FigureMutation {
409
409
  막는 이유는 사유와 함께 낸다. 「발행할 수 없습니다」로 뭉치면 무엇을 고쳐야 하는지 모른다.
410
410
  */
411
411
  /*
412
- 직전 발행판을 먼저 꺼낸다. 판 번호를 세는 데도 쓰고, **약속을 깨는 발행인가**를 견주는 데도
413
- 쓴다(ADR-0063 결정 3) — 도면은 type 만 적고 늘 최신 발행판을 그리므로, 다시 발행하는 것은
412
+ 직전 발행 버전을 먼저 꺼낸다. 버전 번호를 세는 데도 쓰고, **약속을 깨는 발행인가**를 견주는 데도
413
+ 쓴다(ADR-0063 결정 3) — 도면은 type 만 적고 늘 최신 발행 버전을 그리므로, 다시 발행하는 것은
414
414
  그 type 을 놓아 둔 모든 도면에게 같은 약속을 다시 하는 일이다.
415
415
  */
416
416
  const released = await historyRepository
@@ -437,7 +437,7 @@ export class FigureMutation {
437
437
  /*
438
438
  `domain` 을 명시로 넣는다 — 읽어 온 엔티티에는 관계가 안 실려 있다.
439
439
 
440
- 판본 스냅샷은 넘겨받은 엔티티를 베끼므로, 여기서 빠지면 판본의 도메인이 비고 그 판은
440
+ 버전 스냅샷은 넘겨받은 엔티티를 베끼므로, 여기서 빠지면 버전의 도메인이 비고 그 버전은
441
441
  도메인으로 거르는 조회에 **한 줄도 안 걸린다**(실제로 그랬다). board 의 저장들도 같은
442
442
  자리에서 domain 을 함께 넣는다.
443
443
  */
@@ -446,7 +446,7 @@ export class FigureMutation {
446
446
  version: nextVersion,
447
447
  state: 'released',
448
448
  updater: user,
449
- /* 판본 구독자가 이것들을 판본의 comment · assetFormat · kernelVersion · changes 로 옮긴다. Figure 의 칸이 아니다. */
449
+ /* 버전 구독자가 이것들을 버전의 comment · assetFormat · kernelVersion · changes 로 옮긴다. Figure 의 칸이 아니다. */
450
450
  /* The release's own copy, its size range written down; the figure keeps the author's (ADR-0087 decision 6). */
451
451
  __releaseSource: record.source,
452
452
  __releaseComment: comment ?? null,
@@ -459,22 +459,22 @@ export class FigureMutation {
459
459
  }
460
460
 
461
461
  /**
462
- * 옛 판으로 되돌린다.
462
+ * 옛 버전으로 되돌린다.
463
463
  *
464
464
  * ## 무엇이 돌아오나
465
465
  *
466
- * 그 판의 **정본과 속성 정의, 그리고 그림**이다. 이름·설명·분류는 그대로 둔다 — 그것들은 언제든
466
+ * 그 버전의 **정본과 속성 정의, 그리고 그림**이다. 이름·설명·분류는 그대로 둔다 — 그것들은 언제든
467
467
  * 바꿔도 안전한 카탈로그의 말이고, 되돌리기가 개명까지 되돌리면 사람이 시키지 않은 일을 한다.
468
468
  *
469
469
  * ## 되돌려도 발행은 아니다
470
470
  *
471
- * 초안으로 돌아온다. 다시 내보내려면 발행을 한 번 더 하고, 그때 판 번호는 **이미 쓴 번호 다음**을
472
- * 받는다 — 3판을 되살렸다고 다시 3판이 되지 않는다. board 도 같다.
471
+ * 초안으로 돌아온다. 다시 내보내려면 발행을 한 번 더 하고, 그때 버전 번호는 **이미 쓴 번호 다음**을
472
+ * 받는다 — 버전 3을 되살렸다고 다시 버전 3이 되지 않는다. board 도 같다.
473
473
  *
474
474
  * ## 비용은 다시 잰다
475
475
  *
476
- * 판본이 든 점수·삼각형은 **그때의 형식**으로 잰 값이다. 지금 이 피규어가 그 내용이 되었으므로
477
- * 오늘 기준으로 다시 계산한다. 옛 값은 판본에 그대로 남아 있다.
476
+ * 버전이 든 점수·삼각형은 **그때의 형식**으로 잰 값이다. 지금 이 피규어가 그 내용이 되었으므로
477
+ * 오늘 기준으로 다시 계산한다. 옛 값은 버전에 그대로 남아 있다.
478
478
  */
479
479
  @Directive('@transaction')
480
480
  @Directive('@privilege(category: "figure", privilege: "mutation", domainOwnerGranted: true)')
@@ -539,8 +539,8 @@ export class FigureMutation {
539
539
  /**
540
540
  * 퇴역시키거나 되살린다(ADR-0104 결정 6).
541
541
  *
542
- * 표시일 뿐이다. 발행판은 그대로 남고 받는 쪽은 그대로 받는다 — 발행판은 지우지 않는다. 그래서 **발행을 풀지 않는다**:
543
- * 행을 엔티티로 저장하지 않고 질의로 고친다. 엔티티로 저장하면 발행된 행이라 판본 구독자가 같은 번호로 판본을 또
542
+ * 표시일 뿐이다. 발행 버전은 그대로 남고 받는 쪽은 그대로 받는다 — 발행 버전은 지우지 않는다. 그래서 **발행을 풀지 않는다**:
543
+ * 행을 엔티티로 저장하지 않고 질의로 고친다. 엔티티로 저장하면 발행된 행이라 버전 구독자가 같은 번호로 버전을 또
544
544
  * 뜬다. 대신 쓸 것(`supersededBy`)은 같은 도메인(또는 상위)에 있는 다른 type 이어야 한다. 퇴역은 소유 도메인의 figure 만 한다.
545
545
  */
546
546
  @Directive('@transaction')
@@ -94,9 +94,9 @@ export class FigureQuery {
94
94
  * `state` 로 걸러지지 않는다 — `draft` 인 Figure 의 이름도 이미 점유된 것이다.
95
95
  */
96
96
  /**
97
- * 발행된 판들 — 최근 것부터.
97
+ * 발행된 버전들 — 최근 것부터.
98
98
  *
99
- * 저작 중 저장은 여기 없다. 판본은 발행에서만 생기므로(`releaseFigure`), 이 목록이 곧
99
+ * 저작 중 저장은 여기 없다. 버전은 발행에서만 생기므로(`releaseFigure`), 이 목록이 곧
100
100
  * 「이 피규어가 몇 번 약속되었나」다.
101
101
  */
102
102
  @Directive('@privilege(category: "figure", privilege: "query", domainOwnerGranted: true)')
@@ -115,9 +115,9 @@ export class FigureQuery {
115
115
  }
116
116
 
117
117
  /**
118
- * 지금 소비처가 쓰는 판.
118
+ * 지금 소비처가 쓰는 버전.
119
119
  *
120
- * 피규어의 현재 정본은 저작 중일 수 있다(초안). 배치된 것이 보는 것은 **마지막으로 발행된 판**이고,
120
+ * 피규어의 현재 정본은 저작 중일 수 있다(초안). 배치된 것이 보는 것은 **마지막으로 발행된 버전**이고,
121
121
  * 그것을 이 자리가 답한다.
122
122
  */
123
123
  /** What a kept GLB holds, read again from its bytes (ADR-0129): the modeller asks when it reopens a figure. */
@@ -185,7 +185,7 @@ export class FigureQuery {
185
185
  }
186
186
 
187
187
  /*
188
- **화면이 발행 문과 같은 것을 본다.** 직전 발행판을 여기서도 함께 넘기지 않으면, 저작 화면은
188
+ **화면이 발행 문과 같은 것을 본다.** 직전 발행 버전을 여기서도 함께 넘기지 않으면, 저작 화면은
189
189
  조용한데 발행을 누른 순간 계약 위반으로 막힌다 — 그때는 이미 열 군데를 고친 뒤다.
190
190
  */
191
191
  const released = await getRepository(FigureHistory)
@@ -260,10 +260,10 @@ export class FigureQuery {
260
260
  * `{ type, asset }`. 그리는 쪽(`registerFigure`)이 커널로 컴파일한다.
261
261
  *
262
262
  * ## 규칙
263
- * 1. 소비처는 초안(draft)을 볼 수 없다 — **반드시 발행된(released) 판만 전달**한다.
263
+ * 1. 소비처는 초안(draft)을 볼 수 없다 — **반드시 발행된(released) 버전만 전달**한다.
264
264
  * 2. 현재 Figure가 released 상태이면 현재 source를 넘긴다.
265
265
  * 3. 현재 Figure가 저작 중(draft)이더라도 이전에 발행된 이력(FigureHistory)이 있으면
266
- * 가장 최근의 released 판본을 넘긴다.
266
+ * 가장 최근의 released 버전을 넘긴다.
267
267
  * 4. 한 번도 발행된 적 없는 초안 자산이거나 존재하지 않는 타입인 경우 null을 반환하여
268
268
  * 미완성 자산이 씬 화면에 유출되는 것을 엄격히 차단한다.
269
269
  * 5. 도메인 상속 시 자식 도메인의 타입이 부모 도메인의 동일 타입을 항상 오버라이드한다.
@@ -2,7 +2,7 @@
2
2
  * 이름을 바꾸기 전에 읽는 사실 셋 — **sqlite 를 실제로 들고** 확인한다.
3
3
  *
4
4
  * 규칙(`renameDraftType`)은 사실을 받아 판단하므로 DB 없이 시험한다. 그런데 그 사실을 읽는
5
- * 질의가 틀리면 저작자에게는 저장 실패로만 보인다. 실제로 그랬다 — 판본을 `figure: { id }` 로
5
+ * 질의가 틀리면 저작자에게는 저장 실패로만 보인다. 실제로 그랬다 — 버전을 `figure: { id }` 로
6
6
  * 물었고 `FigureHistory` 는 관계 칸이 아니라 `originalId` 로 가리킨다. TypeORM 이 「그런 속성이
7
7
  * 없다」로 던졌고, 순수 시험은 전부 초록이었다.
8
8
  *
@@ -107,13 +107,13 @@ const facts = async (figure: any, wanted: string) =>
107
107
  )
108
108
 
109
109
  describe('이름을 바꾸기 전에 읽는 사실', () => {
110
- it('★ 판본 질의가 실제로 돈다 — 칸 이름이 틀리면 여기서 던진다', async () => {
110
+ it('★ 버전 질의가 실제로 돈다 — 칸 이름이 틀리면 여기서 던진다', async () => {
111
111
  const figure = await seedFigure()
112
112
 
113
113
  expect(await facts(figure, 'robot-arm')).toEqual({ version: 0, hasHistory: false, takenByAnother: false, releasedBefore: false })
114
114
  })
115
115
 
116
- it('★ 판본이 있으면 그것을 읽어 온다', async () => {
116
+ it('★ 버전이 있으면 그것을 읽어 온다', async () => {
117
117
  const figure = await seedFigure()
118
118
  await dataSource!.getRepository(FigureHistory).save({
119
119
  originalId: figure.id,
@@ -39,11 +39,11 @@ describe('초안의 type 고치기', () => {
39
39
  expect(() => renameDraftType(draft(), 'Robot_Arm', never)).toThrow(expect.objectContaining({ code: 'malformed-type' }))
40
40
  })
41
41
 
42
- it('★ 한 번이라도 발행됐으면 거절한다 — 판 번호로', () => {
42
+ it('★ 한 번이라도 발행됐으면 거절한다 — 버전 번호로', () => {
43
43
  expect(() => renameDraftType(draft(), 'robot-arm', { ...never, version: 1 })).toThrow(FigureRenameRefused)
44
44
  })
45
45
 
46
- it('★ 판 번호가 도로 0 이어도 이력이 있으면 거절한다 — 되돌리기가 그 자리를 만든다', () => {
46
+ it('★ 버전 번호가 도로 0 이어도 이력이 있으면 거절한다 — 되돌리기가 그 자리를 만든다', () => {
47
47
  try {
48
48
  renameDraftType(draft(), 'robot-arm', { ...never, hasHistory: true })
49
49
  throw new Error('거절하지 않았다')
@@ -6,7 +6,7 @@ import { TYPE_LENGTH, TYPE_PATTERN } from '@hatiolab/figure-model'
6
6
  * ## 왜 발행 전에만인가
7
7
  *
8
8
  * `type` 은 도면에 적히는 이름이다. 도면은 `{ type, left, top, width, height }` 만 갖고 늘 최신
9
- * 발행판을 그리므로, 발행된 피규어의 이름을 바꾸면 이미 배치된 도면이 아무 오류 없이 빈 자리가
9
+ * 발행 버전을 그리므로, 발행된 피규어의 이름을 바꾸면 이미 배치된 도면이 아무 오류 없이 빈 자리가
10
10
  * 된다. 한 번도 발행되지 않은 피규어는 그려질 자리가 없으니 가리키는 도면도 있을 수 없다.
11
11
  *
12
12
  * ## 왜 열어야 했나
@@ -17,22 +17,22 @@ import { TYPE_LENGTH, TYPE_PATTERN } from '@hatiolab/figure-model'
17
17
  *
18
18
  * ## 셈은 여기, 질의는 부르는 쪽
19
19
  *
20
- * 이 파일은 저장소를 모른다 — 판 번호 · 이력 유무 · 같은 이름의 주인을 **사실로 받는다.**
20
+ * 이 파일은 저장소를 모른다 — 버전 번호 · 이력 유무 · 같은 이름의 주인을 **사실로 받는다.**
21
21
  * 그래야 규칙을 DB 없이 시험한다. 문(`figure-mutation.ts`)이 그 셋을 읽어 넘긴다.
22
22
  */
23
23
 
24
24
 
25
25
  /** 이름을 바꿀 때 알아야 하는 사실. 부르는 쪽이 저장소에서 읽어 온다. */
26
26
  export interface RenameFacts {
27
- /** 발행 판 번호. 0 이면 한 번도 발행되지 않았다. */
27
+ /** 발행 버전 번호. 0 이면 한 번도 발행되지 않았다. */
28
28
  version?: number
29
- /** 판본이 하나라도 있나. 되돌리기로 판 번호가 도로 낮아져도 이력은 남는다. */
29
+ /** 버전이 하나라도 있나. 되돌리기로 버전 번호가 도로 낮아져도 이력은 남는다. */
30
30
  hasHistory: boolean
31
31
  /** 같은 도메인에서 그 이름을 이미 쓰는 **다른** 피규어가 있나. */
32
32
  takenByAnother: boolean
33
33
  /**
34
34
  * 같은 도메인에서 그 이름으로 발행한 뒤 지워진 피규어가 있나. 발행한 피규어를 지울 수 없게 되기(G4) 전에 지워진 것이다.
35
- * 그 이름을 다시 쓰면 판 번호가 1부터 다시 매겨져 같은 `ns/type@n` 이 다른 내용을 가리킨다.
35
+ * 그 이름을 다시 쓰면 버전 번호가 1부터 다시 매겨져 같은 `ns/type@n` 이 다른 내용을 가리킨다.
36
36
  */
37
37
  releasedBefore?: boolean
38
38
  }
@@ -57,7 +57,7 @@ export async function typeReleasedBefore(
57
57
 
58
58
  /** Said when a type was released and deleted before: a new figure may not take it. */
59
59
  export const releasedBeforeMessage = (type: string) =>
60
- `type 「${type}」 는 이 도메인에서 발행한 뒤 지운 피규어의 이름이다 — 다시 쓰면 같은 판 번호가 다른 내용을 가리키므로 다른 이름을 고른다`
60
+ `type 「${type}」 는 이 도메인에서 발행한 뒤 지운 피규어의 이름이다 — 다시 쓰면 같은 버전 번호가 다른 내용을 가리키므로 다른 이름을 고른다`
61
61
 
62
62
  export class FigureRenameRefused extends Error {
63
63
  constructor(
@@ -120,7 +120,7 @@ export function renameDraftType(
120
120
  * 사실 셋을 저장소에서 읽는다.
121
121
  *
122
122
  * 규칙에서 떼어 둔 자리이지만 **질의의 모양이 틀리면 저작자에게는 저장 실패로만 보인다.**
123
- * 실제로 그랬다 — 판본을 `figure: { id }` 로 물었고, `FigureHistory` 는 관계 칸이 아니라
123
+ * 실제로 그랬다 — 버전을 `figure: { id }` 로 물었고, `FigureHistory` 는 관계 칸이 아니라
124
124
  * `originalId` 로 가리킨다. TypeORM 이 「그런 속성이 없다」로 던졌고 화면에는 영문 오류 한 줄이
125
125
  * 떴다. 그래서 이 함수를 내보내 sqlite 를 들고 왕복까지 본다.
126
126
  */
@@ -75,7 +75,7 @@ export async function revertKeepingDraft(
75
75
  const history = await tx.getRepository(FigureHistory).findOne({
76
76
  where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean) as string[]) }, originalId: request.id, version: request.version }
77
77
  })
78
- if (!history) throw refused('FIGURE_VERSION_NOT_FOUND', `Figure '${figure.type}' 에 ${request.version} 판이 없습니다.`)
78
+ if (!history) throw refused('FIGURE_VERSION_NOT_FOUND', `Figure '${figure.type}' 에 ${request.version} 버전이 없습니다.`)
79
79
  /* The format is checked again: an old version may break today's rules, and is not let in quietly. */
80
80
  const { source, derived, violations } = parseSource(draftSourceOfRelease(history.source!))
81
81
 
@@ -8,7 +8,7 @@
8
8
  * · guidance → 도구 호출 끊기면 → 「후보를 만들었습니다」라고만 쓰고 화면에는 아무것도 없다
9
9
  * · hostContext.figureId → 대상 끊기면 → 화면에 피규어가 떠 있는데 「어느 피규어입니까」를 되묻는다
10
10
  * · 도메인 확인 → 대상 끊기면 → 모델이 넘긴 id 로 남의 테넌트를 읽는다
11
- * · hostContext.context·revision → 제안 끊기면 → 모델러가 모델이 본 판이 아닌 판에 명령을 적용한다
11
+ * · hostContext.context·revision → 제안 끊기면 → 모델러가 모델이 본 버전이 아닌 버전에 명령을 적용한다
12
12
  *
13
13
  * 실제 모델은 부르지 않는다. 여기서 볼 것은 모델의 솜씨가 아니라 **우리 배선**이다.
14
14
  */
@@ -410,8 +410,8 @@ describe('목록이 잘릴 때', () => {
410
410
  })
411
411
 
412
412
  /*
413
- 제안은 모델러의 명령 목록이다(ADR-0094). 고치는 제안은 모델러가 모델이 본 판 위에 한 단계로 적용하므로, 고칠 수
414
- 있는 것은 모델러에 열린 피규어뿐이고 그 판(context · revision)을 문맥이 싣고 와야 한다.
413
+ 제안은 모델러의 명령 목록이다(ADR-0094). 고치는 제안은 모델러가 모델이 본 버전 위에 한 단계로 적용하므로, 고칠 수
414
+ 있는 것은 모델러에 열린 피규어뿐이고 그 버전(context · revision)을 문맥이 싣고 와야 한다.
415
415
  */
416
416
  const figureDraft = () => {
417
417
  const model = require('@hatiolab/figure-model')
@@ -422,7 +422,7 @@ const figureDraft = () => {
422
422
  const modeller = (over: any = {}) => ({ figureId: 'fig-1', draftSource: figureDraft(), context: 'ctx-7', revision: 4, ...over })
423
423
 
424
424
  describe('제안을 요청할 때', () => {
425
- it('열린 피규어를 고치면 그 초안이 제안기에 가고, 모델러가 적용할 판이 함께 돌아온다', async () => {
425
+ it('열린 피규어를 고치면 그 초안이 제안기에 가고, 모델러가 적용할 버전이 함께 돌아온다', async () => {
426
426
  const out = await toolNamed('proposeFigureCandidate').builder({ prompt: '다리를 길게' }, ctx(modeller()))
427
427
  expect(proposed[0].base.name).toBe('Probe')
428
428
  expect(proposed[0].base.version).toBe('figure-asset-1')
@@ -432,7 +432,7 @@ describe('제안을 요청할 때', () => {
432
432
  expect(out.create).toBe(false)
433
433
  })
434
434
 
435
- it('판을 모르는 문맥에서는 고치는 제안을 내지 않는다 — 다른 판에 적용되지 않게', async () => {
435
+ it('버전을 모르는 문맥에서는 고치는 제안을 내지 않는다 — 다른 버전에 적용되지 않게', async () => {
436
436
  const out = await toolNamed('proposeFigureCandidate').builder({ prompt: '다리를 길게' }, ctx(modeller({ revision: undefined })))
437
437
  expect(out.error).toBe('FIGURE_NOT_OPEN')
438
438
  expect(proposed).toHaveLength(0)
@@ -614,7 +614,7 @@ describe('피규어가 모델러에 열려 있을 때', () => {
614
614
  seen on (ADR-0097 §5.6 item 5). The model hears it only through a read tool (ADR-0061 decision 3), so a tool that
615
615
  drops it leaves the model guessing which part was meant.
616
616
  */
617
- it('선택한 부품과 시험 중인 값을 같은 판에서 본 것일 때 함께 읽는다', async () => {
617
+ it('선택한 부품과 시험 중인 값을 같은 버전에서 본 것일 때 함께 읽는다', async () => {
618
618
  const host = modeller({
619
619
  selection: { part: 'body', context: 'ctx-7', revision: 4 },
620
620
  trying: { clips: { lift: 0.5 }, controls: { height: 300 }, context: 'ctx-7', revision: 4 }
@@ -624,7 +624,7 @@ describe('피규어가 모델러에 열려 있을 때', () => {
624
624
  expect(got.trying).toEqual({ clips: { lift: 0.5 }, controls: { height: 300 } })
625
625
  })
626
626
 
627
- it('다른 판에서 본 선택이나 초안에 없는 부품은 말하지 않는다 — 없는 부품을 가리키지 않게', async () => {
627
+ it('다른 버전에서 본 선택이나 초안에 없는 부품은 말하지 않는다 — 없는 부품을 가리키지 않게', async () => {
628
628
  const stale = await toolNamed('getFigureSource').builder({}, ctx(modeller({ selection: { part: 'body', context: 'ctx-7', revision: 3 } })))
629
629
  const missing = await toolNamed('getFigureSource').builder({}, ctx(modeller({ selection: { part: 'arm', context: 'ctx-7', revision: 4 } })))
630
630
  expect(stale.selection).toBeUndefined()
@@ -753,7 +753,7 @@ describe('피규어가 한 번에 보일 만큼보다 클 때', () => {
753
753
  expect(got.findings[0]).toEqual(findings[0])
754
754
  })
755
755
 
756
- it('고치는 제안에 고른 부품이 제안기까지 가고, 판은 그대로 돌아온다', async () => {
756
+ it('고치는 제안에 고른 부품이 제안기까지 가고, 버전은 그대로 돌아온다', async () => {
757
757
  const out = await toolNamed('proposeFigureCandidate').builder(
758
758
  { prompt: '3단을 빨갛게', parts: ['shelf-3'], sections: ['/palette', 7] },
759
759
  ctx(modeller({ draftSource: over }))
@@ -791,7 +791,7 @@ describe('저장 전 피규어', () => {
791
791
  expect(got).toMatchObject({ blocked: false, draft: true })
792
792
  })
793
793
 
794
- it('★ 고치는 제안은 그 초안 위에, 모델러가 적용할 판과 함께 낸다', async () => {
794
+ it('★ 고치는 제안은 그 초안 위에, 모델러가 적용할 버전과 함께 낸다', async () => {
795
795
  const out = await toolNamed('proposeFigureCandidate').builder({ prompt: '이 부품을 더 크게' }, ctx(unsaved({ selection: { part: 'body', context: 'ctx-7', revision: 4 } })))
796
796
  expect(proposed[0].base.name).toBe('Probe')
797
797
  expect(proposed[0].focus).toEqual({ selection: { part: 'body' } })
@@ -471,8 +471,8 @@ function figureToolSpecs(): ToolSpec[] {
471
471
  모델이 `create` 를 켜면 만드는 것이다. 이것을 모델의 짐작에 맡기면 열려 있는 피규어를 덮어쓰는
472
472
  후보가 온다.
473
473
 
474
- 고치는 제안은 모델러가 **요청 당시의 판(context · revision)** 위에 한 단계로 적용한다(ADR-0094).
475
- 그래서 고칠 수 있는 것은 모델러에 열린 피규어뿐이고, 그 판을 문맥이 함께 실어 와야 한다.
474
+ 고치는 제안은 모델러가 **요청 당시의 버전(context · revision)** 위에 한 단계로 적용한다(ADR-0094).
475
+ 그래서 고칠 수 있는 것은 모델러에 열린 피규어뿐이고, 그 버전을 문맥이 함께 실어 와야 한다.
476
476
  */
477
477
  const host = ctx?.host
478
478
  const create = args?.create === true || args?.figureId === null
@@ -48,7 +48,7 @@ export class NewFigure {
48
48
  *
49
49
  * `type` 은 **한 번도 발행되지 않은 초안에서만** 바뀐다(ADR-0063 결정 4). 저장되는 식별자라
50
50
  * 발행된 뒤에 바꾸면 이미 배치된 보드가 타입을 못 찾아 오류 없이 빈 화면이 된다. 발행 전에는
51
- * 그 피규어를 가리키는 도면이 있을 수 없다 — 도면은 최신 발행판을 그리므로 발행된 적 없는
51
+ * 그 피규어를 가리키는 도면이 있을 수 없다 — 도면은 최신 발행 버전을 그리므로 발행된 적 없는
52
52
  * 피규어는 그려질 자리가 없다.
53
53
  *
54
54
  * 닫아 두었더니 저작자가 이름을 한 번도 정하지 못했다. 새 Figure 에는 기계가 지은 이름이
@@ -88,8 +88,8 @@ export class FigurePatch {
88
88
  /*
89
89
  `state` 는 여기 없다 — **상태는 저장이 정하지 않는다.**
90
90
 
91
- 발행은 `releaseFigure` 가 한다. 저장으로 상태를 바꿀 수 있게 두면 발행된 판을 덮어쓰면서 같은
92
- 판 번호로 판본을 또 뜨게 되고(유니크 충돌), 무엇이 약속된 판인지도 흐려진다. board 도 같다.
91
+ 발행은 `releaseFigure` 가 한다. 저장으로 상태를 바꿀 수 있게 두면 발행된 버전을 덮어쓰면서 같은
92
+ 버전 번호로 버전을 또 뜨게 되고(유니크 충돌), 무엇이 약속된 버전인지도 흐려진다. board 도 같다.
93
93
  */
94
94
 
95
95
  @Field({ nullable: true, description: 'A base64 encoded thumbnail image.' })