@gruncellka/porto-data 0.3.0 → 0.4.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 (88) hide show
  1. package/CHANGELOG.md +215 -0
  2. package/LICENSE +199 -5
  3. package/README.md +53 -34
  4. package/index.d.ts +35 -18
  5. package/index.js +2 -1
  6. package/package.json +28 -8
  7. package/porto_data/formats/envelopes.json +120 -0
  8. package/porto_data/formats/layouts.json +288 -0
  9. package/porto_data/mappings.json +65 -10
  10. package/porto_data/metadata.json +662 -125
  11. package/porto_data/policy/jurisdictions.json +839 -0
  12. package/porto_data/policy/markets.json +75 -0
  13. package/porto_data/policy/restrictions.json +668 -0
  14. package/porto_data/providers/deutschepost/features.json +42 -0
  15. package/porto_data/providers/deutschepost/graph.json +203 -0
  16. package/porto_data/providers/deutschepost/limits.json +17 -0
  17. package/porto_data/providers/deutschepost/marks.json +71 -0
  18. package/porto_data/providers/deutschepost/prices/products.json +239 -0
  19. package/porto_data/providers/deutschepost/prices/services.json +51 -0
  20. package/porto_data/providers/deutschepost/products.json +197 -0
  21. package/porto_data/providers/deutschepost/services.json +88 -0
  22. package/porto_data/providers/deutschepost/weights.json +46 -0
  23. package/porto_data/providers/deutschepost/zones.json +231 -0
  24. package/porto_data/providers/laposte/features.json +42 -0
  25. package/porto_data/providers/laposte/graph.json +234 -0
  26. package/porto_data/providers/laposte/limits.json +17 -0
  27. package/porto_data/providers/laposte/marks.json +39 -0
  28. package/porto_data/providers/laposte/prices/products.json +947 -0
  29. package/porto_data/providers/laposte/prices/services.json +41 -0
  30. package/porto_data/providers/laposte/products.json +276 -0
  31. package/porto_data/providers/laposte/services.json +63 -0
  32. package/porto_data/providers/laposte/weights.json +38 -0
  33. package/porto_data/providers/laposte/zones.json +230 -0
  34. package/porto_data/providers/swisspost/features.json +21 -0
  35. package/porto_data/providers/swisspost/graph.json +212 -0
  36. package/porto_data/providers/swisspost/limits.json +17 -0
  37. package/porto_data/providers/swisspost/marks.json +41 -0
  38. package/porto_data/providers/swisspost/prices/products.json +347 -0
  39. package/porto_data/providers/swisspost/prices/services.json +31 -0
  40. package/porto_data/providers/swisspost/products.json +193 -0
  41. package/porto_data/providers/swisspost/rules.json +25 -0
  42. package/porto_data/providers/swisspost/services.json +40 -0
  43. package/porto_data/providers/swisspost/weights.json +38 -0
  44. package/porto_data/providers/swisspost/zones.json +223 -0
  45. package/porto_data/providers/ukrposhta/features.json +28 -0
  46. package/porto_data/providers/ukrposhta/graph.json +148 -0
  47. package/porto_data/providers/ukrposhta/limits.json +17 -0
  48. package/porto_data/providers/ukrposhta/marks.json +25 -0
  49. package/porto_data/providers/ukrposhta/prices/products.json +123 -0
  50. package/porto_data/providers/ukrposhta/prices/services.json +42 -0
  51. package/porto_data/providers/ukrposhta/products.json +74 -0
  52. package/porto_data/providers/ukrposhta/services.json +40 -0
  53. package/porto_data/providers/ukrposhta/weights.json +26 -0
  54. package/porto_data/providers/ukrposhta/zones.json +226 -0
  55. package/porto_data/providers.json +37 -0
  56. package/porto_data/schemas/envelopes.schema.json +120 -0
  57. package/porto_data/schemas/features.schema.json +66 -55
  58. package/porto_data/schemas/graph.schema.json +189 -0
  59. package/porto_data/schemas/jurisdictions.schema.json +116 -0
  60. package/porto_data/schemas/layouts.schema.json +156 -0
  61. package/porto_data/schemas/limits.schema.json +253 -0
  62. package/porto_data/schemas/mappings.schema.json +73 -0
  63. package/porto_data/schemas/markets.schema.json +186 -0
  64. package/porto_data/schemas/marks.schema.json +127 -0
  65. package/porto_data/schemas/metadata.schema.json +183 -0
  66. package/porto_data/schemas/porto_ids.schema.json +45 -0
  67. package/porto_data/schemas/product_prices.schema.json +126 -0
  68. package/porto_data/schemas/products.schema.json +338 -110
  69. package/porto_data/schemas/providers.schema.json +71 -0
  70. package/porto_data/schemas/restrictions.schema.json +175 -355
  71. package/porto_data/schemas/rules.schema.json +104 -0
  72. package/porto_data/schemas/service_prices.schema.json +116 -0
  73. package/porto_data/schemas/services.schema.json +113 -70
  74. package/porto_data/schemas/weights.schema.json +70 -0
  75. package/porto_data/schemas/zones.schema.json +78 -72
  76. package/porto_data/data/data_links.json +0 -148
  77. package/porto_data/data/dimensions.json +0 -158
  78. package/porto_data/data/features.json +0 -66
  79. package/porto_data/data/prices.json +0 -242
  80. package/porto_data/data/products.json +0 -84
  81. package/porto_data/data/restrictions.json +0 -795
  82. package/porto_data/data/services.json +0 -61
  83. package/porto_data/data/weight_tiers.json +0 -54
  84. package/porto_data/data/zones.json +0 -230
  85. package/porto_data/schemas/data_links.schema.json +0 -223
  86. package/porto_data/schemas/dimensions.schema.json +0 -215
  87. package/porto_data/schemas/prices.schema.json +0 -180
  88. package/porto_data/schemas/weight_tiers.schema.json +0 -70
