@stamhoofd/backend 2.39.1 → 2.40.1

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 (198) hide show
  1. package/eslint.config.mjs +5 -0
  2. package/index.ts +81 -74
  3. package/jest.config.cjs +10 -0
  4. package/migrations.ts +16 -14
  5. package/package.json +11 -11
  6. package/src/crons/clear-excel-cache.test.ts +48 -50
  7. package/src/crons/clear-excel-cache.ts +18 -18
  8. package/src/crons/setup-steps.ts +2 -2
  9. package/src/crons.ts +325 -306
  10. package/src/decoders/StringArrayDecoder.ts +7 -7
  11. package/src/decoders/StringNullableDecoder.ts +1 -2
  12. package/src/email-recipient-loaders/members.ts +22 -22
  13. package/src/endpoints/admin/memberships/ChargeMembershipsEndpoint.ts +8 -9
  14. package/src/endpoints/admin/memberships/GetChargeMembershipsSummaryEndpoint.ts +39 -40
  15. package/src/endpoints/admin/organizations/GetOrganizationsCountEndpoint.ts +8 -8
  16. package/src/endpoints/admin/organizations/GetOrganizationsEndpoint.ts +44 -45
  17. package/src/endpoints/admin/organizations/PatchOrganizationsEndpoint.ts +58 -57
  18. package/src/endpoints/auth/CreateAdminEndpoint.ts +48 -45
  19. package/src/endpoints/auth/CreateTokenEndpoint.test.ts +31 -31
  20. package/src/endpoints/auth/CreateTokenEndpoint.ts +146 -147
  21. package/src/endpoints/auth/DeleteTokenEndpoint.ts +7 -7
  22. package/src/endpoints/auth/DeleteUserEndpoint.ts +15 -15
  23. package/src/endpoints/auth/ForgotPasswordEndpoint.ts +17 -18
  24. package/src/endpoints/auth/GetOtherUserEndpoint.ts +9 -10
  25. package/src/endpoints/auth/GetUserEndpoint.test.ts +32 -35
  26. package/src/endpoints/auth/GetUserEndpoint.ts +5 -6
  27. package/src/endpoints/auth/PatchApiUserEndpoint.ts +35 -33
  28. package/src/endpoints/auth/PatchUserEndpoint.ts +55 -52
  29. package/src/endpoints/auth/PollEmailVerificationEndpoint.ts +9 -9
  30. package/src/endpoints/auth/RetryEmailVerificationEndpoint.ts +8 -8
  31. package/src/endpoints/auth/SignupEndpoint.ts +37 -36
  32. package/src/endpoints/auth/VerifyEmailEndpoint.ts +29 -28
  33. package/src/endpoints/global/addresses/SearchRegionsEndpoint.ts +33 -33
  34. package/src/endpoints/global/addresses/ValidateAddressEndpoint.ts +7 -7
  35. package/src/endpoints/global/caddy/CheckDomainCertEndpoint.ts +37 -37
  36. package/src/endpoints/global/email/CreateEmailEndpoint.ts +30 -30
  37. package/src/endpoints/global/email/GetEmailAddressEndpoint.ts +13 -13
  38. package/src/endpoints/global/email/GetEmailEndpoint.ts +13 -13
  39. package/src/endpoints/global/email/ManageEmailAddressEndpoint.ts +16 -16
  40. package/src/endpoints/global/email/PatchEmailEndpoint.ts +25 -25
  41. package/src/endpoints/global/events/GetEventsEndpoint.ts +43 -44
  42. package/src/endpoints/global/events/PatchEventsEndpoint.ts +127 -172
  43. package/src/endpoints/global/files/ExportToExcelEndpoint.ts +49 -50
  44. package/src/endpoints/global/files/GetFileCache.ts +13 -13
  45. package/src/endpoints/global/files/UploadFile.ts +51 -54
  46. package/src/endpoints/global/files/UploadImage.ts +53 -53
  47. package/src/endpoints/global/groups/GetGroupsEndpoint.ts +25 -25
  48. package/src/endpoints/global/members/GetMemberFamilyEndpoint.ts +24 -23
  49. package/src/endpoints/global/members/GetMembersCountEndpoint.ts +8 -8
  50. package/src/endpoints/global/members/GetMembersEndpoint.ts +105 -102
  51. package/src/endpoints/global/members/PatchOrganizationMembersEndpoint.ts +240 -239
  52. package/src/endpoints/global/organizations/CheckRegisterCodeEndpoint.ts +12 -14
  53. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.test.ts +32 -33
  54. package/src/endpoints/global/organizations/CreateOrganizationEndpoint.ts +48 -57
  55. package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.test.ts +21 -22
  56. package/src/endpoints/global/organizations/GetOrganizationFromDomainEndpoint.ts +28 -28
  57. package/src/endpoints/global/organizations/GetOrganizationFromUriEndpoint.ts +18 -18
  58. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.test.ts +20 -20
  59. package/src/endpoints/global/organizations/SearchOrganizationEndpoint.ts +17 -17
  60. package/src/endpoints/global/payments/StripeWebhookEndpoint.ts +81 -75
  61. package/src/endpoints/global/platform/GetPlatformAdminsEndpoint.ts +14 -14
  62. package/src/endpoints/global/platform/GetPlatformEnpoint.ts +11 -11
  63. package/src/endpoints/global/platform/PatchPlatformEnpoint.ts +71 -68
  64. package/src/endpoints/global/registration/GetPaymentRegistrations.ts +27 -27
  65. package/src/endpoints/global/registration/GetUserBillingStatusEndpoint.ts +30 -30
  66. package/src/endpoints/global/registration/GetUserDetailedBillingStatusEndpoint.ts +34 -34
  67. package/src/endpoints/global/registration/GetUserDocumentsEndpoint.ts +26 -26
  68. package/src/endpoints/global/registration/GetUserMembersEndpoint.ts +12 -12
  69. package/src/endpoints/global/registration/PatchUserMembersEndpoint.ts +90 -90
  70. package/src/endpoints/global/registration/RegisterMembersEndpoint.test.ts +118 -121
  71. package/src/endpoints/global/registration/RegisterMembersEndpoint.ts +362 -350
  72. package/src/endpoints/global/registration-periods/GetRegistrationPeriodsEndpoint.ts +8 -9
  73. package/src/endpoints/global/registration-periods/PatchRegistrationPeriodsEndpoint.ts +21 -21
  74. package/src/endpoints/global/webshops/GetWebshopFromDomainEndpoint.ts +65 -65
  75. package/src/endpoints/organization/dashboard/billing/GetOrganizationBillingStatusEndpoint.ts +9 -9
  76. package/src/endpoints/organization/dashboard/billing/GetOrganizationDetailedBillingStatusEndpoint.ts +14 -14
  77. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplateXML.ts +17 -17
  78. package/src/endpoints/organization/dashboard/documents/GetDocumentTemplatesEndpoint.ts +21 -21
  79. package/src/endpoints/organization/dashboard/documents/GetDocumentsEndpoint.ts +15 -15
  80. package/src/endpoints/organization/dashboard/documents/PatchDocumentEndpoint.ts +52 -52
  81. package/src/endpoints/organization/dashboard/documents/PatchDocumentTemplateEndpoint.ts +37 -37
  82. package/src/endpoints/organization/dashboard/email/CheckEmailBouncesEndpoint.ts +14 -14
  83. package/src/endpoints/organization/dashboard/email/EmailEndpoint.ts +113 -112
  84. package/src/endpoints/organization/dashboard/email-templates/GetEmailTemplatesEndpoint.ts +29 -29
  85. package/src/endpoints/organization/dashboard/email-templates/PatchEmailTemplatesEndpoint.ts +48 -47
  86. package/src/endpoints/organization/dashboard/mollie/CheckMollieEndpoint.ts +22 -21
  87. package/src/endpoints/organization/dashboard/mollie/ConnectMollieEndpoint.ts +13 -14
  88. package/src/endpoints/organization/dashboard/mollie/DisconnectMollieEndpoint.ts +12 -13
  89. package/src/endpoints/organization/dashboard/mollie/GetMollieDashboardEndpoint.ts +24 -24
  90. package/src/endpoints/organization/dashboard/nolt/CreateNoltTokenEndpoint.ts +10 -12
  91. package/src/endpoints/organization/dashboard/organization/GetOrganizationArchivedGroups.ts +14 -14
  92. package/src/endpoints/organization/dashboard/organization/GetOrganizationDeletedGroups.ts +13 -13
  93. package/src/endpoints/organization/dashboard/organization/GetOrganizationSSOEndpoint.ts +12 -12
  94. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.test.ts +120 -124
  95. package/src/endpoints/organization/dashboard/organization/PatchOrganizationEndpoint.ts +172 -173
  96. package/src/endpoints/organization/dashboard/organization/SetOrganizationDomainEndpoint.ts +88 -89
  97. package/src/endpoints/organization/dashboard/organization/SetOrganizationSSOEndpoint.ts +12 -12
  98. package/src/endpoints/organization/dashboard/payments/GetMemberBalanceEndpoint.ts +17 -17
  99. package/src/endpoints/organization/dashboard/payments/GetPaymentsCountEndpoint.ts +8 -8
  100. package/src/endpoints/organization/dashboard/payments/GetPaymentsEndpoint.ts +66 -67
  101. package/src/endpoints/organization/dashboard/payments/PatchBalanceItemsEndpoint.ts +47 -47
  102. package/src/endpoints/organization/dashboard/payments/PatchPaymentsEndpoint.ts +93 -91
  103. package/src/endpoints/organization/dashboard/registration-periods/GetOrganizationRegistrationPeriodsEndpoint.ts +16 -17
  104. package/src/endpoints/organization/dashboard/registration-periods/PatchOrganizationRegistrationPeriodsEndpoint.ts +170 -167
  105. package/src/endpoints/organization/dashboard/registration-periods/SetupStepReviewEndpoint.ts +25 -24
  106. package/src/endpoints/organization/dashboard/stripe/ConnectStripeEndpoint.ts +22 -23
  107. package/src/endpoints/organization/dashboard/stripe/DeleteStripeAccountEndpoint.ts +22 -22
  108. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountLinkEndpoint.ts +17 -18
  109. package/src/endpoints/organization/dashboard/stripe/GetStripeAccountsEndpoint.ts +8 -9
  110. package/src/endpoints/organization/dashboard/stripe/GetStripeLoginLinkEndpoint.ts +17 -18
  111. package/src/endpoints/organization/dashboard/stripe/UpdateStripeAccountEndpoint.ts +14 -15
  112. package/src/endpoints/organization/dashboard/users/CreateApiUserEndpoint.ts +19 -19
  113. package/src/endpoints/organization/dashboard/users/DeleteUserEndpoint.ts +19 -19
  114. package/src/endpoints/organization/dashboard/users/GetApiUsersEndpoint.ts +14 -14
  115. package/src/endpoints/organization/dashboard/users/GetOrganizationAdminsEndpoint.ts +12 -12
  116. package/src/endpoints/organization/dashboard/webshops/CreateWebshopEndpoint.ts +103 -100
  117. package/src/endpoints/organization/dashboard/webshops/DeleteWebshopEndpoint.ts +11 -12
  118. package/src/endpoints/organization/dashboard/webshops/GetDiscountCodesEndpoint.ts +15 -15
  119. package/src/endpoints/organization/dashboard/webshops/GetWebshopOrdersEndpoint.ts +14 -14
  120. package/src/endpoints/organization/dashboard/webshops/GetWebshopTicketsEndpoint.ts +14 -14
  121. package/src/endpoints/organization/dashboard/webshops/GetWebshopUriAvailabilityEndpoint.ts +23 -23
  122. package/src/endpoints/organization/dashboard/webshops/PatchDiscountCodesEndpoint.ts +54 -52
  123. package/src/endpoints/organization/dashboard/webshops/PatchWebshopEndpoint.ts +84 -81
  124. package/src/endpoints/organization/dashboard/webshops/PatchWebshopOrdersEndpoint.ts +120 -111
  125. package/src/endpoints/organization/dashboard/webshops/PatchWebshopTicketsEndpoint.ts +24 -24
  126. package/src/endpoints/organization/dashboard/webshops/VerifyWebshopDomainEndpoint.ts +18 -18
  127. package/src/endpoints/organization/shared/ExchangePaymentEndpoint.ts +141 -130
  128. package/src/endpoints/organization/shared/GetDocumentHtml.ts +25 -25
  129. package/src/endpoints/organization/shared/GetPaymentEndpoint.ts +18 -18
  130. package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.test.ts +36 -37
  131. package/src/endpoints/organization/shared/auth/GetOrganizationEndpoint.ts +9 -9
  132. package/src/endpoints/organization/shared/auth/OpenIDConnectCallbackEndpoint.ts +11 -11
  133. package/src/endpoints/organization/shared/auth/OpenIDConnectStartEndpoint.ts +28 -27
  134. package/src/endpoints/organization/webshops/CheckWebshopDiscountCodesEndpoint.ts +20 -20
  135. package/src/endpoints/organization/webshops/GetOrderByPaymentEndpoint.ts +22 -22
  136. package/src/endpoints/organization/webshops/GetOrderEndpoint.ts +14 -14
  137. package/src/endpoints/organization/webshops/GetTicketsEndpoint.ts +57 -56
  138. package/src/endpoints/organization/webshops/GetWebshopEndpoint.test.ts +65 -66
  139. package/src/endpoints/organization/webshops/GetWebshopEndpoint.ts +18 -17
  140. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.test.ts +124 -128
  141. package/src/endpoints/organization/webshops/PlaceOrderEndpoint.ts +154 -145
  142. package/src/excel-loaders/members.ts +275 -273
  143. package/src/excel-loaders/payments.ts +155 -156
  144. package/src/helpers/AddressValidator.test.ts +32 -32
  145. package/src/helpers/AddressValidator.ts +128 -122
  146. package/src/helpers/AdminPermissionChecker.ts +339 -236
  147. package/src/helpers/AuthenticatedStructures.ts +233 -134
  148. package/src/helpers/BuckarooHelper.ts +134 -134
  149. package/src/helpers/CheckSettlements.ts +94 -88
  150. package/src/helpers/Context.ts +87 -86
  151. package/src/helpers/CookieHelper.ts +23 -22
  152. package/src/helpers/EmailResumer.ts +10 -10
  153. package/src/helpers/FileCache.ts +62 -62
  154. package/src/helpers/ForwardHandler.test.ts +122 -124
  155. package/src/helpers/ForwardHandler.ts +76 -70
  156. package/src/helpers/MemberUserSyncer.ts +101 -96
  157. package/src/helpers/MembershipCharger.ts +69 -69
  158. package/src/helpers/MembershipHelper.ts +11 -12
  159. package/src/helpers/OpenIDConnectHelper.ts +85 -82
  160. package/src/helpers/PeriodHelper.ts +65 -70
  161. package/src/helpers/StripeHelper.ts +146 -137
  162. package/src/helpers/StripePayoutChecker.ts +51 -52
  163. package/src/helpers/ViesHelper.ts +46 -44
  164. package/src/helpers/fetchToAsyncIterator.ts +14 -14
  165. package/src/helpers/xlsxAddressTransformerColumnFactory.ts +58 -60
  166. package/src/middleware/ContextMiddleware.ts +5 -5
  167. package/src/migrations/1646578856-validate-addresses.ts +6 -9
  168. package/src/seeds/0000000000-example.ts +3 -5
  169. package/src/seeds/1715028563-user-permissions.ts +16 -18
  170. package/src/seeds/1722256498-group-update-occupancy.ts +12 -12
  171. package/src/seeds/1722344162-sync-member-users.ts +14 -15
  172. package/src/seeds/1722344162-update-membership.ts +6 -6
  173. package/src/seeds/1726055544-balance-item-paid.ts +4 -4
  174. package/src/seeds/1726055545-balance-item-pending.ts +4 -4
  175. package/src/seeds/1726494419-update-cached-outstanding-balance.ts +16 -16
  176. package/src/seeds/1726494420-update-cached-outstanding-balance-from-items.ts +12 -12
  177. package/src/seeds/1726572303-schedule-stock-updates.ts +12 -12
  178. package/src/seeds/1726847064-setup-steps.ts +16 -0
  179. package/src/sql-filters/balance-item-payments.ts +7 -7
  180. package/src/sql-filters/events.ts +14 -14
  181. package/src/sql-filters/members.ts +96 -96
  182. package/src/sql-filters/organizations.ts +139 -75
  183. package/src/sql-filters/payments.ts +28 -28
  184. package/src/sql-filters/registrations.ts +14 -14
  185. package/src/sql-sorters/events.ts +25 -25
  186. package/src/sql-sorters/members.ts +26 -26
  187. package/src/sql-sorters/organizations.ts +36 -36
  188. package/src/sql-sorters/payments.ts +26 -26
  189. package/tests/e2e/stock.test.ts +616 -621
  190. package/tests/e2e/tickets.test.ts +255 -260
  191. package/tests/helpers/StripeMocker.ts +177 -179
  192. package/tests/helpers/TestServer.ts +9 -9
  193. package/tests/jest.global.setup.ts +14 -13
  194. package/tests/jest.setup.ts +33 -32
  195. package/.eslintrc.js +0 -61
  196. package/jest.config.js +0 -11
  197. package/src/helpers/SetupStepsUpdater.ts +0 -359
  198. package/src/seeds/1724076679-setup-steps.ts +0 -16
