@things-factory/figure-service 10.1.81 → 10.1.82

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 (60) hide show
  1. package/dist-server/service/figure/figure-format.js +4 -3
  2. package/dist-server/service/figure/figure-format.js.map +1 -1
  3. package/dist-server/service/figure/figure-mutation.d.ts +5 -3
  4. package/dist-server/service/figure/figure-mutation.js +43 -41
  5. package/dist-server/service/figure/figure-mutation.js.map +1 -1
  6. package/dist-server/service/figure/figure-proposal-record.d.ts +16 -0
  7. package/dist-server/service/figure/figure-proposal-record.js +51 -0
  8. package/dist-server/service/figure/figure-proposal-record.js.map +1 -0
  9. package/dist-server/service/figure/figure-proposal.d.ts +14 -0
  10. package/dist-server/service/figure/figure-proposal.js +39 -0
  11. package/dist-server/service/figure/figure-proposal.js.map +1 -0
  12. package/dist-server/service/figure/figure-propose-steps.js +12 -0
  13. package/dist-server/service/figure/figure-propose-steps.js.map +1 -1
  14. package/dist-server/service/figure/figure-query.d.ts +6 -1
  15. package/dist-server/service/figure/figure-query.js +33 -0
  16. package/dist-server/service/figure/figure-query.js.map +1 -1
  17. package/dist-server/service/figure/figure-rename.d.ts +2 -2
  18. package/dist-server/service/figure/figure-rename.js +8 -20
  19. package/dist-server/service/figure/figure-rename.js.map +1 -1
  20. package/dist-server/service/figure/figure-replaced-draft.d.ts +33 -0
  21. package/dist-server/service/figure/figure-replaced-draft.js +114 -0
  22. package/dist-server/service/figure/figure-replaced-draft.js.map +1 -0
  23. package/dist-server/service/figure/figure-revert.d.ts +36 -0
  24. package/dist-server/service/figure/figure-revert.js +155 -0
  25. package/dist-server/service/figure/figure-revert.js.map +1 -0
  26. package/dist-server/service/figure/figure-tools.js +7 -0
  27. package/dist-server/service/figure/figure-tools.js.map +1 -1
  28. package/dist-server/service/figure/figure-type.d.ts +14 -0
  29. package/dist-server/service/figure/figure-type.js +44 -1
  30. package/dist-server/service/figure/figure-type.js.map +1 -1
  31. package/dist-server/service/figure/figure-write.d.ts +7 -0
  32. package/dist-server/service/figure/figure-write.js +12 -2
  33. package/dist-server/service/figure/figure-write.js.map +1 -1
  34. package/dist-server/service/figure/index.d.ts +3 -1
  35. package/dist-server/service/figure/index.js +3 -1
  36. package/dist-server/service/figure/index.js.map +1 -1
  37. package/dist-server/service/index.d.ts +1 -1
  38. package/dist-server/tsconfig.tsbuildinfo +1 -1
  39. package/package.json +3 -3
  40. package/server/service/figure/figure-format.ts +4 -3
  41. package/server/service/figure/figure-mutation.ts +48 -42
  42. package/server/service/figure/figure-proposal-db.test.ts +108 -0
  43. package/server/service/figure/figure-proposal-record.ts +38 -0
  44. package/server/service/figure/figure-proposal.ts +39 -0
  45. package/server/service/figure/figure-propose-clips.test.ts +73 -0
  46. package/server/service/figure/figure-propose-steps.ts +12 -0
  47. package/server/service/figure/figure-query.ts +22 -1
  48. package/server/service/figure/figure-rename.test.ts +13 -2
  49. package/server/service/figure/figure-rename.ts +13 -1
  50. package/server/service/figure/figure-replaced-draft.ts +90 -0
  51. package/server/service/figure/figure-revert-db.test.ts +159 -0
  52. package/server/service/figure/figure-revert-race.pg.test.ts +168 -0
  53. package/server/service/figure/figure-revert.ts +181 -0
  54. package/server/service/figure/figure-tools.ts +7 -0
  55. package/server/service/figure/figure-type.ts +30 -0
  56. package/server/service/figure/figure-write.test.ts +15 -0
  57. package/server/service/figure/figure-write.ts +12 -2
  58. package/server/service/figure/index.ts +3 -1
  59. package/translations/en.json +3 -3
  60. package/translations/ko.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"figure-write.js","sourceRoot":"","sources":["../../../server/service/figure/figure-write.ts"],"names":[],"mappings":";;AAOA,oDASC;AAGD,gDAkBC;AASD,8BAGC;AAjDD,yDAAgI;AAOzH,KAAK,UAAU,oBAAoB,CACxC,MAAgF,EAChF,EAAU,EACV,QAAgB,EAChB,cAAkC;IAElC,IAAI,cAAc,KAAK,SAAS;QAAE,MAAM,KAAK,CAAC,iBAAiB,CAAC,CAAA;IAChE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAA;IACrF,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC;QAAE,MAAM,KAAK,CAAC,wCAAwC,CAAC,CAAA;AAClF,CAAC;AAED,mGAAmG;AACnG,SAAgB,kBAAkB,CAAC,MAAc,EAAE,QAA8B,EAAE,cAAuB;IACxG,IAAI,QAAQ,IAAI,CAAC,cAAc,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,KAAK,cAAc,CAAC,EAAE,CAAC;QACrF,MAAM,KAAK,CAAC,6CAA6C,CAAC,CAAA;IAC5D,CAAC;IACD,MAAM,KAAK,GAAG,IAAA,+BAAgB,EAAC,MAAM,CAAC,CAAA;IACtC,IAAA,iCAAkB,EAAC,KAAK,CAAC,CAAA;IACzB;;MAEE;IACF,MAAM,IAAI,GAAG,IAAA,2BAAY,EAAC,KAAK,CAAC,CAAA;IAChC,OAAO;QACL,MAAM,EAAE,IAAA,mCAAoB,EAAC,KAAK,CAAC;QACnC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,KAAK,EAAE,IAAA,4BAAa,EAAC,KAAK,CAAC,EAAE,KAAK,IAAI,IAAI;QAC1C,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,OAAgB;KACxB,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,SAAS,CAAC,SAAkB,EAAE,QAAiC;IAC7E,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,QAAQ,EAAE,SAAS;QAAE,OAAO,EAAE,CAAA;IAC3E,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,IAAI,IAAI,EAAE,EAAE,CAAA;AACtD,CAAC","sourcesContent":["import { parseFigureAsset, serializeFigureAsset, compileFigureAsset, figureCostOf, figureScoreOf } from '@hatiolab/figure-model'\n\nexport interface FigureWriteCriteria {\n id: string\n domain: { id: string }\n source: string\n}\nexport async function compareAndSwapFigure(\n update: (criteria: FigureWriteCriteria) => Promise<{ affected?: number | null }>,\n id: string,\n domainId: string,\n expectedSource: string | undefined\n) {\n if (expectedSource === undefined) throw Error('수정 전 정본이 필요합니다.')\n const result = await update({ id, domain: { id: domainId }, source: expectedSource })\n if (result.affected !== 1) throw Error('다른 편집에서 모델이 변경되었습니다. 최신 모델을 다시 열어 주세요.')\n}\n\n/** Early validation only. The repository must also compare expectedSource in its atomic UPDATE. */\nexport function prepareFigureWrite(source: string, existing?: { source?: string }, expectedSource?: string) {\n if (existing && (expectedSource === undefined || existing.source !== expectedSource)) {\n throw Error('다른 편집에서 모델이 변경되었습니다. 최신 모델을 다시 연 뒤 적용해 주세요.')\n }\n const asset = parseFigureAsset(source)\n compileFigureAsset(asset)\n /*\n The same measure `parseSource` uses, so the catalogue's columns do not depend on which mutation wrote the row.\n */\n const cost = figureCostOf(asset)\n return {\n source: serializeFigureAsset(asset),\n name: asset.name,\n score: figureScoreOf(asset)?.score ?? null,\n triangles: cost.triangles,\n groups: cost.groups,\n state: 'draft' as const\n }\n}\n\n/**\n * The picture a card shows, when the modeller sent one.\n *\n * Absent means the author saved without one — a tab in the background cannot draw, and the source matters more\n * than the picture, so the save goes on and the modeller fills it in next time. The timestamp moves only when\n * the picture itself is new, so renaming a figure does not make every card look freshly drawn.\n */\nexport function pictureOf(thumbnail?: string, existing?: { thumbnail?: string }) {\n if (thumbnail === undefined || thumbnail === existing?.thumbnail) return {}\n return { thumbnail, thumbnailUpdatedAt: new Date() }\n}\n"]}
