@open-mercato/shared 0.6.1-develop.3291.1.6fad645fd0 → 0.6.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.
@@ -18,6 +18,21 @@ function extractCustomFieldEntries(item) {
18
18
  if (!trimmed) return;
19
19
  out[`cf_${trimmed}`] = normalizeValue(rawValue);
20
20
  };
21
+ const assignObject = (source) => {
22
+ if (!source || typeof source !== "object" || Array.isArray(source)) return;
23
+ for (const [key, value] of Object.entries(source)) {
24
+ assign(key, value);
25
+ }
26
+ };
27
+ const assignEntries = (source) => {
28
+ if (!Array.isArray(source)) return;
29
+ for (const entry of source) {
30
+ if (!entry || typeof entry !== "object") continue;
31
+ const key = typeof entry.key === "string" ? entry.key : null;
32
+ if (!key) continue;
33
+ assign(key, "value" in entry ? entry.value : void 0);
34
+ }
35
+ };
21
36
  for (const [rawKey, rawValue] of Object.entries(item)) {
22
37
  if (rawKey.startsWith("cf_")) {
23
38
  if (rawKey.endsWith("__is_multi")) continue;
@@ -26,24 +41,12 @@ function extractCustomFieldEntries(item) {
26
41
  assign(rawKey.slice(3), rawValue);
27
42
  }
28
43
  }
29
- const customValues = item.customValues;
30
- if (customValues && typeof customValues === "object" && !Array.isArray(customValues)) {
31
- for (const [key, value] of Object.entries(customValues)) {
32
- assign(key, value);
33
- }
34
- }
35
- const customFields = item.customFields;
36
- if (Array.isArray(customFields)) {
37
- for (const entry of customFields) {
38
- const key = entry && typeof entry.key === "string" ? entry.key : null;
39
- if (!key) continue;
40
- assign(key, "value" in entry ? entry.value : void 0);
41
- }
42
- } else if (customFields && typeof customFields === "object") {
43
- for (const [key, value] of Object.entries(customFields)) {
44
- assign(key, value);
45
- }
46
- }
44
+ assignObject(item.customValues);
45
+ assignObject(item.custom_values);
46
+ assignObject(item.customFields);
47
+ assignObject(item.custom_fields);
48
+ assignEntries(item.customFields);
49
+ assignEntries(item.custom_fields);
47
50
  return out;
48
51
  }