@@ -1,267 +1,273 @@
1
- import { Database } from "@simonbackx/simple-database"
2
- import { ArrayDecoder, AutoEncoder, Decoder, field, ObjectData, StringDecoder } from "@simonbackx/simple-encoding"
3
- import { SimpleError } from "@simonbackx/simple-errors"
4
- import { City, PostalCode, Street } from "@stamhoofd/models"
5
- import { Address, Country, ValidatedAddress } from "@stamhoofd/structures"
6
- import { sleep, StringCompare } from "@stamhoofd/utility"
7
- import axios from "axios"
8
- import { v4 as uuidv4 } from "uuid";
1
+ import { Database } from '@simonbackx/simple-database';
2
+ import { ArrayDecoder, AutoEncoder, Decoder, field, ObjectData, StringDecoder } from '@simonbackx/simple-encoding';
3
+ import { SimpleError } from '@simonbackx/simple-errors';
4
+ import { City, PostalCode, Street } from '@stamhoofd/models';
5
+ import { Address, Country, ValidatedAddress } from '@stamhoofd/structures';
6
+ import { sleep, StringCompare } from '@stamhoofd/utility';
7
+ import axios from 'axios';
8
+ import { v4 as uuidv4 } from 'uuid';
9
9
 
10
10
  export class AddressValidatorStatic {
11
11
  // TODO: hold street cache
12
-
12
+
13
13
  async validate(address: Address): Promise<ValidatedAddress> {
14
- address = address.clone()
15
- let postalCode = address.postalCode
14
+ address = address.clone();
15
+ let postalCode = address.postalCode;
16
16
  if (address.country == Country.Netherlands) {
17
17
  // Check if we have the right syntax
18
- const stripped = postalCode.replace(/\s/g, '')
19
- if (stripped.length != 6) {
18
+ const stripped = postalCode.replace(/\s/g, '');
19
+ if (stripped.length !== 6) {
20
20
  throw new SimpleError({
21
- code: "invalid_field",
22
- message: "Invalid postal code format (NL)",
21
+ code: 'invalid_field',
22
+ message: 'Invalid postal code format (NL)',
23
23
  human: "Ongeldig postcode formaat, voer in zoals '8011 PK'",
24
- field: "postalCode"
25
- })
24
+ field: 'postalCode',
25
+ });
26
26
  }
27
27
 
28
- const numbers = stripped.slice(0, 4)
28
+ const numbers = stripped.slice(0, 4);
29
29
  if (!/[0-9]{4}/.test(numbers)) {
30
30
  throw new SimpleError({
31
- code: "invalid_field",
32
- message: "Invalid postal code format (NL)",
31
+ code: 'invalid_field',
32
+ message: 'Invalid postal code format (NL)',
33
33
  human: "Ongeldig postcode formaat, voer in zoals '8011 PK'",
34
- field: "postalCode"
35
- })
34
+ field: 'postalCode',
35
+ });
36
36
  }