1
+ {"version":3,"file":"figure-write.js","sourceRoot":"","sources":["../../../server/service/figure/figure-write.ts"],"names":[],"mappings":";;AAQA,wCAEC;AAOD,oDASC;AAGD,gDAkBC;AASD,8BAGC;AA3DD,qCAAsC;AACtC,yDAAgI;AAEhI;;;;GAIG;AACH,SAAgB,cAAc,CAAC,OAAe;IAC5C,OAAO,IAAI,sBAAY,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,wBAAwB,EAAE,EAAE,CAAC,CAAA;AACtF,CAAC;AAOM,KAAK,UAAU,oBAAoB,CACxC,MAAgF,EAChF,EAAU,EACV,QAAgB,EAChB,cAAkC;IAElC,IAAI,cAAc,KAAK,SAAS;QAAE,MAAM,KAAK,CAAC,iBAAiB,CAAC,CAAA;IAChE,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,MAAM,EAAE,cAAc,EAAE,CAAC,CAAA;IACrF,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC;QAAE,MAAM,cAAc,CAAC,wCAAwC,CAAC,CAAA;AAC3F,CAAC;AAED,mGAAmG;AACnG,SAAgB,kBAAkB,CAAC,MAAc,EAAE,QAA8B,EAAE,cAAuB;IACxG,IAAI,QAAQ,IAAI,CAAC,cAAc,KAAK,SAAS,IAAI,QAAQ,CAAC,MAAM,KAAK,cAAc,CAAC,EAAE,CAAC;QACrF,MAAM,cAAc,CAAC,6CAA6C,CAAC,CAAA;IACrE,CAAC;IACD,MAAM,KAAK,GAAG,IAAA,+BAAgB,EAAC,MAAM,CAAC,CAAA;IACtC,IAAA,iCAAkB,EAAC,KAAK,CAAC,CAAA;IACzB;;MAEE;IACF,MAAM,IAAI,GAAG,IAAA,2BAAY,EAAC,KAAK,CAAC,CAAA;IAChC,OAAO;QACL,MAAM,EAAE,IAAA,mCAAoB,EAAC,KAAK,CAAC;QACnC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,KAAK,EAAE,IAAA,4BAAa,EAAC,KAAK,CAAC,EAAE,KAAK,IAAI,IAAI;QAC1C,SAAS,EAAE,IAAI,CAAC,SAAS;QACzB,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,KAAK,EAAE,OAAgB;KACxB,CAAA;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAgB,SAAS,CAAC,SAAkB,EAAE,QAAiC;IAC7E,IAAI,SAAS,KAAK,SAAS,IAAI,SAAS,KAAK,QAAQ,EAAE,SAAS;QAAE,OAAO,EAAE,CAAA;IAC3E,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,IAAI,IAAI,EAAE,EAAE,CAAA;AACtD,CAAC","sourcesContent":["import { GraphQLError } from 'graphql'\nimport { parseFigureAsset, serializeFigureAsset, compileFigureAsset, figureCostOf, figureScoreOf } from '@hatiolab/figure-model'\n\n/**\n * The row is not what the writer expected: another edit, or the writer's own earlier save whose answer it never got.\n * Coded, so a client can tell it from a refusal on grounds (permission, validation) and read the row back before\n * saying its save failed (D, designer 2026-09-27).\n */\nexport function sourceConflict(message: string) {\n return new GraphQLError(message, { extensions: { code: 'FIGURE_SOURCE_CONFLICT' } })\n}\n\nexport interface FigureWriteCriteria {\n id: string\n domain: { id: string }\n source: string\n}\nexport async function compareAndSwapFigure(\n update: (criteria: FigureWriteCriteria) => Promise<{ affected?: number | null }>,\n id: string,\n domainId: string,\n expectedSource: string | undefined\n) {\n if (expectedSource === undefined) throw Error('수정 전 정본이 필요합니다.')\n const result = await update({ id, domain: { id: domainId }, source: expectedSource })\n if (result.affected !== 1) throw sourceConflict('다른 편집에서 모델이 변경되었습니다. 최신 모델을 다시 열어 주세요.')\n}\n\n/** Early validation only. The repository must also compare expectedSource in its atomic UPDATE. */\nexport function prepareFigureWrite(source: string, existing?: { source?: string }, expectedSource?: string) {\n if (existing && (expectedSource === undefined || existing.source !== expectedSource)) {\n throw sourceConflict('다른 편집에서 모델이 변경되었습니다. 최신 모델을 다시 연 뒤 적용해 주세요.')\n }\n const asset = parseFigureAsset(source)\n compileFigureAsset(asset)\n /*\n The same measure `parseSource` uses, so the catalogue's columns do not depend on which mutation wrote the row.\n */\n const cost = figureCostOf(asset)\n return {\n source: serializeFigureAsset(asset),\n name: asset.name,\n score: figureScoreOf(asset)?.score ?? null,\n triangles: cost.triangles,\n groups: cost.groups,\n state: 'draft' as const\n }\n}\n\n/**\n * The picture a card shows, when the modeller sent one.\n *\n * Absent means the author saved without one — a tab in the background cannot draw, and the source matters more\n * than the picture, so the save goes on and the modeller fills it in next time. The timestamp moves only when\n * the picture itself is new, so renaming a figure does not make every card look freshly drawn.\n */\nexport function pictureOf(thumbnail?: string, existing?: { thumbnail?: string }) {\n if (thumbnail === undefined || thumbnail === existing?.thumbnail) return {}\n return { thumbnail, thumbnailUpdatedAt: new Date() }\n}\n"]}
@@ -1,8 +1,10 @@
1
1
  import { Figure } from './figure.js';
