@things-factory/calendar 10.1.203 → 10.1.206

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 (114) hide show
  1. package/dist-client/pages/calendar/calendar-list-page.d.ts +1 -9
  2. package/dist-client/pages/calendar/calendar-list-page.js +2 -27
  3. package/dist-client/pages/calendar/calendar-list-page.js.map +1 -1
  4. package/dist-client/pages/event/event-list-page.d.ts +5 -28
  5. package/dist-client/pages/event/event-list-page.js +65 -177
  6. package/dist-client/pages/event/event-list-page.js.map +1 -1
  7. package/dist-client/route.d.ts +1 -1
  8. package/dist-client/route.js +0 -3
  9. package/dist-client/route.js.map +1 -1
  10. package/dist-client/tsconfig.tsbuildinfo +1 -1
  11. package/dist-server/index.d.ts +1 -0
  12. package/dist-server/index.js +5 -0
  13. package/dist-server/index.js.map +1 -1
  14. package/dist-server/role-tasks.d.ts +2 -0
  15. package/dist-server/role-tasks.js +16 -0
  16. package/dist-server/role-tasks.js.map +1 -0
  17. package/dist-server/service/attendee/attendee-query.d.ts +7 -4
  18. package/dist-server/service/attendee/attendee-query.js +34 -25
  19. package/dist-server/service/attendee/attendee-query.js.map +1 -1
  20. package/dist-server/service/attendee/attendee-service.d.ts +41 -0
  21. package/dist-server/service/attendee/attendee-service.js +90 -0
  22. package/dist-server/service/attendee/attendee-service.js.map +1 -0
  23. package/dist-server/service/attendee/attendee-type.d.ts +3 -15
  24. package/dist-server/service/attendee/attendee-type.js +12 -53
  25. package/dist-server/service/attendee/attendee-type.js.map +1 -1
  26. package/dist-server/service/attendee/attendee.d.ts +24 -7
  27. package/dist-server/service/attendee/attendee.js +99 -23
  28. package/dist-server/service/attendee/attendee.js.map +1 -1
  29. package/dist-server/service/attendee/index.d.ts +1 -2
  30. package/dist-server/service/attendee/index.js +1 -2
  31. package/dist-server/service/attendee/index.js.map +1 -1
  32. package/dist-server/service/calendar/calendar-mutation.d.ts +1 -3
  33. package/dist-server/service/calendar/calendar-mutation.js +21 -94
  34. package/dist-server/service/calendar/calendar-mutation.js.map +1 -1
  35. package/dist-server/service/calendar/calendar-query.d.ts +1 -1
  36. package/dist-server/service/calendar/calendar-query.js +15 -17
  37. package/dist-server/service/calendar/calendar-query.js.map +1 -1
  38. package/dist-server/service/calendar/calendar-service.d.ts +10 -0
  39. package/dist-server/service/calendar/calendar-service.js +58 -0
  40. package/dist-server/service/calendar/calendar-service.js.map +1 -0
  41. package/dist-server/service/calendar/calendar-type.d.ts +1 -4
  42. package/dist-server/service/calendar/calendar-type.js +13 -25
  43. package/dist-server/service/calendar/calendar-type.js.map +1 -1
  44. package/dist-server/service/calendar/calendar.d.ts +7 -8
  45. package/dist-server/service/calendar/calendar.js +23 -33
  46. package/dist-server/service/calendar/calendar.js.map +1 -1
  47. package/dist-server/service/event/event-mutation.d.ts +6 -4
  48. package/dist-server/service/event/event-mutation.js +60 -83
  49. package/dist-server/service/event/event-mutation.js.map +1 -1
  50. package/dist-server/service/event/event-query.d.ts +11 -1
  51. package/dist-server/service/event/event-query.js +106 -13
  52. package/dist-server/service/event/event-query.js.map +1 -1
  53. package/dist-server/service/event/event-rules.d.ts +10 -0
  54. package/dist-server/service/event/event-rules.js +38 -0
  55. package/dist-server/service/event/event-rules.js.map +1 -0
  56. package/dist-server/service/event/event-service.d.ts +42 -0
  57. package/dist-server/service/event/event-service.js +159 -0
  58. package/dist-server/service/event/event-service.js.map +1 -0
  59. package/dist-server/service/event/event-type.d.ts +10 -11
  60. package/dist-server/service/event/event-type.js +32 -36
  61. package/dist-server/service/event/event-type.js.map +1 -1
  62. package/dist-server/service/event/event.d.ts +25 -11
  63. package/dist-server/service/event/event.js +89 -36
  64. package/dist-server/service/event/event.js.map +1 -1
  65. package/dist-server/service/event-series/event-series-mutation.d.ts +11 -0
  66. package/dist-server/service/event-series/event-series-mutation.js +100 -0
  67. package/dist-server/service/event-series/event-series-mutation.js.map +1 -0
  68. package/dist-server/service/event-series/event-series-query.d.ts +16 -0
  69. package/dist-server/service/event-series/event-series-query.js +109 -0
  70. package/dist-server/service/event-series/event-series-query.js.map +1 -0
  71. package/dist-server/service/event-series/event-series-service.d.ts +40 -0
  72. package/dist-server/service/event-series/event-series-service.js +253 -0
  73. package/dist-server/service/event-series/event-series-service.js.map +1 -0
  74. package/dist-server/service/event-series/event-series-type.d.ts +41 -0
  75. package/dist-server/service/event-series/event-series-type.js +155 -0
  76. package/dist-server/service/event-series/event-series-type.js.map +1 -0
  77. package/dist-server/service/event-series/event-series.d.ts +32 -0
  78. package/dist-server/service/event-series/event-series.js +134 -0
  79. package/dist-server/service/event-series/event-series.js.map +1 -0
  80. package/dist-server/service/event-series/index.d.ts +6 -0
  81. package/dist-server/service/event-series/index.js +10 -0
  82. package/dist-server/service/event-series/index.js.map +1 -0
  83. package/dist-server/service/event-series/recurrence.d.ts +19 -0
  84. package/dist-server/service/event-series/recurrence.js +95 -0
  85. package/dist-server/service/event-series/recurrence.js.map +1 -0
  86. package/dist-server/service/index.d.ts +15 -4
  87. package/dist-server/service/index.js +29 -11
  88. package/dist-server/service/index.js.map +1 -1
  89. package/dist-server/tsconfig.tsbuildinfo +1 -1
  90. package/package.json +8 -5
  91. package/tests/open-doors.test.ts +18 -21
  92. package/things-factory.config.js +0 -4
  93. package/translations/en.json +44 -1
  94. package/translations/es.json +44 -1
  95. package/translations/ja.json +44 -1
  96. package/translations/ko.json +44 -1
  97. package/translations/ms.json +44 -1
  98. package/translations/zh.json +44 -1
  99. package/concept.md +0 -31
  100. package/dist-client/pages/attendee/attendee-importer.d.ts +0 -23
  101. package/dist-client/pages/attendee/attendee-importer.js +0 -93
  102. package/dist-client/pages/attendee/attendee-importer.js.map +0 -1
  103. package/dist-client/pages/attendee/attendee-list-page.d.ts +0 -56
  104. package/dist-client/pages/attendee/attendee-list-page.js +0 -263
  105. package/dist-client/pages/attendee/attendee-list-page.js.map +0 -1
  106. package/dist-client/pages/calendar/calendar-importer.d.ts +0 -23
  107. package/dist-client/pages/calendar/calendar-importer.js +0 -93
  108. package/dist-client/pages/calendar/calendar-importer.js.map +0 -1
  109. package/dist-client/pages/event/event-importer.d.ts +0 -23
  110. package/dist-client/pages/event/event-importer.js +0 -93
  111. package/dist-client/pages/event/event-importer.js.map +0 -1
  112. package/dist-server/service/attendee/attendee-mutation.d.ts +0 -10
  113. package/dist-server/service/attendee/attendee-mutation.js +0 -140
  114. package/dist-server/service/attendee/attendee-mutation.js.map +0 -1
