@thegraphitelab/n8n-nodes-servicetitan 0.8.1 → 0.9.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 CHANGED
@@ -79,12 +79,13 @@ Adding a new resource or trigger event is a localized change — see [`CONTRIBUT
79
79
 
80
80
  ServiceTitan returns custom fields as an array of `{typeId, name, value}` objects. That shape is awkward to consume in downstream n8n nodes — every workflow has to write a JS-code step to find a field by name.
81
81
 
82
- This package returns **both** shapes on every entity that has custom fields:
82
+ This package returns **three shapes** on every entity that has custom fields, so consumers pick what fits:
83
83
 
84
- - `customFields` — the raw array, untouched, so anything that depends on the ServiceTitan shape still works
85
- - `customFieldsByName` — sibling object, keys are field names, values are `{typeId, value}`
84
+ - `customFields` — raw array of `{typeId, name, value}`, untouched. Use this if your workflow already depends on the ST shape, or you need both name + typeId together.
85
+ - `custom_fields_by_name` — flat map: keys are field names, values are the raw values. Use `{{ $json.custom_fields_by_name["Lockbox Code"] }}` to read directly.
86
+ - `custom_fields_by_type_id` — flat map: keys are stringified typeIds, values are the raw values. Use this when you want to address a field by ID (more stable than name across tenant renames).
86
87
 
87
- Downstream workflows can use `{{ $json.customFieldsByName["Field Name"].value }}` directly without a code step. A workflow that already does the manual flattening keeps working because `customFields` is unchanged.
88
+ All three coexist on every entity. None is destructive of the others.
88
89
 
89
90
  ## Roadmap
90
91
 
@@ -19,12 +19,14 @@ export declare function serviceTitanApiRequest(this: IExecuteFunctions | IPollFu
19
19
  */
20
20
  export declare function serviceTitanApiRequestAllItems(this: IExecuteFunctions | IPollFunctions | ILoadOptionsFunctions, method: IHttpRequestMethods, path: string, qs?: IDataObject, body?: IDataObject | undefined): Promise<IDataObject[]>;
21
21
  /**
22
- * Returns the same item with a sibling `customFieldsByName` object added,
23
- * keyed by the customField's `name`, mapping to `{ typeId, value }`.
22
+ * Returns the same item with two sibling flat-map objects added:
23
+ * - `custom_fields_by_name` — keyed by the customField's `name`, value = value
24
+ * - `custom_fields_by_type_id` — keyed by the customField's `typeId` (stringified),
25
+ * value = value
24
26
  *
25
27
  * Idempotent and non-destructive:
26
- * - Original `customFields[]` array is left untouched
28
+ * - Original `customFields[]` array is left untouched, so all three shapes coexist
27
29
  * - Missing or non-array `customFields` returns the input unchanged
28
- * - Duplicate names: last write wins (ST doesn't normally emit duplicates)
30
+ * - Duplicate names or typeIds: last write wins (ST doesn't normally emit duplicates)
29
31
  */
30
32
  export declare function flattenCustomFields(item: IDataObject): IDataObject;
@@ -55,24 +55,35 @@ async function serviceTitanApiRequestAllItems(method, path, qs = {}, body = unde
55
55
  return collected;
56
56
  }
57
57
  /**
58
- * Returns the same item with a sibling `customFieldsByName` object added,
59
- * keyed by the customField's `name`, mapping to `{ typeId, value }`.
58
+ * Returns the same item with two sibling flat-map objects added:
59
+ * - `custom_fields_by_name` — keyed by the customField's `name`, value = value
60
+ * - `custom_fields_by_type_id` — keyed by the customField's `typeId` (stringified),
61
+ * value = value
60
62
  *
61
63
  * Idempotent and non-destructive:
62
- * - Original `customFields[]` array is left untouched
64
+ * - Original `customFields[]` array is left untouched, so all three shapes coexist
63
65
  * - Missing or non-array `customFields` returns the input unchanged
64
- * - Duplicate names: last write wins (ST doesn't normally emit duplicates)
66
+ * - Duplicate names or typeIds: last write wins (ST doesn't normally emit duplicates)
65
67
  */
66
68
  function flattenCustomFields(item) {
67
69
  const customFields = item.customFields;
68
70
  if (!Array.isArray(customFields))
69
71
  return item;
70
72
  const byName = {};
73
+ const byTypeId = {};
71
74
  for (const raw of customFields) {
72
- if (!raw || typeof raw.name !== 'string')
75
+ if (!raw)
73
76
  continue;
74
- byName[raw.name] = { typeId: raw.typeId, value: raw.value };
77
+ if (typeof raw.name === 'string')
78
+ byName[raw.name] = raw.value;
79
+ if (raw.typeId !== undefined && raw.typeId !== null) {
80
+ byTypeId[String(raw.typeId)] = raw.value;
81
+ }
75
82
  }
76
- return { ...item, customFieldsByName: byName };
83
+ return {
84
+ ...item,
85
+ custom_fields_by_name: byName,
86
+ custom_fields_by_type_id: byTypeId,
87
+ };
77
88
  }
78
89
  //# sourceMappingURL=GenericFunctions.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"GenericFunctions.js","sourceRoot":"","sources":["../../../nodes/ServiceTitan/GenericFunctions.ts"],"names":[],"mappings":";;AAiBA,wDA4BC;AAcD,wEAwBC;AAWD,kDAWC;AAhGD,+FAA2E;AAG3E;;;;GAIG;AACI,KAAK,UAAU,sBAAsB,CAE3C,MAA2B,EAC3B,IAAY,EACZ,KAAkB,EAAE,EACpB,OAAgC,SAAS;IAEzC,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;IACjE,MAAM,WAAW,GAAI,WAAW,CAAC,WAAsB,IAAI,aAAa,CAAC;IACzE,MAAM,OAAO,GAAG,IAAA,wCAAU,EAAC,WAAW,CAAC,CAAC;IAExC,MAAM,OAAO,GAAwB;QACpC,MAAM;QACN,GAAG,EAAE,WAAW,OAAO,GAAG,IAAI,EAAE;QAChC,EAAE;QACF,OAAO,EAAE;YACR,MAAM,EAAE,kBAAkB;YAC1B,cAAc,EAAE,kBAAkB;SAClC;QACD,IAAI,EAAE,IAAI;KACV,CAAC;IACF,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAE5C,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,6BAA6B,CAAC,IAAI,CAC5D,IAAI,EACJ,iBAAiB,EACjB,OAAO,CACP,CAAgB,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;GAWG;AACI,KAAK,UAAU,8BAA8B,CAEnD,MAA2B,EAC3B,IAAY,EACZ,KAAkB,EAAE,EACpB,OAAgC,SAAS;IAEzC,MAAM,SAAS,GAAkB,EAAE,CAAC;IACpC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,MAAM,QAAQ,GAAG,EAAE,CAAC;IAEpB,OAAO,IAAI,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,CAAC,MAAM,sBAAsB,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,CAAC,CAClE,CAAC;QAE7B,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,SAAS,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,OAAO;YAAE,MAAM;QAC7B,IAAI,IAAI,CAAC,CAAC;IACX,CAAC;IAED,OAAO,SAAS,CAAC;AAClB,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,mBAAmB,CAAC,IAAiB;IACpD,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;IACvC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IAE9C,MAAM,MAAM,GAAuD,EAAE,CAAC;IACtE,KAAK,MAAM,GAAG,IAAI,YAA+B,EAAE,CAAC;QACnD,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;YAAE,SAAS;QACnD,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC;IAC7D,CAAC;IAED,OAAO,EAAE,GAAG,IAAI,EAAE,kBAAkB,EAAE,MAAM,EAAE,CAAC;AAChD,CAAC"}
1
+ {"version":3,"file":"GenericFunctions.js","sourceRoot":"","sources":["../../../nodes/ServiceTitan/GenericFunctions.ts"],"names":[],"mappings":";;AAiBA,wDA4BC;AAcD,wEAwBC;AAaD,kDAoBC;AA3GD,+FAA2E;AAG3E;;;;GAIG;AACI,KAAK,UAAU,sBAAsB,CAE3C,MAA2B,EAC3B,IAAY,EACZ,KAAkB,EAAE,EACpB,OAAgC,SAAS;IAEzC,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;IACjE,MAAM,WAAW,GAAI,WAAW,CAAC,WAAsB,IAAI,aAAa,CAAC;IACzE,MAAM,OAAO,GAAG,IAAA,wCAAU,EAAC,WAAW,CAAC,CAAC;IAExC,MAAM,OAAO,GAAwB;QACpC,MAAM;QACN,GAAG,EAAE,WAAW,OAAO,GAAG,IAAI,EAAE;QAChC,EAAE;QACF,OAAO,EAAE;YACR,MAAM,EAAE,kBAAkB;YAC1B,cAAc,EAAE,kBAAkB;SAClC;QACD,IAAI,EAAE,IAAI;KACV,CAAC;IACF,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAE5C,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,6BAA6B,CAAC,IAAI,CAC5D,IAAI,EACJ,iBAAiB,EACjB,OAAO,CACP,CAAgB,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;GAWG;AACI,KAAK,UAAU,8BAA8B,CAEnD,MAA2B,EAC3B,IAAY,EACZ,KAAkB,EAAE,EACpB,OAAgC,SAAS;IAEzC,MAAM,SAAS,GAAkB,EAAE,CAAC;IACpC,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,MAAM,QAAQ,GAAG,EAAE,CAAC;IAEpB,OAAO,IAAI,IAAI,QAAQ,EAAE,CAAC;QACzB,MAAM,QAAQ,GAAG,CAAC,MAAM,sBAAsB,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,CAAC,CAClE,CAAC;QAE7B,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,SAAS,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC;QAED,IAAI,CAAC,QAAQ,CAAC,OAAO;YAAE,MAAM;QAC7B,IAAI,IAAI,CAAC,CAAC;IACX,CAAC;IAED,OAAO,SAAS,CAAC;AAClB,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAgB,mBAAmB,CAAC,IAAiB;IACpD,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,CAAC;IACvC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IAE9C,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,MAAM,QAAQ,GAA4B,EAAE,CAAC;IAE7C,KAAK,MAAM,GAAG,IAAI,YAA+B,EAAE,CAAC;QACnD,IAAI,CAAC,GAAG;YAAE,SAAS;QACnB,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC;QAC/D,IAAI,GAAG,CAAC,MAAM,KAAK,SAAS,IAAI,GAAG,CAAC,MAAM,KAAK,IAAI,EAAE,CAAC;YACrD,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC;QAC1C,CAAC;IACF,CAAC;IAED,OAAO;QACN,GAAG,IAAI;QACP,qBAAqB,EAAE,MAAM;QAC7B,wBAAwB,EAAE,QAAQ;KAClC,CAAC;AACH,CAAC"}
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thegraphitelab/n8n-nodes-servicetitan",
3
- "version": "0.8.1",
3
+ "version": "0.9.0",
4
4
  "description": "n8n custom node for ServiceTitan — TGL internal use.",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thegraphitelab/n8n-nodes-servicetitan",
3
- "version": "0.8.1",
3
+ "version": "0.9.0",
4
4
  "description": "n8n custom node for ServiceTitan — TGL internal use.",
5
5
  "keywords": [
6
6
  "n8n-community-node-package",