37
37
 
38
38
  // Don't do validation on last letters
39
- postalCode = numbers
40
- } else {
41
- postalCode = postalCode.trim()
39
+ postalCode = numbers;
40
+ }
41
+ else {
42
+ postalCode = postalCode.trim();
42
43
  }
43
44
 
44
45
  if (postalCode.length == 0) {
45
- const numbers = address.city.substring(0, 4)
46
+ const numbers = address.city.substring(0, 4);
46
47
  if (!/[0-9]{4}/.test(numbers)) {
47
- postalCode = numbers
48
- address.city = address.city.substring(4).trim()
49
- } else {
48
+ postalCode = numbers;
49
+ address.city = address.city.substring(4).trim();
50
+ }
51
+ else {
50
52
  throw new SimpleError({
51
- code: "invalid_field",
52
- message: "Postal code is required",
53
- human: "Voer een postcode in",
54
- field: "postalCode"
55
- })
53
+ code: 'invalid_field',
54
+ message: 'Postal code is required',
55
+ human: 'Voer een postcode in',
56
+ field: 'postalCode',
57
+ });
56
58
  }
57
59
  }
58
60
 
59
61
  if (address.country !== Country.Belgium && address.country !== Country.Netherlands) {
60
62
  // No validation for other countries
61
- return ValidatedAddress.create(Object.assign({ ... address }, {
63
+ return ValidatedAddress.create(Object.assign({ ...address }, {
62
64
  postalCode: address.postalCode,
63
65
  city: address.city,
64
66
  cityId: 'unknown',
65
67
  parentCityId: null,
66
68
  provinceId: 'unknown',
67
- }))
69
+ }));
68
70
  }