@@ -1,3 +1,4 @@
1
1
  export * from './migrations';
2
2
  export * from './middlewares';
3
+ export * from './service';
3
4
  import './routes';
@@ -3,5 +3,10 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  tslib_1.__exportStar(require("./migrations"), exports);
5
5
  tslib_1.__exportStar(require("./middlewares"), exports);
6
+ tslib_1.__exportStar(require("./service"), exports);
6
7
  require("./routes");
8
+ const auth_base_1 = require("@things-factory/auth-base");
9
+ const role_tasks_1 = require("./role-tasks");
10
+ for (const task of role_tasks_1.ROLE_TASKS)
11
+ (0, auth_base_1.registerRoleTask)(task);
7
12
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../server/index.ts"],"names":[],"mappings":";;;AAAA,uDAA4B;AAC5B,wDAA6B;AAE7B,oBAAiB","sourcesContent":["export * from './migrations'\nexport * from './middlewares'\n\nimport './routes'\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../server/index.ts"],"names":[],"mappings":";;;AAAA,uDAA4B;AAC5B,wDAA6B;AAC7B,oDAAyB;AAEzB,oBAAiB;AAEjB,yDAA4D;AAC5D,6CAAyC;AAEzC,KAAK,MAAM,IAAI,IAAI,uBAAU;IAAE,IAAA,4BAAgB,EAAC,IAAI,CAAC,CAAA","sourcesContent":["export * from './migrations'\nexport * from './middlewares'\nexport * from './service'\n\nimport './routes'\n\nimport { registerRoleTask } from '@things-factory/auth-base'\nimport { ROLE_TASKS } from './role-tasks'\n\nfor (const task of ROLE_TASKS) registerRoleTask(task)\n"]}
@@ -0,0 +1,2 @@
1
+ import type { RoleTask } from '@things-factory/auth-base';
2
+ export declare const ROLE_TASKS: RoleTask[];
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ /*
3
+ * The work this module names, for the seats applications build (ADR-0139 decision 11).
4
+ *
5
+ * A task holds whole privileges: each opens everything its doors open, and the words under `task.<id>` in this
6
+ * module's translations say what that is. Seats are put together by applications (`RoleTemplate.tasks`).
7
+ *
8
+ * Data only - `server/index.ts` registers it - so an application's tests read it without starting the framework.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.ROLE_TASKS = void 0;
12
+ exports.ROLE_TASKS = [
13
+ { id: 'calendar.reading', grants: [{ category: 'calendar', axes: ['query'] }] },
14
+ { id: 'calendar.keeping', grants: [{ category: 'calendar', axes: ['query', 'mutation'] }] }
15
+ ];
16
+ //# sourceMappingURL=role-tasks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"role-tasks.js","sourceRoot":"","sources":["../server/role-tasks.ts"],"names":[],"mappings":";AAAA;;;;;;;GAOG;;;AAIU,QAAA,UAAU,GAAe;IACpC,EAAE,EAAE,EAAE,kBAAkB,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE;IAC/E,EAAE,EAAE,EAAE,kBAAkB,EAAE,MAAM,EAAE,CAAC,EAAE,QAAQ,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,CAAC,EAAE;CAC5F,CAAA","sourcesContent":["/*\n * The work this module names, for the seats applications build (ADR-0139 decision 11).\n *\n * A task holds whole privileges: each opens everything its doors open, and the words under `task.<id>` in this\n * module's translations say what that is. Seats are put together by applications (`RoleTemplate.tasks`).\n *\n * Data only - `server/index.ts` registers it - so an application's tests read it without starting the framework.\n */\n\nimport type { RoleTask } from '@things-factory/auth-base'\n\nexport const ROLE_TASKS: RoleTask[] = [\n { id: 'calendar.reading', grants: [{ category: 'calendar', axes: ['query'] }] },\n { id: 'calendar.keeping', grants: [{ category: 'calendar', axes: ['query', 'mutation'] }] }\n]\n"]}
@@ -1,7 +1,10 @@
1
- import { ListParam } from '@things-factory/shell';
1
+ import { User } from '@things-factory/auth-base';
2
+ import { Domain } from '@things-factory/shell';
2
3
  import { Attendee } from './attendee';
3
- import { AttendeeList } from './attendee-type';
4
+ /** Attendees are read through their event or series; this only fills their relations. */
4
5
  export declare class AttendeeQuery {
5
- attendee(id: string, context: ResolverContext): Promise<Attendee>;
6
- attendees(params: ListParam, context: ResolverContext): Promise<AttendeeList>;
6
+ user(attendee: Attendee): Promise<User>;
7
+ domain(attendee: Attendee): Promise<Domain>;
8
+ updater(attendee: Attendee): Promise<User>;
9
+ creator(attendee: Attendee): Promise<User>;
7
10
  }
@@ -3,44 +3,53 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AttendeeQuery = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const type_graphql_1 = require("type-graphql");
6
+ const auth_base_1 = require("@things-factory/auth-base");
6
7
  const shell_1 = require("@things-factory/shell");
7
8
  const attendee_1 = require("./attendee");
