@pacp/spec 1.0.2 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -13
- package/dist/index.cjs +0 -5
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +30 -36
- package/dist/index.d.ts +30 -36
- package/dist/index.js +0 -4
- package/dist/index.js.map +1 -1
- package/dist/pacp.schema.json +795 -217
- package/dist/profiles/fiscal-br.schema.json +1 -1
- package/dist/profiles/iluminacao.schema.json +1 -1
- package/dist/profiles/moveis.schema.json +2 -2
- package/dist/profiles/pisos-revestimentos.schema.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -19,13 +19,10 @@ npm install @pacp/spec ajv ajv-formats
|
|
|
19
19
|
### Schema e profiles (sem dependências extras)
|
|
20
20
|
|
|
21
21
|
```typescript
|
|
22
|
-
import { schema, profiles, profileIds
|
|
22
|
+
import { schema, profiles, profileIds } from '@pacp/spec';
|
|
23
23
|
|
|
24
|
-
// JSON Schema completo do PACP
|
|
25
|
-
console.log(schema.$id);
|
|
26
|
-
|
|
27
|
-
// Versão da spec
|
|
28
|
-
console.log(SPEC_VERSION); // "1.0.0"
|
|
24
|
+
// JSON Schema completo do PACP
|
|
25
|
+
console.log(schema.$id);
|
|
29
26
|
|
|
30
27
|
// Extension profiles disponíveis
|
|
31
28
|
console.log(profileIds); // ["moveis", "iluminacao", "pisos-revestimentos", "fiscal-br"]
|
|
@@ -40,7 +37,6 @@ console.log(profiles.moveis.title); // "PACP Profile: Moveis e Alta Decoracao"
|
|
|
40
37
|
import { validate } from '@pacp/spec';
|
|
41
38
|
|
|
42
39
|
const catalogDocument = {
|
|
43
|
-
spec: '1.0.0',
|
|
44
40
|
document_type: 'CATALOG',
|
|
45
41
|
catalog: { id: 'meu_catalogo' },
|
|
46
42
|
rulesets: [
|
|
@@ -80,9 +76,10 @@ import type {
|
|
|
80
76
|
Dependency,
|
|
81
77
|
Context,
|
|
82
78
|
Option,
|
|
83
|
-
|
|
79
|
+
Image,
|
|
84
80
|
Measure,
|
|
85
|
-
|
|
81
|
+
PhysicalDimensions,
|
|
82
|
+
LookupAxis,
|
|
86
83
|
ValidationResult,
|
|
87
84
|
} from '@pacp/spec';
|
|
88
85
|
|
|
@@ -96,7 +93,7 @@ const product: Product = {
|
|
|
96
93
|
weight: { value: 45, unit: 'kg' },
|
|
97
94
|
dimensions: { width: 160, height: 78, depth: 90, unit: 'cm' },
|
|
98
95
|
options: [
|
|
99
|
-
{ id: 'opt_madeira',
|
|
96
|
+
{ id: 'opt_madeira', attribute_id: 'material', value: 'CARVALHO' },
|
|
100
97
|
],
|
|
101
98
|
'x-finish': 'Natural envernizado',
|
|
102
99
|
'x-warranty_months': 24,
|
|
@@ -122,11 +119,10 @@ const fiscal = require('@pacp/spec/profiles/fiscal-br.json');
|
|
|
122
119
|
|
|
123
120
|
| Export | Descrição |
|
|
124
121
|
|--------|-----------|
|
|
125
|
-
| `schema` | JSON Schema completo do PACP
|
|
122
|
+
| `schema` | JSON Schema completo do PACP |
|
|
126
123
|
| `profiles` | Objeto com todos os profiles oficiais |
|
|
127
124
|
| `profileIds` | Array com IDs dos profiles: `moveis`, `iluminacao`, `pisos-revestimentos`, `fiscal-br` |
|
|
128
125
|
| `validate()` | Função de validação (requer `ajv` + `ajv-formats`) |
|
|
129
|
-
| `SPEC_VERSION` | Constante `"1.0.0"` |
|
|
130
126
|
| Tipos TS | `CatalogDocument`, `ProductDocument`, `Product`, `Rule`, `Table`, etc. |
|
|
131
127
|
|
|
132
128
|
## Extension Profiles
|
|
@@ -140,7 +136,7 @@ const fiscal = require('@pacp/spec/profiles/fiscal-br.json');
|
|
|
140
136
|
|
|
141
137
|
## Links
|
|
142
138
|
|
|
143
|
-
- [Spec
|
|
139
|
+
- [Spec](https://github.com/pacp-org/pacp/blob/main/spec/latest/pacp.md)
|
|
144
140
|
- [Guia de integração](https://github.com/pacp-org/pacp/blob/main/docs/integration-guide.md)
|
|
145
141
|
- [Site](https://pacp-org.github.io/pacp/)
|
|
146
142
|
- [GitHub](https://github.com/pacp-org/pacp)
|
package/dist/index.cjs
CHANGED
|
@@ -20,7 +20,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var src_exports = {};
|
|
22
22
|
__export(src_exports, {
|
|
23
|
-
SPEC_VERSION: () => SPEC_VERSION,
|
|
24
23
|
profileIds: () => profileIds,
|
|
25
24
|
profiles: () => profiles,
|
|
26
25
|
schema: () => schema,
|
|
@@ -119,12 +118,8 @@ function extractXFields(obj) {
|
|
|
119
118
|
}
|
|
120
119
|
return result;
|
|
121
120
|
}
|
|
122
|
-
|
|
123
|
-
// src/index.ts
|
|
124
|
-
var SPEC_VERSION = "1.0.0";
|
|
125
121
|
// Annotate the CommonJS export names for ESM import in node:
|
|
126
122
|
0 && (module.exports = {
|
|
127
|
-
SPEC_VERSION,
|
|
128
123
|
profileIds,
|
|
129
124
|
profiles,
|
|
130
125
|
schema,
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/schema.ts","../src/validate.ts"],"sourcesContent":["export { schema, profiles, profileIds } from \"./schema.js\";\r\nexport { validate } from \"./validate.js\";\r\nexport type {\r\n ScalarValue,\r\n ImageType,\r\n
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/schema.ts","../src/validate.ts"],"sourcesContent":["export { schema, profiles, profileIds } from \"./schema.js\";\r\nexport { validate } from \"./validate.js\";\r\nexport type {\r\n ScalarValue,\r\n ImageType,\r\n Image,\r\n Measure,\r\n PhysicalDimensions,\r\n AttributeRef,\r\n AttributeValue,\r\n Option,\r\n LotPolicy,\r\n SalesUnit,\r\n Product,\r\n Predicate,\r\n Condition,\r\n Component,\r\n RuleOperation,\r\n Rule,\r\n Ruleset,\r\n LookupAxis,\r\n TableRow,\r\n Table,\r\n Dependency,\r\n Constraint,\r\n PriceList,\r\n Catalog,\r\n ProductRef,\r\n Context,\r\n Pricing,\r\n CatalogDocument,\r\n ProductDocument,\r\n PacpDocument,\r\n ProfileId,\r\n ValidationIssue,\r\n ValidationResult,\r\n} from \"./types.js\";\r\n","import { readFileSync } from \"node:fs\";\r\nimport { join } from \"node:path\";\r\n\r\nfunction loadJson(relativePath: string): Record<string, unknown> {\r\n const fullPath = join(__dirname, relativePath);\r\n return JSON.parse(readFileSync(fullPath, \"utf8\"));\r\n}\r\n\r\nexport const schema = loadJson(\"./pacp.schema.json\") as Record<string, unknown>;\r\n\r\nexport const profiles = {\r\n moveis: loadJson(\"./profiles/moveis.schema.json\") as Record<string, unknown>,\r\n iluminacao: loadJson(\"./profiles/iluminacao.schema.json\") as Record<string, unknown>,\r\n \"pisos-revestimentos\": loadJson(\"./profiles/pisos-revestimentos.schema.json\") as Record<string, unknown>,\r\n \"fiscal-br\": loadJson(\"./profiles/fiscal-br.schema.json\") as Record<string, unknown>,\r\n} as const;\r\n\r\nexport type ProfileId = keyof typeof profiles;\r\n\r\nexport const profileIds = Object.keys(profiles) as ProfileId[];\r\n","import type { ValidationResult, ValidationIssue, PacpDocument } from \"./types.js\";\r\nimport { schema, profiles, type ProfileId } from \"./schema.js\";\r\n\r\nexport function validate(document: unknown): ValidationResult {\r\n let Ajv2020: typeof import(\"ajv/dist/2020\").default;\r\n let addFormats: typeof import(\"ajv-formats\").default;\r\n\r\n try {\r\n Ajv2020 = require(\"ajv/dist/2020\") as typeof import(\"ajv/dist/2020\").default;\r\n addFormats = require(\"ajv-formats\") as typeof import(\"ajv-formats\").default;\r\n } catch {\r\n throw new Error(\r\n 'Para usar validate(), instale ajv e ajv-formats: npm install ajv ajv-formats'\r\n );\r\n }\r\n\r\n const ajv = new Ajv2020({ allErrors: true, strict: false });\r\n addFormats(ajv);\r\n\r\n const issues: ValidationIssue[] = [];\r\n\r\n const validateSchema = ajv.compile(schema);\r\n const valid = validateSchema(document);\r\n\r\n if (!valid && validateSchema.errors) {\r\n for (const error of validateSchema.errors) {\r\n issues.push({\r\n code: \"SCHEMA\",\r\n path: error.instancePath || \"/\",\r\n message: error.message ?? \"Erro de validacao de schema\",\r\n });\r\n }\r\n }\r\n\r\n if (document && typeof document === \"object\" && !Array.isArray(document)) {\r\n const doc = document as Record<string, unknown>;\r\n const declaredProfiles = Array.isArray(doc.profiles) ? doc.profiles : [];\r\n\r\n for (const profileId of declaredProfiles) {\r\n if (typeof profileId !== \"string\") continue;\r\n\r\n const profileSchema = profiles[profileId as ProfileId];\r\n if (!profileSchema) {\r\n issues.push({\r\n code: \"UNKNOWN_PROFILE\",\r\n path: \"/profiles\",\r\n message: `Profile \"${profileId}\" nao e um profile oficial PACP`,\r\n });\r\n continue;\r\n }\r\n\r\n const products = extractProducts(doc);\r\n const validateProfile = ajv.compile(profileSchema);\r\n\r\n for (let i = 0; i < products.length; i++) {\r\n const xFields = extractXFields(products[i]);\r\n if (Object.keys(xFields).length === 0) continue;\r\n\r\n const profileValid = validateProfile(xFields);\r\n if (!profileValid && validateProfile.errors) {\r\n for (const error of validateProfile.errors) {\r\n issues.push({\r\n code: \"PROFILE_VALIDATION\",\r\n path: `products[${i}]${error.instancePath || \"/\"}`,\r\n message: `Profile \"${profileId}\": ${error.message ?? \"erro de validacao\"}`,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return { valid: issues.length === 0, issues };\r\n}\r\n\r\nfunction extractProducts(doc: Record<string, unknown>): Record<string, unknown>[] {\r\n if (doc.document_type === \"PRODUCT\" && doc.product && typeof doc.product === \"object\") {\r\n return [doc.product as Record<string, unknown>];\r\n }\r\n return [];\r\n}\r\n\r\nfunction extractXFields(obj: Record<string, unknown>): Record<string, unknown> {\r\n const result: Record<string, unknown> = {};\r\n for (const [key, value] of Object.entries(obj)) {\r\n if (key.startsWith(\"x-\")) {\r\n result[key] = value;\r\n }\r\n }\r\n return result;\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,qBAA6B;AAC7B,uBAAqB;AAErB,SAAS,SAAS,cAA+C;AAC/D,QAAM,eAAW,uBAAK,WAAW,YAAY;AAC7C,SAAO,KAAK,UAAM,6BAAa,UAAU,MAAM,CAAC;AAClD;AAEO,IAAM,SAAS,SAAS,oBAAoB;AAE5C,IAAM,WAAW;AAAA,EACtB,QAAQ,SAAS,+BAA+B;AAAA,EAChD,YAAY,SAAS,mCAAmC;AAAA,EACxD,uBAAuB,SAAS,4CAA4C;AAAA,EAC5E,aAAa,SAAS,kCAAkC;AAC1D;AAIO,IAAM,aAAa,OAAO,KAAK,QAAQ;;;AChBvC,SAAS,SAAS,UAAqC;AAC5D,MAAI;AACJ,MAAI;AAEJ,MAAI;AACF,cAAU,QAAQ,eAAe;AACjC,iBAAa,QAAQ,aAAa;AAAA,EACpC,QAAQ;AACN,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AAEA,QAAM,MAAM,IAAI,QAAQ,EAAE,WAAW,MAAM,QAAQ,MAAM,CAAC;AAC1D,aAAW,GAAG;AAEd,QAAM,SAA4B,CAAC;AAEnC,QAAM,iBAAiB,IAAI,QAAQ,MAAM;AACzC,QAAM,QAAQ,eAAe,QAAQ;AAErC,MAAI,CAAC,SAAS,eAAe,QAAQ;AACnC,eAAW,SAAS,eAAe,QAAQ;AACzC,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,MAAM,MAAM,gBAAgB;AAAA,QAC5B,SAAS,MAAM,WAAW;AAAA,MAC5B,CAAC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,YAAY,OAAO,aAAa,YAAY,CAAC,MAAM,QAAQ,QAAQ,GAAG;AACxE,UAAM,MAAM;AACZ,UAAM,mBAAmB,MAAM,QAAQ,IAAI,QAAQ,IAAI,IAAI,WAAW,CAAC;AAEvE,eAAW,aAAa,kBAAkB;AACxC,UAAI,OAAO,cAAc,SAAU;AAEnC,YAAM,gBAAgB,SAAS,SAAsB;AACrD,UAAI,CAAC,eAAe;AAClB,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,MAAM;AAAA,UACN,SAAS,YAAY,SAAS;AAAA,QAChC,CAAC;AACD;AAAA,MACF;AAEA,YAAM,WAAW,gBAAgB,GAAG;AACpC,YAAM,kBAAkB,IAAI,QAAQ,aAAa;AAEjD,eAAS,IAAI,GAAG,IAAI,SAAS,QAAQ,KAAK;AACxC,cAAM,UAAU,eAAe,SAAS,CAAC,CAAC;AAC1C,YAAI,OAAO,KAAK,OAAO,EAAE,WAAW,EAAG;AAEvC,cAAM,eAAe,gBAAgB,OAAO;AAC5C,YAAI,CAAC,gBAAgB,gBAAgB,QAAQ;AAC3C,qBAAW,SAAS,gBAAgB,QAAQ;AAC1C,mBAAO,KAAK;AAAA,cACV,MAAM;AAAA,cACN,MAAM,YAAY,CAAC,IAAI,MAAM,gBAAgB,GAAG;AAAA,cAChD,SAAS,YAAY,SAAS,MAAM,MAAM,WAAW,mBAAmB;AAAA,YAC1E,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,SAAO,EAAE,OAAO,OAAO,WAAW,GAAG,OAAO;AAC9C;AAEA,SAAS,gBAAgB,KAAyD;AAChF,MAAI,IAAI,kBAAkB,aAAa,IAAI,WAAW,OAAO,IAAI,YAAY,UAAU;AACrF,WAAO,CAAC,IAAI,OAAkC;AAAA,EAChD;AACA,SAAO,CAAC;AACV;AAEA,SAAS,eAAe,KAAuD;AAC7E,QAAM,SAAkC,CAAC;AACzC,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,GAAG,GAAG;AAC9C,QAAI,IAAI,WAAW,IAAI,GAAG;AACxB,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -2,16 +2,18 @@ export { profileIds, profiles, schema } from './schema.cjs';
|
|
|
2
2
|
|
|
3
3
|
type ScalarValue = string | number | boolean;
|
|
4
4
|
type ImageType = "MAIN" | "DETAIL" | "AMBIANCE" | "TECHNICAL" | "OTHER";
|
|
5
|
-
interface
|
|
5
|
+
interface Image {
|
|
6
6
|
url: string;
|
|
7
7
|
label?: string;
|
|
8
|
+
alt?: string;
|
|
9
|
+
position?: number;
|
|
8
10
|
type?: ImageType;
|
|
9
11
|
}
|
|
10
12
|
interface Measure {
|
|
11
13
|
value: number;
|
|
12
14
|
unit: string;
|
|
13
15
|
}
|
|
14
|
-
interface
|
|
16
|
+
interface PhysicalDimensions {
|
|
15
17
|
width?: number;
|
|
16
18
|
height?: number;
|
|
17
19
|
depth?: number;
|
|
@@ -22,27 +24,28 @@ interface AttributeRef {
|
|
|
22
24
|
label?: string;
|
|
23
25
|
}
|
|
24
26
|
interface AttributeValue {
|
|
25
|
-
|
|
27
|
+
attribute_id: string;
|
|
26
28
|
value: ScalarValue;
|
|
27
29
|
label?: string;
|
|
28
30
|
}
|
|
29
31
|
interface Option {
|
|
30
32
|
id: string;
|
|
31
|
-
|
|
33
|
+
attribute_id: string;
|
|
32
34
|
value: ScalarValue;
|
|
33
35
|
label?: string;
|
|
36
|
+
images?: Image[];
|
|
34
37
|
}
|
|
35
38
|
interface LotPolicy {
|
|
36
39
|
required: boolean;
|
|
37
40
|
source: "CONTEXT" | "ATTRIBUTE";
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
context_key?: string;
|
|
42
|
+
attribute_id?: string;
|
|
40
43
|
}
|
|
41
44
|
interface SalesUnit {
|
|
42
45
|
requested_unit: string;
|
|
43
46
|
sell_unit: string;
|
|
44
47
|
quantity_per_sell_unit: number;
|
|
45
|
-
rounding: "CEIL";
|
|
48
|
+
rounding: "CEIL" | "FLOOR" | "ROUND" | "HALF_UP";
|
|
46
49
|
min_sell_units?: number;
|
|
47
50
|
}
|
|
48
51
|
interface Product {
|
|
@@ -56,16 +59,16 @@ interface Product {
|
|
|
56
59
|
gtin?: string;
|
|
57
60
|
base_price?: number;
|
|
58
61
|
unit?: string;
|
|
59
|
-
images?:
|
|
62
|
+
images?: Image[];
|
|
60
63
|
tags?: string[];
|
|
61
64
|
weight?: Measure;
|
|
62
|
-
dimensions?:
|
|
65
|
+
dimensions?: PhysicalDimensions;
|
|
63
66
|
lot_policy?: LotPolicy;
|
|
64
67
|
sales_unit?: SalesUnit;
|
|
65
68
|
attributes?: AttributeRef[];
|
|
66
69
|
attribute_values?: AttributeValue[];
|
|
67
70
|
options: Option[];
|
|
68
|
-
|
|
71
|
+
ruleset_ids?: string[];
|
|
69
72
|
[key: `x-${string}`]: unknown;
|
|
70
73
|
}
|
|
71
74
|
interface Predicate {
|
|
@@ -81,8 +84,8 @@ interface Condition {
|
|
|
81
84
|
interface Component {
|
|
82
85
|
label?: string;
|
|
83
86
|
value?: number;
|
|
84
|
-
|
|
85
|
-
|
|
87
|
+
table_id?: string;
|
|
88
|
+
option_id?: string;
|
|
86
89
|
}
|
|
87
90
|
type RuleOperation = "ADD" | "PERCENT_OF" | "OVERRIDE" | "LOOKUP" | "MAX_OF" | "MIN_OF" | "PICK" | "ROUND" | "CAP" | "FLOOR";
|
|
88
91
|
interface Rule {
|
|
@@ -93,14 +96,14 @@ interface Rule {
|
|
|
93
96
|
when?: Condition;
|
|
94
97
|
value?: number;
|
|
95
98
|
percent?: number;
|
|
96
|
-
|
|
99
|
+
table_id?: string;
|
|
97
100
|
components?: Component[];
|
|
98
101
|
precision?: number;
|
|
99
102
|
max?: number;
|
|
100
103
|
min?: number;
|
|
101
104
|
fallback?: number;
|
|
102
|
-
|
|
103
|
-
|
|
105
|
+
option_id?: string;
|
|
106
|
+
option_ids?: string[];
|
|
104
107
|
[key: `x-${string}`]: unknown;
|
|
105
108
|
}
|
|
106
109
|
interface Ruleset {
|
|
@@ -109,11 +112,11 @@ interface Ruleset {
|
|
|
109
112
|
rules: Rule[];
|
|
110
113
|
[key: `x-${string}`]: unknown;
|
|
111
114
|
}
|
|
112
|
-
interface
|
|
115
|
+
interface LookupAxis {
|
|
113
116
|
key: string;
|
|
114
117
|
source: "ATTRIBUTE" | "CONTEXT" | "LITERAL";
|
|
115
|
-
|
|
116
|
-
|
|
118
|
+
attribute_id?: string;
|
|
119
|
+
context_key?: string;
|
|
117
120
|
literal?: ScalarValue;
|
|
118
121
|
}
|
|
119
122
|
interface TableRow {
|
|
@@ -123,21 +126,16 @@ interface TableRow {
|
|
|
123
126
|
interface Table {
|
|
124
127
|
id: string;
|
|
125
128
|
type: "LOOKUP";
|
|
126
|
-
dimensions:
|
|
129
|
+
dimensions: LookupAxis[];
|
|
127
130
|
rows: TableRow[];
|
|
128
|
-
keys?: (string | {
|
|
129
|
-
optionId?: string;
|
|
130
|
-
id?: string;
|
|
131
|
-
name?: string;
|
|
132
|
-
})[];
|
|
133
131
|
}
|
|
134
132
|
interface Dependency {
|
|
135
133
|
id: string;
|
|
136
134
|
type: "REQUIRES" | "IMPLIES" | "AVAILABLE_OPTIONS_WHEN";
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
135
|
+
product_id?: string;
|
|
136
|
+
option_id?: string;
|
|
137
|
+
requires_option_ids?: string[];
|
|
138
|
+
allowed_option_ids?: string[];
|
|
141
139
|
when?: Condition;
|
|
142
140
|
}
|
|
143
141
|
interface Constraint {
|
|
@@ -145,8 +143,8 @@ interface Constraint {
|
|
|
145
143
|
type: "DENY";
|
|
146
144
|
when: Condition;
|
|
147
145
|
message: string;
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
product_id?: string;
|
|
147
|
+
option_ids?: string[];
|
|
150
148
|
}
|
|
151
149
|
interface PriceList {
|
|
152
150
|
id: string;
|
|
@@ -173,13 +171,12 @@ interface Context {
|
|
|
173
171
|
lot_id?: string;
|
|
174
172
|
requested_quantity?: number;
|
|
175
173
|
requested_unit?: string;
|
|
176
|
-
[key:
|
|
174
|
+
[key: string]: ScalarValue | undefined;
|
|
177
175
|
}
|
|
178
176
|
interface Pricing {
|
|
179
177
|
calculation_mode?: "CASCADE" | "TABLE_LOOKUP" | "OVERRIDE_BY_VARIANT" | "COST_PLUS";
|
|
180
178
|
}
|
|
181
179
|
interface CatalogDocument {
|
|
182
|
-
spec: "1.0.0";
|
|
183
180
|
document_type: "CATALOG";
|
|
184
181
|
catalog: Catalog;
|
|
185
182
|
rulesets: Ruleset[];
|
|
@@ -194,7 +191,6 @@ interface CatalogDocument {
|
|
|
194
191
|
[key: `x-${string}`]: unknown;
|
|
195
192
|
}
|
|
196
193
|
interface ProductDocument {
|
|
197
|
-
spec: "1.0.0";
|
|
198
194
|
document_type: "PRODUCT";
|
|
199
195
|
catalog_id: string;
|
|
200
196
|
product: Product;
|
|
@@ -219,6 +215,4 @@ interface ValidationResult {
|
|
|
219
215
|
|
|
220
216
|
declare function validate(document: unknown): ValidationResult;
|
|
221
217
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
export { type AttributeRef, type AttributeValue, type Catalog, type CatalogDocument, type Component, type Condition, type Constraint, type Context, type Dependency, type Dimension, type DimensionsObj, type ImageRef, type ImageType, type LotPolicy, type Measure, type Option, type PacpDocument, type Predicate, type PriceList, type Pricing, type Product, type ProductDocument, type ProductRef, type ProfileId, type Rule, type RuleOperation, type Ruleset, SPEC_VERSION, type SalesUnit, type ScalarValue, type Table, type TableRow, type ValidationIssue, type ValidationResult, validate };
|
|
218
|
+
export { type AttributeRef, type AttributeValue, type Catalog, type CatalogDocument, type Component, type Condition, type Constraint, type Context, type Dependency, type Image, type ImageType, type LookupAxis, type LotPolicy, type Measure, type Option, type PacpDocument, type PhysicalDimensions, type Predicate, type PriceList, type Pricing, type Product, type ProductDocument, type ProductRef, type ProfileId, type Rule, type RuleOperation, type Ruleset, type SalesUnit, type ScalarValue, type Table, type TableRow, type ValidationIssue, type ValidationResult, validate };
|
package/dist/index.d.ts
CHANGED
|
@@ -2,16 +2,18 @@ export { profileIds, profiles, schema } from './schema.js';
|
|
|
2
2
|
|
|
3
3
|
type ScalarValue = string | number | boolean;
|
|
4
4
|
type ImageType = "MAIN" | "DETAIL" | "AMBIANCE" | "TECHNICAL" | "OTHER";
|
|
5
|
-
interface
|
|
5
|
+
interface Image {
|
|
6
6
|
url: string;
|
|
7
7
|
label?: string;
|
|
8
|
+
alt?: string;
|
|
9
|
+
position?: number;
|
|
8
10
|
type?: ImageType;
|
|
9
11
|
}
|
|
10
12
|
interface Measure {
|
|
11
13
|
value: number;
|
|
12
14
|
unit: string;
|
|
13
15
|
}
|
|
14
|
-
interface
|
|
16
|
+
interface PhysicalDimensions {
|
|
15
17
|
width?: number;
|
|
16
18
|
height?: number;
|
|
17
19
|
depth?: number;
|
|
@@ -22,27 +24,28 @@ interface AttributeRef {
|
|
|
22
24
|
label?: string;
|
|
23
25
|
}
|
|
24
26
|
interface AttributeValue {
|
|
25
|
-
|
|
27
|
+
attribute_id: string;
|
|
26
28
|
value: ScalarValue;
|
|
27
29
|
label?: string;
|
|
28
30
|
}
|
|
29
31
|
interface Option {
|
|
30
32
|
id: string;
|
|
31
|
-
|
|
33
|
+
attribute_id: string;
|
|
32
34
|
value: ScalarValue;
|
|
33
35
|
label?: string;
|
|
36
|
+
images?: Image[];
|
|
34
37
|
}
|
|
35
38
|
interface LotPolicy {
|
|
36
39
|
required: boolean;
|
|
37
40
|
source: "CONTEXT" | "ATTRIBUTE";
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
context_key?: string;
|
|
42
|
+
attribute_id?: string;
|
|
40
43
|
}
|
|
41
44
|
interface SalesUnit {
|
|
42
45
|
requested_unit: string;
|
|
43
46
|
sell_unit: string;
|
|
44
47
|
quantity_per_sell_unit: number;
|
|
45
|
-
rounding: "CEIL";
|
|
48
|
+
rounding: "CEIL" | "FLOOR" | "ROUND" | "HALF_UP";
|
|
46
49
|
min_sell_units?: number;
|
|
47
50
|
}
|
|
48
51
|
interface Product {
|
|
@@ -56,16 +59,16 @@ interface Product {
|
|
|
56
59
|
gtin?: string;
|
|
57
60
|
base_price?: number;
|
|
58
61
|
unit?: string;
|
|
59
|
-
images?:
|
|
62
|
+
images?: Image[];
|
|
60
63
|
tags?: string[];
|
|
61
64
|
weight?: Measure;
|
|
62
|
-
dimensions?:
|
|
65
|
+
dimensions?: PhysicalDimensions;
|
|
63
66
|
lot_policy?: LotPolicy;
|
|
64
67
|
sales_unit?: SalesUnit;
|
|
65
68
|
attributes?: AttributeRef[];
|
|
66
69
|
attribute_values?: AttributeValue[];
|
|
67
70
|
options: Option[];
|
|
68
|
-
|
|
71
|
+
ruleset_ids?: string[];
|
|
69
72
|
[key: `x-${string}`]: unknown;
|
|
70
73
|
}
|
|
71
74
|
interface Predicate {
|
|
@@ -81,8 +84,8 @@ interface Condition {
|
|
|
81
84
|
interface Component {
|
|
82
85
|
label?: string;
|
|
83
86
|
value?: number;
|
|
84
|
-
|
|
85
|
-
|
|
87
|
+
table_id?: string;
|
|
88
|
+
option_id?: string;
|
|
86
89
|
}
|
|
87
90
|
type RuleOperation = "ADD" | "PERCENT_OF" | "OVERRIDE" | "LOOKUP" | "MAX_OF" | "MIN_OF" | "PICK" | "ROUND" | "CAP" | "FLOOR";
|
|
88
91
|
interface Rule {
|
|
@@ -93,14 +96,14 @@ interface Rule {
|
|
|
93
96
|
when?: Condition;
|
|
94
97
|
value?: number;
|
|
95
98
|
percent?: number;
|
|
96
|
-
|
|
99
|
+
table_id?: string;
|
|
97
100
|
components?: Component[];
|
|
98
101
|
precision?: number;
|
|
99
102
|
max?: number;
|
|
100
103
|
min?: number;
|
|
101
104
|
fallback?: number;
|
|
102
|
-
|
|
103
|
-
|
|
105
|
+
option_id?: string;
|
|
106
|
+
option_ids?: string[];
|
|
104
107
|
[key: `x-${string}`]: unknown;
|
|
105
108
|
}
|
|
106
109
|
interface Ruleset {
|
|
@@ -109,11 +112,11 @@ interface Ruleset {
|
|
|
109
112
|
rules: Rule[];
|
|
110
113
|
[key: `x-${string}`]: unknown;
|
|
111
114
|
}
|
|
112
|
-
interface
|
|
115
|
+
interface LookupAxis {
|
|
113
116
|
key: string;
|
|
114
117
|
source: "ATTRIBUTE" | "CONTEXT" | "LITERAL";
|
|
115
|
-
|
|
116
|
-
|
|
118
|
+
attribute_id?: string;
|
|
119
|
+
context_key?: string;
|
|
117
120
|
literal?: ScalarValue;
|
|
118
121
|
}
|
|
119
122
|
interface TableRow {
|
|
@@ -123,21 +126,16 @@ interface TableRow {
|
|
|
123
126
|
interface Table {
|
|
124
127
|
id: string;
|
|
125
128
|
type: "LOOKUP";
|
|
126
|
-
dimensions:
|
|
129
|
+
dimensions: LookupAxis[];
|
|
127
130
|
rows: TableRow[];
|
|
128
|
-
keys?: (string | {
|
|
129
|
-
optionId?: string;
|
|
130
|
-
id?: string;
|
|
131
|
-
name?: string;
|
|
132
|
-
})[];
|
|
133
131
|
}
|
|
134
132
|
interface Dependency {
|
|
135
133
|
id: string;
|
|
136
134
|
type: "REQUIRES" | "IMPLIES" | "AVAILABLE_OPTIONS_WHEN";
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
135
|
+
product_id?: string;
|
|
136
|
+
option_id?: string;
|
|
137
|
+
requires_option_ids?: string[];
|
|
138
|
+
allowed_option_ids?: string[];
|
|
141
139
|
when?: Condition;
|
|
142
140
|
}
|
|
143
141
|
interface Constraint {
|
|
@@ -145,8 +143,8 @@ interface Constraint {
|
|
|
145
143
|
type: "DENY";
|
|
146
144
|
when: Condition;
|
|
147
145
|
message: string;
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
product_id?: string;
|
|
147
|
+
option_ids?: string[];
|
|
150
148
|
}
|
|
151
149
|
interface PriceList {
|
|
152
150
|
id: string;
|
|
@@ -173,13 +171,12 @@ interface Context {
|
|
|
173
171
|
lot_id?: string;
|
|
174
172
|
requested_quantity?: number;
|
|
175
173
|
requested_unit?: string;
|
|
176
|
-
[key:
|
|
174
|
+
[key: string]: ScalarValue | undefined;
|
|
177
175
|
}
|
|
178
176
|
interface Pricing {
|
|
179
177
|
calculation_mode?: "CASCADE" | "TABLE_LOOKUP" | "OVERRIDE_BY_VARIANT" | "COST_PLUS";
|
|
180
178
|
}
|
|
181
179
|
interface CatalogDocument {
|
|
182
|
-
spec: "1.0.0";
|
|
183
180
|
document_type: "CATALOG";
|
|
184
181
|
catalog: Catalog;
|
|
185
182
|
rulesets: Ruleset[];
|
|
@@ -194,7 +191,6 @@ interface CatalogDocument {
|
|
|
194
191
|
[key: `x-${string}`]: unknown;
|
|
195
192
|
}
|
|
196
193
|
interface ProductDocument {
|
|
197
|
-
spec: "1.0.0";
|
|
198
194
|
document_type: "PRODUCT";
|
|
199
195
|
catalog_id: string;
|
|
200
196
|
product: Product;
|
|
@@ -219,6 +215,4 @@ interface ValidationResult {
|
|
|
219
215
|
|
|
220
216
|
declare function validate(document: unknown): ValidationResult;
|
|
221
217
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
export { type AttributeRef, type AttributeValue, type Catalog, type CatalogDocument, type Component, type Condition, type Constraint, type Context, type Dependency, type Dimension, type DimensionsObj, type ImageRef, type ImageType, type LotPolicy, type Measure, type Option, type PacpDocument, type Predicate, type PriceList, type Pricing, type Product, type ProductDocument, type ProductRef, type ProfileId, type Rule, type RuleOperation, type Ruleset, SPEC_VERSION, type SalesUnit, type ScalarValue, type Table, type TableRow, type ValidationIssue, type ValidationResult, validate };
|
|
218
|
+
export { type AttributeRef, type AttributeValue, type Catalog, type CatalogDocument, type Component, type Condition, type Constraint, type Context, type Dependency, type Image, type ImageType, type LookupAxis, type LotPolicy, type Measure, type Option, type PacpDocument, type PhysicalDimensions, type Predicate, type PriceList, type Pricing, type Product, type ProductDocument, type ProductRef, type ProfileId, type Rule, type RuleOperation, type Ruleset, type SalesUnit, type ScalarValue, type Table, type TableRow, type ValidationIssue, type ValidationResult, validate };
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/schema.ts","../src/validate.ts"
|
|
1
|
+
{"version":3,"sources":["../node_modules/tsup/assets/esm_shims.js","../src/schema.ts","../src/validate.ts"],"sourcesContent":["// Shim globals in esm bundle\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\n\nconst getFilename = () => fileURLToPath(import.meta.url)\nconst getDirname = () => path.dirname(getFilename())\n\nexport const __dirname = /* @__PURE__ */ getDirname()\nexport const __filename = /* @__PURE__ */ getFilename()\n","import { readFileSync } from \"node:fs\";\r\nimport { join } from \"node:path\";\r\n\r\nfunction loadJson(relativePath: string): Record<string, unknown> {\r\n const fullPath = join(__dirname, relativePath);\r\n return JSON.parse(readFileSync(fullPath, \"utf8\"));\r\n}\r\n\r\nexport const schema = loadJson(\"./pacp.schema.json\") as Record<string, unknown>;\r\n\r\nexport const profiles = {\r\n moveis: loadJson(\"./profiles/moveis.schema.json\") as Record<string, unknown>,\r\n iluminacao: loadJson(\"./profiles/iluminacao.schema.json\") as Record<string, unknown>,\r\n \"pisos-revestimentos\": loadJson(\"./profiles/pisos-revestimentos.schema.json\") as Record<string, unknown>,\r\n \"fiscal-br\": loadJson(\"./profiles/fiscal-br.schema.json\") as Record<string, unknown>,\r\n} as const;\r\n\r\nexport type ProfileId = keyof typeof profiles;\r\n\r\nexport const profileIds = Object.keys(profiles) as ProfileId[];\r\n","import type { ValidationResult, ValidationIssue, PacpDocument } from \"./types.js\";\r\nimport { schema, profiles, type ProfileId } from \"./schema.js\";\r\n\r\nexport function validate(document: unknown): ValidationResult {\r\n let Ajv2020: typeof import(\"ajv/dist/2020\").default;\r\n let addFormats: typeof import(\"ajv-formats\").default;\r\n\r\n try {\r\n Ajv2020 = require(\"ajv/dist/2020\") as typeof import(\"ajv/dist/2020\").default;\r\n addFormats = require(\"ajv-formats\") as typeof import(\"ajv-formats\").default;\r\n } catch {\r\n throw new Error(\r\n 'Para usar validate(), instale ajv e ajv-formats: npm install ajv ajv-formats'\r\n );\r\n }\r\n\r\n const ajv = new Ajv2020({ allErrors: true, strict: false });\r\n addFormats(ajv);\r\n\r\n const issues: ValidationIssue[] = [];\r\n\r\n const validateSchema = ajv.compile(schema);\r\n const valid = validateSchema(document);\r\n\r\n if (!valid && validateSchema.errors) {\r\n for (const error of validateSchema.errors) {\r\n issues.push({\r\n code: \"SCHEMA\",\r\n path: error.instancePath || \"/\",\r\n message: error.message ?? \"Erro de validacao de schema\",\r\n });\r\n }\r\n }\r\n\r\n if (document && typeof document === \"object\" && !Array.isArray(document)) {\r\n const doc = document as Record<string, unknown>;\r\n const declaredProfiles = Array.isArray(doc.profiles) ? doc.profiles : [];\r\n\r\n for (const profileId of declaredProfiles) {\r\n if (typeof profileId !== \"string\") continue;\r\n\r\n const profileSchema = profiles[profileId as ProfileId];\r\n if (!profileSchema) {\r\n issues.push({\r\n code: \"UNKNOWN_PROFILE\",\r\n path: \"/profiles\",\r\n message: `Profile \"${profileId}\" nao e um profile oficial PACP`,\r\n });\r\n continue;\r\n }\r\n\r\n const products = extractProducts(doc);\r\n const validateProfile = ajv.compile(profileSchema);\r\n\r\n for (let i = 0; i < products.length; i++) {\r\n const xFields = extractXFields(products[i]);\r\n if (Object.keys(xFields).length === 0) continue;\r\n\r\n const profileValid = validateProfile(xFields);\r\n if (!profileValid && validateProfile.errors) {\r\n for (const error of validateProfile.errors) {\r\n issues.push({\r\n code: \"PROFILE_VALIDATION\",\r\n path: `products[${i}]${error.instancePath || \"/\"}`,\r\n message: `Profile \"${profileId}\": ${error.message ?? \"erro de validacao\"}`,\r\n });\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return { valid: issues.length === 0, issues };\r\n}\r\n\r\nfunction extractProducts(doc: Record<string, unknown>): Record<string, unknown>[] {\r\n if (doc.document_type === \"PRODUCT\" && doc.product && typeof doc.product === \"object\") {\r\n return [doc.product as Record<string, unknown>];\r\n }\r\n return [];\r\n}\r\n\r\nfunction extractXFields(obj: Record<string, unknown>): Record<string, unknown> {\r\n const result: Record<string, unknown> = {};\r\n for (const [key, value] of Object.entries(obj)) {\r\n if (key.startsWith(\"x-\")) {\r\n result[key] = value;\r\n }\r\n }\r\n return result;\r\n}\r\n"],"mappings":"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","names":[]}
|