@wasto/sdk 1.0.3 → 1.0.5

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 (56) hide show
  1. package/dist/index.d.mts +60 -3
  2. package/dist/index.d.ts +60 -3
  3. package/dist/index.js +79 -0
  4. package/dist/index.mjs +79 -0
  5. package/package.json +1 -1
  6. package/src/client.ts +791 -692
  7. package/src/dashboard-apps.ts +367 -350
  8. package/src/dto/cms-app-settings.ts +91 -91
  9. package/src/enums.ts +298 -298
  10. package/src/free-tier.ts +56 -56
  11. package/src/index.ts +35 -35
  12. package/src/opening-hours/constants.ts +48 -48
  13. package/src/opening-hours/convert.ts +276 -276
  14. package/src/opening-hours/format.ts +99 -99
  15. package/src/opening-hours/index.ts +9 -9
  16. package/src/opening-hours/is-open-now.ts +38 -38
  17. package/src/opening-hours/resolve.ts +71 -71
  18. package/src/opening-hours/time.ts +74 -74
  19. package/src/opening-hours/timezone.ts +34 -34
  20. package/src/opening-hours/types.ts +53 -53
  21. package/src/opening-hours/validate.ts +182 -182
  22. package/src/roi/calculations.ts +732 -732
  23. package/src/roi/index.ts +1 -1
  24. package/src/types/app-preload.types.ts +10 -0
  25. package/src/types/asset-bookings.types.ts +19 -19
  26. package/src/types/asset-interventions.types.ts +24 -24
  27. package/src/types/assets.types.ts +68 -68
  28. package/src/types/auth.types.ts +37 -37
  29. package/src/types/blog-posts.types.ts +19 -19
  30. package/src/types/calendar-pdf.types.ts +24 -24
  31. package/src/types/calendo-events.types.ts +64 -64
  32. package/src/types/challenges.types.ts +30 -30
  33. package/src/types/chatbot.types.ts +82 -82
  34. package/src/types/cities.types.ts +27 -27
  35. package/src/types/city-groups.types.ts +46 -46
  36. package/src/types/cms.types.ts +87 -87
  37. package/src/types/field-reports.types.ts +66 -66
  38. package/src/types/free-tier.types.ts +54 -54
  39. package/src/types/index.ts +33 -32
  40. package/src/types/iot.types.ts +31 -31
  41. package/src/types/maintenance.types.ts +44 -44
  42. package/src/types/mapso.types.ts +146 -146
  43. package/src/types/notifications.types.ts +68 -68
  44. package/src/types/onboarding.types.ts +117 -117
  45. package/src/types/operational-zones.types.ts +70 -70
  46. package/src/types/pagination.types.ts +33 -33
  47. package/src/types/providers.types.ts +29 -29
  48. package/src/types/quiz-questions.types.ts +59 -59
  49. package/src/types/recycling-points.types.ts +47 -47
  50. package/src/types/roi.types.ts +60 -60
  51. package/src/types/surveys.types.ts +103 -103
  52. package/src/types/tickets.types.ts +65 -65
  53. package/src/types/users.types.ts +30 -30
  54. package/src/types/waste-collection-places-query.types.ts +4 -4
  55. package/src/types/waste-collection-places.types.ts +34 -33
  56. package/src/types/waste-types.types.ts +21 -21