8
- const attendee_type_1 = require("./attendee-type");
9
+ /** Attendees are read through their event or series; this only fills their relations. */
9
10
  let AttendeeQuery = class AttendeeQuery {
10
- async attendee(id, context) {
11
- return await (0, shell_1.getRepository)(attendee_1.Attendee).findOne({
12
- where: { id }
13
- });
11
+ user(attendee) {
12
+ return attendee.userId ? (0, shell_1.getRepository)(auth_base_1.User).findOneBy({ id: attendee.userId }) : null;
14
13
  }
15
- async attendees(params, context) {
16
- const { domain } = context.state;
17
- const queryBuilder = (0, shell_1.getQueryBuilderFromListParams)({
18
- domain,
19
- params,
20
- repository: await (0, shell_1.getRepository)(attendee_1.Attendee),
21
- searchables: ['name', 'description']
22
- });
23
- const [items, total] = await queryBuilder.getManyAndCount();
24
- return { items, total };
14
+ domain(attendee) {
15
+ return (0, shell_1.getRepository)(shell_1.Domain).findOneBy({ id: attendee.domainId });
16
+ }
17
+ updater(attendee) {
18
+ return attendee.updaterId ? (0, shell_1.getRepository)(auth_base_1.User).findOneBy({ id: attendee.updaterId }) : null;
19
+ }
20
+ creator(attendee) {
21
+ return attendee.creatorId ? (0, shell_1.getRepository)(auth_base_1.User).findOneBy({ id: attendee.creatorId }) : null;
25
22
  }
26
23
  };
27
24
  exports.AttendeeQuery = AttendeeQuery;
28
25
  tslib_1.__decorate([
29
- (0, type_graphql_1.Query)(returns => attendee_1.Attendee, { nullable: true, description: 'To fetch a Attendee' }),
30
- tslib_1.__param(0, (0, type_graphql_1.Arg)('id')),
31
- tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
26
+ (0, type_graphql_1.FieldResolver)(type => auth_base_1.User, { nullable: true }),
27
+ tslib_1.__param(0, (0, type_graphql_1.Root)()),
28
+ tslib_1.__metadata("design:type", Function),
29
+ tslib_1.__metadata("design:paramtypes", [attendee_1.Attendee]),
30
+ tslib_1.__metadata("design:returntype", Promise)
31
+ ], AttendeeQuery.prototype, "user", null);
32
+ tslib_1.__decorate([
33
+ (0, type_graphql_1.FieldResolver)(type => shell_1.Domain),
34
+ tslib_1.__param(0, (0, type_graphql_1.Root)()),
35
+ tslib_1.__metadata("design:type", Function),
36
+ tslib_1.__metadata("design:paramtypes", [attendee_1.Attendee]),
37
+ tslib_1.__metadata("design:returntype", Promise)
38
+ ], AttendeeQuery.prototype, "domain", null);
39
+ tslib_1.__decorate([
40
+ (0, type_graphql_1.FieldResolver)(type => auth_base_1.User),
41
+ tslib_1.__param(0, (0, type_graphql_1.Root)()),
32
42
  tslib_1.__metadata("design:type", Function),
33
- tslib_1.__metadata("design:paramtypes", [String, Object]),
43
+ tslib_1.__metadata("design:paramtypes", [attendee_1.Attendee]),
34
44
  tslib_1.__metadata("design:returntype", Promise)
35
- ], AttendeeQuery.prototype, "attendee", null);
45
+ ], AttendeeQuery.prototype, "updater", null);
36
46
  tslib_1.__decorate([
37
- (0, type_graphql_1.Query)(returns => attendee_type_1.AttendeeList, { description: 'To fetch multiple Attendees' }),
38
- tslib_1.__param(0, (0, type_graphql_1.Args)(type => shell_1.ListParam)),
39
- tslib_1.__param(1, (0, type_graphql_1.Ctx)()),
47
+ (0, type_graphql_1.FieldResolver)(type => auth_base_1.User),
48
+ tslib_1.__param(0, (0, type_graphql_1.Root)()),
40
49
  tslib_1.__metadata("design:type", Function),
41
- tslib_1.__metadata("design:paramtypes", [shell_1.ListParam, Object]),
50
+ tslib_1.__metadata("design:paramtypes", [attendee_1.Attendee]),
42
51
  tslib_1.__metadata("design:returntype", Promise)
43
- ], AttendeeQuery.prototype, "attendees", null);
52
+ ], AttendeeQuery.prototype, "creator", null);
44
53
  exports.AttendeeQuery = AttendeeQuery = tslib_1.__decorate([
45
54
  (0, type_graphql_1.Resolver)(attendee_1.Attendee)
46
55
  ], AttendeeQuery);
