@things-factory/figure-service 10.1.69 → 10.1.70
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-recipe/figure-recipe-resolver.d.ts +2 -0
- package/dist-server/service/figure-recipe/figure-recipe-resolver.js +25 -0
- package/dist-server/service/figure-recipe/figure-recipe-resolver.js.map +1 -1
- package/dist-server/service/figure-recipe/figure-recipe-store.d.ts +11 -0
- package/dist-server/service/figure-recipe/figure-recipe-store.js +26 -0
- package/dist-server/service/figure-recipe/figure-recipe-store.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/server/service/figure-recipe/figure-recipe-db.test.ts +20 -0
- package/server/service/figure-recipe/figure-recipe-resolver.ts +17 -1
- package/server/service/figure-recipe/figure-recipe-store.ts +26 -0
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.70",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public",
|
|
6
6
|
"@things-factory:registry": "https://registry.npmjs.org"
|
|
@@ -33,5 +33,5 @@
|
|
|
33
33
|
"graphql-upload": "^15.0.2",
|
|
34
34
|
"koa-router": "^7.4.0"
|
|
35
35
|
},
|
|
36
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "7c9c614b0cb1d02d401211db76ec0ca0ead344af"
|
|
37
37
|
}
|
|
@@ -101,3 +101,23 @@ describe('조각 — 저장은 빈 방에 넣어 본 뒤에', () => {
|
|
|
101
101
|
expect(await rows()).toEqual([])
|
|
102
102
|
})
|
|
103
103
|
})
|
|
104
|
+
|
|
105
|
+
describe('조각 — 제 도메인 것만 바꾼다', () => {
|
|
106
|
+
it('★ 자식은 부모의 조각을 발행 · 삭제하지 못한다; 제 것은 초안으로 돌리면 모델러 목록에서 빠지고, 지우면 부모 것이 다시 보인다', async () => {
|
|
107
|
+
await store.seedBuiltInRecipes()
|
|
108
|
+
const child = { id: CHILD.id, parentId: SYSTEM.id }
|
|
109
|
+
await expect(store.deleteRecipe(child, 'sliding-door')).rejects.toThrow(/copied here to be changed/)
|
|
110
|
+
await expect(store.setRecipeState(child, 'sliding-door', 'draft')).rejects.toThrow(/copied here/)
|
|
111
|
+
|
|
112
|
+
const door = JSON.parse(store.builtInRecipes().find((r: any) => r.name === 'sliding-door').source)
|
|
113
|
+
door.title = { ko: '우리 문' }
|
|
114
|
+
await store.saveRecipe(CHILD, JSON.stringify(door))
|
|
115
|
+
await store.setRecipeState(child, 'sliding-door', 'draft')
|
|
116
|
+
const released = await store.recipesFor(child, 'released')
|
|
117
|
+
expect(JSON.parse(released.find((r: any) => r.name === 'sliding-door').source).title.ko).not.toBe('우리 문')
|
|
118
|
+
|
|
119
|
+
await store.deleteRecipe(child, 'sliding-door')
|
|
120
|
+
const all = await store.recipesFor(child)
|
|
121
|
+
expect(all.find((r: any) => r.name === 'sliding-door').domainId).toBe(SYSTEM.id)
|
|
122
|
+
})
|
|
123
|
+
})
|
|
@@ -3,7 +3,7 @@ import { Arg, Ctx, Directive, Mutation, Query, Resolver, UseMiddleware } from 't
|
|
|
3
3
|
import { SpeakRefusals } from '@things-factory/shell'
|
|
4
4
|
|
|
5
5
|
import { FigureRecipe } from './figure-recipe.js'
|
|
6
|
-
import { recipesFor, saveRecipe } from './figure-recipe-store.js'
|
|
6
|
+
import { deleteRecipe, recipesFor, saveRecipe, setRecipeState } from './figure-recipe-store.js'
|
|
7
7
|
|
|
8
8
|
@Resolver(FigureRecipe)
|
|
9
9
|
@UseMiddleware(SpeakRefusals)
|
|
@@ -23,4 +23,20 @@ export class FigureRecipeResolver {
|
|
|
23
23
|
): Promise<FigureRecipe> {
|
|
24
24
|
return await saveRecipe(context.state.domain, source, state === 'draft' ? 'draft' : 'released')
|
|
25
25
|
}
|
|
26
|
+
|
|
27
|
+
@Directive('@privilege(category: "figure", privilege: "mutation", domainOwnerGranted: true)')
|
|
28
|
+
@Mutation(returns => FigureRecipe, { description: "Releases a recipe of this domain's own, or takes it back to draft. A parent's recipe is copied in to be changed." })
|
|
29
|
+
async setFigureRecipeState(
|
|
30
|
+
@Arg('name', { description: 'The recipe name.' }) name: string,
|
|
31
|
+
@Arg('state', { description: "'draft' or 'released'." }) state: string,
|
|
32
|
+
@Ctx() context: ResolverContext
|
|
33
|
+
): Promise<FigureRecipe> {
|
|
34
|
+
return await setRecipeState(context.state.domain, name, state === 'draft' ? 'draft' : 'released')
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
@Directive('@privilege(category: "figure", privilege: "mutation", domainOwnerGranted: true)')
|
|
38
|
+
@Mutation(returns => Boolean, { description: "Deletes a recipe of this domain's own. Figures it was put into keep their parts." })
|
|
39
|
+
async deleteFigureRecipe(@Arg('name', { description: 'The recipe name.' }) name: string, @Ctx() context: ResolverContext): Promise<boolean> {
|
|
40
|
+
return await deleteRecipe(context.state.domain, name)
|
|
41
|
+
}
|
|
26
42
|
}
|
|
@@ -37,6 +37,32 @@ export async function saveRecipe(domain: Domain, source: unknown, state: 'draft'
|
|
|
37
37
|
return await repository.save({ ...(existing ?? {}), domain, name: recipe.name, source: JSON.stringify(recipe), state })
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
/**
|
|
41
|
+
* A recipe of the domain's own, by name. A parent's recipe is not the domain's to change: it is copied in under the same
|
|
42
|
+
* name (`saveRecipe`), and the copy stands in for it.
|
|
43
|
+
*/
|
|
44
|
+
async function ownRecipe(domain: { id: string }, name: string): Promise<FigureRecipe> {
|
|
45
|
+
const row = await getRepository(FigureRecipe).findOne({ where: { domain: { id: domain.id }, name } })
|
|
46
|
+
if (!row) throw new Error(`${name} is not a recipe of this domain; a parent's recipe is copied here to be changed`)
|
|
47
|
+
return row
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/** Released or back to draft: only released recipes are offered in the modeller. */
|
|
51
|
+
export async function setRecipeState(domain: { id: string }, name: string, state: 'draft' | 'released'): Promise<FigureRecipe> {
|
|
52
|
+
const row = await ownRecipe(domain, name)
|
|
53
|
+
return await getRepository(FigureRecipe).save({ ...row, state })
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* A recipe of the domain's own taken away. Figures it was put into keep their parts -- nothing ties them to it
|
|
58
|
+
* (ADR-0095). Where the parent has one by that name, the parent's is seen again.
|
|
59
|
+
*/
|
|
60
|
+
export async function deleteRecipe(domain: { id: string }, name: string): Promise<boolean> {
|
|
61
|
+
const row = await ownRecipe(domain, name)
|
|
62
|
+
await getRepository(FigureRecipe).softRemove(row)
|
|
63
|
+
return true
|
|
64
|
+
}
|
|
65
|
+
|
|
40
66
|
/** The recipes figure-model ships (`recipes/*.json`), as they are. */
|
|
41
67
|
export function builtInRecipes(): Array<{ name: string; source: string }> {
|
|
42
68
|
const dir = join(dirname(require.resolve('@hatiolab/figure-model/package.json')), 'recipes')
|