@things-factory/worklist 10.1.36 → 10.1.38
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-client/components/activity-instance-preview.js +2 -13
- package/dist-client/components/activity-instance-preview.js.map +1 -1
- package/dist-client/components/activity-thread-timeline.d.ts +2 -2
- package/dist-client/components/can-pick.d.ts +15 -0
- package/dist-client/components/can-pick.js +16 -0
- package/dist-client/components/can-pick.js.map +1 -0
- package/dist-client/index.d.ts +1 -0
- package/dist-client/index.js +1 -0
- package/dist-client/index.js.map +1 -1
- package/dist-client/pages/activity-catalog/activity-catalog-page.js +50 -40
- package/dist-client/pages/activity-catalog/activity-catalog-page.js.map +1 -1
- package/dist-client/pages/activity-catalog/activity-detail-actions.d.ts +34 -0
- package/dist-client/pages/activity-catalog/activity-detail-actions.js +18 -0
- package/dist-client/pages/activity-catalog/activity-detail-actions.js.map +1 -0
- package/dist-client/pages/activity-catalog/activity-detail-page.d.ts +68 -0
- package/dist-client/pages/activity-catalog/activity-detail-page.js +489 -0
- package/dist-client/pages/activity-catalog/activity-detail-page.js.map +1 -0
- package/dist-client/pages/activity-catalog/activity-guide.d.ts +16 -0
- package/dist-client/pages/activity-catalog/activity-guide.js +5 -0
- package/dist-client/pages/activity-catalog/activity-guide.js.map +1 -0
- package/dist-client/pages/activity-catalog/activity-panels.d.ts +80 -0
- package/dist-client/pages/activity-catalog/activity-panels.js +53 -0
- package/dist-client/pages/activity-catalog/activity-panels.js.map +1 -0
- package/dist-client/pages/activity-catalog/activity-stage.d.ts +31 -0
- package/dist-client/pages/activity-catalog/activity-stage.js +44 -0
- package/dist-client/pages/activity-catalog/activity-stage.js.map +1 -0
- package/dist-client/pages/activity-instance/activity-instance-start-page.d.ts +1 -0
- package/dist-client/pages/activity-instance/activity-instance-start-page.js +33 -1
- package/dist-client/pages/activity-instance/activity-instance-start-page.js.map +1 -1
- package/dist-client/pages/activity-instance/discard-offer.d.ts +11 -0
- package/dist-client/pages/activity-instance/discard-offer.js +11 -0
- package/dist-client/pages/activity-instance/discard-offer.js.map +1 -0
- package/dist-client/pages/activity-thread/activity-thread-view.d.ts +1 -1
- package/dist-client/pages/todo/approval-done-list-page.d.ts +5 -1
- package/dist-client/pages/todo/approval-done-list-page.js +8 -1
- package/dist-client/pages/todo/approval-done-list-page.js.map +1 -1
- package/dist-client/pages/todo/approval-pending-list-page.d.ts +5 -1
- package/dist-client/pages/todo/approval-pending-list-page.js +8 -1
- package/dist-client/pages/todo/approval-pending-list-page.js.map +1 -1
- package/dist-client/pages/todo/done-list-page.d.ts +5 -1
- package/dist-client/pages/todo/done-list-page.js +8 -1
- package/dist-client/pages/todo/done-list-page.js.map +1 -1
- package/dist-client/pages/todo/draft-list-page.d.ts +5 -1
- package/dist-client/pages/todo/draft-list-page.js +18 -12
- package/dist-client/pages/todo/draft-list-page.js.map +1 -1
- package/dist-client/pages/todo/list-thumbnail.d.ts +25 -0
- package/dist-client/pages/todo/list-thumbnail.js +25 -0
- package/dist-client/pages/todo/list-thumbnail.js.map +1 -0
- package/dist-client/pages/todo/todo-list-page.d.ts +5 -1
- package/dist-client/pages/todo/todo-list-page.js +8 -1
- package/dist-client/pages/todo/todo-list-page.js.map +1 -1
- package/dist-client/pages/work-door/door-links.d.ts +30 -0
- package/dist-client/pages/work-door/door-links.js +30 -0
- package/dist-client/pages/work-door/door-links.js.map +1 -0
- package/dist-client/pages/work-door/work-doors-page.js +15 -5
- package/dist-client/pages/work-door/work-doors-page.js.map +1 -1
- package/dist-client/route.d.ts +1 -1
- package/dist-client/route.js +3 -0
- package/dist-client/route.js.map +1 -1
- package/dist-client/tsconfig.tsbuildinfo +1 -1
- package/dist-server/controllers/activity-approval/delegate.js +27 -2
- package/dist-server/controllers/activity-approval/delegate.js.map +1 -1
- package/dist-server/controllers/activity-approval/delegation.d.ts +31 -0
- package/dist-server/controllers/activity-approval/delegation.js +31 -0
- package/dist-server/controllers/activity-approval/delegation.js.map +1 -0
- package/dist-server/controllers/activity-instance/discard-draft.d.ts +22 -0
- package/dist-server/controllers/activity-instance/discard-draft.js +54 -0
- package/dist-server/controllers/activity-instance/discard-draft.js.map +1 -0
- package/dist-server/controllers/activity-read/assert-may-read.d.ts +15 -0
- package/dist-server/controllers/activity-read/assert-may-read.js +99 -0
- package/dist-server/controllers/activity-read/assert-may-read.js.map +1 -0
- package/dist-server/controllers/activity-read/participates.d.ts +41 -0
- package/dist-server/controllers/activity-read/participates.js +42 -0
- package/dist-server/controllers/activity-read/participates.js.map +1 -0
- package/dist-server/controllers/activity-thread/delegate.js +23 -1
- package/dist-server/controllers/activity-thread/delegate.js.map +1 -1
- package/dist-server/service/activity/activity-mutation.js +1 -0
- package/dist-server/service/activity/activity-mutation.js.map +1 -1
- package/dist-server/service/activity-approval/activity-approval-query.js +7 -1
- package/dist-server/service/activity-approval/activity-approval-query.js.map +1 -1
- package/dist-server/service/activity-approval/activity-approval-subscription.js +2 -11
- package/dist-server/service/activity-approval/activity-approval-subscription.js.map +1 -1
- package/dist-server/service/activity-instance/activity-instance-mutation.js +12 -20
- package/dist-server/service/activity-instance/activity-instance-mutation.js.map +1 -1
- package/dist-server/service/activity-instance/activity-instance-query.js +30 -9
- package/dist-server/service/activity-instance/activity-instance-query.js.map +1 -1
- package/dist-server/service/activity-instance/activity-instance-subscription.js +4 -12
- package/dist-server/service/activity-instance/activity-instance-subscription.js.map +1 -1
- package/dist-server/service/activity-instance/draft-list-states.d.ts +39 -0
- package/dist-server/service/activity-instance/draft-list-states.js +51 -0
- package/dist-server/service/activity-instance/draft-list-states.js.map +1 -0
- package/dist-server/service/activity-instance/index.d.ts +1 -2
- package/dist-server/service/activity-instance/index.js +1 -2
- package/dist-server/service/activity-instance/index.js.map +1 -1
- package/dist-server/service/activity-template/activity-template-mutation.js +6 -0
- package/dist-server/service/activity-template/activity-template-mutation.js.map +1 -1
- package/dist-server/service/activity-thread/activity-thread-mutation.d.ts +0 -3
- package/dist-server/service/activity-thread/activity-thread-mutation.js +0 -19
- package/dist-server/service/activity-thread/activity-thread-mutation.js.map +1 -1
- package/dist-server/service/activity-thread/activity-thread-query.js +7 -1
- package/dist-server/service/activity-thread/activity-thread-query.js.map +1 -1
- package/dist-server/service/activity-thread/activity-thread-subscription.js +2 -8
- package/dist-server/service/activity-thread/activity-thread-subscription.js.map +1 -1
- package/dist-server/service/index.d.ts +2 -2
- package/dist-server/service/subscription/subscription-filters.d.ts +36 -0
- package/dist-server/service/subscription/subscription-filters.js +41 -0
- package/dist-server/service/subscription/subscription-filters.js.map +1 -0
- package/dist-server/service/work-door/work-door-declaration.d.ts +15 -0
- package/dist-server/service/work-door/work-door-declaration.js +18 -0
- package/dist-server/service/work-door/work-door-declaration.js.map +1 -1
- package/dist-server/service/work-door/work-door-resolver.d.ts +3 -0
- package/dist-server/service/work-door/work-door-resolver.js +21 -1
- package/dist-server/service/work-door/work-door-resolver.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +10 -10
- package/tests/delegate-approval.test.ts +112 -0
- package/tests/discard-draft.test.ts +145 -0
- package/tests/may-read-case.test.ts +166 -0
- package/tests/open-doors.test.ts +274 -0
- package/tests/published-shape.test.ts +85 -0
- package/tests/work-door-not-used-refuse.test.ts +110 -0
- package/things-factory.config.js +1 -0
- package/translations/en.json +32 -3
- package/translations/ja.json +33 -4
- package/translations/ko.json +33 -4
- package/translations/ms.json +32 -3
- package/translations/zh.json +33 -4
- package/dist-server/service/activity-instance/activity-instance-history-query.d.ts +0 -12
- package/dist-server/service/activity-instance/activity-instance-history-query.js +0 -79
- package/dist-server/service/activity-instance/activity-instance-history-query.js.map +0 -1
- package/dist-server/service/activity-instance/activity-instance-history-type.d.ts +0 -5
- package/dist-server/service/activity-instance/activity-instance-history-type.js +0 -21
- package/dist-server/service/activity-instance/activity-instance-history-type.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity-thread-query.js","sourceRoot":"","sources":["../../../server/service/activity-thread/activity-thread-query.ts"],"names":[],"mappings":"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","sourcesContent":["import { Brackets } from 'typeorm'\nimport { Arg, Args, Ctx, FieldResolver, Query, Resolver, Root } from 'type-graphql'\n\nimport { User } from '@things-factory/auth-base'\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'\n\nimport { ActivityInstance } from '../activity-instance/activity-instance.js'\nimport { ActivityThread, ActivityThreadStatus } from './activity-thread.js'\nimport { myOpenThreadsWhere } from './my-open-threads.js'\nimport { ActivityApproval } from '../activity-approval/activity-approval.js'\nimport { ActivityThreadList } from './activity-thread-type.js'\nimport { ActivityThreadHistory } from './activity-thread-history.js'\nimport { TODO_INSTANCE_SORTS, todoOrderTerms } from './todo-order.js'\n\n\n/**\n * 「할 일」 목록의 정렬 — **기한이 없는 것은 뒤로 간다.**\n *\n * ── 무엇이 잘못되고 있었나 (2026-09-06) ────────────────────────────────────\n * 화면의 기본 정렬은 `dueAt` 오름차순이다. 급한 것부터 보라는 뜻인데, **기한이 없는 것이 맨 위에\n * 왔다.** 실측(sqlite): 9건 중 기한 없는 6건이 먼저 나오고 「3일 지남」 3건이 맨 아래였다.\n *\n * NULL 을 앞에 둘지 뒤에 둘지는 **DB 마다 다르다** — sqlite 는 오름차순에서 NULL 이 먼저, postgres 는\n * 나중이다. 그래서 같은 코드가 개발 환경과 운영 환경에서 다른 순서를 낸다.\n *\n * ── 왜 NULLS LAST 를 쓰지 않나 ─────────────────────────────────────────────\n * `ORDER BY ... NULLS LAST` 는 postgres · oracle 문법이다. mysql · mssql 에서는 구문 오류가 난다.\n * 이 프레임워크는 다섯 드라이버를 다 지켜야 한다.\n *\n * `CASE WHEN ... IS NULL THEN 1 ELSE 0 END` 는 표준 SQL 이고 다섯 곳에서 다 돈다. 컬럼 이름은\n * 손으로 적지 않고 TypeORM 의 메타데이터에서 꺼낸다 — 이 프로젝트의 명명 규칙이 snake_case 라\n * `dueAt` 은 실제로 `due_at` 이다(shell 의 NamingStrategy).\n *\n * ── 공용 함수를 고치지 않는다 ──────────────────────────────────────────────\n * `getQueryBuilderFromListParams` 는 136개 꾸러미가 함께 쓴다. 정렬은 이 목록의 사정이므로\n * 여기서 맡는다 — 그 함수에는 정렬을 넘기지 않고(빈 배열) 아래에서 직접 건다.\n */\n\nfunction applyTodoSortings(queryBuilder: any, sortings: { name: string; desc?: boolean }[]) {\n const terms = todoOrderTerms(sortings, name => {\n const alias = TODO_INSTANCE_SORTS.has(name) ? 'ai' : 'at'\n const metadata = getRepository(alias === 'ai' ? ActivityInstance : ActivityThread).metadata\n const column = metadata.findColumnWithPropertyName(name)\n\n if (!column) {\n return undefined\n }\n\n const escape = (part: string) => queryBuilder.connection.driver.escape(part)\n\n return `${escape(alias)}.${escape(column.databaseName)}`\n })\n\n terms.forEach(({ expression, direction, select }, index) => {\n /* 식은 select 에 이름 붙여 올린다 — orderBy 는 식을 못 받는다(todo-order 머리말). */\n if (select) {\n queryBuilder.addSelect(select, expression)\n }\n\n index === 0 ? queryBuilder.orderBy(expression, direction) : queryBuilder.addOrderBy(expression, direction)\n })\n}\n\n@Resolver(ActivityThread)\nexport class ActivityThreadQuery {\n @Query(returns => ActivityThread!, { nullable: true, description: 'To fetch a ActivityThread' })\n async activityThread(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<ActivityThread> {\n const { domain } = context.state\n\n return await getRepository(ActivityThread).findOne({\n where: { domain: { id: domain.id }, id }\n })\n }\n\n @Query(returns => ActivityThreadList, { description: 'To fetch multiple ActivityThreads' })\n async activityThreads(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ActivityThreadList> {\n const { domain } = context.state\n\n const queryBuilder = getQueryBuilderFromListParams({\n domain,\n params,\n repository: getRepository(ActivityThread),\n searchables: ['name', 'description']\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n @Query(returns => ActivityThreadList, { description: 'To fetch my own ActivityThreads' })\n async todoList(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ActivityThreadList> {\n var { domain, user } = context.state\n\n user = await getRepository(User).findOne({\n where: { id: user.id },\n relations: ['roles']\n })\n const roles = user.roles.filter(role => role.domainId === domain.id).map(role => role.id)\n\n const queryBuilder = getQueryBuilderFromListParams({\n repository: getRepository(ActivityThread),\n /* 정렬은 아래에서 직접 건다(applyTodoSortings 머리말) — 여기에 넘기면 NULL 자리를 못 정한다. */\n params: { ...params, sortings: [] },\n domain,\n alias: 'at',\n searchables: ['name', 'description'],\n filtersMap: {\n name: { columnName: 'name', relationColumn: 'activityInstance' },\n description: { columnName: 'description', relationColumn: 'activityInstance' },\n priority: { columnName: 'priority', relationColumn: 'activityInstance' }\n }\n })\n .innerJoinAndSelect('at.activityInstance', 'ai')\n /* 「내 앞에 있는 일」의 정의는 한 자리에 있다 — 달력도 같은 것을 읽는다. */\n .andWhere(myOpenThreadsWhere({ userId: user.id, roles }))\n\n applyTodoSortings(queryBuilder, params.sortings || [])\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n @Query(returns => ActivityThreadList, { description: 'To fetch the tasks(ActivityThreads) which has done by me' })\n async doneList(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ActivityThreadList> {\n var { domain, user } = context.state\n\n const status = [ActivityThreadStatus.Ended, ActivityThreadStatus.Aborted]\n\n const [items, total] = await getQueryBuilderFromListParams({\n repository: getRepository(ActivityThread),\n params,\n domain,\n alias: 'at',\n searchables: ['name', 'description'],\n filtersMap: {\n name: { columnName: 'name', relationColumn: 'activityInstance' },\n description: { columnName: 'description', relationColumn: 'activityInstance' },\n priority: { columnName: 'priority', relationColumn: 'activityInstance' }\n }\n })\n .andWhere('at.state IN (:...status)', { status })\n .andWhere('at.assignee = :user', { user: user.id })\n .getManyAndCount()\n\n return { items, total }\n }\n\n @FieldResolver(type => User)\n async assignee(@Root() activityThread: ActivityThread): Promise<User> {\n return activityThread.assigneeId\n ? activityThread.assignee || (await getRepository(User).findOneBy({ id: activityThread.assigneeId }))\n : null\n }\n\n @FieldResolver(type => ActivityInstance)\n async activityInstance(@Root() activityThread: ActivityThread): Promise<ActivityInstance> {\n return await getRepository(ActivityInstance).findOneBy({ id: activityThread.activityInstanceId })\n }\n\n @FieldResolver(type => [ActivityApproval])\n async activityApprovals(\n @Root() activityThread: ActivityThread,\n @Ctx() context: ResolverContext\n ): Promise<ActivityApproval[]> {\n return await getRepository(ActivityApproval).findBy({\n activityThread: { id: activityThread.id }\n })\n }\n\n @FieldResolver(type => [ActivityThreadHistory])\n async activityThreadHistories(\n @Root() activityThread: ActivityThread,\n @Ctx() context: ResolverContext\n ): Promise<ActivityThreadHistory[]> {\n return await getRepository(ActivityThreadHistory).find({\n where: {\n originalId: activityThread.id\n },\n order: {\n version: 'ASC'\n }\n })\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() activityThread: ActivityThread): Promise<Domain> {\n return await getRepository(Domain).findOneBy({ id: activityThread.domainId })\n }\n\n @FieldResolver(type => User)\n async updater(@Root() activityThread: ActivityThread): Promise<User> {\n return activityThread.updaterId && (await getRepository(User).findOneBy({ id: activityThread.updaterId }))\n }\n\n @FieldResolver(type => User)\n async creator(@Root() activityThread: ActivityThread): Promise<User> {\n return activityThread.creatorId && (await getRepository(User).findOneBy({ id: activityThread.creatorId }))\n }\n\n @FieldResolver(type => User)\n async terminator(@Root() activityThread: ActivityThread): Promise<User> {\n return activityThread.terminatorId && (await getRepository(User).findOneBy({ id: activityThread.terminatorId }))\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"activity-thread-query.js","sourceRoot":"","sources":["../../../server/service/activity-thread/activity-thread-query.ts"],"names":[],"mappings":";;;;AACA,+CAA8F;AAE9F,yDAAgD;AAChD,iDAAuG;AAEvG,oFAA4E;AAC5E,6DAA2E;AAC3E,6DAAyD;AACzD,2FAAwF;AACxF,oFAA4E;AAC5E,uEAA8D;AAC9D,6EAAoE;AACpE,mDAAqE;AAGrE;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,SAAS,iBAAiB,CAAC,YAAiB,EAAE,QAA4C;IACxF,MAAM,KAAK,GAAG,IAAA,8BAAc,EAAC,QAAQ,EAAE,IAAI,CAAC,EAAE;QAC5C,MAAM,KAAK,GAAG,mCAAmB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA;QACzD,MAAM,QAAQ,GAAG,IAAA,qBAAa,EAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,uCAAgB,CAAC,CAAC,CAAC,mCAAc,CAAC,CAAC,QAAQ,CAAA;QAC3F,MAAM,MAAM,GAAG,QAAQ,CAAC,0BAA0B,CAAC,IAAI,CAAC,CAAA;QAExD,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,SAAS,CAAA;QAClB,CAAC;QAED,MAAM,MAAM,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;QAE5E,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAA;IAC1D,CAAC,CAAC,CAAA;IAEF,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,EAAE;QACzD,iEAAiE;QACjE,IAAI,MAAM,EAAE,CAAC;YACX,YAAY,CAAC,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC,CAAA;QAC5C,CAAC;QAED,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,UAAU,EAAE,SAAS,CAAC,CAAA;IAC5G,CAAC,CAAC,CAAA;AACJ,CAAC;AAGM,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IAExB,AAAN,KAAK,CAAC,cAAc,CAAY,EAAU,EAAS,OAAwB;QACzE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAEhC,MAAM,MAAM,GAAG,MAAM,IAAA,qBAAa,EAAC,mCAAc,CAAC,CAAC,OAAO,CAAC;YACzD,KAAK,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,MAAM,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE;SACzC,CAAC,CAAA;QAEF,oEAAoE;QACpE,IAAI,MAAM;YAAE,MAAM,IAAA,wCAAmB,EAAC,MAAM,EAAE,OAAO,CAAC,CAAA;QAEtD,OAAO,MAAM,CAAA;IACf,CAAC;IAIK,AAAN,KAAK,CAAC,eAAe,CACM,MAAiB,EACnC,OAAwB;QAE/B,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAEhC,MAAM,YAAY,GAAG,IAAA,qCAA6B,EAAC;YACjD,MAAM;YACN,MAAM;YACN,UAAU,EAAE,IAAA,qBAAa,EAAC,mCAAc,CAAC;YACzC,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC;SACrC,CAAC,CAAA;QAEF,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,YAAY,CAAC,eAAe,EAAE,CAAA;QAE3D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;IACzB,CAAC;IAGK,AAAN,KAAK,CAAC,QAAQ,CACa,MAAiB,EACnC,OAAwB;QAE/B,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAEpC,IAAI,GAAG,MAAM,IAAA,qBAAa,EAAC,gBAAI,CAAC,CAAC,OAAO,CAAC;YACvC,KAAK,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE;YACtB,SAAS,EAAE,CAAC,OAAO,CAAC;SACrB,CAAC,CAAA;QACF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAEzF,MAAM,YAAY,GAAG,IAAA,qCAA6B,EAAC;YACjD,UAAU,EAAE,IAAA,qBAAa,EAAC,mCAAc,CAAC;YACzC,qEAAqE;YACrE,MAAM,EAAE,EAAE,GAAG,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE;YACnC,MAAM;YACN,KAAK,EAAE,IAAI;YACX,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC;YACpC,UAAU,EAAE;gBACV,IAAI,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAChE,WAAW,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC9E,QAAQ,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,kBAAkB,EAAE;aACzE;SACF,CAAC;aACC,kBAAkB,CAAC,qBAAqB,EAAE,IAAI,CAAC;YAChD,gDAAgD;aAC/C,QAAQ,CAAC,IAAA,uCAAkB,EAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;QAE3D,iBAAiB,CAAC,YAAY,EAAE,MAAM,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAA;QAEtD,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,YAAY,CAAC,eAAe,EAAE,CAAA;QAE3D,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;IACzB,CAAC;IAGK,AAAN,KAAK,CAAC,QAAQ,CACa,MAAiB,EACnC,OAAwB;QAE/B,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAEpC,MAAM,MAAM,GAAG,CAAC,yCAAoB,CAAC,KAAK,EAAE,yCAAoB,CAAC,OAAO,CAAC,CAAA;QAEzE,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,MAAM,IAAA,qCAA6B,EAAC;YACzD,UAAU,EAAE,IAAA,qBAAa,EAAC,mCAAc,CAAC;YACzC,MAAM;YACN,MAAM;YACN,KAAK,EAAE,IAAI;YACX,WAAW,EAAE,CAAC,MAAM,EAAE,aAAa,CAAC;YACpC,UAAU,EAAE;gBACV,IAAI,EAAE,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAChE,WAAW,EAAE,EAAE,UAAU,EAAE,aAAa,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC9E,QAAQ,EAAE,EAAE,UAAU,EAAE,UAAU,EAAE,cAAc,EAAE,kBAAkB,EAAE;aACzE;SACF,CAAC;aACC,QAAQ,CAAC,0BAA0B,EAAE,EAAE,MAAM,EAAE,CAAC;aAChD,QAAQ,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC;aAClD,eAAe,EAAE,CAAA;QAEpB,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAA;IACzB,CAAC;IAGK,AAAN,KAAK,CAAC,QAAQ,CAAS,cAA8B;QACnD,OAAO,cAAc,CAAC,UAAU;YAC9B,CAAC,CAAC,cAAc,CAAC,QAAQ,IAAI,CAAC,MAAM,IAAA,qBAAa,EAAC,gBAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,cAAc,CAAC,UAAU,EAAE,CAAC,CAAC;YACrG,CAAC,CAAC,IAAI,CAAA;IACV,CAAC;IAGK,AAAN,KAAK,CAAC,gBAAgB,CAAS,cAA8B;QAC3D,OAAO,MAAM,IAAA,qBAAa,EAAC,uCAAgB,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,cAAc,CAAC,kBAAkB,EAAE,CAAC,CAAA;IACnG,CAAC;IAGK,AAAN,KAAK,CAAC,iBAAiB,CACb,cAA8B,EAC/B,OAAwB;QAE/B,OAAO,MAAM,IAAA,qBAAa,EAAC,uCAAgB,CAAC,CAAC,MAAM,CAAC;YAClD,cAAc,EAAE,EAAE,EAAE,EAAE,cAAc,CAAC,EAAE,EAAE;SAC1C,CAAC,CAAA;IACJ,CAAC;IAGK,AAAN,KAAK,CAAC,uBAAuB,CACnB,cAA8B,EAC/B,OAAwB;QAE/B,OAAO,MAAM,IAAA,qBAAa,EAAC,kDAAqB,CAAC,CAAC,IAAI,CAAC;YACrD,KAAK,EAAE;gBACL,UAAU,EAAE,cAAc,CAAC,EAAE;aAC9B;YACD,KAAK,EAAE;gBACL,OAAO,EAAE,KAAK;aACf;SACF,CAAC,CAAA;IACJ,CAAC;IAGK,AAAN,KAAK,CAAC,MAAM,CAAS,cAA8B;QACjD,OAAO,MAAM,IAAA,qBAAa,EAAC,cAAM,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,cAAc,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC/E,CAAC;IAGK,AAAN,KAAK,CAAC,OAAO,CAAS,cAA8B;QAClD,OAAO,cAAc,CAAC,SAAS,IAAI,CAAC,MAAM,IAAA,qBAAa,EAAC,gBAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,cAAc,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;IAC5G,CAAC;IAGK,AAAN,KAAK,CAAC,OAAO,CAAS,cAA8B;QAClD,OAAO,cAAc,CAAC,SAAS,IAAI,CAAC,MAAM,IAAA,qBAAa,EAAC,gBAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,cAAc,CAAC,SAAS,EAAE,CAAC,CAAC,CAAA;IAC5G,CAAC;IAGK,AAAN,KAAK,CAAC,UAAU,CAAS,cAA8B;QACrD,OAAO,cAAc,CAAC,YAAY,IAAI,CAAC,MAAM,IAAA,qBAAa,EAAC,gBAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,cAAc,CAAC,YAAY,EAAE,CAAC,CAAC,CAAA;IAClH,CAAC;CACF,CAAA;AA5JY,kDAAmB;AAExB;IADL,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,mCAAe,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC;IAC1E,mBAAA,IAAA,kBAAG,EAAC,IAAI,CAAC,CAAA;IAAc,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;yDAWjD;AAIK;IAFL,IAAA,wBAAS,EAAC,yFAAyF,CAAC;IACpG,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,4CAAkB,EAAE,EAAE,WAAW,EAAE,mCAAmC,EAAE,CAAC;IAExF,mBAAA,IAAA,mBAAI,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAS,CAAC,CAAA;IACvB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAD2B,iBAAS;;0DAe3C;AAGK;IADL,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,4CAAkB,EAAE,EAAE,WAAW,EAAE,iCAAiC,EAAE,CAAC;IAEtF,mBAAA,IAAA,mBAAI,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAS,CAAC,CAAA;IACvB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAD2B,iBAAS;;mDAiC3C;AAGK;IADL,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,4CAAkB,EAAE,EAAE,WAAW,EAAE,0DAA0D,EAAE,CAAC;IAE/G,mBAAA,IAAA,mBAAI,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAS,CAAC,CAAA;IACvB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAD2B,iBAAS;;mDAwB3C;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,CAAC;IACZ,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAiB,mCAAc;;mDAIpD;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,uCAAgB,CAAC;IAChB,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAiB,mCAAc;;2DAE5D;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,uCAAgB,CAAC,CAAC;IAEvC,mBAAA,IAAA,mBAAI,GAAE,CAAA;IACN,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CADkB,mCAAc;;4DAMvC;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,kDAAqB,CAAC,CAAC;IAE5C,mBAAA,IAAA,mBAAI,GAAE,CAAA;IACN,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CADkB,mCAAc;;kEAWvC;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,CAAC;IAChB,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAiB,mCAAc;;iDAElD;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,CAAC;IACb,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAiB,mCAAc;;kDAEnD;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,CAAC;IACb,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAiB,mCAAc;;kDAEnD;AAGK;IADL,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,CAAC;IACV,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAiB,mCAAc;;qDAEtD;8BA3JU,mBAAmB;IAD/B,IAAA,uBAAQ,EAAC,mCAAc,CAAC;GACZ,mBAAmB,CA4J/B","sourcesContent":["import { Brackets } from 'typeorm'\nimport { Arg, Args, Ctx, Directive, FieldResolver, Query, Resolver, Root } from 'type-graphql'\n\nimport { User } from '@things-factory/auth-base'\nimport { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'\n\nimport { ActivityInstance } from '../activity-instance/activity-instance.js'\nimport { ActivityThread, ActivityThreadStatus } from './activity-thread.js'\nimport { myOpenThreadsWhere } from './my-open-threads.js'\nimport { assertMayReadThread } from '../../controllers/activity-read/assert-may-read.js'\nimport { ActivityApproval } from '../activity-approval/activity-approval.js'\nimport { ActivityThreadList } from './activity-thread-type.js'\nimport { ActivityThreadHistory } from './activity-thread-history.js'\nimport { TODO_INSTANCE_SORTS, todoOrderTerms } from './todo-order.js'\n\n\n/**\n * 「할 일」 목록의 정렬 — **기한이 없는 것은 뒤로 간다.**\n *\n * ── 무엇이 잘못되고 있었나 (2026-09-06) ────────────────────────────────────\n * 화면의 기본 정렬은 `dueAt` 오름차순이다. 급한 것부터 보라는 뜻인데, **기한이 없는 것이 맨 위에\n * 왔다.** 실측(sqlite): 9건 중 기한 없는 6건이 먼저 나오고 「3일 지남」 3건이 맨 아래였다.\n *\n * NULL 을 앞에 둘지 뒤에 둘지는 **DB 마다 다르다** — sqlite 는 오름차순에서 NULL 이 먼저, postgres 는\n * 나중이다. 그래서 같은 코드가 개발 환경과 운영 환경에서 다른 순서를 낸다.\n *\n * ── 왜 NULLS LAST 를 쓰지 않나 ─────────────────────────────────────────────\n * `ORDER BY ... NULLS LAST` 는 postgres · oracle 문법이다. mysql · mssql 에서는 구문 오류가 난다.\n * 이 프레임워크는 다섯 드라이버를 다 지켜야 한다.\n *\n * `CASE WHEN ... IS NULL THEN 1 ELSE 0 END` 는 표준 SQL 이고 다섯 곳에서 다 돈다. 컬럼 이름은\n * 손으로 적지 않고 TypeORM 의 메타데이터에서 꺼낸다 — 이 프로젝트의 명명 규칙이 snake_case 라\n * `dueAt` 은 실제로 `due_at` 이다(shell 의 NamingStrategy).\n *\n * ── 공용 함수를 고치지 않는다 ──────────────────────────────────────────────\n * `getQueryBuilderFromListParams` 는 136개 꾸러미가 함께 쓴다. 정렬은 이 목록의 사정이므로\n * 여기서 맡는다 — 그 함수에는 정렬을 넘기지 않고(빈 배열) 아래에서 직접 건다.\n */\n\nfunction applyTodoSortings(queryBuilder: any, sortings: { name: string; desc?: boolean }[]) {\n const terms = todoOrderTerms(sortings, name => {\n const alias = TODO_INSTANCE_SORTS.has(name) ? 'ai' : 'at'\n const metadata = getRepository(alias === 'ai' ? ActivityInstance : ActivityThread).metadata\n const column = metadata.findColumnWithPropertyName(name)\n\n if (!column) {\n return undefined\n }\n\n const escape = (part: string) => queryBuilder.connection.driver.escape(part)\n\n return `${escape(alias)}.${escape(column.databaseName)}`\n })\n\n terms.forEach(({ expression, direction, select }, index) => {\n /* 식은 select 에 이름 붙여 올린다 — orderBy 는 식을 못 받는다(todo-order 머리말). */\n if (select) {\n queryBuilder.addSelect(select, expression)\n }\n\n index === 0 ? queryBuilder.orderBy(expression, direction) : queryBuilder.addOrderBy(expression, direction)\n })\n}\n\n@Resolver(ActivityThread)\nexport class ActivityThreadQuery {\n @Query(returns => ActivityThread!, { nullable: true, description: 'To fetch a ActivityThread' })\n async activityThread(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<ActivityThread> {\n const { domain } = context.state\n\n const thread = await getRepository(ActivityThread).findOne({\n where: { domain: { id: domain.id }, id }\n })\n\n /* 없는 건은 없다고(null). 있는데 못 읽는 건은 이름 붙여 거절한다 — § assert-may-read.ts */\n if (thread) await assertMayReadThread(thread, context)\n\n return thread\n }\n\n @Directive('@privilege(category: \"activity-instance\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => ActivityThreadList, { description: 'To fetch multiple ActivityThreads' })\n async activityThreads(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ActivityThreadList> {\n const { domain } = context.state\n\n const queryBuilder = getQueryBuilderFromListParams({\n domain,\n params,\n repository: getRepository(ActivityThread),\n searchables: ['name', 'description']\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n @Query(returns => ActivityThreadList, { description: 'To fetch my own ActivityThreads' })\n async todoList(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ActivityThreadList> {\n var { domain, user } = context.state\n\n user = await getRepository(User).findOne({\n where: { id: user.id },\n relations: ['roles']\n })\n const roles = user.roles.filter(role => role.domainId === domain.id).map(role => role.id)\n\n const queryBuilder = getQueryBuilderFromListParams({\n repository: getRepository(ActivityThread),\n /* 정렬은 아래에서 직접 건다(applyTodoSortings 머리말) — 여기에 넘기면 NULL 자리를 못 정한다. */\n params: { ...params, sortings: [] },\n domain,\n alias: 'at',\n searchables: ['name', 'description'],\n filtersMap: {\n name: { columnName: 'name', relationColumn: 'activityInstance' },\n description: { columnName: 'description', relationColumn: 'activityInstance' },\n priority: { columnName: 'priority', relationColumn: 'activityInstance' }\n }\n })\n .innerJoinAndSelect('at.activityInstance', 'ai')\n /* 「내 앞에 있는 일」의 정의는 한 자리에 있다 — 달력도 같은 것을 읽는다. */\n .andWhere(myOpenThreadsWhere({ userId: user.id, roles }))\n\n applyTodoSortings(queryBuilder, params.sortings || [])\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n\n @Query(returns => ActivityThreadList, { description: 'To fetch the tasks(ActivityThreads) which has done by me' })\n async doneList(\n @Args(type => ListParam) params: ListParam,\n @Ctx() context: ResolverContext\n ): Promise<ActivityThreadList> {\n var { domain, user } = context.state\n\n const status = [ActivityThreadStatus.Ended, ActivityThreadStatus.Aborted]\n\n const [items, total] = await getQueryBuilderFromListParams({\n repository: getRepository(ActivityThread),\n params,\n domain,\n alias: 'at',\n searchables: ['name', 'description'],\n filtersMap: {\n name: { columnName: 'name', relationColumn: 'activityInstance' },\n description: { columnName: 'description', relationColumn: 'activityInstance' },\n priority: { columnName: 'priority', relationColumn: 'activityInstance' }\n }\n })\n .andWhere('at.state IN (:...status)', { status })\n .andWhere('at.assignee = :user', { user: user.id })\n .getManyAndCount()\n\n return { items, total }\n }\n\n @FieldResolver(type => User)\n async assignee(@Root() activityThread: ActivityThread): Promise<User> {\n return activityThread.assigneeId\n ? activityThread.assignee || (await getRepository(User).findOneBy({ id: activityThread.assigneeId }))\n : null\n }\n\n @FieldResolver(type => ActivityInstance)\n async activityInstance(@Root() activityThread: ActivityThread): Promise<ActivityInstance> {\n return await getRepository(ActivityInstance).findOneBy({ id: activityThread.activityInstanceId })\n }\n\n @FieldResolver(type => [ActivityApproval])\n async activityApprovals(\n @Root() activityThread: ActivityThread,\n @Ctx() context: ResolverContext\n ): Promise<ActivityApproval[]> {\n return await getRepository(ActivityApproval).findBy({\n activityThread: { id: activityThread.id }\n })\n }\n\n @FieldResolver(type => [ActivityThreadHistory])\n async activityThreadHistories(\n @Root() activityThread: ActivityThread,\n @Ctx() context: ResolverContext\n ): Promise<ActivityThreadHistory[]> {\n return await getRepository(ActivityThreadHistory).find({\n where: {\n originalId: activityThread.id\n },\n order: {\n version: 'ASC'\n }\n })\n }\n\n @FieldResolver(type => Domain)\n async domain(@Root() activityThread: ActivityThread): Promise<Domain> {\n return await getRepository(Domain).findOneBy({ id: activityThread.domainId })\n }\n\n @FieldResolver(type => User)\n async updater(@Root() activityThread: ActivityThread): Promise<User> {\n return activityThread.updaterId && (await getRepository(User).findOneBy({ id: activityThread.updaterId }))\n }\n\n @FieldResolver(type => User)\n async creator(@Root() activityThread: ActivityThread): Promise<User> {\n return activityThread.creatorId && (await getRepository(User).findOneBy({ id: activityThread.creatorId }))\n }\n\n @FieldResolver(type => User)\n async terminator(@Root() activityThread: ActivityThread): Promise<User> {\n return activityThread.terminatorId && (await getRepository(User).findOneBy({ id: activityThread.terminatorId }))\n }\n}\n"]}
|
|
@@ -6,6 +6,7 @@ const graphql_yoga_1 = require("graphql-yoga");
|
|
|
6
6
|
const type_graphql_1 = require("type-graphql");
|
|
7
7
|
const shell_1 = require("@things-factory/shell");
|
|
8
8
|
const activity_thread_js_1 = require("./activity-thread.js");
|
|
9
|
+
const subscription_filters_js_1 = require("../subscription/subscription-filters.js");
|
|
9
10
|
let ActivityThreadSubscription = class ActivityThreadSubscription {
|
|
10
11
|
activityThread(payload) {
|
|
11
12
|
return payload.activityThread;
|
|
@@ -23,14 +24,7 @@ tslib_1.__decorate([
|
|
|
23
24
|
if (!user.domains?.find(d => d.subdomain === subdomain) && !(await process.superUserGranted(domain, user))) {
|
|
24
25
|
throw new Error(`domain(${subdomain}) is not working for user(${user.email}).`);
|
|
25
26
|
}
|
|
26
|
-
return (0, graphql_yoga_1.pipe)(shell_1.pubsub.subscribe('activity-thread'), (0, graphql_yoga_1.filter)((payload) =>
|
|
27
|
-
const { activityThread } = payload;
|
|
28
|
-
const { domainId } = activityThread;
|
|
29
|
-
if (domainId !== domain?.id) {
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
return activityThread.assigneeId === user.id;
|
|
33
|
-
}));
|
|
27
|
+
return (0, graphql_yoga_1.pipe)(shell_1.pubsub.subscribe('activity-thread'), (0, graphql_yoga_1.filter)((payload) => (0, subscription_filters_js_1.hearsThread)(payload.activityThread, domain, user.id)));
|
|
34
28
|
}
|
|
35
29
|
}),
|
|
36
30
|
tslib_1.__param(0, (0, type_graphql_1.Root)()),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity-thread-subscription.js","sourceRoot":"","sources":["../../../server/service/activity-thread/activity-thread-subscription.ts"],"names":[],"mappings":";;;;AAAA,+CAA2C;AAC3C,+CAA2D;AAE3D,iDAA8C;AAE9C,6DAAqD;
|
|
1
|
+
{"version":3,"file":"activity-thread-subscription.js","sourceRoot":"","sources":["../../../server/service/activity-thread/activity-thread-subscription.ts"],"names":[],"mappings":";;;;AAAA,+CAA2C;AAC3C,+CAA2D;AAE3D,iDAA8C;AAE9C,6DAAqD;AACrD,qFAAqE;AAG9D,IAAM,0BAA0B,GAAhC,MAAM,0BAA0B;IAoBrC,cAAc,CAAS,OAA2C;QAChE,OAAO,OAAO,CAAC,cAAc,CAAA;IAC/B,CAAC;CACF,CAAA;AAvBY,gEAA0B;AAoBrC;IAnBC,IAAA,2BAAY,EAAC;QACZ,SAAS,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE;YAC3C,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;YACtC,MAAM,SAAS,GAAG,MAAM,EAAE,SAAS,CAAA;YAEnC,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAA;YACpC,CAAC;YAED,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,IAAI,CAAC,CAAC,MAAM,OAAO,CAAC,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,EAAE,CAAC;gBAC3G,MAAM,IAAI,KAAK,CAAC,UAAU,SAAS,6BAA6B,IAAI,CAAC,KAAK,IAAI,CAAC,CAAA;YACjF,CAAC;YAED,OAAO,IAAA,mBAAI,EACT,cAAM,CAAC,SAAS,CAAC,iBAAiB,CAAC,EACnC,IAAA,qBAAM,EAAC,CAAC,OAA2C,EAAE,EAAE,CAAC,IAAA,qCAAW,EAAC,OAAO,CAAC,cAAc,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,CAAC,CAC9G,CAAA;QACH,CAAC;KACF,CAAC;IACc,mBAAA,IAAA,mBAAI,GAAE,CAAA;;;4CAA+C,mCAAc;gEAElF;qCAtBU,0BAA0B;IADtC,IAAA,uBAAQ,EAAC,mCAAc,CAAC;GACZ,0BAA0B,CAuBtC","sourcesContent":["import { filter, pipe } from 'graphql-yoga'\nimport { Resolver, Root, Subscription } from 'type-graphql'\n\nimport { pubsub } from '@things-factory/shell'\n\nimport { ActivityThread } from './activity-thread.js'\nimport { hearsThread } from '../subscription/subscription-filters.js'\n\n@Resolver(ActivityThread)\nexport class ActivityThreadSubscription {\n @Subscription({\n subscribe: async ({ args, context, info }) => {\n const { domain, user } = context.state\n const subdomain = domain?.subdomain\n\n if (!domain) {\n throw new Error('domain required')\n }\n\n if (!user.domains?.find(d => d.subdomain === subdomain) && !(await process.superUserGranted(domain, user))) {\n throw new Error(`domain(${subdomain}) is not working for user(${user.email}).`)\n }\n\n return pipe(\n pubsub.subscribe('activity-thread'),\n filter((payload: { activityThread: ActivityThread }) => hearsThread(payload.activityThread, domain, user.id))\n )\n }\n })\n activityThread(@Root() payload: { activityThread: ActivityThread }): ActivityThread {\n return payload.activityThread\n }\n}\n"]}
|
|
@@ -16,8 +16,8 @@ export * from './work-door/work-door-not-used.js';
|
|
|
16
16
|
export * from './work-door/work-door-journal.js';
|
|
17
17
|
export * from './work-door/work-door-journal-service.js';
|
|
18
18
|
export * from './work-door/work-door-service.js';
|
|
19
|
-
export declare const entities: (typeof import("./activity/activity.js").Activity | typeof import("./activity-approval/activity-approval.js").ActivityApproval | typeof import("./activity-thread/activity-thread.js").ActivityThread | typeof import("./activity-instance/activity-instance.js").ActivityInstance | typeof import("./installable-activity/installable-activity.js").InstallableActivity | typeof import("./activity-template/activity-template.js").ActivityTemplate | typeof import("./activity
|
|
19
|
+
export declare const entities: (typeof import("./activity/activity.js").Activity | typeof import("./activity-approval/activity-approval.js").ActivityApproval | typeof import("./activity-thread/activity-thread.js").ActivityThread | typeof import("./activity-instance/activity-instance.js").ActivityInstance | typeof import("./installable-activity/installable-activity.js").InstallableActivity | typeof import("./activity-template/activity-template.js").ActivityTemplate | typeof import("./activity/activity-history.js").ActivityHistory | typeof import("./activity-instance/activity-instance-history.js").ActivityInstanceHistory | typeof import("./activity-template/activity-template-history.js").ActivityTemplateHistory | typeof import("./activity-thread/activity-thread-history.js").ActivityThreadHistory | typeof import("./activity-summary/activity-summary.js").ActivitySummary | typeof import("./work-door/work-door-not-used.js").WorkDoorNotUsed | typeof import("./work-door/work-door-journal.js").WorkDoorJournal)[];
|
|
20
20
|
export declare const subscribers: (typeof import("./activity-approval/event-subscriber.js").ActivityApprovalSubscriber | typeof import("./activity/event-subscriber.js").ActivityHistoryEntitySubscriber | typeof import("./activity/declaration-guard-subscriber.js").ActivityDeclarationGuardSubscriber | typeof import("./activity-instance/event-subscriber.js").ActivityInstanceSubscriber | typeof import("./activity-instance/event-subscriber.js").ActivityInstanceHistoryEntitySubscriber | typeof import("./activity-thread/event-subscriber.js").ActivityThreadSubscriber | typeof import("./activity-thread/event-subscriber.js").ActivityThreadHistoryEntitySubscriber)[];
|
|
21
21
|
export declare const schema: {
|
|
22
|
-
resolverClasses: (typeof import("./activity-stats/activity-stats-query.js").ActivityStatsQuery | typeof import("./activity-approval/activity-approval-query.js").ActivityApprovalQuery | typeof import("./activity-approval/activity-approval-mutation.js").ActivityApprovalMutation | typeof import("./activity-approval/activity-approval-subscription.js").ActivityApprovalSubscription | typeof import("./activity/activity-mutation.js").ActivityMutation | typeof import("./activity/activity-query.js").ActivityQuery | typeof import("./activity-instance/activity-instance-mutation.js").ActivityInstanceMutation | typeof import("./activity-instance/activity-instance-query.js").ActivityInstanceQuery | typeof import("./activity-instance/activity-instance-
|
|
22
|
+
resolverClasses: (typeof import("./activity-stats/activity-stats-query.js").ActivityStatsQuery | typeof import("./activity-approval/activity-approval-query.js").ActivityApprovalQuery | typeof import("./activity-approval/activity-approval-mutation.js").ActivityApprovalMutation | typeof import("./activity-approval/activity-approval-subscription.js").ActivityApprovalSubscription | typeof import("./activity/activity-mutation.js").ActivityMutation | typeof import("./activity/activity-query.js").ActivityQuery | typeof import("./activity-instance/activity-instance-mutation.js").ActivityInstanceMutation | typeof import("./activity-instance/activity-instance-query.js").ActivityInstanceQuery | typeof import("./activity-instance/activity-instance-subscription.js").ActivityInstanceSubscription | typeof import("./activity-template/activity-template-mutation.js").ActivityTemplateMutation | typeof import("./activity-template/activity-template-query.js").ActivityTemplateQuery | typeof import("./activity-thread/activity-thread-mutation.js").ActivityThreadMutation | typeof import("./activity-thread/activity-thread-query.js").ActivityThreadQuery | typeof import("./activity-thread/activity-thread-history-query.js").ActivityThreadHistoryQuery | typeof import("./activity-thread/activity-thread-subscription.js").ActivityThreadSubscription | typeof import("./installable-activity/installable-activity-query.js").InstallableActivityQuery | typeof import("./installable-activity/installable-activity-mutation.js").InstallableActivityMutation | typeof import("./activity-summary/activity-summary-query.js").ActivitySummaryQuery | typeof import("./work-door/work-door-resolver.js").WorkDoorResolver)[];
|
|
23
23
|
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Who hears which worklist event — the filters behind the three subscriptions, kept free of
|
|
3
|
+
* entities and pubsub so they can be tested.
|
|
4
|
+
*
|
|
5
|
+
* Every filter compares the event's domain to the subscriber's first. A thread or an approval in
|
|
6
|
+
* another tenant must never reach this socket, even when the ids beside it happen to match.
|
|
7
|
+
* An event whose domain is not known is dropped: without it the filter cannot tell tenants apart.
|
|
8
|
+
*
|
|
9
|
+
* The ids are the entity's @RelationId fields. TypeORM fills them on the entity it hands the
|
|
10
|
+
* subscriber, on insert as well as update - measured, and held by tests/published-shape.test.ts.
|
|
11
|
+
*/
|
|
12
|
+
type DomainLike = {
|
|
13
|
+
id?: string;
|
|
14
|
+
} | null | undefined;
|
|
15
|
+
/** A thread reaches the person it is assigned to. */
|
|
16
|
+
export declare function hearsThread(thread: {
|
|
17
|
+
domainId?: string;
|
|
18
|
+
assigneeId?: string;
|
|
19
|
+
}, domain: DomainLike, userId: string): boolean;
|
|
20
|
+
/** An approval reaches its approver. */
|
|
21
|
+
export declare function hearsApproval(approval: {
|
|
22
|
+
domainId?: string;
|
|
23
|
+
approverId?: string;
|
|
24
|
+
}, domain: DomainLike, userId: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* An instance reaches whoever made it, and anyone holding the role it is waiting for. The roles are
|
|
27
|
+
* asked only after the domain matched — the lookup is not free and is never needed for another tenant.
|
|
28
|
+
*/
|
|
29
|
+
export declare function hearsInstance(instance: {
|
|
30
|
+
domainId?: string;
|
|
31
|
+
creatorId?: string;
|
|
32
|
+
assigneeRoleId?: string;
|
|
33
|
+
}, domain: DomainLike, userId: string, rolesOf: () => Promise<{
|
|
34
|
+
id: string;
|
|
35
|
+
}[]>): Promise<boolean>;
|
|
36
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Who hears which worklist event — the filters behind the three subscriptions, kept free of
|
|
4
|
+
* entities and pubsub so they can be tested.
|
|
5
|
+
*
|
|
6
|
+
* Every filter compares the event's domain to the subscriber's first. A thread or an approval in
|
|
7
|
+
* another tenant must never reach this socket, even when the ids beside it happen to match.
|
|
8
|
+
* An event whose domain is not known is dropped: without it the filter cannot tell tenants apart.
|
|
9
|
+
*
|
|
10
|
+
* The ids are the entity's @RelationId fields. TypeORM fills them on the entity it hands the
|
|
11
|
+
* subscriber, on insert as well as update - measured, and held by tests/published-shape.test.ts.
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.hearsThread = hearsThread;
|
|
15
|
+
exports.hearsApproval = hearsApproval;
|
|
16
|
+
exports.hearsInstance = hearsInstance;
|
|
17
|
+
function inDomain(eventDomainId, domain) {
|
|
18
|
+
return !!eventDomainId && !!domain?.id && eventDomainId === domain.id;
|
|
19
|
+
}
|
|
20
|
+
/** A thread reaches the person it is assigned to. */
|
|
21
|
+
function hearsThread(thread, domain, userId) {
|
|
22
|
+
return inDomain(thread?.domainId, domain) && thread.assigneeId === userId;
|
|
23
|
+
}
|
|
24
|
+
/** An approval reaches its approver. */
|
|
25
|
+
function hearsApproval(approval, domain, userId) {
|
|
26
|
+
return inDomain(approval?.domainId, domain) && approval.approverId === userId;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* An instance reaches whoever made it, and anyone holding the role it is waiting for. The roles are
|
|
30
|
+
* asked only after the domain matched — the lookup is not free and is never needed for another tenant.
|
|
31
|
+
*/
|
|
32
|
+
async function hearsInstance(instance, domain, userId, rolesOf) {
|
|
33
|
+
if (!inDomain(instance?.domainId, domain))
|
|
34
|
+
return false;
|
|
35
|
+
if (instance.creatorId === userId)
|
|
36
|
+
return true;
|
|
37
|
+
if (!instance.assigneeRoleId)
|
|
38
|
+
return false;
|
|
39
|
+
return (await rolesOf()).some(role => role.id === instance.assigneeRoleId);
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=subscription-filters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"subscription-filters.js","sourceRoot":"","sources":["../../../server/service/subscription/subscription-filters.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AASH,kCAEC;AAGD,sCAEC;AAMD,sCAWC;AA7BD,SAAS,QAAQ,CAAC,aAAiC,EAAE,MAAkB;IACrE,OAAO,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,IAAI,aAAa,KAAK,MAAM,CAAC,EAAE,CAAA;AACvE,CAAC;AAED,qDAAqD;AACrD,SAAgB,WAAW,CAAC,MAAkD,EAAE,MAAkB,EAAE,MAAc;IAChH,OAAO,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,UAAU,KAAK,MAAM,CAAA;AAC3E,CAAC;AAED,wCAAwC;AACxC,SAAgB,aAAa,CAAC,QAAoD,EAAE,MAAkB,EAAE,MAAc;IACpH,OAAO,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,QAAQ,CAAC,UAAU,KAAK,MAAM,CAAA;AAC/E,CAAC;AAED;;;GAGG;AACI,KAAK,UAAU,aAAa,CACjC,QAA4E,EAC5E,MAAkB,EAClB,MAAc,EACd,OAAwC;IAExC,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC;QAAE,OAAO,KAAK,CAAA;IACvD,IAAI,QAAQ,CAAC,SAAS,KAAK,MAAM;QAAE,OAAO,IAAI,CAAA;IAC9C,IAAI,CAAC,QAAQ,CAAC,cAAc;QAAE,OAAO,KAAK,CAAA;IAE1C,OAAO,CAAC,MAAM,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,QAAQ,CAAC,cAAc,CAAC,CAAA;AAC5E,CAAC","sourcesContent":["/**\n * Who hears which worklist event — the filters behind the three subscriptions, kept free of\n * entities and pubsub so they can be tested.\n *\n * Every filter compares the event's domain to the subscriber's first. A thread or an approval in\n * another tenant must never reach this socket, even when the ids beside it happen to match.\n * An event whose domain is not known is dropped: without it the filter cannot tell tenants apart.\n *\n * The ids are the entity's @RelationId fields. TypeORM fills them on the entity it hands the\n * subscriber, on insert as well as update - measured, and held by tests/published-shape.test.ts.\n */\n\ntype DomainLike = { id?: string } | null | undefined\n\nfunction inDomain(eventDomainId: string | undefined, domain: DomainLike): boolean {\n return !!eventDomainId && !!domain?.id && eventDomainId === domain.id\n}\n\n/** A thread reaches the person it is assigned to. */\nexport function hearsThread(thread: { domainId?: string; assigneeId?: string }, domain: DomainLike, userId: string) {\n return inDomain(thread?.domainId, domain) && thread.assigneeId === userId\n}\n\n/** An approval reaches its approver. */\nexport function hearsApproval(approval: { domainId?: string; approverId?: string }, domain: DomainLike, userId: string) {\n return inDomain(approval?.domainId, domain) && approval.approverId === userId\n}\n\n/**\n * An instance reaches whoever made it, and anyone holding the role it is waiting for. The roles are\n * asked only after the domain matched — the lookup is not free and is never needed for another tenant.\n */\nexport async function hearsInstance(\n instance: { domainId?: string; creatorId?: string; assigneeRoleId?: string },\n domain: DomainLike,\n userId: string,\n rolesOf: () => Promise<{ id: string }[]>\n): Promise<boolean> {\n if (!inDomain(instance?.domainId, domain)) return false\n if (instance.creatorId === userId) return true\n if (!instance.assigneeRoleId) return false\n\n return (await rolesOf()).some(role => role.id === instance.assigneeRoleId)\n}\n"]}
|
|
@@ -111,4 +111,19 @@ export declare function declaredDoors(): WorkDoorDeclaration[];
|
|
|
111
111
|
export declare function offeredSeatNames(): string[];
|
|
112
112
|
/** One door by form name, whichever module declared it. */
|
|
113
113
|
export declare function declaredDoor(name: string): WorkDoorDeclaration | undefined;
|
|
114
|
+
/**
|
|
115
|
+
* **Can this door be declared unused?** Not when it refuses on an empty line (ADR-0077 decision 3).
|
|
116
|
+
*
|
|
117
|
+
* "We do not use this door" means the work runs with no approval step (`ran-not-used`). `refuse`
|
|
118
|
+
* means the work cannot stand without an approval line. The two cannot hold for one door, and each of
|
|
119
|
+
* the three reasons says why: what an `irreversible` door does cannot be taken back, an
|
|
120
|
+
* `approval-is-the-act` door's work is the approval, and a `lowers-a-control` door lowers a control
|
|
121
|
+
* that stands. Accepting the declaration would leave the door screen showing the door as off while
|
|
122
|
+
* the product still demands approval - or, if the product honoured it, run those three kinds of work
|
|
123
|
+
* unapproved.
|
|
124
|
+
*
|
|
125
|
+
* Answers the reason, so the refusal can say which one. `run`, `as-established` and assignment doors
|
|
126
|
+
* answer nothing - they can be declared unused as before.
|
|
127
|
+
*/
|
|
128
|
+
export declare function whyNotUsedCannotBeDeclared(door: WorkDoorDeclaration): WhenNoLineBecause | undefined;
|
|
114
129
|
export {};
|
|
@@ -31,6 +31,7 @@ exports.registeredWorkDoors = registeredWorkDoors;
|
|
|
31
31
|
exports.declaredDoors = declaredDoors;
|
|
32
32
|
exports.offeredSeatNames = offeredSeatNames;
|
|
33
33
|
exports.declaredDoor = declaredDoor;
|
|
34
|
+
exports.whyNotUsedCannotBeDeclared = whyNotUsedCannotBeDeclared;
|
|
34
35
|
const registered = new Map();
|
|
35
36
|
/**
|
|
36
37
|
* An application declares its doors. Called at module import time, once per module.
|
|
@@ -64,4 +65,21 @@ function declaredDoor(name) {
|
|
|
64
65
|
}
|
|
65
66
|
return undefined;
|
|
66
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* **Can this door be declared unused?** Not when it refuses on an empty line (ADR-0077 decision 3).
|
|
70
|
+
*
|
|
71
|
+
* "We do not use this door" means the work runs with no approval step (`ran-not-used`). `refuse`
|
|
72
|
+
* means the work cannot stand without an approval line. The two cannot hold for one door, and each of
|
|
73
|
+
* the three reasons says why: what an `irreversible` door does cannot be taken back, an
|
|
74
|
+
* `approval-is-the-act` door's work is the approval, and a `lowers-a-control` door lowers a control
|
|
75
|
+
* that stands. Accepting the declaration would leave the door screen showing the door as off while
|
|
76
|
+
* the product still demands approval - or, if the product honoured it, run those three kinds of work
|
|
77
|
+
* unapproved.
|
|
78
|
+
*
|
|
79
|
+
* Answers the reason, so the refusal can say which one. `run`, `as-established` and assignment doors
|
|
80
|
+
* answer nothing - they can be declared unused as before.
|
|
81
|
+
*/
|
|
82
|
+
function whyNotUsedCannotBeDeclared(door) {
|
|
83
|
+
return door.kind === 'approval' && door.whenNoLine === 'refuse' ? door.because : undefined;
|
|
84
|
+
}
|
|
67
85
|
//# sourceMappingURL=work-door-declaration.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"work-door-declaration.js","sourceRoot":"","sources":["../../../server/service/work-door/work-door-declaration.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;;AAgFH,8CAEC;AAGD,kDAEC;AAGD,sCAEC;AAGD,4CAEC;AAGD,oCAUC;
|
|
1
|
+
{"version":3,"file":"work-door-declaration.js","sourceRoot":"","sources":["../../../server/service/work-door/work-door-declaration.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;;AAgFH,8CAEC;AAGD,kDAEC;AAGD,sCAEC;AAGD,4CAEC;AAGD,oCAUC;AAgBD,gEAEC;AAzDD,MAAM,UAAU,GAAG,IAAI,GAAG,EAAgC,CAAA;AAE1D;;;;;;GAMG;AACH,SAAgB,iBAAiB,CAAC,YAAkC;IAClE,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;AACnD,CAAC;AAED,sEAAsE;AACtE,SAAgB,mBAAmB;IACjC,OAAO,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAA;AACjC,CAAC;AAED,6DAA6D;AAC7D,SAAgB,aAAa;IAC3B,OAAO,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,CAAA;AAChE,CAAC;AAED,6EAA6E;AAC7E,SAAgB,gBAAgB;IAC9B,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AACtF,CAAC;AAED,2DAA2D;AAC3D,SAAgB,YAAY,CAAC,IAAY;IACvC,KAAK,MAAM,YAAY,IAAI,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;QAC/C,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAA;QAEjE,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,KAAK,CAAA;QACd,CAAC;IACH,CAAC;IAED,OAAO,SAAS,CAAA;AAClB,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,SAAgB,0BAA0B,CAAC,IAAyB;IAClE,OAAO,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAA;AAC5F,CAAC","sourcesContent":["/**\n * **What an application declares about its own work doors** (ADR-0069 decision 3, ADR-0077).\n *\n * ═══════════════════════════════════════════════════════════════════════════\n * ── Who says what ─────────────────────────────────────────────────────────\n * The form is installed by the product at boot, and the plant fills in who approves it. Filling it\n * in is the declaration that this factory uses that step. So two facts have two owners:\n *\n * ```\n * the list of doors, and what each one is the application - it declares them here\n * whether a door stands in this domain the worklist - it reads the activity and its line\n * ```\n *\n * An application registers its list; the screens and the judgement live here. Without that split the\n * worklist would have to know operato-plant's activities, and every application would carry its own\n * copy of the same screen (operato-warehouse asked for it second, which is what moved this).\n *\n * ── Registration happens at module import ─────────────────────────────────\n * Not on a bootstrap hook. A hook runs after the schema is built, which is too late for anything the\n * schema or a boot-time install reads - `declareAxes` in auth-base carries the same warning.\n *\n * ── Labels travel as keys, never as words ─────────────────────────────────\n * `labelKey` names a translation in the declaring module's own namespace. A word here would put one\n * product's vocabulary (\"plant\", \"factory floor\") on every other product's screen.\n * ═══════════════════════════════════════════════════════════════════════════\n */\n\n/**\n * What happens when the approval line is empty. **This records what each door already does** - it is\n * not a new policy (ADR-0077 decision 1).\n *\n * - `run` - the work happens and the approval step is skipped. The worklist writes a line saying so;\n * until that record existed there was no way to tell it from a factory that approved it.\n * - `refuse` - the caller is refused and told why the line does not stand.\n * - `as-established` - the branch depends on **the row's own history**: a period declared through\n * approval is withdrawn through approval, and one that stood without approval is simply removed.\n * Only a door whose branch turns on the row may use this, and both branches are tested. The\n * judgement stays with the door; the worklist asks it which way this row goes.\n */\nexport type WhenNoLine = 'refuse' | 'run' | 'as-established'\n\n/**\n * Why a door refuses rather than running. Two doors that both refuse can refuse for different\n * reasons, and an administrator reads the reason to know whether filling the line is the fix.\n *\n * - `irreversible` - what the door does cannot be taken back (`mutation-reversibility`).\n * - `approval-is-the-act` - the door's whole work **is** the approval. Letting it through with no\n * line would put an unsigned controlled document on the floor.\n * - `lowers-a-control` - the door lowers a control that stands: turning document control off, or\n * moving a maintenance due date. Such a door refuses whatever its reversibility says, because the\n * time that passed under the lowered control does not come back.\n */\nexport type WhenNoLineBecause = 'irreversible' | 'approval-is-the-act' | 'lowers-a-control'\n\ninterface DoorBase {\n /** The form name - the same key the callback is found by. Labels change; this does not. */\n name: string\n /** A translation key in the declaring module's namespace. Never a word. */\n labelKey: string\n /**\n * This door borrows another door's approval line. Written once, in one place: two doors carrying\n * the same line as a value drift, and then turning a control on and off are approved by different\n * people (ADR-0047 ⑨).\n */\n lineFollows?: string\n}\n\ntype ApprovalDoor = DoorBase & { kind: 'approval' } & (\n | { whenNoLine: 'run'; because?: never }\n | { whenNoLine: 'refuse' | 'as-established'; because: WhenNoLineBecause }\n )\n\n/**\n * `whenNoLine?: never` is the point of this type: an assignment door has no approval line, so the\n * field cannot be written here at all. Left optional it would be filled in one day with a value that\n * reads true and means nothing.\n */\ntype AssignmentDoor = DoorBase & { kind: 'assignment'; whenNoLine?: never; because?: never }\n\nexport type WorkDoorDeclaration = ApprovalDoor | AssignmentDoor\n\nexport interface WorkDoorRegistration {\n /** The declaring module, as its package's short name. It groups the screen and names the source. */\n module: string\n doors: readonly WorkDoorDeclaration[]\n /**\n * The role seats this module offers, by name.\n *\n * An approval line points at roles, so a domain with none of them cannot build one - and today\n * that is found out on the form screen, too late. The door screen counts how many of these stand\n * here and says what to do first. A domain's own roles are not counted: this number answers \"of\n * what the product offered\", and a line built from other roles works just as well.\n */\n seats?: readonly string[]\n}\n\nconst registered = new Map<string, WorkDoorRegistration>()\n\n/**\n * An application declares its doors. Called at module import time, once per module.\n *\n * Re-registering the same module replaces it rather than appending: a module imported twice under a\n * watch rebuild would otherwise show every door twice, and a screen that double-counts the doors\n * that need attention is one nobody trusts.\n */\nexport function registerWorkDoors(registration: WorkDoorRegistration): void {\n registered.set(registration.module, registration)\n}\n\n/** Every registration in this installation, in registration order. */\nexport function registeredWorkDoors(): WorkDoorRegistration[] {\n return [...registered.values()]\n}\n\n/** Every declared door, flattened, in registration order. */\nexport function declaredDoors(): WorkDoorDeclaration[] {\n return [...registered.values()].flatMap(one => [...one.doors])\n}\n\n/** Every role seat the declaring modules offer, by name, without repeats. */\nexport function offeredSeatNames(): string[] {\n return [...new Set([...registered.values()].flatMap(one => [...(one.seats ?? [])]))]\n}\n\n/** One door by form name, whichever module declared it. */\nexport function declaredDoor(name: string): WorkDoorDeclaration | undefined {\n for (const registration of registered.values()) {\n const found = registration.doors.find(door => door.name === name)\n\n if (found) {\n return found\n }\n }\n\n return undefined\n}\n\n/**\n * **Can this door be declared unused?** Not when it refuses on an empty line (ADR-0077 decision 3).\n *\n * \"We do not use this door\" means the work runs with no approval step (`ran-not-used`). `refuse`\n * means the work cannot stand without an approval line. The two cannot hold for one door, and each of\n * the three reasons says why: what an `irreversible` door does cannot be taken back, an\n * `approval-is-the-act` door's work is the approval, and a `lowers-a-control` door lowers a control\n * that stands. Accepting the declaration would leave the door screen showing the door as off while\n * the product still demands approval - or, if the product honoured it, run those three kinds of work\n * unapproved.\n *\n * Answers the reason, so the refusal can say which one. `run`, `as-established` and assignment doors\n * answer nothing - they can be declared unused as before.\n */\nexport function whyNotUsedCannotBeDeclared(door: WorkDoorDeclaration): WhenNoLineBecause | undefined {\n return door.kind === 'approval' && door.whenNoLine === 'refuse' ? door.because : undefined\n}\n"]}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { Refusal } from '@things-factory/shell';
|
|
2
|
+
import { type WhenNoLineBecause } from './work-door-declaration.js';
|
|
1
3
|
import { WorkDoorsType } from './work-door-type.js';
|
|
2
4
|
/**
|
|
3
5
|
* 이 공장의 결재 문 현황을 묻는 자리.
|
|
@@ -27,3 +29,4 @@ export declare class WorkDoorResolver {
|
|
|
27
29
|
/** 다시 쓰기로 했다. 선언을 지운다 — 지우면 그 문은 다시 조치 대상으로 돌아온다. */
|
|
28
30
|
useWorkDoorAgain(doorName: string, context: ResolverContext): Promise<WorkDoorsType>;
|
|
29
31
|
}
|
|
32
|
+
export declare function notUsedCannotBeDeclared(name: string, because: WhenNoLineBecause): Refusal;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.WorkDoorResolver = void 0;
|
|
4
|
+
exports.notUsedCannotBeDeclared = notUsedCannotBeDeclared;
|
|
4
5
|
const tslib_1 = require("tslib");
|
|
5
6
|
const type_graphql_1 = require("type-graphql");
|
|
6
7
|
const shell_1 = require("@things-factory/shell");
|
|
@@ -50,9 +51,19 @@ let WorkDoorResolver = class WorkDoorResolver {
|
|
|
50
51
|
*/
|
|
51
52
|
async declareWorkDoorNotUsed(doorName, because, context) {
|
|
52
53
|
const { domain, user, tx } = context.state;
|
|
53
|
-
|
|
54
|
+
const door = (0, work_door_declaration_js_1.declaredDoor)(doorName);
|
|
55
|
+
if (!door) {
|
|
54
56
|
throw new shell_2.Refusal('work-door-unknown', { name: doorName }, 'unknown task "{name}". use a task name from the status screen.');
|
|
55
57
|
}
|
|
58
|
+
/*
|
|
59
|
+
* **결재선 없이는 설 수 없는 문은 끌 수 없다**(ADR-0077 결정 3). 받아 두면 이 화면은 「꺼짐」이라
|
|
60
|
+
* 말하는데 제품은 계속 결재를 요구하고, 제품이 이 선언을 따르면 되돌릴 수 없는 일이 결재 없이 돈다.
|
|
61
|
+
* 까닭마다 문장이 다르다 — 관리자가 읽고 「결재선을 세우면 된다」까지 알아야 한다.
|
|
62
|
+
*/
|
|
63
|
+
const cannot = (0, work_door_declaration_js_1.whyNotUsedCannotBeDeclared)(door);
|
|
64
|
+
if (cannot) {
|
|
65
|
+
throw notUsedCannotBeDeclared(doorName, cannot);
|
|
66
|
+
}
|
|
56
67
|
if (!because?.trim()) {
|
|
57
68
|
throw new shell_2.Refusal('work-door-not-used-reason-missing', {}, 'enter why this task is not used.');
|
|
58
69
|
}
|
|
@@ -124,4 +135,13 @@ exports.WorkDoorResolver = WorkDoorResolver = tslib_1.__decorate([
|
|
|
124
135
|
(0, type_graphql_1.Resolver)(),
|
|
125
136
|
(0, type_graphql_1.UseMiddleware)(shell_2.SpeakRefusals)
|
|
126
137
|
], WorkDoorResolver);
|
|
138
|
+
/** The refusal for each reason. One code per reason, so each language has its own whole sentence. */
|
|
139
|
+
const NOT_USED_REFUSALS = {
|
|
140
|
+
irreversible: '"{name}" cannot be turned off. what it does cannot be undone, so it only runs through approval. set its approval line instead.',
|
|
141
|
+
'approval-is-the-act': '"{name}" cannot be turned off. its approval is the work itself. set its approval line instead.',
|
|
142
|
+
'lowers-a-control': '"{name}" cannot be turned off. it lowers a control that stands, so it only runs through approval. set its approval line instead.'
|
|
143
|
+
};
|
|
144
|
+
function notUsedCannotBeDeclared(name, because) {
|
|
145
|
+
return new shell_2.Refusal(`work-door-not-used-refused-${because}`, { name }, NOT_USED_REFUSALS[because]);
|
|
146
|
+
}
|
|
127
147
|
//# sourceMappingURL=work-door-resolver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"work-door-resolver.js","sourceRoot":"","sources":["../../../server/service/work-door/work-door-resolver.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"work-door-resolver.js","sourceRoot":"","sources":["../../../server/service/work-door/work-door-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["import { EntityManager } from 'typeorm'\n\nimport { Arg, Ctx, Directive, Mutation, Query, Resolver, UseMiddleware } from 'type-graphql'\n\nimport { Role } from '@things-factory/auth-base'\nimport { Domain, getRepository } from '@things-factory/shell'\nimport { Activity } from '../activity/activity.js'\n\nimport { Refusal, SpeakRefusals } from '@things-factory/shell'\n\nimport { activityNamedIn } from './activity-lookup.js'\nimport { doorsToFill, summarizeDoors, workDoorNotUsedBefore } from './work-door.js'\nimport { seatsOffered, seatsStanding, workDoorsFor } from './work-door-service.js'\nimport { declaredDoor, whyNotUsedCannotBeDeclared, type WhenNoLineBecause } from './work-door-declaration.js'\nimport { WorkDoorNotUsed } from './work-door-not-used.js'\nimport { WorkDoorsType, toDoorType } from './work-door-type.js'\nimport { WorkDoorEvent } from './work-door-journal.js'\nimport { noteWorkDoor } from './work-door-journal-service.js'\n\n/**\n * 이 공장의 결재 문 현황을 묻는 자리.\n *\n * ── 왜 질의인가 ────────────────────────────────────────────────────────────\n * 기동할 때 로그로 한 번 지나가는 사실이었다(`install-boot.ts`). 사람이 조치해야 하는 사실은\n * **물어볼 수 있어야** 한다 — 지나간 로그를 찾아 올라가게 하면 아무도 안 본다.\n *\n * ── 부모까지 보는 것은 `activityNamedIn` 의 규칙을 그대로 쓴다 ─────────────\n * 상신하는 쪽이 그 규칙으로 양식을 찾으므로, 보는 쪽이 다른 규칙으로 찾으면 **화면이 「없다」고 하는데\n * 실제로는 서는** 상태가 생긴다. 같은 함수를 부른다.\n */\n@Resolver()\n@UseMiddleware(SpeakRefusals)\nexport class WorkDoorResolver {\n @Directive('@privilege(category: \"activity\", privilege: \"query\", domainOwnerGranted: true)')\n @Query(returns => WorkDoorsType, {\n description: 'To see which approval steps this plant actually has standing, and which pass with nobody on them'\n })\n async workDoors(@Ctx() context: ResolverContext): Promise<WorkDoorsType> {\n const manager = getRepository(Activity).manager\n const { domain } = context.state\n const doors = await workDoorsFor(manager, domain)\n\n return {\n doors: doors.map(toDoorType),\n summary: summarizeDoors(doors),\n todo: doorsToFill(doors),\n seatsStanding: await seatsStanding(manager, domain),\n seatsOffered: seatsOffered()\n }\n }\n\n /**\n * **이 공장은 이 문을 안 쓴다**고 선언한다.\n *\n * ── 왜 사유를 받나 ──────────────────────────────────────────────────────\n * 이 선언은 승인 단계를 끄는 것이다. 반년 뒤 「왜 폐기 승인이 없나」를 묻는 사람이 나오고, 그때\n * 사유가 없으면 누가 왜 껐는지 알 수 없다. 사람과 시각은 표가 들고 이유는 사람이 적는다.\n *\n * ── 모르는 이름은 받지 않는다 ───────────────────────────────────────────\n * 오타로 선언하면 그 줄은 아무 문에도 안 걸리고, 정작 끄려던 문은 계속 조치 대상으로 남는다.\n * 끈 줄 알고 있는데 화면은 그대로다 — 화면이 그 오타를 말해 주지 않는다.\n */\n @Directive('@privilege(category: \"activity\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => WorkDoorsType, { description: 'To declare that this plant does not use one work door' })\n async declareWorkDoorNotUsed(\n @Arg('doorName') doorName: string,\n @Arg('because', { description: 'why — somebody will ask in six months' }) because: string,\n @Ctx() context: ResolverContext\n ): Promise<WorkDoorsType> {\n const { domain, user, tx } = context.state\n\n const door = declaredDoor(doorName)\n\n if (!door) {\n throw new Refusal(\n 'work-door-unknown',\n { name: doorName },\n 'unknown task \"{name}\". use a task name from the status screen.'\n )\n }\n\n /*\n * **결재선 없이는 설 수 없는 문은 끌 수 없다**(ADR-0077 결정 3). 받아 두면 이 화면은 「꺼짐」이라\n * 말하는데 제품은 계속 결재를 요구하고, 제품이 이 선언을 따르면 되돌릴 수 없는 일이 결재 없이 돈다.\n * 까닭마다 문장이 다르다 — 관리자가 읽고 「결재선을 세우면 된다」까지 알아야 한다.\n */\n const cannot = whyNotUsedCannotBeDeclared(door)\n\n if (cannot) {\n throw notUsedCannotBeDeclared(doorName, cannot)\n }\n\n if (!because?.trim()) {\n throw new Refusal('work-door-not-used-reason-missing', {}, 'enter why this task is not used.')\n }\n\n const repository = tx.getRepository(WorkDoorNotUsed)\n const existing = await repository.findOne({ where: { domain: { id: domain.id }, doorName } })\n\n await repository.save({\n ...(existing ?? {}),\n domain,\n doorName,\n because: because.trim(),\n declaredBy: user\n } as any)\n\n return await this.workDoors(context)\n }\n\n /** 다시 쓰기로 했다. 선언을 지운다 — 지우면 그 문은 다시 조치 대상으로 돌아온다. */\n @Directive('@privilege(category: \"activity\", privilege: \"mutation\", domainOwnerGranted: true)')\n @Directive('@transaction')\n @Mutation(returns => WorkDoorsType, { description: 'To withdraw the declaration and use that door again' })\n async useWorkDoorAgain(@Arg('doorName') doorName: string, @Ctx() context: ResolverContext): Promise<WorkDoorsType> {\n const { domain, user, tx } = context.state\n const repository = tx.getRepository(WorkDoorNotUsed)\n const existing = await repository.findOne({ where: { domain: { id: domain.id }, doorName }, relations: ['declaredBy'] })\n\n /* 없는 것을 지우라는 것은 이미 쓰고 있다는 뜻이다. 오류로 막지 않고 지금 현황을 낸다. */\n if (existing) {\n /*\n * **지우는 선언을 이력에 남긴다.** 왜 안 쓰기로 했고 누가 정했는지가 지우면 어디에도 없어진다\n * (ADR-0064 ③, 2026-09-17). 다시 선언할 때 그 내용을 여기서 읽는다.\n */\n await noteWorkDoor(\n tx,\n domain,\n {\n kind: WorkDoorEvent.NotUsedWithdrawn,\n door: existing.doorName,\n detail: workDoorNotUsedBefore(existing)\n },\n user\n )\n\n await repository.remove(existing)\n }\n\n return await this.workDoors(context)\n }\n}\n\n/** The refusal for each reason. One code per reason, so each language has its own whole sentence. */\nconst NOT_USED_REFUSALS: Record<WhenNoLineBecause, string> = {\n irreversible:\n '\"{name}\" cannot be turned off. what it does cannot be undone, so it only runs through approval. set its approval line instead.',\n 'approval-is-the-act': '\"{name}\" cannot be turned off. its approval is the work itself. set its approval line instead.',\n 'lowers-a-control':\n '\"{name}\" cannot be turned off. it lowers a control that stands, so it only runs through approval. set its approval line instead.'\n}\n\nexport function notUsedCannotBeDeclared(name: string, because: WhenNoLineBecause): Refusal {\n return new Refusal(`work-door-not-used-refused-${because}`, { name }, NOT_USED_REFUSALS[because])\n}\n"]}
|