@@ -1,53 +1,53 @@
1
- export const WEEKDAYS = [
2
- 'monday',
3
- 'tuesday',
4
- 'wednesday',
5
- 'thursday',
6
- 'friday',
7
- 'saturday',
8
- 'sunday',
9
- ] as const;
10
-
11
- export type Weekday = (typeof WEEKDAYS)[number];
12
-
13
- export type TimeSlot = { open: string; close: string };
14
-
15
- export type OpeningHoursRule = { days: Weekday[]; slots: TimeSlot[] };
16
-
17
- export type OpeningHoursExceptionClosed = {
18
- date: string;
19
- closed: true;
20
- label?: string;
21
- };
22
-
23
- export type OpeningHoursExceptionOpen = {
24
- date: string;
25
- closed: false;
26
- slots: TimeSlot[];
27
- label?: string;
28
- };
29
-
30
- export type OpeningHoursException =
31
- | OpeningHoursExceptionClosed
32
- | OpeningHoursExceptionOpen;
33
-
34
- /** Horaires structurés persistés en UTC+0 */
35
- export type OpeningHours = {
36
- version: 1;
37
- storage: 'utc';
38
- rules: OpeningHoursRule[];
39
- exceptions?: OpeningHoursException[];
40
- };
41
-
42
- export type HoursInputMode = 'structured' | 'text';
43
-
44
- export type WeeklyHoursRow = {
45
- day: Weekday;
46
- label: string;
47
- closed: boolean;
48
- slots: TimeSlot[];
49
- };
50
-
51
- export type OpeningHoursValidationResult =
52
- | { ok: true; value: OpeningHours }
53
- | { ok: false; errors: string[] };
1
+ export const WEEKDAYS = [
2
+ 'monday',
3
+ 'tuesday',
4
+ 'wednesday',
5
+ 'thursday',
6
+ 'friday',
7
+ 'saturday',
8
+ 'sunday',
9
+ ] as const;
10
+
11
+ export type Weekday = (typeof WEEKDAYS)[number];
12
+
13
+ export type TimeSlot = { open: string; close: string };
14
+
15
+ export type OpeningHoursRule = { days: Weekday[]; slots: TimeSlot[] };
16
+
17
+ export type OpeningHoursExceptionClosed = {
18
+ date: string;
19
+ closed: true;
20
+ label?: string;
21
+ };
22
+
23
+ export type OpeningHoursExceptionOpen = {
24
+ date: string;
25
+ closed: false;
26
+ slots: TimeSlot[];
27
+ label?: string;
28
+ };
29
+
30
+ export type OpeningHoursException =
31
+ | OpeningHoursExceptionClosed
32
+ | OpeningHoursExceptionOpen;
33
+
34
+ /** Horaires structurés persistés en UTC+0 */
35
+ export type OpeningHours = {
36
+ version: 1;
37
+ storage: 'utc';
38
+ rules: OpeningHoursRule[];
39
+ exceptions?: OpeningHoursException[];
40
+ };
41
+
42
+ export type HoursInputMode = 'structured' | 'text';
43
+
44
+ export type WeeklyHoursRow = {
45
+ day: Weekday;
46
+ label: string;
47
+ closed: boolean;
48
+ slots: TimeSlot[];
49
+ };
50
+
51
+ export type OpeningHoursValidationResult =
52
+ | { ok: true; value: OpeningHours }
53
+ | { ok: false; errors: string[] };
@@ -1,182 +1,182 @@
1
- import {
2
- WEEKDAYS,
3
- type OpeningHours,
4
- type OpeningHoursException,
5
- type OpeningHoursRule,
6
- type OpeningHoursValidationResult,
7
- type TimeSlot,
8
- type Weekday,
9
- } from './types';
10
- import { parseTimeMinutes, slotsOverlap, sortSlots } from './time';
11
-
12
- const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
13
-
14
- function isPlainObject(v: unknown): v is Record<string, unknown> {
15
- return v != null && typeof v === 'object' && !Array.isArray(v);
16
- }
17
-
18
- function validateTimeSlot(slot: unknown, path: string, errors: string[]): slot is TimeSlot {
19
- if (!isPlainObject(slot)) {
20
- errors.push(`${path} : créneau invalide`);
21
- return false;
22
- }
23
- const open = slot.open;
24
- const close = slot.close;
25
- if (typeof open !== 'string' || parseTimeMinutes(open) == null) {
26
- errors.push(`${path}.open : heure invalide (HH:mm)`);
27
- return false;
28
- }
29
- if (typeof close !== 'string' || parseTimeMinutes(close) == null) {
30
- errors.push(`${path}.close : heure invalide (HH:mm)`);
31
- return false;
32
- }
33
- const openMin = parseTimeMinutes(open)!;
34
- const closeMin = parseTimeMinutes(close)!;
35
- if (closeMin <= openMin) {
36
- errors.push(`${path} : l'heure de fermeture doit être après l'ouverture (UTC)`);
37
- return false;
38
- }
39
- return true;
40
- }
41
-
42
- function validateRule(rule: unknown, index: number, errors: string[]): rule is OpeningHoursRule {
43
- if (!isPlainObject(rule)) {
44
- errors.push(`rules[${index}] : règle invalide`);
45
- return false;
46
- }
47
- if (!Array.isArray(rule.days) || rule.days.length === 0) {
48
- errors.push(`rules[${index}].days : au moins un jour requis`);
49
- return false;
50
- }
51
- for (const day of rule.days) {
52
- if (typeof day !== 'string' || !WEEKDAYS.includes(day as Weekday)) {
53
- errors.push(`rules[${index}].days : jour invalide (${String(day)})`);
54
- }
55
- }
56
- if (!Array.isArray(rule.slots) || rule.slots.length === 0) {
57
- errors.push(`rules[${index}].slots : au moins un créneau requis`);
58
- return false;
59
- }
60
- const slots: TimeSlot[] = [];
61
- rule.slots.forEach((slot, slotIndex) => {
62
- if (validateTimeSlot(slot, `rules[${index}].slots[${slotIndex}]`, errors)) {
63
- slots.push(slot);
64
- }
65
- });
66
- const sorted = sortSlots(slots);
67
- for (let i = 0; i < sorted.length - 1; i++) {
68
- if (slotsOverlap(sorted[i], sorted[i + 1])) {
69
- errors.push(`rules[${index}].slots : créneaux qui se chevauchent`);
70
- break;
71
- }
72
- }
73
- return errors.length === 0;
74
- }
75
-
76
- function validateException(
77
- exc: unknown,
78
- index: number,
79
- errors: string[],
80
- ): exc is OpeningHoursException {
81
- if (!isPlainObject(exc)) {
82
- errors.push(`exceptions[${index}] : exception invalide`);
83
- return false;
84
- }
85
- if (typeof exc.date !== 'string' || !DATE_RE.test(exc.date)) {
86
- errors.push(`exceptions[${index}].date : date invalide (YYYY-MM-DD)`);
87
- return false;
88
- }
89
- if (exc.closed === true) return true;
90
- if (exc.closed === false) {
91
- if (!Array.isArray(exc.slots) || exc.slots.length === 0) {
92
- errors.push(`exceptions[${index}].slots : requis si non fermé`);
93
- return false;
94
- }
95
- exc.slots.forEach((slot, slotIndex) => {
96
- validateTimeSlot(slot, `exceptions[${index}].slots[${slotIndex}]`, errors);
97
- });
98
- return true;
99
- }
100
- errors.push(`exceptions[${index}].closed : booléen requis`);
101
- return false;
102
- }
103
-
104
- export function validateOpeningHours(input: unknown): OpeningHoursValidationResult {
105
- const errors: string[] = [];
106
- if (!isPlainObject(input)) {
107
- return { ok: false, errors: ['Horaires : objet attendu'] };
108
- }
109
- if (input.version !== 1) {
110
- errors.push('version : doit être 1');
111
- }
112
- if (input.storage !== 'utc') {
113
- errors.push('storage : doit être "utc"');
114
- }
115
- if (!Array.isArray(input.rules)) {
116
- errors.push('rules : tableau attendu');
117
- return { ok: false, errors };
118
- }
119
- input.rules.forEach((rule, index) => validateRule(rule, index, errors));
120
-
121
- const daySet = new Set<Weekday>();
122
- if (Array.isArray(input.rules)) {
123
- for (const rule of input.rules) {
124
- if (!isPlainObject(rule) || !Array.isArray(rule.days)) continue;
125
- for (const day of rule.days) {
126
- if (typeof day === 'string' && WEEKDAYS.includes(day as Weekday)) {
127
- const wd = day as Weekday;
128
- if (daySet.has(wd)) {
129
- errors.push(`rules : le jour ${wd} apparaît dans plusieurs règles`);
130
- }
131
- daySet.add(wd);
132
- }
133
- }
134
- }
135
- }
136
-
137
- if (input.exceptions != null) {
138
- if (!Array.isArray(input.exceptions)) {
139
- errors.push('exceptions : tableau attendu');
140
- } else {
141
- input.exceptions.forEach((exc, index) => validateException(exc, index, errors));
142
- }
143
- }
144
-
145
- if (errors.length > 0) {
146
- return { ok: false, errors };
147
- }
148
-
149
- return {
150
- ok: true,
151
- value: {
152
- version: 1,
153
- storage: 'utc',
154
- rules: (input.rules as OpeningHoursRule[]).map((r) => ({
155
- days: [...r.days],
156
- slots: sortSlots([...r.slots]),
157
- })),
158
- exceptions: input.exceptions as OpeningHoursException[] | undefined,
159
- },
160
- };
161
- }
162
-
163
- /** Valide des horaires saisis en heure locale (même structure, sans storage/version). */
164
- export function validateLocalOpeningHours(input: {
165
- rules: OpeningHoursRule[];
166
- exceptions?: OpeningHoursException[];
167
- }): OpeningHoursValidationResult {
168
- return validateOpeningHours({
169
- version: 1,
170
- storage: 'utc',
171
- rules: input.rules,
172
- exceptions: input.exceptions,
173
- });
174
- }
175
-
176
- export function createEmptyOpeningHours(): OpeningHours {
177
- return { version: 1, storage: 'utc', rules: [] };
178
- }
179
-
180
- export function createEmptyLocalRules(): OpeningHoursRule[] {
181
- return [];
182
- }
1
+ import {
2
+ WEEKDAYS,
3
+ type OpeningHours,
4
+ type OpeningHoursException,
5
+ type OpeningHoursRule,
6
+ type OpeningHoursValidationResult,
7
+ type TimeSlot,
8
+ type Weekday,
9
+ } from './types';
10
+ import { parseTimeMinutes, slotsOverlap, sortSlots } from './time';
11
+
12
+ const DATE_RE = /^\d{4}-\d{2}-\d{2}$/;
13
+
14
+ function isPlainObject(v: unknown): v is Record<string, unknown> {
15
+ return v != null && typeof v === 'object' && !Array.isArray(v);
16
+ }
17
+
18
+ function validateTimeSlot(slot: unknown, path: string, errors: string[]): slot is TimeSlot {
19
+ if (!isPlainObject(slot)) {
20
+ errors.push(`${path} : créneau invalide`);
21
+ return false;
22
+ }
23
+ const open = slot.open;
24
+ const close = slot.close;
25
+ if (typeof open !== 'string' || parseTimeMinutes(open) == null) {
26
+ errors.push(`${path}.open : heure invalide (HH:mm)`);
27
+ return false;
28
+ }
29
+ if (typeof close !== 'string' || parseTimeMinutes(close) == null) {
30
+ errors.push(`${path}.close : heure invalide (HH:mm)`);
31
+ return false;
32
+ }
33
+ const openMin = parseTimeMinutes(open)!;
34
+ const closeMin = parseTimeMinutes(close)!;
35
+ if (closeMin <= openMin) {
36
+ errors.push(`${path} : l'heure de fermeture doit être après l'ouverture (UTC)`);
37
+ return false;
38
+ }
39
+ return true;
40
+ }
41
+
42
+ function validateRule(rule: unknown, index: number, errors: string[]): rule is OpeningHoursRule {
43
+ if (!isPlainObject(rule)) {
44
+ errors.push(`rules[${index}] : règle invalide`);
45
+ return false;
46
+ }
47
+ if (!Array.isArray(rule.days) || rule.days.length === 0) {
48
+ errors.push(`rules[${index}].days : au moins un jour requis`);
49
+ return false;
50
+ }
51
+ for (const day of rule.days) {
52
+ if (typeof day !== 'string' || !WEEKDAYS.includes(day as Weekday)) {
53
+ errors.push(`rules[${index}].days : jour invalide (${String(day)})`);
54
+ }
55
+ }
56
+ if (!Array.isArray(rule.slots) || rule.slots.length === 0) {
57
+ errors.push(`rules[${index}].slots : au moins un créneau requis`);
58
+ return false;
59
+ }
60
+ const slots: TimeSlot[] = [];
61
+ rule.slots.forEach((slot, slotIndex) => {
62
+ if (validateTimeSlot(slot, `rules[${index}].slots[${slotIndex}]`, errors)) {
63
+ slots.push(slot);
64
+ }
65
+ });
66
+ const sorted = sortSlots(slots);
67
+ for (let i = 0; i < sorted.length - 1; i++) {
68
+ if (slotsOverlap(sorted[i], sorted[i + 1])) {
69
+ errors.push(`rules[${index}].slots : créneaux qui se chevauchent`);
70
+ break;
71
+ }
72
+ }
73
+ return errors.length === 0;
74
+ }
75
+
76
+ function validateException(
77
+ exc: unknown,
78
+ index: number,
79
+ errors: string[],
80
+ ): exc is OpeningHoursException {
81
+ if (!isPlainObject(exc)) {
82
+ errors.push(`exceptions[${index}] : exception invalide`);
83
+ return false;
84
+ }
85
+ if (typeof exc.date !== 'string' || !DATE_RE.test(exc.date)) {
86
+ errors.push(`exceptions[${index}].date : date invalide (YYYY-MM-DD)`);
87
+ return false;
88
+ }
89
+ if (exc.closed === true) return true;
90
+ if (exc.closed === false) {
91
+ if (!Array.isArray(exc.slots) || exc.slots.length === 0) {
92
+ errors.push(`exceptions[${index}].slots : requis si non fermé`);
93
+ return false;
94
+ }
95
+ exc.slots.forEach((slot, slotIndex) => {
96
+ validateTimeSlot(slot, `exceptions[${index}].slots[${slotIndex}]`, errors);
97
+ });
98
+ return true;
99
+ }
100
+ errors.push(`exceptions[${index}].closed : booléen requis`);
101
+ return false;
102
+ }
103
+
104
+ export function validateOpeningHours(input: unknown): OpeningHoursValidationResult {
105
+ const errors: string[] = [];
106
+ if (!isPlainObject(input)) {
107
+ return { ok: false, errors: ['Horaires : objet attendu'] };
108
+ }
109
+ if (input.version !== 1) {
110
+ errors.push('version : doit être 1');
111
+ }
112
+ if (input.storage !== 'utc') {
113
+ errors.push('storage : doit être "utc"');
114
+ }
115
+ if (!Array.isArray(input.rules)) {
116
+ errors.push('rules : tableau attendu');
117
+ return { ok: false, errors };
118
+ }
119
+ input.rules.forEach((rule, index) => validateRule(rule, index, errors));
120
+
121
+ const daySet = new Set<Weekday>();
122
+ if (Array.isArray(input.rules)) {
123
+ for (const rule of input.rules) {
124
+ if (!isPlainObject(rule) || !Array.isArray(rule.days)) continue;
125
+ for (const day of rule.days) {
126
+ if (typeof day === 'string' && WEEKDAYS.includes(day as Weekday)) {
127
+ const wd = day as Weekday;
128
+ if (daySet.has(wd)) {
129
+ errors.push(`rules : le jour ${wd} apparaît dans plusieurs règles`);
130
+ }
131
+ daySet.add(wd);
132
+ }
133
+ }
134
+ }
135
+ }
136
+
137
+ if (input.exceptions != null) {
138
+ if (!Array.isArray(input.exceptions)) {
139
+ errors.push('exceptions : tableau attendu');
140
+ } else {
141
+ input.exceptions.forEach((exc, index) => validateException(exc, index, errors));
142
+ }
143
+ }
144
+
145
+ if (errors.length > 0) {
146
+ return { ok: false, errors };
147
+ }
148
+
149
+ return {
150
+ ok: true,
151
+ value: {
152
+ version: 1,
153
+ storage: 'utc',
154
+ rules: (input.rules as OpeningHoursRule[]).map((r) => ({
155
+ days: [...r.days],
156
+ slots: sortSlots([...r.slots]),
157
+ })),
158
+ exceptions: input.exceptions as OpeningHoursException[] | undefined,
159
+ },
160
+ };
161
+ }
162
+
163
+ /** Valide des horaires saisis en heure locale (même structure, sans storage/version). */
164
+ export function validateLocalOpeningHours(input: {
165
+ rules: OpeningHoursRule[];
166
+ exceptions?: OpeningHoursException[];
167
+ }): OpeningHoursValidationResult {
168
+ return validateOpeningHours({
169
+ version: 1,
170
+ storage: 'utc',
171
+ rules: input.rules,
172
+ exceptions: input.exceptions,
173
+ });
174
+ }
175
+
176
+ export function createEmptyOpeningHours(): OpeningHours {
177
+ return { version: 1, storage: 'utc', rules: [] };
178
+ }
179
+
180
+ export function createEmptyLocalRules(): OpeningHoursRule[] {
181
+ return [];
182
+ }