2
2
  import { FigureHistory } from './figure-history.js';
3
+ import { FigureReplacedDraft } from './figure-replaced-draft.js';
4
+ import { FigureProposalRecord } from './figure-proposal-record.js';
3
5
  import { FigureQuery } from './figure-query.js';
4
6
  import { FigureMutation } from './figure-mutation.js';
5
7
  import { FigureHistoryEntitySubscriber } from './event-subscriber.js';
6
- export declare const entities: (typeof Figure | typeof FigureHistory)[];
8
+ export declare const entities: (typeof Figure | typeof FigureReplacedDraft | typeof FigureHistory | typeof FigureProposalRecord)[];
7
9
  export declare const resolvers: (typeof FigureQuery | typeof FigureMutation)[];
8
10
  export declare const subscribers: (typeof FigureHistoryEntitySubscriber)[];
@@ -3,10 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.subscribers = exports.resolvers = exports.entities = void 0;
4
4
  const figure_js_1 = require("./figure.js");
5
5
  const figure_history_js_1 = require("./figure-history.js");
6
+ const figure_replaced_draft_js_1 = require("./figure-replaced-draft.js");
7
+ const figure_proposal_record_js_1 = require("./figure-proposal-record.js");
6
8
  const figure_query_js_1 = require("./figure-query.js");