@@ -1 +1 @@
1
- {"version":3,"file":"attendee-query.js","sourceRoot":"","sources":["../../../server/service/attendee/attendee-query.ts"],"names":[],"mappings":";;;;AAAA,+CAA8F;AAC9F,iDAA+F;AAE/F,yCAAqC;AACrC,mDAA8C;AAGvC,IAAM,aAAa,GAAnB,MAAM,aAAa;IAElB,AAAN,KAAK,CAAC,QAAQ,CAAY,EAAU,EAAS,OAAwB;QACnE,OAAO,MAAM,IAAA,qBAAa,EAAC,mBAAQ,CAAC,CAAC,OAAO,CAAC;YAC3C,KAAK,EAAE,EAAE,EAAE,EAAE;SACd,CAAC,CAAA;IACJ,CAAC;IAGK,AAAN,KAAK,CAAC,SAAS,CAA0B,MAAiB,EAAS,OAAwB;QACzF,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;QAEhC,MAAM,YAAY,GAAG,IAAA,qCAA6B,EAAC;YACjD,MAAM;YACN,MAAM;YACN,UAAU,EAAE,MAAM,IAAA,qBAAa,EAAC,mBAAQ,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;CACF,CAAA;AAvBY,sCAAa;AAElB;IADL,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,mBAAS,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,qBAAqB,EAAE,CAAC;IACpE,mBAAA,IAAA,kBAAG,EAAC,IAAI,CAAC,CAAA;IAAc,mBAAA,IAAA,kBAAG,GAAE,CAAA;;;;6CAI3C;AAGK;IADL,IAAA,oBAAK,EAAC,OAAO,CAAC,EAAE,CAAC,4BAAY,EAAE,EAAE,WAAW,EAAE,6BAA6B,EAAE,CAAC;IAC9D,mBAAA,IAAA,mBAAI,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAS,CAAC,CAAA;IAAqB,mBAAA,IAAA,kBAAG,GAAE,CAAA;;6CAAjB,iBAAS;;8CAazD;wBAtBU,aAAa;IADzB,IAAA,uBAAQ,EAAC,mBAAQ,CAAC;GACN,aAAa,CAuBzB","sourcesContent":["import { Resolver, Query, FieldResolver, Root, Args, Arg, Ctx, Directive } from 'type-graphql'\nimport { getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'\nimport { User } from '@things-factory/auth-base'\nimport { Attendee } from './attendee'\nimport { AttendeeList } from './attendee-type'\n\n@Resolver(Attendee)\nexport class AttendeeQuery {\n @Query(returns => Attendee!, { nullable: true, description: 'To fetch a Attendee' })\n async attendee(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Attendee> {\n return await getRepository(Attendee).findOne({\n where: { id }\n })\n }\n\n @Query(returns => AttendeeList, { description: 'To fetch multiple Attendees' })\n async attendees(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<AttendeeList> {\n const { domain } = context.state\n\n const queryBuilder = getQueryBuilderFromListParams({\n domain,\n params,\n repository: await getRepository(Attendee),\n searchables: ['name', 'description']\n })\n\n const [items, total] = await queryBuilder.getManyAndCount()\n\n return { items, total }\n }\n}\n"]}
1
+ {"version":3,"file":"attendee-query.js","sourceRoot":"","sources":["../../../server/service/attendee/attendee-query.ts"],"names":[],"mappings":";;;;AAAA,+CAA4D;AAE5D,yDAAgD;AAChD,iDAA6D;AAE7D,yCAAqC;AAErC,yFAAyF;AAElF,IAAM,aAAa,GAAnB,MAAM,aAAa;IAExB,IAAI,CAAS,QAAkB;QAC7B,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,IAAA,qBAAa,EAAC,gBAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IACxF,CAAC;IAGD,MAAM,CAAS,QAAkB;QAC/B,OAAO,IAAA,qBAAa,EAAC,cAAM,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,QAAQ,EAAE,CAAC,CAAA;IACnE,CAAC;IAGD,OAAO,CAAS,QAAkB;QAChC,OAAO,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,IAAA,qBAAa,EAAC,gBAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAC9F,CAAC;IAGD,OAAO,CAAS,QAAkB;QAChC,OAAO,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,IAAA,qBAAa,EAAC,gBAAI,CAAC,CAAC,SAAS,CAAC,EAAE,EAAE,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAC9F,CAAC;CACF,CAAA;AApBY,sCAAa;AAExB;IADC,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC1C,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAW,mBAAQ;;yCAE9B;AAGD;IADC,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,cAAM,CAAC;IACtB,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAW,mBAAQ;;2CAEhC;AAGD;IADC,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,CAAC;IACnB,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAW,mBAAQ;;4CAEjC;AAGD;IADC,IAAA,4BAAa,EAAC,IAAI,CAAC,EAAE,CAAC,gBAAI,CAAC;IACnB,mBAAA,IAAA,mBAAI,GAAE,CAAA;;6CAAW,mBAAQ;;4CAEjC;wBAnBU,aAAa;IADzB,IAAA,uBAAQ,EAAC,mBAAQ,CAAC;GACN,aAAa,CAoBzB","sourcesContent":["import { FieldResolver, Resolver, Root } from 'type-graphql'\n\nimport { User } from '@things-factory/auth-base'\nimport { Domain, getRepository } from '@things-factory/shell'\n\nimport { Attendee } from './attendee'\n\n/** Attendees are read through their event or series; this only fills their relations. */\n@Resolver(Attendee)\nexport class AttendeeQuery {\n @FieldResolver(type => User, { nullable: true })\n user(@Root() attendee: Attendee): Promise<User> {\n return attendee.userId ? getRepository(User).findOneBy({ id: attendee.userId }) : null\n }\n\n @FieldResolver(type => Domain)\n domain(@Root() attendee: Attendee): Promise<Domain> {\n return getRepository(Domain).findOneBy({ id: attendee.domainId })\n }\n\n @FieldResolver(type => User)\n updater(@Root() attendee: Attendee): Promise<User> {\n return attendee.updaterId ? getRepository(User).findOneBy({ id: attendee.updaterId }) : null\n }\n\n @FieldResolver(type => User)\n creator(@Root() attendee: Attendee): Promise<User> {\n return attendee.creatorId ? getRepository(User).findOneBy({ id: attendee.creatorId }) : null\n }\n}\n"]}
@@ -0,0 +1,41 @@
1
+ import { EntityManager } from 'typeorm';
2
+ import { User } from '@things-factory/auth-base';
3
+ import { Domain } from '@things-factory/shell';
4
+ import { Attendee } from './attendee';
5
+ import { AttendeeInput } from './attendee-type';
6
+ /** One person as checked: a user of the domain, or an e-mail address. `key` tells two of them apart. */
7
+ export type AttendeeEntry = {
8
+ key: string;
9
+ userId?: string;
10
+ email?: string;
11
+ name: string;
12
+ };
13
+ export declare function attendeeKey(entry: {
14
+ userId?: string;
15
+ email?: string;
16
+ }): string;
17
+ /**
18
+ * Check the people to name. A user must be activated and enter the domain as a member or an owner (auth-base's one
19
+ * answer); an e-mail address is a name only. Nothing here grants anything.
20
+ */
21
+ export declare function checkAttendees(tx: EntityManager, domain: Domain, inputs?: AttendeeInput[]): Promise<AttendeeEntry[]>;
22
+ type Owner = {
23
+ event: {
24
+ id: string;
25
+ };
26
+ } | {
27
+ series: {
28
+ id: string;
29
+ };
30
+ };
31
+ export declare function attendeesOf(tx: EntityManager, domain: Domain, owner: Owner): Promise<Attendee[]>;
32
+ /** The checked entries of rows already saved — what a series hands its occurrences. */
33
+ export declare function entriesOf(rows: Attendee[]): AttendeeEntry[];
34
+ /**
35
+ * Add `add` and remove `remove` (by key) on one event or series; rows not named in either stay as they are, so an
36
+ * occurrence keeps the people only it was given.
37
+ */
38
+ export declare function changeAttendees(tx: EntityManager, domain: Domain, user: User, owner: Owner, add: AttendeeEntry[], remove: string[]): Promise<void>;
39
+ /** Make the attendees exactly `entries`: what is missing is added, what is not named is removed. */
40
+ export declare function replaceAttendees(tx: EntityManager, domain: Domain, user: User, owner: Owner, entries: AttendeeEntry[]): Promise<void>;
41
+ export {};
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.attendeeKey = attendeeKey;
4
+ exports.checkAttendees = checkAttendees;
5
+ exports.attendeesOf = attendeesOf;
6
+ exports.entriesOf = entriesOf;
7
+ exports.changeAttendees = changeAttendees;
8
+ exports.replaceAttendees = replaceAttendees;
9
+ const typeorm_1 = require("typeorm");
10
+ const auth_base_1 = require("@things-factory/auth-base");
11
+ const shell_1 = require("@things-factory/shell");
12
+ const attendee_1 = require("./attendee");
13
+ const EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
14
+ function attendeeKey(entry) {
15
+ return entry.userId ? `user:${entry.userId}` : `email:${entry.email.toLowerCase()}`;
16
+ }
17
+ /**
18
+ * Check the people to name. A user must be activated and enter the domain as a member or an owner (auth-base's one
19
+ * answer); an e-mail address is a name only. Nothing here grants anything.
20
+ */
21
+ async function checkAttendees(tx, domain, inputs = []) {
22
+ const entries = [];
23
+ for (const input of inputs) {
24
+ const userId = input.userId?.trim() || undefined;
25
+ const email = input.email?.trim().toLowerCase() || undefined;
26
+ if (!!userId === !!email)
27
+ throw new shell_1.Refusal('attendee-user-or-email', {}, 'Name an attendee by a user or by an e-mail address, not both');
28
+ if (userId) {
29
+ const user = await tx.getRepository(auth_base_1.User).findOne({ where: { id: userId } });
30
+ if (!user || user.status !== auth_base_1.UserStatus.ACTIVATED || !(await (0, auth_base_1.entersDomainAsAssignee)(domain, user, tx)))
31
+ throw new shell_1.Refusal('attendee-user-invalid', {}, 'Name a user of this domain');
32
+ entries.push({ key: attendeeKey({ userId }), userId, name: input.name?.trim() || user.name || user.email });
33
+ }
34
+ else {
35
+ if (!EMAIL.test(email))
36
+ throw new shell_1.Refusal('attendee-email-invalid', {}, 'Give a valid e-mail address');
37
+ entries.push({ key: attendeeKey({ email }), email, name: input.name?.trim() || email });
38
+ }
39
+ }
40
+ const keys = entries.map(entry => entry.key);
41
+ if (new Set(keys).size !== keys.length)
42
+ throw new shell_1.Refusal('attendee-duplicate', {}, 'Name each attendee once');
43
+ return entries;
44
+ }
45
+ function whereOwner(owner) {
46
+ return 'event' in owner ? { event: { id: owner.event.id } } : { series: { id: owner.series.id } };
47
+ }
48
+ function attendeesOf(tx, domain, owner) {
49
+ return tx.getRepository(attendee_1.Attendee).find({ where: { domain: { id: domain.id }, ...whereOwner(owner) }, order: { createdAt: 'ASC' } });
50
+ }
51
+ /** The checked entries of rows already saved — what a series hands its occurrences. */
52
+ function entriesOf(rows) {
53
+ return rows.map(row => ({ key: attendeeKey(row), userId: row.userId ?? undefined, email: row.email ?? undefined, name: row.name }));
54
+ }
55
+ /**
56
+ * Add `add` and remove `remove` (by key) on one event or series; rows not named in either stay as they are, so an
57
+ * occurrence keeps the people only it was given.
58
+ */
59
+ async function changeAttendees(tx, domain, user, owner, add, remove) {
60
+ const repository = tx.getRepository(attendee_1.Attendee);
61
+ const present = await attendeesOf(tx, domain, owner);
62
+ const gone = present.filter(row => remove.includes(attendeeKey(row)));
63
+ if (gone.length)
64
+ await repository.softDelete({ id: (0, typeorm_1.In)(gone.map(row => row.id)) });
65
+ const kept = new Map(present.filter(row => !gone.includes(row)).map(row => [attendeeKey(row), row]));
66
+ for (const entry of add) {
67
+ const row = kept.get(entry.key);
68
+ if (row) {
69
+ if (row.name !== entry.name)
70
+ await repository.update({ id: row.id }, { name: entry.name, updater: user });
71
+ continue;
72
+ }
73
+ await repository.save(repository.create({
74
+ domain,
75
+ ...whereOwner(owner),
76
+ user: entry.userId ? { id: entry.userId } : null,
77
+ email: entry.email ?? null,
78
+ name: entry.name,
79
+ creator: user,
80
+ updater: user
81
+ }));
82
+ }
83
+ }
84
+ /** Make the attendees exactly `entries`: what is missing is added, what is not named is removed. */
85
+ async function replaceAttendees(tx, domain, user, owner, entries) {
86
+ const present = await attendeesOf(tx, domain, owner);
87
+ const keys = entries.map(entry => entry.key);
88
+ await changeAttendees(tx, domain, user, owner, entries, present.map(attendeeKey).filter(key => !keys.includes(key)));
89
+ }
90
+ //# sourceMappingURL=attendee-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"attendee-service.js","sourceRoot":"","sources":["../../../server/service/attendee/attendee-service.ts"],"names":[],"mappings":"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","sourcesContent":["import { EntityManager, In } from 'typeorm'\n\nimport { entersDomainAsAssignee, User, UserStatus } from '@things-factory/auth-base'\nimport { Domain, Refusal } from '@things-factory/shell'\n\nimport { Attendee } from './attendee'\nimport { AttendeeInput } from './attendee-type'\n\n/** One person as checked: a user of the domain, or an e-mail address. `key` tells two of them apart. */\nexport type AttendeeEntry = { key: string; userId?: string; email?: string; name: string }\n\nconst EMAIL = /^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$/\n\nexport function attendeeKey(entry: { userId?: string; email?: string }): string {\n return entry.userId ? `user:${entry.userId}` : `email:${entry.email.toLowerCase()}`\n}\n\n/**\n * Check the people to name. A user must be activated and enter the domain as a member or an owner (auth-base's one\n * answer); an e-mail address is a name only. Nothing here grants anything.\n */\nexport async function checkAttendees(tx: EntityManager, domain: Domain, inputs: AttendeeInput[] = []): Promise<AttendeeEntry[]> {\n const entries: AttendeeEntry[] = []\n for (const input of inputs) {\n const userId = input.userId?.trim() || undefined\n const email = input.email?.trim().toLowerCase() || undefined\n if (!!userId === !!email) throw new Refusal('attendee-user-or-email', {}, 'Name an attendee by a user or by an e-mail address, not both')\n\n if (userId) {\n const user = await tx.getRepository(User).findOne({ where: { id: userId } })\n if (!user || user.status !== UserStatus.ACTIVATED || !(await entersDomainAsAssignee(domain, user, tx)))\n throw new Refusal('attendee-user-invalid', {}, 'Name a user of this domain')\n entries.push({ key: attendeeKey({ userId }), userId, name: input.name?.trim() || user.name || user.email })\n } else {\n if (!EMAIL.test(email)) throw new Refusal('attendee-email-invalid', {}, 'Give a valid e-mail address')\n entries.push({ key: attendeeKey({ email }), email, name: input.name?.trim() || email })\n }\n }\n\n const keys = entries.map(entry => entry.key)\n if (new Set(keys).size !== keys.length) throw new Refusal('attendee-duplicate', {}, 'Name each attendee once')\n return entries\n}\n\ntype Owner = { event: { id: string } } | { series: { id: string } }\n\nfunction whereOwner(owner: Owner) {\n return 'event' in owner ? { event: { id: owner.event.id } } : { series: { id: owner.series.id } }\n}\n\nexport function attendeesOf(tx: EntityManager, domain: Domain, owner: Owner): Promise<Attendee[]> {\n return tx.getRepository(Attendee).find({ where: { domain: { id: domain.id }, ...whereOwner(owner) }, order: { createdAt: 'ASC' } })\n}\n\n/** The checked entries of rows already saved — what a series hands its occurrences. */\nexport function entriesOf(rows: Attendee[]): AttendeeEntry[] {\n return rows.map(row => ({ key: attendeeKey(row), userId: row.userId ?? undefined, email: row.email ?? undefined, name: row.name }))\n}\n\n/**\n * Add `add` and remove `remove` (by key) on one event or series; rows not named in either stay as they are, so an\n * occurrence keeps the people only it was given.\n */\nexport async function changeAttendees(tx: EntityManager, domain: Domain, user: User, owner: Owner, add: AttendeeEntry[], remove: string[]) {\n const repository = tx.getRepository(Attendee)\n const present = await attendeesOf(tx, domain, owner)\n const gone = present.filter(row => remove.includes(attendeeKey(row)))\n if (gone.length) await repository.softDelete({ id: In(gone.map(row => row.id)) })\n\n const kept = new Map(present.filter(row => !gone.includes(row)).map(row => [attendeeKey(row), row]))\n for (const entry of add) {\n const row = kept.get(entry.key)\n if (row) {\n if (row.name !== entry.name) await repository.update({ id: row.id }, { name: entry.name, updater: user })\n continue\n }\n await repository.save(\n repository.create({\n domain,\n ...whereOwner(owner),\n user: entry.userId ? ({ id: entry.userId } as User) : null,\n email: entry.email ?? null,\n name: entry.name,\n creator: user,\n updater: user\n })\n )\n }\n}\n\n/** Make the attendees exactly `entries`: what is missing is added, what is not named is removed. */\nexport async function replaceAttendees(tx: EntityManager, domain: Domain, user: User, owner: Owner, entries: AttendeeEntry[]) {\n const present = await attendeesOf(tx, domain, owner)\n const keys = entries.map(entry => entry.key)\n await changeAttendees(tx, domain, user, owner, entries, present.map(attendeeKey).filter(key => !keys.includes(key)))\n}\n"]}
@@ -1,17 +1,5 @@
1
- import { Attendee, AttendeeStatus } from './attendee';
2
- export declare class NewAttendee {
3
- name: string;
4
- description?: string;
5
- state?: AttendeeStatus;
6
- }
7
- export declare class AttendeePatch {
8
- id?: string;
1
+ export declare class AttendeeInput {
2
+ userId?: string;
3
+ email?: string;
9
4
  name?: string;
10
- description?: string;
11
- state?: AttendeeStatus;
12
- cuFlag?: string;
13
- }
14
- export declare class AttendeeList {
15
- items: Attendee[];
16
- total: number;
17
5
  }
@@ -1,65 +1,24 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AttendeeList = exports.AttendeePatch = exports.NewAttendee = void 0;
3
+ exports.AttendeeInput = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const type_graphql_1 = require("type-graphql");
6
- const attendee_1 = require("./attendee");
7
- let NewAttendee = class NewAttendee {
6
+ let AttendeeInput = class AttendeeInput {
8
7
  };
9
- exports.NewAttendee = NewAttendee;
8
+ exports.AttendeeInput = AttendeeInput;
10
9
  tslib_1.__decorate([
11
- (0, type_graphql_1.Field)(),
10
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Id of a user who enters the domain' }),
12
11
  tslib_1.__metadata("design:type", String)
13
- ], NewAttendee.prototype, "name", void 0);
12
+ ], AttendeeInput.prototype, "userId", void 0);
14
13
  tslib_1.__decorate([
15
- (0, type_graphql_1.Field)({ nullable: true }),
14
+ (0, type_graphql_1.Field)({ nullable: true, description: 'E-mail address of someone who is not a user of the domain' }),
16
15
  tslib_1.__metadata("design:type", String)
17
- ], NewAttendee.prototype, "description", void 0);
16
+ ], AttendeeInput.prototype, "email", void 0);
18
17
  tslib_1.__decorate([
19
- (0, type_graphql_1.Field)(type => attendee_1.AttendeeStatus, { nullable: true }),
18
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Name to show; a user\'s own name when empty' }),
20
19
  tslib_1.__metadata("design:type", String)