49
52
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/crud/custom-fields-client.ts"],
4
- "sourcesContent": ["export function extractCustomFieldEntries(item: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n if (!item || typeof item !== 'object') return out\n\n const normalizeValue = (value: unknown): unknown => {\n if (Array.isArray(value)) return value\n if (typeof value !== 'string') return value\n const trimmed = value.trim()\n if (trimmed.startsWith('{') && trimmed.endsWith('}')) {\n const inner = trimmed.slice(1, -1).trim()\n if (!inner) return []\n return inner.split(/[\\s,]+/).map((entry) => entry.trim()).filter(Boolean)\n }\n return trimmed\n }\n\n const assign = (rawKey: unknown, rawValue: unknown) => {\n if (typeof rawKey !== 'string') return\n const trimmed = rawKey.trim()\n if (!trimmed) return\n out[`cf_${trimmed}`] = normalizeValue(rawValue)\n }\n\n for (const [rawKey, rawValue] of Object.entries(item)) {\n if (rawKey.startsWith('cf_')) {\n if (rawKey.endsWith('__is_multi')) continue\n out[rawKey] = normalizeValue(rawValue)\n } else if (rawKey.startsWith('cf:')) {\n assign(rawKey.slice(3), rawValue)\n }\n }\n\n const customValues = (item as any).customValues\n if (customValues && typeof customValues === 'object' && !Array.isArray(customValues)) {\n for (const [key, value] of Object.entries(customValues as Record<string, unknown>)) {\n assign(key, value)\n }\n }\n\n const customFields = (item as any).customFields\n if (Array.isArray(customFields)) {\n for (const entry of customFields as Array<Record<string, unknown>>) {\n const key = entry && typeof entry.key === 'string' ? entry.key : null\n if (!key) continue\n assign(key, 'value' in entry ? (entry as any).value : undefined)\n }\n } else if (customFields && typeof customFields === 'object') {\n for (const [key, value] of Object.entries(customFields as Record<string, unknown>)) {\n assign(key, value)\n }\n }\n\n return out\n}\n"],
5
- "mappings": "AAAO,SAAS,0BAA0B,MAAwD;AAChG,QAAM,MAA+B,CAAC;AACtC,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAE9C,QAAM,iBAAiB,CAAC,UAA4B;AAClD,QAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,QAAI,OAAO,UAAU,SAAU,QAAO;AACtC,UAAM,UAAU,MAAM,KAAK;AAC3B,QAAI,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG,GAAG;AACpD,YAAM,QAAQ,QAAQ,MAAM,GAAG,EAAE,EAAE,KAAK;AACxC,UAAI,CAAC,MAAO,QAAO,CAAC;AACpB,aAAO,MAAM,MAAM,QAAQ,EAAE,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAAE,OAAO,OAAO;AAAA,IAC1E;AACA,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,CAAC,QAAiB,aAAsB;AACrD,QAAI,OAAO,WAAW,SAAU;AAChC,UAAM,UAAU,OAAO,KAAK;AAC5B,QAAI,CAAC,QAAS;AACd,QAAI,MAAM,OAAO,EAAE,IAAI,eAAe,QAAQ;AAAA,EAChD;AAEA,aAAW,CAAC,QAAQ,QAAQ,KAAK,OAAO,QAAQ,IAAI,GAAG;AACrD,QAAI,OAAO,WAAW,KAAK,GAAG;AAC5B,UAAI,OAAO,SAAS,YAAY,EAAG;AACnC,UAAI,MAAM,IAAI,eAAe,QAAQ;AAAA,IACvC,WAAW,OAAO,WAAW,KAAK,GAAG;AACnC,aAAO,OAAO,MAAM,CAAC,GAAG,QAAQ;AAAA,IAClC;AAAA,EACF;AAEA,QAAM,eAAgB,KAAa;AACnC,MAAI,gBAAgB,OAAO,iBAAiB,YAAY,CAAC,MAAM,QAAQ,YAAY,GAAG;AACpF,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,YAAuC,GAAG;AAClF,aAAO,KAAK,KAAK;AAAA,IACnB;AAAA,EACF;AAEA,QAAM,eAAgB,KAAa;AACnC,MAAI,MAAM,QAAQ,YAAY,GAAG;AAC/B,eAAW,SAAS,cAAgD;AAClE,YAAM,MAAM,SAAS,OAAO,MAAM,QAAQ,WAAW,MAAM,MAAM;AACjE,UAAI,CAAC,IAAK;AACV,aAAO,KAAK,WAAW,QAAS,MAAc,QAAQ,MAAS;AAAA,IACjE;AAAA,EACF,WAAW,gBAAgB,OAAO,iBAAiB,UAAU;AAC3D,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,YAAuC,GAAG;AAClF,aAAO,KAAK,KAAK;AAAA,IACnB;AAAA,EACF;AAEA,SAAO;AACT;",
4
+ "sourcesContent": ["export function extractCustomFieldEntries(item: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {}\n if (!item || typeof item !== 'object') return out\n\n const normalizeValue = (value: unknown): unknown => {\n if (Array.isArray(value)) return value\n if (typeof value !== 'string') return value\n const trimmed = value.trim()\n if (trimmed.startsWith('{') && trimmed.endsWith('}')) {\n const inner = trimmed.slice(1, -1).trim()\n if (!inner) return []\n return inner.split(/[\\s,]+/).map((entry) => entry.trim()).filter(Boolean)\n }\n return trimmed\n }\n\n const assign = (rawKey: unknown, rawValue: unknown) => {\n if (typeof rawKey !== 'string') return\n const trimmed = rawKey.trim()\n if (!trimmed) return\n out[`cf_${trimmed}`] = normalizeValue(rawValue)\n }\n\n const assignObject = (source: unknown) => {\n if (!source || typeof source !== 'object' || Array.isArray(source)) return\n for (const [key, value] of Object.entries(source as Record<string, unknown>)) {\n assign(key, value)\n }\n }\n\n const assignEntries = (source: unknown) => {\n if (!Array.isArray(source)) return\n for (const entry of source as Array<Record<string, unknown>>) {\n if (!entry || typeof entry !== 'object') continue\n const key = typeof entry.key === 'string' ? entry.key : null\n if (!key) continue\n assign(key, 'value' in entry ? (entry as any).value : undefined)\n }\n }\n\n for (const [rawKey, rawValue] of Object.entries(item)) {\n if (rawKey.startsWith('cf_')) {\n if (rawKey.endsWith('__is_multi')) continue\n out[rawKey] = normalizeValue(rawValue)\n } else if (rawKey.startsWith('cf:')) {\n assign(rawKey.slice(3), rawValue)\n }\n }\n\n assignObject((item as any).customValues)\n assignObject((item as any).custom_values)\n assignObject((item as any).customFields)\n assignObject((item as any).custom_fields)\n assignEntries((item as any).customFields)\n assignEntries((item as any).custom_fields)\n\n return out\n}\n"],
5
+ "mappings": "AAAO,SAAS,0BAA0B,MAAwD;AAChG,QAAM,MAA+B,CAAC;AACtC,MAAI,CAAC,QAAQ,OAAO,SAAS,SAAU,QAAO;AAE9C,QAAM,iBAAiB,CAAC,UAA4B;AAClD,QAAI,MAAM,QAAQ,KAAK,EAAG,QAAO;AACjC,QAAI,OAAO,UAAU,SAAU,QAAO;AACtC,UAAM,UAAU,MAAM,KAAK;AAC3B,QAAI,QAAQ,WAAW,GAAG,KAAK,QAAQ,SAAS,GAAG,GAAG;AACpD,YAAM,QAAQ,QAAQ,MAAM,GAAG,EAAE,EAAE,KAAK;AACxC,UAAI,CAAC,MAAO,QAAO,CAAC;AACpB,aAAO,MAAM,MAAM,QAAQ,EAAE,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC,EAAE,OAAO,OAAO;AAAA,IAC1E;AACA,WAAO;AAAA,EACT;AAEA,QAAM,SAAS,CAAC,QAAiB,aAAsB;AACrD,QAAI,OAAO,WAAW,SAAU;AAChC,UAAM,UAAU,OAAO,KAAK;AAC5B,QAAI,CAAC,QAAS;AACd,QAAI,MAAM,OAAO,EAAE,IAAI,eAAe,QAAQ;AAAA,EAChD;AAEA,QAAM,eAAe,CAAC,WAAoB;AACxC,QAAI,CAAC,UAAU,OAAO,WAAW,YAAY,MAAM,QAAQ,MAAM,EAAG;AACpE,eAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,MAAiC,GAAG;AAC5E,aAAO,KAAK,KAAK;AAAA,IACnB;AAAA,EACF;AAEA,QAAM,gBAAgB,CAAC,WAAoB;AACzC,QAAI,CAAC,MAAM,QAAQ,MAAM,EAAG;AAC5B,eAAW,SAAS,QAA0C;AAC5D,UAAI,CAAC,SAAS,OAAO,UAAU,SAAU;AACzC,YAAM,MAAM,OAAO,MAAM,QAAQ,WAAW,MAAM,MAAM;AACxD,UAAI,CAAC,IAAK;AACV,aAAO,KAAK,WAAW,QAAS,MAAc,QAAQ,MAAS;AAAA,IACjE;AAAA,EACF;AAEA,aAAW,CAAC,QAAQ,QAAQ,KAAK,OAAO,QAAQ,IAAI,GAAG;AACrD,QAAI,OAAO,WAAW,KAAK,GAAG;AAC5B,UAAI,OAAO,SAAS,YAAY,EAAG;AACnC,UAAI,MAAM,IAAI,eAAe,QAAQ;AAAA,IACvC,WAAW,OAAO,WAAW,KAAK,GAAG;AACnC,aAAO,OAAO,MAAM,CAAC,GAAG,QAAQ;AAAA,IAClC;AAAA,EACF;AAEA,eAAc,KAAa,YAAY;AACvC,eAAc,KAAa,aAAa;AACxC,eAAc,KAAa,YAAY;AACvC,eAAc,KAAa,aAAa;AACxC,gBAAe,KAAa,YAAY;AACxC,gBAAe,KAAa,aAAa;AAEzC,SAAO;AACT;",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/frontend/progressEvents.ts"],
4
- "sourcesContent": ["export const PROGRESS_DOM_EVENTS = {\n UPDATE: 'om:progress:update',\n COMPLETE: 'om:progress:complete',\n ERROR: 'om:progress:error',\n CANCELLED: 'om:progress:cancelled',\n} as const\n\nexport type ProgressUpdateDetail = {\n jobId: string\n jobType: string\n name: string\n progressPercent: number\n processedCount: number\n totalCount?: number | null\n etaSeconds?: number | null\n status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled'\n}\n\nexport function emitProgressUpdate(detail: ProgressUpdateDetail): void {\n if (typeof window === 'undefined' || typeof CustomEvent === 'undefined') return\n window.dispatchEvent(new CustomEvent(PROGRESS_DOM_EVENTS.UPDATE, { detail }))\n}\n\nexport function emitProgressComplete(jobId: string, jobType: string): void {\n if (typeof window === 'undefined' || typeof CustomEvent === 'undefined') return\n window.dispatchEvent(new CustomEvent(PROGRESS_DOM_EVENTS.COMPLETE, { detail: { jobId, jobType } }))\n}\n\nexport function emitProgressError(jobId: string, errorMessage: string): void {\n if (typeof window === 'undefined' || typeof CustomEvent === 'undefined') return\n window.dispatchEvent(new CustomEvent(PROGRESS_DOM_EVENTS.ERROR, { detail: { jobId, errorMessage } }))\n}\n\nexport function subscribeProgressUpdate(handler: (detail: ProgressUpdateDetail) => void): () => void {\n if (typeof window === 'undefined') return () => {}\n const listener = (event: Event) => handler((event as CustomEvent<ProgressUpdateDetail>).detail)\n window.addEventListener(PROGRESS_DOM_EVENTS.UPDATE, listener)\n return () => window.removeEventListener(PROGRESS_DOM_EVENTS.UPDATE, listener)\n}\n\nexport function subscribeProgressComplete(handler: (detail: { jobId: string; jobType: string }) => void): () => void {\n if (typeof window === 'undefined') return () => {}\n const listener = (event: Event) => handler((event as CustomEvent<{ jobId: string; jobType: string }>).detail)\n window.addEventListener(PROGRESS_DOM_EVENTS.COMPLETE, listener)\n return () => window.removeEventListener(PROGRESS_DOM_EVENTS.COMPLETE, listener)\n}\n"],
5
- "mappings": "AAAO,MAAM,sBAAsB;AAAA,EACjC,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,OAAO;AAAA,EACP,WAAW;AACb;AAaO,SAAS,mBAAmB,QAAoC;AACrE,MAAI,OAAO,WAAW,eAAe,OAAO,gBAAgB,YAAa;AACzE,SAAO,cAAc,IAAI,YAAY,oBAAoB,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC9E;AAEO,SAAS,qBAAqB,OAAe,SAAuB;AACzE,MAAI,OAAO,WAAW,eAAe,OAAO,gBAAgB,YAAa;AACzE,SAAO,cAAc,IAAI,YAAY,oBAAoB,UAAU,EAAE,QAAQ,EAAE,OAAO,QAAQ,EAAE,CAAC,CAAC;AACpG;AAEO,SAAS,kBAAkB,OAAe,cAA4B;AAC3E,MAAI,OAAO,WAAW,eAAe,OAAO,gBAAgB,YAAa;AACzE,SAAO,cAAc,IAAI,YAAY,oBAAoB,OAAO,EAAE,QAAQ,EAAE,OAAO,aAAa,EAAE,CAAC,CAAC;AACtG;AAEO,SAAS,wBAAwB,SAA6D;AACnG,MAAI,OAAO,WAAW,YAAa,QAAO,MAAM;AAAA,EAAC;AACjD,QAAM,WAAW,CAAC,UAAiB,QAAS,MAA4C,MAAM;AAC9F,SAAO,iBAAiB,oBAAoB,QAAQ,QAAQ;AAC5D,SAAO,MAAM,OAAO,oBAAoB,oBAAoB,QAAQ,QAAQ;AAC9E;AAEO,SAAS,0BAA0B,SAA2E;AACnH,MAAI,OAAO,WAAW,YAAa,QAAO,MAAM;AAAA,EAAC;AACjD,QAAM,WAAW,CAAC,UAAiB,QAAS,MAA0D,MAAM;AAC5G,SAAO,iBAAiB,oBAAoB,UAAU,QAAQ;AAC9D,SAAO,MAAM,OAAO,oBAAoB,oBAAoB,UAAU,QAAQ;AAChF;",
4
+ "sourcesContent": ["export const PROGRESS_DOM_EVENTS = {\n UPDATE: 'om:progress:update',\n COMPLETE: 'om:progress:complete',\n ERROR: 'om:progress:error',\n CANCELLED: 'om:progress:cancelled',\n} as const\n\nexport type ProgressUpdateDetail = {\n jobId: string\n jobType: string\n name: string\n description?: string | null\n meta?: Record<string, unknown> | null\n progressPercent: number\n processedCount: number\n totalCount?: number | null\n etaSeconds?: number | null\n status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled'\n cancellable?: boolean\n startedAt?: string | null\n finishedAt?: string | null\n errorMessage?: string | null\n}\n\nexport function emitProgressUpdate(detail: ProgressUpdateDetail): void {\n if (typeof window === 'undefined' || typeof CustomEvent === 'undefined') return\n window.dispatchEvent(new CustomEvent(PROGRESS_DOM_EVENTS.UPDATE, { detail }))\n}\n\nexport function emitProgressComplete(jobId: string, jobType: string): void {\n if (typeof window === 'undefined' || typeof CustomEvent === 'undefined') return\n window.dispatchEvent(new CustomEvent(PROGRESS_DOM_EVENTS.COMPLETE, { detail: { jobId, jobType } }))\n}\n\nexport function emitProgressError(jobId: string, errorMessage: string): void {\n if (typeof window === 'undefined' || typeof CustomEvent === 'undefined') return\n window.dispatchEvent(new CustomEvent(PROGRESS_DOM_EVENTS.ERROR, { detail: { jobId, errorMessage } }))\n}\n\nexport function subscribeProgressUpdate(handler: (detail: ProgressUpdateDetail) => void): () => void {\n if (typeof window === 'undefined') return () => {}\n const listener = (event: Event) => handler((event as CustomEvent<ProgressUpdateDetail>).detail)\n window.addEventListener(PROGRESS_DOM_EVENTS.UPDATE, listener)\n return () => window.removeEventListener(PROGRESS_DOM_EVENTS.UPDATE, listener)\n}\n\nexport function subscribeProgressComplete(handler: (detail: { jobId: string; jobType: string }) => void): () => void {\n if (typeof window === 'undefined') return () => {}\n const listener = (event: Event) => handler((event as CustomEvent<{ jobId: string; jobType: string }>).detail)\n window.addEventListener(PROGRESS_DOM_EVENTS.COMPLETE, listener)\n return () => window.removeEventListener(PROGRESS_DOM_EVENTS.COMPLETE, listener)\n}\n"],
5
+ "mappings": "AAAO,MAAM,sBAAsB;AAAA,EACjC,QAAQ;AAAA,EACR,UAAU;AAAA,EACV,OAAO;AAAA,EACP,WAAW;AACb;AAmBO,SAAS,mBAAmB,QAAoC;AACrE,MAAI,OAAO,WAAW,eAAe,OAAO,gBAAgB,YAAa;AACzE,SAAO,cAAc,IAAI,YAAY,oBAAoB,QAAQ,EAAE,OAAO,CAAC,CAAC;AAC9E;AAEO,SAAS,qBAAqB,OAAe,SAAuB;AACzE,MAAI,OAAO,WAAW,eAAe,OAAO,gBAAgB,YAAa;AACzE,SAAO,cAAc,IAAI,YAAY,oBAAoB,UAAU,EAAE,QAAQ,EAAE,OAAO,QAAQ,EAAE,CAAC,CAAC;AACpG;AAEO,SAAS,kBAAkB,OAAe,cAA4B;AAC3E,MAAI,OAAO,WAAW,eAAe,OAAO,gBAAgB,YAAa;AACzE,SAAO,cAAc,IAAI,YAAY,oBAAoB,OAAO,EAAE,QAAQ,EAAE,OAAO,aAAa,EAAE,CAAC,CAAC;AACtG;AAEO,SAAS,wBAAwB,SAA6D;AACnG,MAAI,OAAO,WAAW,YAAa,QAAO,MAAM;AAAA,EAAC;AACjD,QAAM,WAAW,CAAC,UAAiB,QAAS,MAA4C,MAAM;AAC9F,SAAO,iBAAiB,oBAAoB,QAAQ,QAAQ;AAC5D,SAAO,MAAM,OAAO,oBAAoB,oBAAoB,QAAQ,QAAQ;AAC9E;AAEO,SAAS,0BAA0B,SAA2E;AACnH,MAAI,OAAO,WAAW,YAAa,QAAO,MAAM;AAAA,EAAC;AACjD,QAAM,WAAW,CAAC,UAAiB,QAAS,MAA0D,MAAM;AAC5G,SAAO,iBAAiB,oBAAoB,UAAU,QAAQ;AAC9D,SAAO,MAAM,OAAO,oBAAoB,oBAAoB,UAAU,QAAQ;AAChF;",
6
6
  "names": []