69
-
70
- const city = await PostalCode.getCity(postalCode, address.city, address.country)
71
+
72
+ const city = await PostalCode.getCity(postalCode, address.city, address.country);
71
73
 
72
74
  if (!city) {
73
75
  throw new SimpleError({
74
- code: "invalid_field",
75
- message: "Invalid postal code or city",
76
- human: "Deze postcode en/of gemeente bestaat niet, kijk je even na op een typfout?",
77
- field: "postalCode"
78
- })
76
+ code: 'invalid_field',
77
+ message: 'Invalid postal code or city',
78
+ human: 'Deze postcode en/of gemeente bestaat niet, kijk je even na op een typfout?',
79
+ field: 'postalCode',
80
+ });
79
81
  }
80
82
 
81
83
  // Validate street and try to correct it
82
84
  if (address.country === Country.Belgium) {
83
85
  // Also validate the street
84
- let streets = await Street.where({ cityId: city.parentCityId ?? city.id })
86
+ let streets = await Street.where({ cityId: city.parentCityId ?? city.id });
85
87
 
86
- if (streets.length == 0 && STAMHOOFD.environment === "development") {
87
- console.log("Forcing sync of city")
88
- const c = await City.getByID(city.parentCityId ?? city.id)
88
+ if (streets.length == 0 && STAMHOOFD.environment === 'development') {
89
+ console.log('Forcing sync of city');
90
+ const c = await City.getByID(city.parentCityId ?? city.id);
89
91
  try {
90
- await this.syncCity(c!)
91
- } catch (e) {
92
- console.error('Ignored error while syncing city')
93
- console.error(e)
92
+ await this.syncCity(c!);
94
93
  }
95
- streets = await Street.where({ cityId: city.parentCityId ?? city.id })
94
+ catch (e) {
95
+ console.error('Ignored error while syncing city');
96
+ console.error(e);
97
+ }
98
+ streets = await Street.where({ cityId: city.parentCityId ?? city.id });
96
99
  }
97
100
 
98
- if (STAMHOOFD.environment === "development" && streets.length > 0) {
101
+ if (STAMHOOFD.environment === 'development' && streets.length > 0) {
99
102
  // First search by typo count
100
- let bestScore = 0
101
- let bestStreet: Street | undefined = undefined
103
+ let bestScore = 0;
104
+ let bestStreet: Street | undefined = undefined;
102
105
  for (const street of streets) {
103
- const score = StringCompare.typoCount(street.name, address.street)
106
+ const score = StringCompare.typoCount(street.name, address.street);
104
107
  if ((bestStreet === undefined || score < bestScore)) {
105
- bestScore = score
106
- bestStreet = street
108
+ bestScore = score;
109
+ bestStreet = street;
107
110
  }
108
111
  }
109
112
 
110
113
  if (bestStreet && bestScore < 3) {
111
- address.street = bestStreet.name
112
- } else {
114
+ address.street = bestStreet.name;
115
+ }
116
+ else {
113
117
  // Search for the street
114
- bestScore = 0
115
- bestStreet = undefined
118
+ bestScore = 0;
119
+ bestStreet = undefined;
116
120
  for (const street of streets) {
117
- const score = StringCompare.compare(street.name, address.street)
121
+ const score = StringCompare.compare(street.name, address.street);
118
122
  if ((bestStreet === undefined || score > bestScore)) {
119
- bestScore = score
120
- bestStreet = street
123
+ bestScore = score;
124
+ bestStreet = street;
121
125
  }
122
126
  }
123
127
 
124
- if (!bestStreet || bestScore < 3 || bestScore < bestStreet.name.length/3) {
128
+ if (!bestStreet || bestScore < 3 || bestScore < bestStreet.name.length / 3) {
125
129
  throw new SimpleError({
126
- code: "invalid_field",
127
- message: "Invalid street",
128
- human: "Deze straat bestaat niet, kijk je deze even na op fouten? Formuleer de naam zonder afkortingen.",
129
- field: "street"
130
- })
130
+ code: 'invalid_field',
131
+ message: 'Invalid street',
132
+ human: 'Deze straat bestaat niet, kijk je deze even na op fouten? Formuleer de naam zonder afkortingen.',
133
+ field: 'street',
134
+ });
131
135
  }
132
136
 
133
137
  throw new SimpleError({
134
- code: "invalid_field",
135
- message: "Invalid street, do you mean " + bestStreet.name + "?",
138
+ code: 'invalid_field',
139
+ message: 'Invalid street, do you mean ' + bestStreet.name + '?',
136
140
  human: "Deze straat bestaat niet, bedoel je '" + bestStreet.name + "'?",
137
- field: "street"
138
- })
141
+ field: 'street',
142
+ });
139
143
  }
140
- } else {
144
+ }
145
+ else {
141
146
  // Skip validation for some regions that don't support validation
142
147
  }