21
- ], NewAttendee.prototype, "state", void 0);
22
- exports.NewAttendee = NewAttendee = tslib_1.__decorate([
23
- (0, type_graphql_1.InputType)()
24
- ], NewAttendee);
25
- let AttendeePatch = class AttendeePatch {
26
- };
27
- exports.AttendeePatch = AttendeePatch;
28
- tslib_1.__decorate([
29
- (0, type_graphql_1.Field)(type => type_graphql_1.ID, { nullable: true }),
30
- tslib_1.__metadata("design:type", String)
31
- ], AttendeePatch.prototype, "id", void 0);
32
- tslib_1.__decorate([
33
- (0, type_graphql_1.Field)({ nullable: true }),
34
- tslib_1.__metadata("design:type", String)
35
- ], AttendeePatch.prototype, "name", void 0);
36
- tslib_1.__decorate([
37
- (0, type_graphql_1.Field)({ nullable: true }),
38
- tslib_1.__metadata("design:type", String)
39
- ], AttendeePatch.prototype, "description", void 0);
40
- tslib_1.__decorate([
41
- (0, type_graphql_1.Field)(type => attendee_1.AttendeeStatus, { nullable: true }),
42
- tslib_1.__metadata("design:type", String)
43
- ], AttendeePatch.prototype, "state", void 0);
44
- tslib_1.__decorate([
45
- (0, type_graphql_1.Field)({ nullable: true }),
46
- tslib_1.__metadata("design:type", String)
47
- ], AttendeePatch.prototype, "cuFlag", void 0);
48
- exports.AttendeePatch = AttendeePatch = tslib_1.__decorate([
49
- (0, type_graphql_1.InputType)()
50
- ], AttendeePatch);
51
- let AttendeeList = class AttendeeList {
52
- };
53
- exports.AttendeeList = AttendeeList;
54
- tslib_1.__decorate([
55
- (0, type_graphql_1.Field)(type => [attendee_1.Attendee]),
56
- tslib_1.__metadata("design:type", Array)
57
- ], AttendeeList.prototype, "items", void 0);
58
- tslib_1.__decorate([
59
- (0, type_graphql_1.Field)(type => type_graphql_1.Int),
60
- tslib_1.__metadata("design:type", Number)
61
- ], AttendeeList.prototype, "total", void 0);
62
- exports.AttendeeList = AttendeeList = tslib_1.__decorate([
63
- (0, type_graphql_1.ObjectType)()
64
- ], AttendeeList);
20
+ ], AttendeeInput.prototype, "name", void 0);
21
+ exports.AttendeeInput = AttendeeInput = tslib_1.__decorate([
22
+ (0, type_graphql_1.InputType)({ description: 'A person to name on an event or a series: a user of the domain, or an e-mail address' })
23
+ ], AttendeeInput);
65
24
  //# sourceMappingURL=attendee-type.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"attendee-type.js","sourceRoot":"","sources":["../../../server/service/attendee/attendee-type.ts"],"names":[],"mappings":";;;;AAAA,+CAAsF;AAItF,yCAAqD;AAG9C,IAAM,WAAW,GAAjB,MAAM,WAAW;CASvB,CAAA;AATY,kCAAW;AAEtB;IADC,IAAA,oBAAK,GAAE;;yCACI;AAGZ;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;gDACN;AAGpB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,yBAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;0CAC5B;sBARX,WAAW;IADvB,IAAA,wBAAS,GAAE;GACC,WAAW,CASvB;AAGM,IAAM,aAAa,GAAnB,MAAM,aAAa;CAezB,CAAA;AAfY,sCAAa;AAExB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,iBAAE,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;yCAC3B;AAGX;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;2CACb;AAGb;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;kDACN;AAGpB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,yBAAc,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;4CAC5B;AAGtB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;;6CACX;wBAdJ,aAAa;IADzB,IAAA,wBAAS,GAAE;GACC,aAAa,CAezB;AAGM,IAAM,YAAY,GAAlB,MAAM,YAAY;CAMxB,CAAA;AANY,oCAAY;AAEvB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,CAAC,mBAAQ,CAAC,CAAC;;2CACT;AAGjB;IADC,IAAA,oBAAK,EAAC,IAAI,CAAC,EAAE,CAAC,kBAAG,CAAC;;2CACN;uBALF,YAAY;IADxB,IAAA,yBAAU,GAAE;GACA,YAAY,CAMxB","sourcesContent":["import { ObjectType, Field, InputType, Int, ID, registerEnumType } from 'type-graphql'\n\nimport { ObjectRef, ScalarObject } from '@things-factory/shell'\n\nimport { Attendee, AttendeeStatus } from './attendee'\n\n@InputType()\nexport class NewAttendee {\n @Field()\n name: string\n\n @Field({ nullable: true })\n description?: string\n\n @Field(type => AttendeeStatus, { nullable: true })\n state?: AttendeeStatus\n}\n\n@InputType()\nexport class AttendeePatch {\n @Field(type => ID, { nullable: true })\n id?: string\n\n @Field({ nullable: true })\n name?: string\n\n @Field({ nullable: true })\n description?: string\n\n @Field(type => AttendeeStatus, { nullable: true })\n state?: AttendeeStatus\n\n @Field({ nullable: true })\n cuFlag?: string\n}\n\n@ObjectType()\nexport class AttendeeList {\n @Field(type => [Attendee])\n items: Attendee[]\n\n @Field(type => Int)\n total: number\n}\n"]}