@@ -1,122 +1,350 @@
1
1
  {
2
- "$schema": "http://json-schema.org/draft-07/schema#",
3
- "$id": "https://raw.githubusercontent.com/gruncellka/porto-data/refs/heads/main/porto_data/schemas/products.schema.json",
4
- "title": "Products Schema",
5
- "description": "Schema for postal products definitions",
6
- "type": "object",
7
- "required": [
8
- "file_type",
9
- "unit",
10
- "products"
11
- ],
12
- "properties": {
13
- "$schema": {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://raw.githubusercontent.com/gruncellka/porto-data/refs/heads/main/porto_data/schemas/products.schema.json",
4
+ "title": "Products Schema",
5
+ "description": "Schema for postal products definitions",
6
+ "type": "object",
7
+ "required": [
8
+ "file_type",
9
+ "provider",
10
+ "unit",
11
+ "products"
12
+ ],
13
+ "properties": {
14
+ "$schema": {
15
+ "type": "string",
16
+ "format": "uri",
17
+ "description": "JSON Schema URI reference"
18
+ },
19
+ "file_type": {
20
+ "type": "string",
21
+ "const": "products",
22
+ "description": "File type identifier"
23
+ },
24
+ "provider": {
25
+ "type": "string",
26
+ "pattern": "^[a-z_]+$",
27
+ "description": "Provider identifier (e.g. deutschepost, ukrposhta, laposte, swisspost)"
28
+ },
29
+ "unit": {
30
+ "type": "object",
31
+ "description": "Product-level units: weight only. Envelope formats: envelope_ids reference formats/envelopes.json; print layout via formats/layouts.json by jurisdiction.",
32
+ "required": [
33
+ "weight"
34
+ ],
35
+ "properties": {
36
+ "weight": {
37
+ "type": "string",
38
+ "const": "g"
39
+ }
40
+ },
41
+ "additionalProperties": false
42
+ },
43
+ "products": {
44
+ "type": "array",
45
+ "minItems": 1,
46
+ "items": {
47
+ "type": "object",
48
+ "required": [
49
+ "id",
50
+ "porto_id",
51
+ "name",
52
+ "envelope_ids",
53
+ "zones",
54
+ "effective_from",
55
+ "effective_to",
56
+ "mark_type",
57
+ "tracking_mode",
58
+ "delivery"
59
+ ],
60
+ "properties": {
61
+ "id": {
62
+ "type": "string",
63
+ "pattern": "^[a-z_]+$",
64
+ "description": "Semantic English product ID"
65
+ },
66
+ "name": {
67
+ "type": "string",
68
+ "minLength": 1,
69
+ "description": "Official product name (original language)"
70
+ },
71
+ "native_id": {
72
+ "description": "Carrier API product identifier for this row (contract catalog / ordering). Not the bundle `id` and not unified `porto_id`. Examples: DHL Internetmarke REST `productCode` (integer). Values must match the operator’s live catalog (e.g. `/app/catalog` contract products).",
73
+ "oneOf": [
74
+ {
75
+ "type": "integer",
76
+ "minimum": 1
77
+ },
78
+ {
79
+ "type": "string",
80
+ "minLength": 1
81
+ }
82
+ ]
83
+ },
84
+ "porto_id": {
85
+ "$ref": "porto_ids.schema.json#/definitions/product_porto_id",
86
+ "description": "Unified Porto letter size bucket (small … extra_large). Not service semantics — use services.json for registered/tracking add-ons. Graph and prices use native `id`, not `porto_id`."
87
+ },
88
+ "envelope_ids": {
89
+ "type": "array",
90
+ "minItems": 1,
91
+ "items": {
92
+ "type": "string",
93
+ "enum": [
94
+ "C8",
95
+ "C7",
96
+ "C6",
97
+ "DL",
98
+ "C5",
99
+ "B6",
100
+ "B5",
101
+ "C4",
102
+ "C3",
103
+ "B4"
104
+ ]
105
+ },
106
+ "description": "Supported envelope format ids (global envelopes.json)"
107
+ },
108
+ "zones": {
109
+ "type": "array",
110
+ "minItems": 1,
111
+ "items": {
112
+ "type": "string",
113
+ "pattern": "^[a-z0-9_]+$"
114
+ },
115
+ "description": "Zones where this product is available (must align with graph.edges.products for this product_id)"
116
+ },
117
+ "weight_tier": {
14
118
  "type": "string",
15
- "format": "uri",
16
- "description": "JSON Schema URI reference"
119
+ "pattern": "^W[0-9]+$",
120
+ "description": "Optional single weight tier id when the product maps to one step; full matrix is graph.edges + weights + prices."
121
+ },
122
+ "effective_from": {
123
+ "type": [
124
+ "string",
125
+ "null"
126
+ ],
127
+ "format": "date",
128
+ "description": "Catalog baseline for this product row (e.g. 2026-01-01); not a claim about carrier real-world introduction."
129
+ },
130
+ "effective_to": {
131
+ "type": [
132
+ "string",
133
+ "null"
134
+ ],
135
+ "format": "date",
136
+ "description": "Null while modeled; set when the product row is retired in the bundle."
137
+ },
138
+ "mark_type": {
139
+ "type": "string",
140
+ "enum": [
141
+ "stamp",
142
+ "label"
143
+ ],
144
+ "description": "What kind of provider mark this product produces when executed (data-driven; not inferred in adapters)."
145
+ },
146
+ "tracking_mode": {
147
+ "type": "string",
148
+ "enum": [
149
+ "none",
150
+ "optional",
151
+ "included"
152
+ ],
153
+ "description": "Whether tracking is expected on the execution result; actual tracking numbers are runtime-only (PortoMark), never stored in porto-data."
154
+ },
155
+ "delivery": {
156
+ "type": "array",
157
+ "minItems": 1,
158
+ "description": "Operator-stated delivery SLA per zone group. Union of all entry zones must equal product.zones exactly.",
159
+ "items": {
160
+ "$ref": "#/definitions/delivery_entry"
161
+ }
162
+ },
163
+ "included_features": {
164
+ "type": "array",
165
+ "uniqueItems": true,
166
+ "items": {
167
+ "type": "string",
168
+ "pattern": "^[a-z_]+$"
169
+ },
170
+ "description": "Provider feature ids bundled in base postage (see features.json). Optional add-ons remain in services.json."
171
+ },
172
+ "indemnity": {
173
+ "$ref": "#/definitions/indemnity",
174
+ "description": "Operator-stated loss/damage indemnity cap when the product tier defines one."
175
+ }
176
+ },
177
+ "additionalProperties": false,
178
+ "allOf": [
179
+ {
180
+ "if": {
181
+ "properties": {
182
+ "mark_type": {
183
+ "const": "label"
184
+ }
185
+ },
186
+ "required": [
187
+ "mark_type"
188
+ ]
189
+ },
190
+ "then": {
191
+ "properties": {
192
+ "tracking_mode": {
193
+ "enum": [
194
+ "optional",
195
+ "included"
196
+ ]
197
+ }
198
+ }
199
+ }
200
+ }
201
+ ]
202
+ }
203
+ }
204
+ },
205
+ "definitions": {
206
+ "indemnity_max": {
207
+ "type": "object",
208
+ "required": [
209
+ "amount"
210
+ ],
211
+ "properties": {
212
+ "amount": {
213
+ "type": "integer",
214
+ "minimum": 1,
215
+ "description": "Indemnification cap in provider market minor units (markets[country].currency)."
216
+ }
217
+ },
218
+ "additionalProperties": false
219
+ },
220
+ "indemnity": {
221
+ "type": "object",
222
+ "required": [
223
+ "tier",
224
+ "max"
225
+ ],
226
+ "properties": {
227
+ "tier": {
228
+ "type": "string",
229
+ "minLength": 1,
230
+ "description": "Operator-native indemnity"
17
231
  },
18
- "file_type": {
232
+ "max": {
233
+ "$ref": "#/definitions/indemnity_max",
234
+ "description": "Maximum indemnification in case of loss or damage per operator tariff."
235
+ }
236
+ },
237
+ "additionalProperties": false
238
+ },
239
+ "delivery_entry": {
240
+ "type": "object",
241
+ "required": [
242
+ "zones",
243
+ "span",
244
+ "days_max"
245
+ ],
246
+ "properties": {
247
+ "zones": {
248
+ "type": "array",
249
+ "minItems": 1,
250
+ "items": {
19
251
  "type": "string",
20
- "const": "products",
21
- "description": "File type identifier"
252
+ "pattern": "^[a-z0-9_]+$"
253
+ },
254
+ "description": "Zone ids from this product's zones[]; each product zone must appear in exactly one delivery entry."
22
255
  },
23
- "unit": {
24
- "type": "object",
256
+ "span": {
257
+ "type": "string",
258
+ "enum": [
259
+ "next",
260
+ "within",
261
+ "between"
262
+ ],
263
+ "description": "How to read days_max: next (exactly 1 day), within (up to days_max), between (days_min..days_max)."
264
+ },
265
+ "days_max": {
266
+ "type": "integer",
267
+ "minimum": 1,
268
+ "description": "Maximum counted delivery days for this zone group per operator tariff wording."
269
+ },
270
+ "days_min": {
271
+ "type": "integer",
272
+ "minimum": 1,
273
+ "description": "Minimum counted delivery days when span is between."
274
+ },
275
+ "weekdays": {
276
+ "type": "string",
277
+ "enum": [
278
+ "mon_fri",
279
+ "mon_sat"
280
+ ],
281
+ "description": "Optional override when operator text narrows or widens weekdays vs markets[country].working_days."
282
+ }
283
+ },
284
+ "additionalProperties": false,
285
+ "allOf": [
286
+ {
287
+ "if": {
288
+ "properties": {
289
+ "span": {
290
+ "const": "next"
291
+ }
292
+ },
25
293
  "required": [
26
- "dimension",
27
- "weight"
28
- ],
294
+ "span"
295
+ ]
296
+ },
297
+ "then": {
29
298
  "properties": {
30
- "dimension": {
31
- "type": "string",
32
- "const": "mm"
33
- },
34
- "weight": {
35
- "type": "string",
36
- "const": "g"
37
- }
299
+ "days_max": {
300
+ "const": 1
301
+ }
38
302
  },
39
- "additionalProperties": false
303
+ "not": {
304
+ "required": [
305
+ "days_min"
306
+ ]
307
+ }
308
+ }
40
309
  },
41
- "products": {
42
- "type": "array",
43
- "minItems": 1,
44
- "items": {
45
- "type": "object",
46
- "required": [
47
- "id",
48
- "name",
49
- "dimension_ids",
50
- "supported_zones",
51
- "weight_tier",
52
- "effective_from",
53
- "effective_to"
54
- ],
55
- "properties": {
56
- "id": {
57
- "type": "string",
58
- "pattern": "^[a-z_]+$",
59
- "description": "Semantic English product ID"
60
- },
61
- "name": {
62
- "type": "string",
63
- "minLength": 1,
64
- "description": "Official German product name"
65
- },
66
- "dimension_ids": {
67
- "type": "array",
68
- "minItems": 1,
69
- "items": {
70
- "type": "string",
71
- "enum": [
72
- "DL",
73
- "C6",
74
- "C5",
75
- "C4",
76
- "B4"
77
- ]
78
- },
79
- "description": "Supported dimension IDs"
80
- },
81
- "supported_zones": {
82
- "type": "array",
83
- "minItems": 1,
84
- "items": {
85
- "type": "string",
86
- "enum": [
87
- "domestic",
88
- "zone_1_eu",
89
- "zone_2_europe",
90
- "world"
91
- ]
92
- },
93
- "description": "Zones where this product is available"
94
- },
95
- "weight_tier": {
96
- "type": "string",
97
- "pattern": "^W[0-9]+$",
98
- "description": "Weight tier ID"
99
- },
100
- "effective_from": {
101
- "type": [
102
- "string",
103
- "null"
104
- ],
105
- "format": "date",
106
- "description": "Product effective start date"
107
- },
108
- "effective_to": {
109
- "type": [
110
- "string",
111
- "null"
112
- ],
113
- "format": "date",
114
- "description": "Product effective end date"
115
- }
116
- },
117
- "additionalProperties": false
310
+ {
311
+ "if": {
312
+ "properties": {
313
+ "span": {
314
+ "const": "within"
315
+ }
316
+ },
317
+ "required": [
318
+ "span"
319
+ ]
320
+ },
321
+ "then": {
322
+ "not": {
323
+ "required": [
324
+ "days_min"
325
+ ]
118
326
  }
327
+ }
328
+ },
329
+ {
330
+ "if": {
331
+ "properties": {
332
+ "span": {
333
+ "const": "between"
334
+ }
335
+ },
336
+ "required": [
337
+ "span"
338
+ ]
339
+ },
340
+ "then": {
341
+ "required": [
342
+ "days_min"
343
+ ]
344
+ }
119
345
  }
120
- },
121
- "additionalProperties": false
346
+ ]
347
+ }
348
+ },
349
+ "additionalProperties": false
122
350
  }
@@ -0,0 +1,71 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "$id": "https://raw.githubusercontent.com/gruncellka/porto-data/refs/heads/main/porto_data/schemas/providers.schema.json",
4
+ "title": "Provider registry",
5
+ "description": "Domain registry for postal providers. Folder providers/<id>/ is implementation storage only; authoritative ids and coarse metadata live here. IANA timezone: policy/jurisdictions.json → jurisdictions[country].timezone. Currency and VAT: policy/markets.json → markets[country]. Product-level mark_type and tracking_mode remain the execution source of truth.",
6
+ "type": "object",
7
+ "required": [
8
+ "providers"
9
+ ],
10
+ "properties": {
11
+ "$schema": {
12
+ "type": "string",
13
+ "format": "uri"
14
+ },
15
+ "providers": {
16
+ "type": "object",
17
+ "minProperties": 1,
18
+ "additionalProperties": {
19
+ "type": "object",
20
+ "required": [
21
+ "label",
22
+ "name",
23
+ "country",
24
+ "mark_types"
25
+ ],
26
+ "properties": {
27
+ "label": {
28
+ "type": "string",
29
+ "minLength": 1,
30
+ "description": "Short display name (UI / prose)"
31
+ },
32
+ "name": {
33
+ "type": "string",
34
+ "minLength": 1,
35
+ "description": "Registered legal entity name"
36
+ },
37
+ "country": {
38
+ "type": "string",
39
+ "pattern": "^[A-Z]{2}$",
40
+ "description": "Primary country (ISO 3166-1 alpha-2). Timezone: policy/jurisdictions.json jurisdictions[this code].timezone. Currency and VAT: policy/markets.json markets[this code]."
41
+ },
42
+ "mark_types": {
43
+ "type": "array",
44
+ "minItems": 1,
45
+ "uniqueItems": true,
46
+ "items": {
47
+ "type": "string",
48
+ "enum": [
49
+ "stamp",
50
+ "label"
51
+ ]
52
+ },
53
+ "description": "Coarse overview; exact execution comes from each product"
54
+ },
55
+ "tracking_model": {
56
+ "type": "string",
57
+ "enum": [
58
+ "mixed",
59
+ "included",
60
+ "none",
61
+ "optional"
62
+ ],
63
+ "description": "Optional coarse provider-level tracking posture; products define tracking_mode precisely."
64
+ }
65
+ },
66
+ "additionalProperties": false
67
+ }
68
+ }
69
+ },
70
+ "additionalProperties": false
71
+ }