7
7
  }
@@ -1,4 +1,4 @@
1
- const APP_VERSION = "0.6.1-develop.3291.1.6fad645fd0";
1
+ const APP_VERSION = "0.6.1";
2
2
  const appVersion = APP_VERSION;
3
3
  export {
4
4
  APP_VERSION,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/lib/version.ts"],
4
- "sourcesContent": ["// Build-time generated version\nexport const APP_VERSION = '0.6.1-develop.3291.1.6fad645fd0'\nexport const appVersion = APP_VERSION\n"],
4
+ "sourcesContent": ["// Build-time generated version\nexport const APP_VERSION = '0.6.1'\nexport const appVersion = APP_VERSION\n"],
5
5
  "mappings": "AACO,MAAM,cAAc;AACpB,MAAM,aAAa;",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/shared",
3
- "version": "0.6.1-develop.3291.1.6fad645fd0",
3
+ "version": "0.6.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -92,7 +92,7 @@
92
92
  "@mikro-orm/core": "^7.0.15",
93
93
  "@mikro-orm/decorators": "^7.0.15",
94
94
  "@mikro-orm/postgresql": "^7.0.15",
95
- "@open-mercato/cache": "0.6.1-develop.3291.1.6fad645fd0",
95
+ "@open-mercato/cache": "0.6.1",
96
96
  "dotenv": "^17.4.2",
97
97
  "rate-limiter-flexible": "^11.1.0",
98
98
  "reflect-metadata": "^0.2.2",
@@ -112,6 +112,5 @@
112
112
  "type": "git",
113
113
  "url": "https://github.com/open-mercato/open-mercato",
114
114
  "directory": "packages/shared"
115
- },
116
- "stableVersion": "0.6.0"
115
+ }
117
116
  }
