@shopimind/integration-kit-js 1.2.0 → 1.3.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/dist/contracts/sdk.d.ts
CHANGED
|
@@ -40,9 +40,11 @@ export interface NewCustomDataDefinition {
|
|
|
40
40
|
/**
|
|
41
41
|
* Schema-level relationships to other definitions (forwarded as-is to the API).
|
|
42
42
|
* `sourceField` is a field of THIS definition; it links to `targetSchema` — a
|
|
43
|
-
* `'system'` schema (e.g. `contacts`, `products`) or another `'custom'` definition
|
|
44
|
-
*
|
|
45
|
-
*
|
|
43
|
+
* `'system'` schema (e.g. `contacts`, `products`) or another `'custom'` definition.
|
|
44
|
+
* For a custom target, `targetSchema` is the target's numeric id — OR, inside a
|
|
45
|
+
* `provisioning.customData` plan, the NAME of a sibling definition (declared before
|
|
46
|
+
* this one), which the kit resolves to its id at creation. Optionally matched on
|
|
47
|
+
* `targetField` (defaults to the target's id). `custom`→`custom` is supported.
|
|
46
48
|
*/
|
|
47
49
|
relationships?: Array<{
|
|
48
50
|
sourceField: string;
|
|
@@ -72,12 +72,19 @@ export async function ensureCustomDataDefinition(client, def) {
|
|
|
72
72
|
if (found) {
|
|
73
73
|
const id = numId(found, 'id_definition', 'id');
|
|
74
74
|
const full = SpmHelpers.unwrapOrThrow(await SpmCustomDataDefinitions.get(client, id), 'getCustomDataDefinition');
|
|
75
|
+
// Convergent extend: send only what the existing definition LACKS — new fields
|
|
76
|
+
// (by `name`) AND new relationships (by `sourceField`). The API appends, so
|
|
77
|
+
// existing fields/relationships are preserved.
|
|
75
78
|
const fields = Array.isArray(full.fields) ? full.fields : [];
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
+
const haveFields = new Set(fields.map((f) => f.name).filter((n) => !!n));
|
|
80
|
+
const missingFields = def.fields.filter((f) => !haveFields.has(f.name));
|
|
81
|
+
const rels = Array.isArray(full.relationships) ? full.relationships : [];
|
|
82
|
+
const haveRels = new Set(rels.map((r) => r.sourceField).filter((s) => !!s));
|
|
83
|
+
const missingRels = (def.relationships ?? []).filter((r) => !haveRels.has(r.sourceField));
|
|
84
|
+
if (missingFields.length > 0 || missingRels.length > 0) {
|
|
79
85
|
SpmHelpers.unwrapOrThrow(await SpmCustomDataDefinitions.extend(client, id, {
|
|
80
|
-
fields:
|
|
86
|
+
...(missingFields.length > 0 ? { fields: missingFields.map(toSdkField) } : {}),
|
|
87
|
+
...(missingRels.length > 0 ? { relationships: missingRels } : {}),
|
|
81
88
|
}), 'extendCustomDataDefinition');
|
|
82
89
|
}
|
|
83
90
|
return id;
|
|
@@ -15,7 +15,7 @@ export async function runProvisioning(client, plan) {
|
|
|
15
15
|
}
|
|
16
16
|
for (const def of plan.customData ?? []) {
|
|
17
17
|
try {
|
|
18
|
-
result.defIds[def.name] = await ensureCustomDataDefinition(client, def);
|
|
18
|
+
result.defIds[def.name] = await ensureCustomDataDefinition(client, resolveCustomRelationTargets(def, result.defIds));
|
|
19
19
|
}
|
|
20
20
|
catch (e) {
|
|
21
21
|
result.errors.push(`def ${def.name}: ${errMsg(e)}`);
|
|
@@ -44,6 +44,24 @@ export async function runProvisioning(client, plan) {
|
|
|
44
44
|
}
|
|
45
45
|
return result;
|
|
46
46
|
}
|
|
47
|
+
/**
|
|
48
|
+
* Resolves a custom relationship's `targetSchema` declared by NAME (a sibling
|
|
49
|
+
* definition in the same plan) to the sibling's numeric id — mirroring how
|
|
50
|
+
* dataSources resolve `parentKey` -> `parent_id`. The target must have been created
|
|
51
|
+
* earlier in the run (declare it BEFORE the definition that references it); a
|
|
52
|
+
* `targetSchema` that is already an id, or that names an out-of-plan definition, is
|
|
53
|
+
* left untouched.
|
|
54
|
+
*/
|
|
55
|
+
function resolveCustomRelationTargets(def, defIds) {
|
|
56
|
+
if (!def.relationships?.length)
|
|
57
|
+
return def;
|
|
58
|
+
return {
|
|
59
|
+
...def,
|
|
60
|
+
relationships: def.relationships.map((r) => r.targetSchemaType === 'custom' && defIds[r.targetSchema] != null
|
|
61
|
+
? { ...r, targetSchema: String(defIds[r.targetSchema]) }
|
|
62
|
+
: r),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
47
65
|
function errMsg(e) {
|
|
48
66
|
return e instanceof Error ? e.message : String(e);
|
|
49
67
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shopimind/integration-kit-js",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "Foundation for building ShopiMind integrations: a runtime plus typed, once-tested primitives (HMAC webhook signatures, encryption, log redaction, a safe cursor-based sync engine, pagination/concurrency, persistence, ShopiMind SDK re-export, idempotent provisioning, secured inbound middleware, HTTP server). An integration only writes pure functions and declarations passed to defineIntegration.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"repository": {
|