143
148
  }
144
149
 
145
- return ValidatedAddress.create(Object.assign({ ... address }, {
150
+ return ValidatedAddress.create(Object.assign({ ...address }, {
146
151
  postalCode: address.country === Country.Belgium ? postalCode : address.postalCode,
147
152
  city: city.name, // override misspelled addresses
148
153
  cityId: city.id,
149
154
  parentCityId: city.parentCityId,
150
155
  provinceId: city.provinceId,
151
- }))
156
+ }));
152
157
  }
153
158
 
154
159
  async downloadStreets(country: Country, city: string): Promise<string[]> {
155
- let url: string | undefined = "https://api.basisregisters.vlaanderen.be/v2/straatnamen?gemeentenaam=" + encodeURIComponent(city)
156
- const streetNames: string[] = []
160
+ let url: string | undefined = 'https://api.basisregisters.vlaanderen.be/v2/straatnamen?gemeentenaam=' + encodeURIComponent(city);
161
+ const streetNames: string[] = [];
157
162
 
158
163
  try {
159
164
  while (url) {
160
165
  const response = await axios.request({
161
- method: "GET",
166
+ method: 'GET',
162
167
  url,
163
168
  headers: {
164
- "Accept": "application/ld+json",
165
- }
166
- })
169
+ Accept: 'application/ld+json',
170
+ },
171
+ });
167
172
 