@@ -145,6 +145,21 @@ describe('extractAllCustomFieldEntries', () => {
145
145
  cf_existing: 'foo',
146
146
  })
147
147
  })
148
+
149
+ it('reads snake-case custom field containers', () => {
150
+ const item = {
151
+ custom_values: { api_url: 'https://snake.example', priority: 7 },
152
+ custom_fields: [
153
+ { key: 'array_key', value: 'array-value' },
154
+ ],
155
+ }
156
+
157
+ expect(extractAllCustomFieldEntries(item)).toEqual({
158
+ cf_api_url: 'https://snake.example',
159
+ cf_priority: 7,
160
+ cf_array_key: 'array-value',
161
+ })
162
+ })
148
163
  })
149
164
 
150
165
  describe('loadCustomFieldValues (encryption)', () => {
@@ -21,34 +21,38 @@ export function extractCustomFieldEntries(item: Record<string, unknown>): Record
21
21
  out[`cf_${trimmed}`] = normalizeValue(rawValue)
22
22
  }
23
23
 
24
- for (const [rawKey, rawValue] of Object.entries(item)) {
25
- if (rawKey.startsWith('cf_')) {
26
- if (rawKey.endsWith('__is_multi')) continue
27
- out[rawKey] = normalizeValue(rawValue)
28
- } else if (rawKey.startsWith('cf:')) {
29
- assign(rawKey.slice(3), rawValue)
30
- }
31
- }
32
-
33
- const customValues = (item as any).customValues
34
- if (customValues && typeof customValues === 'object' && !Array.isArray(customValues)) {
35
- for (const [key, value] of Object.entries(customValues as Record<string, unknown>)) {
24
+ const assignObject = (source: unknown) => {
25
+ if (!source || typeof source !== 'object' || Array.isArray(source)) return
26
+ for (const [key, value] of Object.entries(source as Record<string, unknown>)) {
36
27
  assign(key, value)
37
28
  }
38
29
  }
39
30
 
40
- const customFields = (item as any).customFields
41
- if (Array.isArray(customFields)) {
42
- for (const entry of customFields as Array<Record<string, unknown>>) {
43
- const key = entry && typeof entry.key === 'string' ? entry.key : null
31
+ const assignEntries = (source: unknown) => {
32
+ if (!Array.isArray(source)) return
33
+ for (const entry of source as Array<Record<string, unknown>>) {
34
+ if (!entry || typeof entry !== 'object') continue
35
+ const key = typeof entry.key === 'string' ? entry.key : null
44
36
  if (!key) continue
45
37
  assign(key, 'value' in entry ? (entry as any).value : undefined)
46
38
  }
47
- } else if (customFields && typeof customFields === 'object') {
48
- for (const [key, value] of Object.entries(customFields as Record<string, unknown>)) {
49
- assign(key, value)
39
+ }
40
+
41
+ for (const [rawKey, rawValue] of Object.entries(item)) {
42
+ if (rawKey.startsWith('cf_')) {
43
+ if (rawKey.endsWith('__is_multi')) continue
44
+ out[rawKey] = normalizeValue(rawValue)
45
+ } else if (rawKey.startsWith('cf:')) {
46
+ assign(rawKey.slice(3), rawValue)
50
47
  }
51
48
  }
52
49
 
50
+ assignObject((item as any).customValues)
51
+ assignObject((item as any).custom_values)
52
+ assignObject((item as any).customFields)
53
+ assignObject((item as any).custom_fields)
54
+ assignEntries((item as any).customFields)
55
+ assignEntries((item as any).custom_fields)
56
+
53
57
  return out
54
58
  }
@@ -9,11 +9,17 @@ export type ProgressUpdateDetail = {
9
9
  jobId: string
10
10
  jobType: string
11
11
  name: string
12
+ description?: string | null
13
+ meta?: Record<string, unknown> | null
12
14
  progressPercent: number
13
15
  processedCount: number
14
16
  totalCount?: number | null
15
17
  etaSeconds?: number | null
16
18
  status: 'pending' | 'running' | 'completed' | 'failed' | 'cancelled'
19
+ cancellable?: boolean
20
+ startedAt?: string | null
21
+ finishedAt?: string | null
22
+ errorMessage?: string | null
17
23
  }
18
24
 
19
25
  export function emitProgressUpdate(detail: ProgressUpdateDetail): void {