7
9
  const figure_mutation_js_1 = require("./figure-mutation.js");
8
10
  const event_subscriber_js_1 = require("./event-subscriber.js");
9
- exports.entities = [figure_js_1.Figure, figure_history_js_1.FigureHistory];
11
+ exports.entities = [figure_js_1.Figure, figure_history_js_1.FigureHistory, figure_replaced_draft_js_1.FigureReplacedDraft, figure_proposal_record_js_1.FigureProposalRecord];
10
12
  exports.resolvers = [figure_query_js_1.FigureQuery, figure_mutation_js_1.FigureMutation];
11
13
  exports.subscribers = [event_subscriber_js_1.FigureHistoryEntitySubscriber];
12
14
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/figure/index.ts"],"names":[],"mappings":";;;AAAA,2CAAoC;AACpC,2DAAmD;AACnD,uDAA+C;AAC/C,6DAAqD;AACrD,+DAAqE;AAExD,QAAA,QAAQ,GAAG,CAAC,kBAAM,EAAE,iCAAa,CAAC,CAAA;AAClC,QAAA,SAAS,GAAG,CAAC,6BAAW,EAAE,mCAAc,CAAC,CAAA;AACzC,QAAA,WAAW,GAAG,CAAC,mDAA6B,CAAC,CAAA","sourcesContent":["import { Figure } from './figure.js'\nimport { FigureHistory } from './figure-history.js'\nimport { FigureQuery } from './figure-query.js'\nimport { FigureMutation } from './figure-mutation.js'\nimport { FigureHistoryEntitySubscriber } from './event-subscriber.js'\n\nexport const entities = [Figure, FigureHistory]\nexport const resolvers = [FigureQuery, FigureMutation]\nexport const subscribers = [FigureHistoryEntitySubscriber]\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/figure/index.ts"],"names":[],"mappings":";;;AAAA,2CAAoC;AACpC,2DAAmD;AACnD,yEAAgE;AAChE,2EAAkE;AAClE,uDAA+C;AAC/C,6DAAqD;AACrD,+DAAqE;AAExD,QAAA,QAAQ,GAAG,CAAC,kBAAM,EAAE,iCAAa,EAAE,8CAAmB,EAAE,gDAAoB,CAAC,CAAA;AAC7E,QAAA,SAAS,GAAG,CAAC,6BAAW,EAAE,mCAAc,CAAC,CAAA;AACzC,QAAA,WAAW,GAAG,CAAC,mDAA6B,CAAC,CAAA","sourcesContent":["import { Figure } from './figure.js'\nimport { FigureHistory } from './figure-history.js'\nimport { FigureReplacedDraft } from './figure-replaced-draft.js'\nimport { FigureProposalRecord } from './figure-proposal-record.js'\nimport { FigureQuery } from './figure-query.js'\nimport { FigureMutation } from './figure-mutation.js'\nimport { FigureHistoryEntitySubscriber } from './event-subscriber.js'\n\nexport const entities = [Figure, FigureHistory, FigureReplacedDraft, FigureProposalRecord]\nexport const resolvers = [FigureQuery, FigureMutation]\nexport const subscribers = [FigureHistoryEntitySubscriber]\n"]}
@@ -4,7 +4,7 @@ export * from './figure/figure-format.js';
4
4
  export * from './figure/figure-history.js';
5
5
  export * from './figure-recipe/figure-recipe-type.js';
6
6
  export { recipeTemplates, inLanguage, RECIPE_DIR } from './figure-recipe/figure-recipe-templates.js';
7
- export declare const entities: (typeof import("./figure/figure.js").Figure | typeof import("./figure/figure-history.js").FigureHistory)[];
7
+ export declare const entities: (typeof import("./figure/figure.js").Figure | typeof import("./figure/figure-replaced-draft.js").FigureReplacedDraft | typeof import("./figure/figure-history.js").FigureHistory | typeof import("./figure/figure-proposal-record.js").FigureProposalRecord)[];
8
8
  export declare const subscribers: typeof import("./figure/event-subscriber.js").FigureHistoryEntitySubscriber[];
9
9
  export declare const schema: {
10
10
  resolverClasses: (typeof import("./figure/figure-query.js").FigureQuery | typeof import("./figure/figure-mutation.js").FigureMutation | typeof import("./figure-recipe/figure-recipe-resolver.js").FigureRecipeTemplateQuery)[];