168
173
  // TypeScript is going insane here, hence the weird type casting
169
174
  const result = new ObjectData(response.data, { version: 0 }).decode(StraatnamenResult as Decoder<StraatnamenResult>) as any as StraatnamenResult;
170
175
  const streets = result.straatnamen.map(street => street.straatnaam.geografischeNaam.spelling);
171
176
 
172
177
  streetNames.push(...streets);
173
- url = result.volgende
178
+ url = result.volgende;
174
179
  }
175
-
176
- } catch (e) {
177
- console.error(e.response.data)
178
- throw new Error("Failed to fetch streets")
180
+ }
181
+ catch (e) {
182
+ console.error(e.response.data);
183
+ throw new Error('Failed to fetch streets');
179
184
  }
180
185
 
181
- return streetNames
186
+ return streetNames;
182
187
  }
183
188
 
184
189
  async syncCity(city: City): Promise<void> {
185
- const streetNames = await this.downloadStreets(city.country, city.name)
190
+ const streetNames = await this.downloadStreets(city.country, city.name);
186
191
  if (streetNames.length == 0) {
187
- return
192
+ return;
188
193
  }
189
-
190
- await Database.delete("DELETE from `streets` WHERE `cityId` = ?", [city.id])
191
- await Database.insert("INSERT INTO `streets` (`id`, `name`, `cityId`) VALUES ?", [streetNames.map(street => [uuidv4(), street, city.id])])
194
+
195
+ await Database.delete('DELETE from `streets` WHERE `cityId` = ?', [city.id]);
196
+ await Database.insert('INSERT INTO `streets` (`id`, `name`, `cityId`) VALUES ?', [streetNames.map(street => [uuidv4(), street, city.id])]);
192
197
  }
