@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.
- package/dist-server/routers/figure-thumbnail-router.js +1 -1
- package/dist-server/routers/figure-thumbnail-router.js.map +1 -1
- package/dist-server/service/figure/event-subscriber.js +5 -5
- package/dist-server/service/figure/event-subscriber.js.map +1 -1
- package/dist-server/service/figure/figure-format.js +3 -3
- package/dist-server/service/figure/figure-format.js.map +1 -1
- package/dist-server/service/figure/figure-history.d.ts +3 -3
- package/dist-server/service/figure/figure-history.js +3 -3
- package/dist-server/service/figure/figure-history.js.map +1 -1
- package/dist-server/service/figure/figure-mutation.d.ts +13 -13
- package/dist-server/service/figure/figure-mutation.js +23 -23
- package/dist-server/service/figure/figure-mutation.js.map +1 -1
- package/dist-server/service/figure/figure-query.d.ts +6 -6
- package/dist-server/service/figure/figure-query.js +7 -7
- package/dist-server/service/figure/figure-query.js.map +1 -1
- package/dist-server/service/figure/figure-rename.d.ts +6 -6
- package/dist-server/service/figure/figure-rename.js +2 -2
- package/dist-server/service/figure/figure-rename.js.map +1 -1
- package/dist-server/service/figure/figure-revert.js +1 -1
- package/dist-server/service/figure/figure-revert.js.map +1 -1
- package/dist-server/service/figure/figure-tools.js +2 -2
- package/dist-server/service/figure/figure-tools.js.map +1 -1
- package/dist-server/service/figure/figure-type.d.ts +1 -1
- package/dist-server/service/figure/figure-type.js +1 -1
- package/dist-server/service/figure/figure-type.js.map +1 -1
- package/dist-server/service/figure/figure.d.ts +3 -3
- package/dist-server/service/figure/figure.js +3 -3
- package/dist-server/service/figure/figure.js.map +1 -1
- package/dist-server/service/index.js +1 -1
- package/dist-server/service/index.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +8 -8
- package/server/routers/figure-thumbnail-router.ts +1 -1
- package/server/service/figure/event-subscriber.ts +5 -5
- package/server/service/figure/figure-blueprint-query.test.ts +3 -3
- package/server/service/figure/figure-format.test.ts +4 -4
- package/server/service/figure/figure-format.ts +3 -3
- package/server/service/figure/figure-history.ts +8 -8
- package/server/service/figure/figure-mutation.ts +23 -23
- package/server/service/figure/figure-query.ts +7 -7
- package/server/service/figure/figure-rename-db.test.ts +3 -3
- package/server/service/figure/figure-rename.test.ts +2 -2
- package/server/service/figure/figure-rename.ts +7 -7
- package/server/service/figure/figure-revert.ts +1 -1
- package/server/service/figure/figure-tools.test.ts +9 -9
- package/server/service/figure/figure-tools.ts +2 -2
- package/server/service/figure/figure-type.ts +3 -3
- package/server/service/figure/figure.ts +4 -4
- package/server/service/index.ts +1 -1
- package/translations/en.json +2 -2
- 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.
|
|
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.
|
|
28
|
+
"@hatiolab/figure-model": "^0.12.1",
|
|
29
29
|
"@operato/typeorm-history": "^10.0.0",
|
|
30
|
-
"@things-factory/ai-client-base": "^10.1.
|
|
31
|
-
"@things-factory/attachment-base": "^10.1.
|
|
32
|
-
"@things-factory/auth-base": "^10.1.
|
|
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.
|
|
35
|
-
"@things-factory/shell": "^10.1.
|
|
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": "
|
|
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
|
-
*
|
|
15
|
+
* 발행 버전의 정본(`__releaseSource`)은 크기 범위를 적은 발행 버전 사본이다 — Figure 행에는 작성자가 좁힌 끝만 남는다.
|
|
16
16
|
*
|
|
17
17
|
* 발행 메모는 Figure 의 칸이 아니다. `releaseFigure` 가 저장할 엔티티에 `__releaseComment` 로 얹어
|
|
18
|
-
* 두면 여기서
|
|
19
|
-
* (`__releaseFormat`), 잰 커널의
|
|
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)이더라도 과거
|
|
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)이 아니라 기발행된
|
|
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: `정본의
|
|
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
|
|
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
|
|
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
|
-
* 이
|
|
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
|
-
* 이
|
|
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
|
-
|
|
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
|
-
(
|
|
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
|
-
* 피규어의 현재 번호가 아니라
|
|
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
|
-
/*
|
|
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
|
|
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
|
-
* 저작 중 저장은 여기 없다.
|
|
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
|
-
* 질의가 틀리면 저작자에게는 저장 실패로만 보인다. 실제로 그랬다 —
|
|
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('★
|
|
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('★
|
|
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('★
|
|
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
|
-
/** 발행
|
|
27
|
+
/** 발행 버전 번호. 0 이면 한 번도 발행되지 않았다. */
|
|
28
28
|
version?: number
|
|
29
|
-
/**
|
|
29
|
+
/** 버전이 하나라도 있나. 되돌리기로 버전 번호가 도로 낮아져도 이력은 남는다. */
|
|
30
30
|
hasHistory: boolean
|
|
31
31
|
/** 같은 도메인에서 그 이름을 이미 쓰는 **다른** 피규어가 있나. */
|
|
32
32
|
takenByAnother: boolean
|
|
33
33
|
/**
|
|
34
34
|
* 같은 도메인에서 그 이름으로 발행한 뒤 지워진 피규어가 있나. 발행한 피규어를 지울 수 없게 되기(G4) 전에 지워진 것이다.
|
|
35
|
-
* 그 이름을 다시 쓰면
|
|
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
|
-
* 실제로 그랬다 —
|
|
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
|
-
있는 것은 모델러에 열린 피규어뿐이고 그
|
|
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('열린 피규어를 고치면 그 초안이 제안기에 가고, 모델러가 적용할
|
|
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('
|
|
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('선택한 부품과 시험 중인 값을 같은
|
|
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('다른
|
|
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('고치는 제안에 고른 부품이 제안기까지 가고,
|
|
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('★ 고치는 제안은 그 초안 위에, 모델러가 적용할
|
|
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
|
-
고치는 제안은 모델러가 **요청 당시의
|
|
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
|
-
|
|
91
|
+
발행은 `releaseFigure` 가 한다. 저장으로 상태를 바꿀 수 있게 두면 발행된 버전을 덮어쓰면서 같은
|
|
92
|
+
버전 번호로 버전을 또 뜨게 되고(유니크 충돌), 무엇이 약속된 버전인지도 흐려진다. board 도 같다.
|
|
93
93
|
*/
|
|
94
94
|
|
|
95
95
|
@Field({ nullable: true, description: 'A base64 encoded thumbnail image.' })
|