1
+ {"version":3,"file":"attendee-type.js","sourceRoot":"","sources":["../../../server/service/attendee/attendee-type.ts"],"names":[],"mappings":";;;;AAAA,+CAA+C;AAGxC,IAAM,aAAa,GAAnB,MAAM,aAAa;CASzB,CAAA;AATY,sCAAa;AAExB;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,oCAAoC,EAAE,CAAC;;6CAC9D;AAGf;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,2DAA2D,EAAE,CAAC;;4CACtF;AAGd;IADC,IAAA,oBAAK,EAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,6CAA6C,EAAE,CAAC;;2CACzE;wBARF,aAAa;IADzB,IAAA,wBAAS,EAAC,EAAE,WAAW,EAAE,sFAAsF,EAAE,CAAC;GACtG,aAAa,CASzB","sourcesContent":["import { Field, InputType } from 'type-graphql'\n\n@InputType({ description: 'A person to name on an event or a series: a user of the domain, or an e-mail address' })\nexport class AttendeeInput {\n @Field({ nullable: true, description: 'Id of a user who enters the domain' })\n userId?: string\n\n @Field({ nullable: true, description: 'E-mail address of someone who is not a user of the domain' })\n email?: string\n\n @Field({ nullable: true, description: 'Name to show; a user\\'s own name when empty' })\n name?: string\n}\n"]}
@@ -1,11 +1,28 @@
1
+ import { Domain } from '@things-factory/shell';
2
+ import { User } from '@things-factory/auth-base';
1
3
  import { Event } from '../event/event';