193
198
 
194
199
  async syncAll(): Promise<void> {
195
- const cities = await City.where({ country: Country.Belgium, parentCityId: null })
200
+ const cities = await City.where({ country: Country.Belgium, parentCityId: null });
196
201
  for (const city of cities) {
197
- await this.syncCity(city)
202
+ await this.syncCity(city);
198
203
 
199
204
  // Rate limit
200
- await sleep(1000)
205
+ await sleep(1000);
201
206
  }
202
207
  }
203
208
 
204
209
  getSlowSync(): () => Promise<void> {
205
- let lastFullCitySync: Date | null = null
206
- let lastCityId = ""
210
+ let lastFullCitySync: Date | null = null;
211
+ let lastCityId = '';
207
212
  async function syncNext() {
208
213
  // Wait 24 hours between every full update
209
214
  if (lastFullCitySync && lastFullCitySync > new Date(new Date().getTime() - 24 * 60 * 60 * 1000)) {
210
- console.log("Skip city sync")
211
- return
215
+ console.log('Skip city sync');
216
+ return;
212
217
  }
213
-
214
- const cities = await City.where({
218
+
219
+ const cities = await City.where({
215
220
  id: { sign: '>', value: lastCityId },
216
- country: Country.Belgium,
217
- parentCityId: null
221
+ country: Country.Belgium,
222
+ parentCityId: null,
218
223
  }, {
219
224
  limit: 1,
220
- sort: ["id"]
221
- })
225
+ sort: ['id'],
226
+ });
222
227
 
223
228
  if (cities.length == 0) {
224
229
  // Wait an half hour before starting again
225
- lastCityId = ""
226
- lastFullCitySync = new Date()
227
- return
230
+ lastCityId = '';
231
+ lastFullCitySync = new Date();
232
+ return;
228
233
  }
229
234
 
230
235
  for (const city of cities) {
231
236
  try {
232
- await this.syncCity(city)
233
- } catch (e) {
234
- console.error("Failed city sync for "+city.name, e)
237
+ await this.syncCity(city);
238
+ }
239
+ catch (e) {
240
+ console.error('Failed city sync for ' + city.name, e);
235
241
  }
236
242
  }
237
243
 
238
- lastCityId = cities[cities.length - 1].id
244
+ lastCityId = cities[cities.length - 1].id;
239
245
  }
240
246
 
241
- return syncNext
247
+ return syncNext;
242
248
  }
243
249
  }
244
250
  class GeografischeNaam extends AutoEncoder {
245
251
  @field({ decoder: StringDecoder })
246
- spelling: string
252
+ spelling: string;
247
253
  }
248
254
 
249
255
  class Straatnaam extends AutoEncoder {
250
256
  @field({ decoder: GeografischeNaam })
251
- geografischeNaam: GeografischeNaam
257
+ geografischeNaam: GeografischeNaam;
252
258
  }
253
259
 
254
260
  class StraatnaamResult extends AutoEncoder {
255
261
  @field({ decoder: Straatnaam })
256
- straatnaam: Straatnaam
262
+ straatnaam: Straatnaam;
257
263
  }
258
264
 
259
265
  class StraatnamenResult extends AutoEncoder {
260
266
  @field({ decoder: new ArrayDecoder(StraatnaamResult) })
261
- straatnamen: StraatnaamResult[]
267
+ straatnamen: StraatnaamResult[];
262
268
 
263
269
  @field({ decoder: StringDecoder, optional: true })
264
- volgende?: string
270
+ volgende?: string;
265
271
  }
266
272
 
267
- export const AddressValidator = new AddressValidatorStatic()
273
+ export const AddressValidator = new AddressValidatorStatic();