@growth-operations/ui-shared 1.6.17 → 1.8.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@growth-operations/ui-shared",
3
- "version": "1.6.17",
3
+ "version": "1.8.0",
4
4
  "description": "Shared HubSpot UI-extension modules (Home, Billing) for Growth Operations apps.",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -27,7 +27,12 @@ const SOURCES = {
27
27
  return results.map((f) => ({ label: f.name, value: f.id }));
28
28
  },
29
29
  lists: async (context, token, opts) => {
30
- const { lists = [] } = await getLists(context, token, opts?.query ?? "");
30
+ const { lists = [] } = await getLists(
31
+ context,
32
+ token,
33
+ opts?.query ?? "",
34
+ opts?.objectTypeId ?? null
35
+ );
31
36
  return lists.map((l) => ({ label: l.name, value: String(l.listId) }));
32
37
  },
33
38
  pipelines: async (context, token, opts) => {
@@ -61,7 +66,7 @@ export function OptionSelect({
61
66
  // url is null/absent the link is skipped, so callers can pass an "Edit" action
62
67
  // gated on a selected value.
63
68
  actions = [],
64
- // Extra source args (pipelineId/objectType for pipelineStages, query for lists)
69
+ // Extra source args (pipelineId/objectType for pipelineStages, query/objectTypeId for lists)
65
70
  ...opts
66
71
  }) {
67
72
  const [options, setOptions] = useState([]);
@@ -75,6 +80,7 @@ export function OptionSelect({
75
80
  pipelineId: opts.pipelineId,
76
81
  objectType: opts.objectType,
77
82
  query: opts.query,
83
+ objectTypeId: opts.objectTypeId,
78
84
  });
79
85
 
80
86
  useStrictModeEffect(
package/src/index.js CHANGED
@@ -78,6 +78,7 @@ export {
78
78
  HubSpotApiError,
79
79
  getObjectProperties,
80
80
  getProperties,
81
+ getPropertyOptions,
81
82
  updateProperties,
82
83
  getForms,
83
84
  getLists,
@@ -1,11 +1,14 @@
1
- // HubSpot contact-list fetcher (for list-selection pickers).
1
+ // HubSpot list fetcher (for list-selection pickers).
2
2
  //
3
3
  // Paginates crm/v3/lists/search until all DYNAMIC lists are collected. The POST
4
4
  // body is a plain OBJECT — callHubSpotApi sends it as-is (NEVER JSON.stringify).
5
5
  import { buildHubSpotUrl, callHubSpotApi } from "./base";
6
6
 
7
7
  // context is accepted for signature consistency. query: optional name filter.
8
- export async function getLists(context, token, query = "") {
8
+ // objectTypeId: optional HubSpot object type id (e.g. "0-1" for contacts, or a
9
+ // custom object's numeric type id) to scope results to lists built on that
10
+ // object — omit to search across all objects, as before.
11
+ export async function getLists(context, token, query = "", objectTypeId = null) {
9
12
  const url = buildHubSpotUrl("crm/v3/lists/search");
10
13
  const allLists = [];
11
14
  let offset = 0;
@@ -18,6 +21,7 @@ export async function getLists(context, token, query = "") {
18
21
  count: count,
19
22
  offset: offset,
20
23
  processingTypes: ["DYNAMIC"],
24
+ ...(objectTypeId ? { objectTypeId } : {}),
21
25
  };
22
26
 
23
27
  const response = await callHubSpotApi(url, token, "POST", payload);
@@ -4,6 +4,7 @@
4
4
  // rules apply (object body, Authorization-only header). The PATCH body is passed
5
5
  // as a plain object (NOT JSON.stringify'd).
6
6
  import { buildHubSpotUrl, callHubSpotApi } from "./base";
7
+ import { buildPropertyName } from "../../lib/urls";
7
8
 
8
9
  // List the writable properties for a HubSpot object type, shaped for a mapping
9
10
  // picker: [{ name, label, type }] sorted by label. Excludes hidden, archived,
@@ -48,3 +49,22 @@ export async function updateProperties(context, token, properties) {
48
49
  // properties is wrapped in a plain object — callHubSpotApi sends it as-is.
49
50
  return callHubSpotApi(url, token, "PATCH", { properties });
50
51
  }
52
+
53
+ // The enumeration options for a single property, shaped for a
54
+ // Select/MultiSelect/checkbox-list picker: [{ label, value }]. Returns [] if
55
+ // the property doesn't exist or isn't an enumeration (no `options` array).
56
+ //
57
+ // App-object properties defined in a *-hsmeta.json (e.g. an app-object's
58
+ // `status`) are integrator-defined and land PREFIXED (a{app_id}_status), not
59
+ // bare, once installed — pass appPrefix (from context.extension.appId) and
60
+ // this checks the prefixed name first, falling back to bare for properties
61
+ // that aren't app-namespaced. Omit appPrefix for object types with no app
62
+ // prefix at all (e.g. standard objects like contacts).
63
+ export async function getPropertyOptions(context, token, objectType, propertyName, appPrefix) {
64
+ const response = await getProperties(context, token, objectType);
65
+ const prefixedName = appPrefix ? buildPropertyName(appPrefix, propertyName) : null;
66
+ const prop = (response.results || []).find(
67
+ (p) => (prefixedName && p.name === prefixedName) || p.name === propertyName
68
+ );
69
+ return (prop?.options || []).map((o) => ({ label: o.label, value: o.value }));
70
+ }
package/src/sdk/index.js CHANGED
@@ -18,6 +18,7 @@ export { callHubSpotApi, buildHubSpotUrl, HubSpotApiError } from "./hubspot/base
18
18
  export {
19
19
  getObjectProperties,
20
20
  getProperties,
21
+ getPropertyOptions,
21
22
  updateProperties,
22
23
  } from "./hubspot/properties";
23
24
  export { getForms } from "./hubspot/forms";