2
- export declare enum AttendeeStatus {
3
- STATUS_A = "STATUS_A",
4
- STATUS_B = "STATUS_B"
5
- }
4
+ import { EventSeries } from '../event-series/event-series';
5
+ /**
6
+ * A person named on an event or a series — a user who enters the domain, or someone known only by an e-mail address.
7
+ * Naming a person grants nothing: no role, no privilege, no reading of the event.
8
+ */
6
9
  export declare class Attendee {
7
10
  readonly id: string;
8
- name?: string;
9
- email: string;
10
- events: Event[];
11
+ domain?: Domain;
12
+ domainId?: string;
13
+ event?: Event;
14
+ eventId?: string;
15
+ series?: EventSeries;
16
+ seriesId?: string;
17
+ user?: User;
18
+ userId?: string;
19
+ email?: string;
20
+ name: string;
21
+ createdAt?: Date;
22
+ updatedAt?: Date;
23
+ deletedAt?: Date;
24
+ creator?: User;
25
+ creatorId?: string;
26
+ updater?: User;
27
+ updaterId?: string;
11
28
  }
@@ -1,47 +1,123 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Attendee = exports.AttendeeStatus = void 0;
3
+ exports.Attendee = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const typeorm_1 = require("typeorm");
6
6
  const type_graphql_1 = require("type-graphql");
7
- const graphql_scalars_1 = require("graphql-scalars");
7
+ const shell_1 = require("@things-factory/shell");
8
+ const auth_base_1 = require("@things-factory/auth-base");
8
9
  const event_1 = require("../event/event");
9
- var AttendeeStatus;
10
- (function (AttendeeStatus) {
11
- AttendeeStatus["STATUS_A"] = "STATUS_A";
12
- AttendeeStatus["STATUS_B"] = "STATUS_B";
13
- })(AttendeeStatus || (exports.AttendeeStatus = AttendeeStatus = {}));
14
- (0, type_graphql_1.registerEnumType)(AttendeeStatus, {
15
- name: 'AttendeeStatus',
16
- description: 'state enumeration of a attendee'
17
- });
10
+ const event_series_1 = require("../event-series/event-series");
11
+ /**
12
+ * A person named on an event or a series — a user who enters the domain, or someone known only by an e-mail address.
13
+ * Naming a person grants nothing: no role, no privilege, no reading of the event.
14
+ */
18
15
  let Attendee = class Attendee {
19
16
  };
20
17
  exports.Attendee = Attendee;
21
18
  tslib_1.__decorate([
22
19
  (0, typeorm_1.PrimaryGeneratedColumn)('uuid'),
23
- (0, type_graphql_1.Field)(type => type_graphql_1.ID),
20
+ (0, type_graphql_1.Field)(type => type_graphql_1.ID, { description: 'Unique identifier of the attendee row' }),
24
21
  tslib_1.__metadata("design:type", String)
25
22
  ], Attendee.prototype, "id", void 0);
23
+ tslib_1.__decorate([
24
+ (0, typeorm_1.ManyToOne)(type => shell_1.Domain),
25
+ (0, type_graphql_1.Field)(type => shell_1.Domain, { nullable: true, description: 'The domain the attendee row belongs to' }),
26
+ tslib_1.__metadata("design:type", shell_1.Domain)
27
+ ], Attendee.prototype, "domain", void 0);
28
+ tslib_1.__decorate([
29
+ (0, typeorm_1.RelationId)((attendee) => attendee.domain),
30
+ tslib_1.__metadata("design:type", String)
31
+ ], Attendee.prototype, "domainId", void 0);
32
+ tslib_1.__decorate([
33
+ (0, typeorm_1.ManyToOne)(type => event_1.Event, { nullable: true }),
34
+ tslib_1.__metadata("design:type", event_1.Event)
35
+ ], Attendee.prototype, "event", void 0);
36
+ tslib_1.__decorate([
37
+ (0, typeorm_1.RelationId)((attendee) => attendee.event),
38
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Id of the event the person is named on' }),
39
+ tslib_1.__metadata("design:type", String)
40
+ ], Attendee.prototype, "eventId", void 0);
41
+ tslib_1.__decorate([
42
+ (0, typeorm_1.ManyToOne)(type => event_series_1.EventSeries, { nullable: true }),
43
+ tslib_1.__metadata("design:type", event_series_1.EventSeries)
44
+ ], Attendee.prototype, "series", void 0);
45
+ tslib_1.__decorate([
46
+ (0, typeorm_1.RelationId)((attendee) => attendee.series),
47
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Id of the series the person is named on' }),
48
+ tslib_1.__metadata("design:type", String)
49
+ ], Attendee.prototype, "seriesId", void 0);
50
+ tslib_1.__decorate([
51
+ (0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
52
+ (0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true, description: 'The user, when the attendee signs in to the domain' }),
53
+ tslib_1.__metadata("design:type", auth_base_1.User)
54
+ ], Attendee.prototype, "user", void 0);
55
+ tslib_1.__decorate([
56
+ (0, typeorm_1.RelationId)((attendee) => attendee.user),
57
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Id of the user, when the attendee signs in to the domain' }),
58
+ tslib_1.__metadata("design:type", String)
59
+ ], Attendee.prototype, "userId", void 0);
60
+ tslib_1.__decorate([
61
+ (0, typeorm_1.Column)({ nullable: true }),
62
+ (0, type_graphql_1.Field)({ nullable: true, description: 'E-mail address, when the attendee is not a user of the domain' }),
63
+ tslib_1.__metadata("design:type", String)
64
+ ], Attendee.prototype, "email", void 0);
26
65
  tslib_1.__decorate([
27
66
  (0, typeorm_1.Column)(),
28
- (0, type_graphql_1.Field)({ nullable: true }),
67
+ (0, type_graphql_1.Field)({ description: 'Name shown for the attendee' }),
29
68
  tslib_1.__metadata("design:type", String)
30
69
  ], Attendee.prototype, "name", void 0);
31
70
  tslib_1.__decorate([
32
- (0, typeorm_1.Column)(),
33
- (0, type_graphql_1.Field)(type => graphql_scalars_1.GraphQLEmailAddress, { nullable: true }),
71
+ (0, typeorm_1.CreateDateColumn)(),
72
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Creation timestamp' }),
73
+ tslib_1.__metadata("design:type", Date)
74
+ ], Attendee.prototype, "createdAt", void 0);
75
+ tslib_1.__decorate([
76
+ (0, typeorm_1.UpdateDateColumn)(),
77
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Last update timestamp' }),
78
+ tslib_1.__metadata("design:type", Date)
79
+ ], Attendee.prototype, "updatedAt", void 0);
80
+ tslib_1.__decorate([
81
+ (0, typeorm_1.DeleteDateColumn)(),
82
+ (0, type_graphql_1.Field)({ nullable: true, description: 'Soft delete timestamp' }),
83
+ tslib_1.__metadata("design:type", Date)
84
+ ], Attendee.prototype, "deletedAt", void 0);
85
+ tslib_1.__decorate([
86
+ (0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
87
+ (0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true, description: 'Who named the attendee' }),
88
+ tslib_1.__metadata("design:type", auth_base_1.User)
89
+ ], Attendee.prototype, "creator", void 0);
90
+ tslib_1.__decorate([
91
+ (0, typeorm_1.RelationId)((attendee) => attendee.creator),
34
92
  tslib_1.__metadata("design:type", String)
35
- ], Attendee.prototype, "email", void 0);
93
+ ], Attendee.prototype, "creatorId", void 0);
36
94
  tslib_1.__decorate([
37
- (0, typeorm_1.ManyToMany)(() => event_1.Event),
38
- (0, typeorm_1.JoinTable)(),
39
- (0, type_graphql_1.Field)(type => [event_1.Event], { nullable: true }),
40
- tslib_1.__metadata("design:type", Array)
41
- ], Attendee.prototype, "events", void 0);
95
+ (0, typeorm_1.ManyToOne)(type => auth_base_1.User, { nullable: true }),
96
+ (0, type_graphql_1.Field)(type => auth_base_1.User, { nullable: true, description: 'Who last changed the attendee row' }),
97
+ tslib_1.__metadata("design:type", auth_base_1.User)
98
+ ], Attendee.prototype, "updater", void 0);
99
+ tslib_1.__decorate([
100
+ (0, typeorm_1.RelationId)((attendee) => attendee.updater),
101
+ tslib_1.__metadata("design:type", String)
102
+ ], Attendee.prototype, "updaterId", void 0);
42
103
  exports.Attendee = Attendee = tslib_1.__decorate([
43
104
  (0, typeorm_1.Entity)(),
44
- (0, typeorm_1.Index)('ix_attendee_0', (attendee) => [attendee.email], { unique: false }),
45
- (0, type_graphql_1.ObjectType)({ description: 'Entity for Attendee' })
105
+ (0, typeorm_1.Index)('ix_attendee_0', (attendee) => [attendee.domain, attendee.event, attendee.user], {
106
+ unique: true,
107
+ where: '"deleted_at" IS NULL AND "event_id" IS NOT NULL AND "user_id" IS NOT NULL'
108
+ }),
109
+ (0, typeorm_1.Index)('ix_attendee_1', (attendee) => [attendee.domain, attendee.event, attendee.email], {
110
+ unique: true,
111
+ where: '"deleted_at" IS NULL AND "event_id" IS NOT NULL AND "email" IS NOT NULL'
112
+ }),
113
+ (0, typeorm_1.Index)('ix_attendee_2', (attendee) => [attendee.domain, attendee.series, attendee.user], {
114
+ unique: true,
115
+ where: '"deleted_at" IS NULL AND "series_id" IS NOT NULL AND "user_id" IS NOT NULL'
116
+ }),
117
+ (0, typeorm_1.Index)('ix_attendee_3', (attendee) => [attendee.domain, attendee.series, attendee.email], {
118
+ unique: true,
119
+ where: '"deleted_at" IS NULL AND "series_id" IS NOT NULL AND "email" IS NOT NULL'
120
+ }),
121
+ (0, type_graphql_1.ObjectType)({ description: 'A person named on an event or a series; naming grants nothing' })
46
122
  ], Attendee);
47
123
  //# sourceMappingURL=attendee.js.map