@zapier/zapier-sdk 0.13.9 → 0.14.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/CHANGELOG.md +7 -0
- package/dist/index.cjs +114 -41
- package/dist/index.mjs +114 -41
- package/dist/plugins/listInputFieldChoices/index.d.ts +3 -1
- package/dist/plugins/listInputFieldChoices/index.d.ts.map +1 -1
- package/dist/plugins/listInputFieldChoices/index.js +42 -21
- package/dist/plugins/listInputFieldChoices/index.test.js +183 -6
- package/dist/plugins/listInputFields/index.d.ts.map +1 -1
- package/dist/plugins/listInputFields/index.js +11 -16
- package/dist/plugins/listInputFields/index.test.js +4 -2
- package/dist/services/implementations.d.ts +63 -0
- package/dist/services/implementations.d.ts.map +1 -0
- package/dist/services/implementations.js +79 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -1812,6 +1812,64 @@ var RootFieldItemSchema = zod.z.union([
|
|
|
1812
1812
|
FieldsetItemSchema
|
|
1813
1813
|
]);
|
|
1814
1814
|
|
|
1815
|
+
// src/services/implementations.ts
|
|
1816
|
+
async function fetchImplementationNeeds({
|
|
1817
|
+
api,
|
|
1818
|
+
selectedApi,
|
|
1819
|
+
action,
|
|
1820
|
+
actionType,
|
|
1821
|
+
authenticationId,
|
|
1822
|
+
inputs
|
|
1823
|
+
}) {
|
|
1824
|
+
const request = {
|
|
1825
|
+
selected_api: selectedApi,
|
|
1826
|
+
action,
|
|
1827
|
+
type_of: actionType,
|
|
1828
|
+
params: inputs || {}
|
|
1829
|
+
};
|
|
1830
|
+
if (authenticationId !== null) {
|
|
1831
|
+
request.authentication_id = authenticationId;
|
|
1832
|
+
}
|
|
1833
|
+
const response = await api.post(
|
|
1834
|
+
"/api/v4/implementations/needs/",
|
|
1835
|
+
request
|
|
1836
|
+
);
|
|
1837
|
+
if (!response.success) {
|
|
1838
|
+
throw new ZapierApiError(
|
|
1839
|
+
`Failed to get input fields: ${response.errors?.join(", ") || "Unknown error"}`
|
|
1840
|
+
);
|
|
1841
|
+
}
|
|
1842
|
+
return response;
|
|
1843
|
+
}
|
|
1844
|
+
async function fetchImplementationChoices({
|
|
1845
|
+
api,
|
|
1846
|
+
actionId,
|
|
1847
|
+
inputFieldId,
|
|
1848
|
+
authenticationId,
|
|
1849
|
+
inputs,
|
|
1850
|
+
page
|
|
1851
|
+
}) {
|
|
1852
|
+
const request = {
|
|
1853
|
+
action_id: actionId,
|
|
1854
|
+
input_field_id: inputFieldId,
|
|
1855
|
+
page,
|
|
1856
|
+
params: inputs || {}
|
|
1857
|
+
};
|
|
1858
|
+
if (authenticationId !== null) {
|
|
1859
|
+
request.authentication_id = authenticationId;
|
|
1860
|
+
}
|
|
1861
|
+
const response = await api.post(
|
|
1862
|
+
"/api/v4/implementations/choices/",
|
|
1863
|
+
request
|
|
1864
|
+
);
|
|
1865
|
+
if (!response.success) {
|
|
1866
|
+
throw new ZapierApiError(
|
|
1867
|
+
`Failed to get input field choices: ${response.errors?.join(", ") || "Unknown error"}`
|
|
1868
|
+
);
|
|
1869
|
+
}
|
|
1870
|
+
return response;
|
|
1871
|
+
}
|
|
1872
|
+
|
|
1815
1873
|
// src/plugins/listInputFields/index.ts
|
|
1816
1874
|
function getInputFieldTypeFromNeed(need) {
|
|
1817
1875
|
if (need.list) {
|
|
@@ -1915,7 +1973,13 @@ var listInputFieldsPlugin = ({ sdk, context }) => {
|
|
|
1915
1973
|
const listInputFields = createPaginatedFunction(
|
|
1916
1974
|
async function listInputFieldsPage(options) {
|
|
1917
1975
|
const { api, getVersionedImplementationId } = context;
|
|
1918
|
-
const {
|
|
1976
|
+
const {
|
|
1977
|
+
appKey,
|
|
1978
|
+
actionKey,
|
|
1979
|
+
actionType,
|
|
1980
|
+
authenticationId = null,
|
|
1981
|
+
inputs
|
|
1982
|
+
} = options;
|
|
1919
1983
|
const selectedApi = await getVersionedImplementationId(appKey);
|
|
1920
1984
|
if (!selectedApi) {
|
|
1921
1985
|
throw new ZapierConfigurationError(
|
|
@@ -1928,24 +1992,14 @@ var listInputFieldsPlugin = ({ sdk, context }) => {
|
|
|
1928
1992
|
actionType,
|
|
1929
1993
|
actionKey
|
|
1930
1994
|
});
|
|
1931
|
-
const
|
|
1932
|
-
|
|
1995
|
+
const needsData = await fetchImplementationNeeds({
|
|
1996
|
+
api,
|
|
1997
|
+
selectedApi,
|
|
1933
1998
|
action: action.key,
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
1937
|
-
|
|
1938
|
-
needsRequest.authentication_id = authenticationId;
|
|
1939
|
-
}
|
|
1940
|
-
const needsData = await api.post(
|
|
1941
|
-
"/api/v4/implementations/needs/",
|
|
1942
|
-
needsRequest
|
|
1943
|
-
);
|
|
1944
|
-
if (!needsData.success) {
|
|
1945
|
-
throw new ZapierApiError(
|
|
1946
|
-
`Failed to get action fields: ${needsData.errors?.join(", ") || "Unknown error"}`
|
|
1947
|
-
);
|
|
1948
|
-
}
|
|
1999
|
+
actionType,
|
|
2000
|
+
authenticationId,
|
|
2001
|
+
inputs
|
|
2002
|
+
});
|
|
1949
2003
|
const rootFieldset = transformNeedsToFields(needsData.needs || []);
|
|
1950
2004
|
return {
|
|
1951
2005
|
data: rootFieldset,
|
|
@@ -3855,43 +3909,62 @@ function transformNeedChoicesToInputFieldChoiceItem(choice) {
|
|
|
3855
3909
|
}
|
|
3856
3910
|
var listInputFieldChoicesPlugin = ({ context, sdk }) => {
|
|
3857
3911
|
const listInputFieldChoices = createPaginatedFunction(async function listInputFieldChoicesPage(options) {
|
|
3858
|
-
const { api } = context;
|
|
3912
|
+
const { api, getVersionedImplementationId } = context;
|
|
3859
3913
|
const {
|
|
3860
3914
|
appKey,
|
|
3861
3915
|
actionType,
|
|
3862
3916
|
actionKey,
|
|
3863
3917
|
inputFieldKey,
|
|
3864
|
-
authenticationId,
|
|
3918
|
+
authenticationId = null,
|
|
3865
3919
|
inputs,
|
|
3866
3920
|
page,
|
|
3867
3921
|
cursor
|
|
3868
3922
|
} = options;
|
|
3869
|
-
const
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
|
|
3923
|
+
const selectedApi = await getVersionedImplementationId(appKey);
|
|
3924
|
+
if (!selectedApi) {
|
|
3925
|
+
throw new ZapierConfigurationError(
|
|
3926
|
+
"No current_implementation_id found for app",
|
|
3927
|
+
{ configType: "current_implementation_id" }
|
|
3874
3928
|
);
|
|
3875
3929
|
}
|
|
3876
|
-
const
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3930
|
+
const { data: action } = await sdk.getAction({
|
|
3931
|
+
appKey,
|
|
3932
|
+
actionType,
|
|
3933
|
+
actionKey
|
|
3934
|
+
});
|
|
3935
|
+
const needsData = await fetchImplementationNeeds({
|
|
3936
|
+
api,
|
|
3937
|
+
selectedApi,
|
|
3938
|
+
action: action.key,
|
|
3939
|
+
actionType,
|
|
3940
|
+
authenticationId,
|
|
3941
|
+
inputs
|
|
3942
|
+
});
|
|
3943
|
+
const targetNeed = needsData.needs?.find(
|
|
3944
|
+
(need) => need.key === inputFieldKey
|
|
3889
3945
|
);
|
|
3890
|
-
if (
|
|
3946
|
+
if (targetNeed?.choices && targetNeed.choices.length > 0) {
|
|
3947
|
+
return {
|
|
3948
|
+
data: targetNeed.choices.map(
|
|
3949
|
+
transformNeedChoicesToInputFieldChoiceItem
|
|
3950
|
+
),
|
|
3951
|
+
nextCursor: void 0
|
|
3952
|
+
};
|
|
3953
|
+
}
|
|
3954
|
+
if (!action.id) {
|
|
3891
3955
|
throw new ZapierApiError(
|
|
3892
|
-
`
|
|
3956
|
+
`Action ${actionKey} does not have an ID - cannot retrieve input field choices`
|
|
3893
3957
|
);
|
|
3894
3958
|
}
|
|
3959
|
+
const requestPage = cursor ? parseInt(cursor, 10) : page ?? 0;
|
|
3960
|
+
const choicesData = await fetchImplementationChoices({
|
|
3961
|
+
api,
|
|
3962
|
+
actionId: action.id,
|
|
3963
|
+
inputFieldId: inputFieldKey,
|
|
3964
|
+
authenticationId,
|
|
3965
|
+
inputs,
|
|
3966
|
+
page: requestPage
|
|
3967
|
+
});
|
|
3895
3968
|
const choices = (choicesData.choices || []).map(
|
|
3896
3969
|
transformNeedChoicesToInputFieldChoiceItem
|
|
3897
3970
|
);
|
|
@@ -4089,7 +4162,7 @@ function getCpuTime() {
|
|
|
4089
4162
|
|
|
4090
4163
|
// package.json
|
|
4091
4164
|
var package_default = {
|
|
4092
|
-
version: "0.
|
|
4165
|
+
version: "0.14.0"};
|
|
4093
4166
|
|
|
4094
4167
|
// src/plugins/eventEmission/builders.ts
|
|
4095
4168
|
function createBaseEvent(context = {}) {
|
package/dist/index.mjs
CHANGED
|
@@ -1790,6 +1790,64 @@ var RootFieldItemSchema = z.union([
|
|
|
1790
1790
|
FieldsetItemSchema
|
|
1791
1791
|
]);
|
|
1792
1792
|
|
|
1793
|
+
// src/services/implementations.ts
|
|
1794
|
+
async function fetchImplementationNeeds({
|
|
1795
|
+
api,
|
|
1796
|
+
selectedApi,
|
|
1797
|
+
action,
|
|
1798
|
+
actionType,
|
|
1799
|
+
authenticationId,
|
|
1800
|
+
inputs
|
|
1801
|
+
}) {
|
|
1802
|
+
const request = {
|
|
1803
|
+
selected_api: selectedApi,
|
|
1804
|
+
action,
|
|
1805
|
+
type_of: actionType,
|
|
1806
|
+
params: inputs || {}
|
|
1807
|
+
};
|
|
1808
|
+
if (authenticationId !== null) {
|
|
1809
|
+
request.authentication_id = authenticationId;
|
|
1810
|
+
}
|
|
1811
|
+
const response = await api.post(
|
|
1812
|
+
"/api/v4/implementations/needs/",
|
|
1813
|
+
request
|
|
1814
|
+
);
|
|
1815
|
+
if (!response.success) {
|
|
1816
|
+
throw new ZapierApiError(
|
|
1817
|
+
`Failed to get input fields: ${response.errors?.join(", ") || "Unknown error"}`
|
|
1818
|
+
);
|
|
1819
|
+
}
|
|
1820
|
+
return response;
|
|
1821
|
+
}
|
|
1822
|
+
async function fetchImplementationChoices({
|
|
1823
|
+
api,
|
|
1824
|
+
actionId,
|
|
1825
|
+
inputFieldId,
|
|
1826
|
+
authenticationId,
|
|
1827
|
+
inputs,
|
|
1828
|
+
page
|
|
1829
|
+
}) {
|
|
1830
|
+
const request = {
|
|
1831
|
+
action_id: actionId,
|
|
1832
|
+
input_field_id: inputFieldId,
|
|
1833
|
+
page,
|
|
1834
|
+
params: inputs || {}
|
|
1835
|
+
};
|
|
1836
|
+
if (authenticationId !== null) {
|
|
1837
|
+
request.authentication_id = authenticationId;
|
|
1838
|
+
}
|
|
1839
|
+
const response = await api.post(
|
|
1840
|
+
"/api/v4/implementations/choices/",
|
|
1841
|
+
request
|
|
1842
|
+
);
|
|
1843
|
+
if (!response.success) {
|
|
1844
|
+
throw new ZapierApiError(
|
|
1845
|
+
`Failed to get input field choices: ${response.errors?.join(", ") || "Unknown error"}`
|
|
1846
|
+
);
|
|
1847
|
+
}
|
|
1848
|
+
return response;
|
|
1849
|
+
}
|
|
1850
|
+
|
|
1793
1851
|
// src/plugins/listInputFields/index.ts
|
|
1794
1852
|
function getInputFieldTypeFromNeed(need) {
|
|
1795
1853
|
if (need.list) {
|
|
@@ -1893,7 +1951,13 @@ var listInputFieldsPlugin = ({ sdk, context }) => {
|
|
|
1893
1951
|
const listInputFields = createPaginatedFunction(
|
|
1894
1952
|
async function listInputFieldsPage(options) {
|
|
1895
1953
|
const { api, getVersionedImplementationId } = context;
|
|
1896
|
-
const {
|
|
1954
|
+
const {
|
|
1955
|
+
appKey,
|
|
1956
|
+
actionKey,
|
|
1957
|
+
actionType,
|
|
1958
|
+
authenticationId = null,
|
|
1959
|
+
inputs
|
|
1960
|
+
} = options;
|
|
1897
1961
|
const selectedApi = await getVersionedImplementationId(appKey);
|
|
1898
1962
|
if (!selectedApi) {
|
|
1899
1963
|
throw new ZapierConfigurationError(
|
|
@@ -1906,24 +1970,14 @@ var listInputFieldsPlugin = ({ sdk, context }) => {
|
|
|
1906
1970
|
actionType,
|
|
1907
1971
|
actionKey
|
|
1908
1972
|
});
|
|
1909
|
-
const
|
|
1910
|
-
|
|
1973
|
+
const needsData = await fetchImplementationNeeds({
|
|
1974
|
+
api,
|
|
1975
|
+
selectedApi,
|
|
1911
1976
|
action: action.key,
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
needsRequest.authentication_id = authenticationId;
|
|
1917
|
-
}
|
|
1918
|
-
const needsData = await api.post(
|
|
1919
|
-
"/api/v4/implementations/needs/",
|
|
1920
|
-
needsRequest
|
|
1921
|
-
);
|
|
1922
|
-
if (!needsData.success) {
|
|
1923
|
-
throw new ZapierApiError(
|
|
1924
|
-
`Failed to get action fields: ${needsData.errors?.join(", ") || "Unknown error"}`
|
|
1925
|
-
);
|
|
1926
|
-
}
|
|
1977
|
+
actionType,
|
|
1978
|
+
authenticationId,
|
|
1979
|
+
inputs
|
|
1980
|
+
});
|
|
1927
1981
|
const rootFieldset = transformNeedsToFields(needsData.needs || []);
|
|
1928
1982
|
return {
|
|
1929
1983
|
data: rootFieldset,
|
|
@@ -3833,43 +3887,62 @@ function transformNeedChoicesToInputFieldChoiceItem(choice) {
|
|
|
3833
3887
|
}
|
|
3834
3888
|
var listInputFieldChoicesPlugin = ({ context, sdk }) => {
|
|
3835
3889
|
const listInputFieldChoices = createPaginatedFunction(async function listInputFieldChoicesPage(options) {
|
|
3836
|
-
const { api } = context;
|
|
3890
|
+
const { api, getVersionedImplementationId } = context;
|
|
3837
3891
|
const {
|
|
3838
3892
|
appKey,
|
|
3839
3893
|
actionType,
|
|
3840
3894
|
actionKey,
|
|
3841
3895
|
inputFieldKey,
|
|
3842
|
-
authenticationId,
|
|
3896
|
+
authenticationId = null,
|
|
3843
3897
|
inputs,
|
|
3844
3898
|
page,
|
|
3845
3899
|
cursor
|
|
3846
3900
|
} = options;
|
|
3847
|
-
const
|
|
3848
|
-
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3901
|
+
const selectedApi = await getVersionedImplementationId(appKey);
|
|
3902
|
+
if (!selectedApi) {
|
|
3903
|
+
throw new ZapierConfigurationError(
|
|
3904
|
+
"No current_implementation_id found for app",
|
|
3905
|
+
{ configType: "current_implementation_id" }
|
|
3852
3906
|
);
|
|
3853
3907
|
}
|
|
3854
|
-
const
|
|
3855
|
-
|
|
3856
|
-
|
|
3857
|
-
|
|
3858
|
-
|
|
3859
|
-
|
|
3860
|
-
|
|
3861
|
-
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3908
|
+
const { data: action } = await sdk.getAction({
|
|
3909
|
+
appKey,
|
|
3910
|
+
actionType,
|
|
3911
|
+
actionKey
|
|
3912
|
+
});
|
|
3913
|
+
const needsData = await fetchImplementationNeeds({
|
|
3914
|
+
api,
|
|
3915
|
+
selectedApi,
|
|
3916
|
+
action: action.key,
|
|
3917
|
+
actionType,
|
|
3918
|
+
authenticationId,
|
|
3919
|
+
inputs
|
|
3920
|
+
});
|
|
3921
|
+
const targetNeed = needsData.needs?.find(
|
|
3922
|
+
(need) => need.key === inputFieldKey
|
|
3867
3923
|
);
|
|
3868
|
-
if (
|
|
3924
|
+
if (targetNeed?.choices && targetNeed.choices.length > 0) {
|
|
3925
|
+
return {
|
|
3926
|
+
data: targetNeed.choices.map(
|
|
3927
|
+
transformNeedChoicesToInputFieldChoiceItem
|
|
3928
|
+
),
|
|
3929
|
+
nextCursor: void 0
|
|
3930
|
+
};
|
|
3931
|
+
}
|
|
3932
|
+
if (!action.id) {
|
|
3869
3933
|
throw new ZapierApiError(
|
|
3870
|
-
`
|
|
3934
|
+
`Action ${actionKey} does not have an ID - cannot retrieve input field choices`
|
|
3871
3935
|
);
|
|
3872
3936
|
}
|
|
3937
|
+
const requestPage = cursor ? parseInt(cursor, 10) : page ?? 0;
|
|
3938
|
+
const choicesData = await fetchImplementationChoices({
|
|
3939
|
+
api,
|
|
3940
|
+
actionId: action.id,
|
|
3941
|
+
inputFieldId: inputFieldKey,
|
|
3942
|
+
authenticationId,
|
|
3943
|
+
inputs,
|
|
3944
|
+
page: requestPage
|
|
3945
|
+
});
|
|
3873
3946
|
const choices = (choicesData.choices || []).map(
|
|
3874
3947
|
transformNeedChoicesToInputFieldChoiceItem
|
|
3875
3948
|
);
|
|
@@ -4067,7 +4140,7 @@ function getCpuTime() {
|
|
|
4067
4140
|
|
|
4068
4141
|
// package.json
|
|
4069
4142
|
var package_default = {
|
|
4070
|
-
version: "0.
|
|
4143
|
+
version: "0.14.0"};
|
|
4071
4144
|
|
|
4072
4145
|
// src/plugins/eventEmission/builders.ts
|
|
4073
4146
|
function createBaseEvent(context = {}) {
|
|
@@ -3,6 +3,7 @@ import type { ApiClient } from "../../api";
|
|
|
3
3
|
import type { InputFieldChoiceItem } from "./schemas";
|
|
4
4
|
import { ListInputFieldChoicesSchema, type ListInputFieldChoicesOptions } from "./schemas";
|
|
5
5
|
import type { GetActionPluginProvides } from "../getAction";
|
|
6
|
+
import type { GetVersionedImplementationId } from "../manifest/schemas";
|
|
6
7
|
export interface ListInputFieldChoicesPluginProvides {
|
|
7
8
|
listInputFieldChoices: (options: ListInputFieldChoicesOptions) => Promise<{
|
|
8
9
|
data: InputFieldChoiceItem[];
|
|
@@ -24,6 +25,7 @@ export interface ListInputFieldChoicesPluginProvides {
|
|
|
24
25
|
export declare const listInputFieldChoicesPlugin: Plugin<GetSdkType<GetActionPluginProvides>, // requires getAction in SDK
|
|
25
26
|
{
|
|
26
27
|
api: ApiClient;
|
|
27
|
-
|
|
28
|
+
getVersionedImplementationId: GetVersionedImplementationId;
|
|
29
|
+
}, // requires api and getVersionedImplementationId in context
|
|
28
30
|
ListInputFieldChoicesPluginProvides>;
|
|
29
31
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/listInputFieldChoices/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/listInputFieldChoices/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EACL,2BAA2B,EAC3B,KAAK,4BAA4B,EAGlC,MAAM,WAAW,CAAC;AAGnB,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AA0BxE,MAAM,WAAW,mCAAmC;IAClD,qBAAqB,EAAE,CAAC,OAAO,EAAE,4BAA4B,KAAK,OAAO,CAAC;QACxE,IAAI,EAAE,oBAAoB,EAAE,CAAC;QAC7B,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC,GACA,aAAa,CAAC;QAAE,IAAI,EAAE,oBAAoB,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG;QACrE,KAAK,IAAI,aAAa,CAAC,oBAAoB,CAAC,CAAC;KAC9C,CAAC;IACJ,OAAO,EAAE;QACP,IAAI,EAAE;YACJ,qBAAqB,EAAE;gBACrB,WAAW,EAAE,OAAO,2BAA2B,CAAC;aACjD,CAAC;SACH,CAAC;KACH,CAAC;CACH;AAED,eAAO,MAAM,2BAA2B,EAAE,MAAM,CAC9C,UAAU,CAAC,uBAAuB,CAAC,EAAE,4BAA4B;AACjE;IACE,GAAG,EAAE,SAAS,CAAC;IACf,4BAA4B,EAAE,4BAA4B,CAAC;CAC5D,EAAE,2DAA2D;AAC9D,mCAAmC,CAyIpC,CAAC"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ListInputFieldChoicesSchema, InputFieldChoiceItemSchema, } from "./schemas";
|
|
2
|
-
import { ZapierApiError } from "../../types/errors";
|
|
2
|
+
import { ZapierApiError, ZapierConfigurationError } from "../../types/errors";
|
|
3
3
|
import { createPaginatedFunction } from "../../utils/function-utils";
|
|
4
4
|
import { appKeyResolver, actionTypeResolver, actionKeyResolver, authenticationIdResolver, inputFieldKeyResolver, inputsAllOptionalResolver, } from "../../resolvers";
|
|
5
|
+
import { fetchImplementationNeeds, fetchImplementationChoices, } from "../../services/implementations";
|
|
5
6
|
// Transform NeedChoices to InputFieldChoiceItem
|
|
6
7
|
function transformNeedChoicesToInputFieldChoiceItem(choice) {
|
|
7
8
|
return {
|
|
@@ -13,32 +14,52 @@ function transformNeedChoicesToInputFieldChoiceItem(choice) {
|
|
|
13
14
|
}
|
|
14
15
|
export const listInputFieldChoicesPlugin = ({ context, sdk }) => {
|
|
15
16
|
const listInputFieldChoices = createPaginatedFunction(async function listInputFieldChoicesPage(options) {
|
|
16
|
-
const { api } = context;
|
|
17
|
+
const { api, getVersionedImplementationId } = context;
|
|
17
18
|
// Extract parameters
|
|
18
|
-
const { appKey, actionType, actionKey, inputFieldKey, authenticationId, inputs, page, cursor, } = options;
|
|
19
|
-
//
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
const { appKey, actionType, actionKey, inputFieldKey, authenticationId = null, inputs, page, cursor, } = options;
|
|
20
|
+
// Get versioned implementation ID for the app
|
|
21
|
+
const selectedApi = await getVersionedImplementationId(appKey);
|
|
22
|
+
if (!selectedApi) {
|
|
23
|
+
throw new ZapierConfigurationError("No current_implementation_id found for app", { configType: "current_implementation_id" });
|
|
24
|
+
}
|
|
25
|
+
// Get action details
|
|
26
|
+
const { data: action } = await sdk.getAction({
|
|
27
|
+
appKey,
|
|
28
|
+
actionType,
|
|
29
|
+
actionKey,
|
|
30
|
+
});
|
|
31
|
+
// First, check for static choices by fetching implementation needs directly
|
|
32
|
+
const needsData = await fetchImplementationNeeds({
|
|
33
|
+
api,
|
|
34
|
+
selectedApi,
|
|
35
|
+
action: action.key,
|
|
36
|
+
actionType,
|
|
37
|
+
authenticationId,
|
|
38
|
+
inputs,
|
|
39
|
+
});
|
|
40
|
+
// Find the specific Need by key - search through raw needs array
|
|
41
|
+
const targetNeed = needsData.needs?.find((need) => need.key === inputFieldKey);
|
|
42
|
+
// If the need has static choices, return them
|
|
43
|
+
if (targetNeed?.choices && targetNeed.choices.length > 0) {
|
|
44
|
+
return {
|
|
45
|
+
data: targetNeed.choices.map(transformNeedChoicesToInputFieldChoiceItem),
|
|
46
|
+
nextCursor: undefined,
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
if (!action.id) {
|
|
23
50
|
throw new ZapierApiError(`Action ${actionKey} does not have an ID - cannot retrieve input field choices`);
|
|
24
51
|
}
|
|
25
|
-
// Build choices request using action ID from getAction
|
|
26
52
|
// Use cursor (from pagination) as page number if available, otherwise use explicit page or default to 0
|
|
27
53
|
const requestPage = cursor ? parseInt(cursor, 10) : (page ?? 0);
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
54
|
+
// Use service layer to fetch dynamic choices
|
|
55
|
+
const choicesData = await fetchImplementationChoices({
|
|
56
|
+
api,
|
|
57
|
+
actionId: action.id,
|
|
58
|
+
inputFieldId: inputFieldKey,
|
|
59
|
+
authenticationId,
|
|
60
|
+
inputs,
|
|
31
61
|
page: requestPage,
|
|
32
|
-
|
|
33
|
-
};
|
|
34
|
-
// Only include authentication_id if it's not null (skip authentication when null)
|
|
35
|
-
if (authenticationId !== null) {
|
|
36
|
-
choicesRequest.authentication_id = authenticationId;
|
|
37
|
-
}
|
|
38
|
-
const choicesData = await api.post("/api/v4/implementations/choices/", choicesRequest);
|
|
39
|
-
if (!choicesData.success) {
|
|
40
|
-
throw new ZapierApiError(`Failed to get input field choices: ${choicesData.errors?.join(", ") || "Unknown error"}`);
|
|
41
|
-
}
|
|
62
|
+
});
|
|
42
63
|
// Transform NeedChoices objects to InputFieldChoiceItem objects
|
|
43
64
|
const choices = (choicesData.choices || []).map(transformNeedChoicesToInputFieldChoiceItem);
|
|
44
65
|
// Handle pagination
|
|
@@ -41,17 +41,73 @@ const mockExternalChoicesResponse = {
|
|
|
41
41
|
prev: null,
|
|
42
42
|
},
|
|
43
43
|
};
|
|
44
|
+
// Mock needs data for static choices
|
|
45
|
+
const mockNeedsWithStaticChoices = [
|
|
46
|
+
{
|
|
47
|
+
key: "priority",
|
|
48
|
+
label: "Priority",
|
|
49
|
+
help_text: "Select priority",
|
|
50
|
+
required: true,
|
|
51
|
+
type: "string",
|
|
52
|
+
choices: [
|
|
53
|
+
{
|
|
54
|
+
key: "high",
|
|
55
|
+
sample: "high",
|
|
56
|
+
label: "High Priority",
|
|
57
|
+
value: "high",
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
key: "medium",
|
|
61
|
+
sample: "medium",
|
|
62
|
+
label: "Medium Priority",
|
|
63
|
+
value: "medium",
|
|
64
|
+
},
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
];
|
|
68
|
+
const mockNeedsWithoutChoices = [
|
|
69
|
+
{
|
|
70
|
+
key: "channel",
|
|
71
|
+
label: "Channel",
|
|
72
|
+
help_text: "Select a channel",
|
|
73
|
+
required: true,
|
|
74
|
+
type: "string",
|
|
75
|
+
choices: [], // Empty choices
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
const mockNeedsResponse = {
|
|
79
|
+
success: true,
|
|
80
|
+
needs: mockNeedsWithoutChoices,
|
|
81
|
+
};
|
|
82
|
+
const mockNeedsResponseWithStaticChoices = {
|
|
83
|
+
success: true,
|
|
84
|
+
needs: mockNeedsWithStaticChoices,
|
|
85
|
+
};
|
|
44
86
|
describe("listInputFieldChoices plugin", () => {
|
|
45
87
|
let mockApiClient;
|
|
46
88
|
let mockGetAction;
|
|
89
|
+
let mockGetVersionedImplementationId;
|
|
47
90
|
beforeEach(() => {
|
|
48
91
|
vi.clearAllMocks();
|
|
92
|
+
// Mock api.post to handle both endpoints
|
|
93
|
+
const mockPost = vi.fn().mockImplementation((path) => {
|
|
94
|
+
if (path === "/api/v4/implementations/needs/") {
|
|
95
|
+
return Promise.resolve(mockNeedsResponse);
|
|
96
|
+
}
|
|
97
|
+
else if (path === "/api/v4/implementations/choices/") {
|
|
98
|
+
return Promise.resolve(mockChoicesResponse);
|
|
99
|
+
}
|
|
100
|
+
return Promise.reject(new Error(`Unexpected endpoint: ${path}`));
|
|
101
|
+
});
|
|
49
102
|
mockApiClient = {
|
|
50
|
-
post:
|
|
103
|
+
post: mockPost,
|
|
51
104
|
};
|
|
52
105
|
mockGetAction = vi.fn().mockResolvedValue({
|
|
53
106
|
data: { id: "core:123", key: "send_message", action_type: "read" },
|
|
54
107
|
});
|
|
108
|
+
mockGetVersionedImplementationId = vi
|
|
109
|
+
.fn()
|
|
110
|
+
.mockResolvedValue("SlackCLIAPI@1.21.1");
|
|
55
111
|
});
|
|
56
112
|
function createTestSdk() {
|
|
57
113
|
// Create a mock getAction plugin
|
|
@@ -66,7 +122,11 @@ describe("listInputFieldChoices plugin", () => {
|
|
|
66
122
|
},
|
|
67
123
|
});
|
|
68
124
|
// Build SDK with proper plugin composition
|
|
69
|
-
return createSdk({}, {}, {
|
|
125
|
+
return createSdk({}, {}, {
|
|
126
|
+
api: mockApiClient,
|
|
127
|
+
meta: {},
|
|
128
|
+
getVersionedImplementationId: mockGetVersionedImplementationId,
|
|
129
|
+
})
|
|
70
130
|
.addPlugin(mockGetActionPlugin)
|
|
71
131
|
.addPlugin(listInputFieldChoicesPlugin);
|
|
72
132
|
}
|
|
@@ -155,6 +215,122 @@ describe("listInputFieldChoices plugin", () => {
|
|
|
155
215
|
}
|
|
156
216
|
});
|
|
157
217
|
});
|
|
218
|
+
describe("static choices from needs endpoint", () => {
|
|
219
|
+
it("should return static choices when field has them", async () => {
|
|
220
|
+
// Mock api.post to return needs with static choices
|
|
221
|
+
const mockPost = vi.fn().mockImplementation((path) => {
|
|
222
|
+
if (path === "/api/v4/implementations/needs/") {
|
|
223
|
+
return Promise.resolve(mockNeedsResponseWithStaticChoices);
|
|
224
|
+
}
|
|
225
|
+
else if (path === "/api/v4/implementations/choices/") {
|
|
226
|
+
return Promise.resolve(mockChoicesResponse);
|
|
227
|
+
}
|
|
228
|
+
return Promise.reject(new Error(`Unexpected endpoint: ${path}`));
|
|
229
|
+
});
|
|
230
|
+
mockApiClient.post = mockPost;
|
|
231
|
+
const sdk = createTestSdk();
|
|
232
|
+
const result = await sdk.listInputFieldChoices({
|
|
233
|
+
appKey: "slack",
|
|
234
|
+
actionType: "read",
|
|
235
|
+
actionKey: "send_message",
|
|
236
|
+
inputFieldKey: "priority",
|
|
237
|
+
});
|
|
238
|
+
// Should return static choices
|
|
239
|
+
expect(result.data).toHaveLength(2);
|
|
240
|
+
expect(result.data[0]).toEqual({
|
|
241
|
+
key: "high",
|
|
242
|
+
label: "High Priority",
|
|
243
|
+
sample: "high",
|
|
244
|
+
value: "high",
|
|
245
|
+
});
|
|
246
|
+
expect(result.data[1]).toEqual({
|
|
247
|
+
key: "medium",
|
|
248
|
+
label: "Medium Priority",
|
|
249
|
+
sample: "medium",
|
|
250
|
+
value: "medium",
|
|
251
|
+
});
|
|
252
|
+
// Should have called needs endpoint to check for static choices
|
|
253
|
+
expect(mockApiClient.post).toHaveBeenCalledWith("/api/v4/implementations/needs/", {
|
|
254
|
+
selected_api: "SlackCLIAPI@1.21.1",
|
|
255
|
+
action: "send_message",
|
|
256
|
+
type_of: "read",
|
|
257
|
+
params: {},
|
|
258
|
+
});
|
|
259
|
+
// Should not call choices endpoint since static choices were found
|
|
260
|
+
expect(mockApiClient.post).not.toHaveBeenCalledWith("/api/v4/implementations/choices/", expect.anything());
|
|
261
|
+
});
|
|
262
|
+
it("should fall back to dynamic choices when field has empty choices array", async () => {
|
|
263
|
+
// Mock api.post - needs endpoint returns field with empty choices
|
|
264
|
+
const mockPost = vi.fn().mockImplementation((path) => {
|
|
265
|
+
if (path === "/api/v4/implementations/needs/") {
|
|
266
|
+
return Promise.resolve(mockNeedsResponse); // Has empty choices
|
|
267
|
+
}
|
|
268
|
+
else if (path === "/api/v4/implementations/choices/") {
|
|
269
|
+
return Promise.resolve(mockChoicesResponse);
|
|
270
|
+
}
|
|
271
|
+
return Promise.reject(new Error(`Unexpected endpoint: ${path}`));
|
|
272
|
+
});
|
|
273
|
+
mockApiClient.post = mockPost;
|
|
274
|
+
const sdk = createTestSdk();
|
|
275
|
+
const result = await sdk.listInputFieldChoices({
|
|
276
|
+
appKey: "slack",
|
|
277
|
+
actionType: "read",
|
|
278
|
+
actionKey: "send_message",
|
|
279
|
+
inputFieldKey: "channel",
|
|
280
|
+
});
|
|
281
|
+
// Should first call needs endpoint
|
|
282
|
+
expect(mockApiClient.post).toHaveBeenCalledWith("/api/v4/implementations/needs/", {
|
|
283
|
+
selected_api: "SlackCLIAPI@1.21.1",
|
|
284
|
+
action: "send_message",
|
|
285
|
+
type_of: "read",
|
|
286
|
+
params: {},
|
|
287
|
+
});
|
|
288
|
+
// Should then call choices endpoint for dynamic choices
|
|
289
|
+
expect(mockApiClient.post).toHaveBeenCalledWith("/api/v4/implementations/choices/", expect.objectContaining({
|
|
290
|
+
action_id: "core:123",
|
|
291
|
+
input_field_id: "channel",
|
|
292
|
+
}));
|
|
293
|
+
// Should return dynamic choices
|
|
294
|
+
expect(result.data).toHaveLength(3);
|
|
295
|
+
});
|
|
296
|
+
it("should fall back to dynamic choices when field is not found", async () => {
|
|
297
|
+
// Mock api.post - needs endpoint returns different field
|
|
298
|
+
const mockNeedsWithOtherField = {
|
|
299
|
+
success: true,
|
|
300
|
+
needs: [
|
|
301
|
+
{
|
|
302
|
+
key: "other_field",
|
|
303
|
+
label: "Other Field",
|
|
304
|
+
help_text: "Some other field",
|
|
305
|
+
required: false,
|
|
306
|
+
type: "string",
|
|
307
|
+
choices: [],
|
|
308
|
+
},
|
|
309
|
+
],
|
|
310
|
+
};
|
|
311
|
+
const mockPost = vi.fn().mockImplementation((path) => {
|
|
312
|
+
if (path === "/api/v4/implementations/needs/") {
|
|
313
|
+
return Promise.resolve(mockNeedsWithOtherField);
|
|
314
|
+
}
|
|
315
|
+
else if (path === "/api/v4/implementations/choices/") {
|
|
316
|
+
return Promise.resolve(mockChoicesResponse);
|
|
317
|
+
}
|
|
318
|
+
return Promise.reject(new Error(`Unexpected endpoint: ${path}`));
|
|
319
|
+
});
|
|
320
|
+
mockApiClient.post = mockPost;
|
|
321
|
+
const sdk = createTestSdk();
|
|
322
|
+
await sdk.listInputFieldChoices({
|
|
323
|
+
appKey: "slack",
|
|
324
|
+
actionType: "read",
|
|
325
|
+
actionKey: "send_message",
|
|
326
|
+
inputFieldKey: "channel",
|
|
327
|
+
});
|
|
328
|
+
// Should call needs endpoint first
|
|
329
|
+
expect(mockApiClient.post).toHaveBeenCalledWith("/api/v4/implementations/needs/", expect.anything());
|
|
330
|
+
// Should call choices endpoint since field was not found in needs
|
|
331
|
+
expect(mockApiClient.post).toHaveBeenCalledWith("/api/v4/implementations/choices/", expect.anything());
|
|
332
|
+
});
|
|
333
|
+
});
|
|
158
334
|
describe("API integration - action method", () => {
|
|
159
335
|
it("should call the correct API endpoint with action method", async () => {
|
|
160
336
|
const sdk = createTestSdk();
|
|
@@ -439,12 +615,13 @@ describe("listInputFieldChoices plugin", () => {
|
|
|
439
615
|
actionKey: "send_message",
|
|
440
616
|
inputFieldKey: "invalid_field",
|
|
441
617
|
})).rejects.toThrow(ZapierApiError);
|
|
618
|
+
// Error comes from needs endpoint (first call) with user-friendly message
|
|
442
619
|
await expect(sdk.listInputFieldChoices({
|
|
443
620
|
appKey: "slack",
|
|
444
621
|
actionType: "read",
|
|
445
622
|
actionKey: "send_message",
|
|
446
623
|
inputFieldKey: "invalid_field",
|
|
447
|
-
})).rejects.toThrow("Failed to get input
|
|
624
|
+
})).rejects.toThrow("Failed to get input fields: Invalid field, Missing authentication");
|
|
448
625
|
});
|
|
449
626
|
it("should handle API errors gracefully", async () => {
|
|
450
627
|
mockApiClient.post = vi
|
|
@@ -497,7 +674,7 @@ describe("listInputFieldChoices plugin", () => {
|
|
|
497
674
|
actionType: "read",
|
|
498
675
|
actionKey: "send_message",
|
|
499
676
|
inputFieldKey: "channel",
|
|
500
|
-
})).rejects.toThrow("Failed to get input
|
|
677
|
+
})).rejects.toThrow("Failed to get input fields: Unknown error");
|
|
501
678
|
});
|
|
502
679
|
it("should handle API response with errors but no error messages", async () => {
|
|
503
680
|
mockApiClient.post = vi.fn().mockResolvedValue({
|
|
@@ -510,7 +687,7 @@ describe("listInputFieldChoices plugin", () => {
|
|
|
510
687
|
actionType: "read",
|
|
511
688
|
actionKey: "send_message",
|
|
512
689
|
inputFieldKey: "channel",
|
|
513
|
-
})).rejects.toThrow("Failed to get input
|
|
690
|
+
})).rejects.toThrow("Failed to get input fields: Unknown error");
|
|
514
691
|
});
|
|
515
692
|
it("should handle API response with empty errors array", async () => {
|
|
516
693
|
mockApiClient.post = vi.fn().mockResolvedValue({
|
|
@@ -523,7 +700,7 @@ describe("listInputFieldChoices plugin", () => {
|
|
|
523
700
|
actionType: "read",
|
|
524
701
|
actionKey: "send_message",
|
|
525
702
|
inputFieldKey: "channel",
|
|
526
|
-
})).rejects.toThrow("Failed to get input
|
|
703
|
+
})).rejects.toThrow("Failed to get input fields: Unknown error");
|
|
527
704
|
});
|
|
528
705
|
});
|
|
529
706
|
describe("context and metadata", () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/listInputFields/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,YAAY,EACZ,aAAa,EACd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,qBAAqB,EACrB,KAAK,sBAAsB,EAE5B,MAAM,WAAW,CAAC;AAGnB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/plugins/listInputFields/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAE3C,OAAO,KAAK,EACV,cAAc,EACd,aAAa,EACb,YAAY,EACZ,aAAa,EACd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,qBAAqB,EACrB,KAAK,sBAAsB,EAE5B,MAAM,WAAW,CAAC;AAGnB,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,cAAc,CAAC;AAC5D,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAC;AAoKxE,MAAM,WAAW,6BAA6B;IAC5C,eAAe,EAAE,CAAC,OAAO,CAAC,EAAE,sBAAsB,KAAK,OAAO,CAAC;QAC7D,IAAI,EAAE,aAAa,EAAE,CAAC;QACtB,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,CAAC,GACA,aAAa,CAAC;QAAE,IAAI,EAAE,aAAa,EAAE,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG;QAC9D,KAAK,IAAI,aAAa,CAAC,cAAc,GAAG,aAAa,GAAG,YAAY,CAAC,CAAC;KACvE,CAAC;IACJ,OAAO,EAAE;QACP,IAAI,EAAE;YACJ,eAAe,EAAE;gBACf,WAAW,EAAE,OAAO,qBAAqB,CAAC;aAC3C,CAAC;SACH,CAAC;KACH,CAAC;CACH;AAED,eAAO,MAAM,qBAAqB,EAAE,MAAM,CACxC,UAAU,CAAC,oBAAoB,GAAG,uBAAuB,CAAC,EAAE,uCAAuC;AACnG;IACE,GAAG,EAAE,SAAS,CAAC;IACf,4BAA4B,EAAE,4BAA4B,CAAC;CAC5D,EAAE,2DAA2D;AAC9D,6BAA6B,CA8E9B,CAAC"}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { ListInputFieldsSchema, } from "./schemas";
|
|
2
|
-
import { ZapierConfigurationError
|
|
2
|
+
import { ZapierConfigurationError } from "../../types/errors";
|
|
3
3
|
import { createPaginatedFunction } from "../../utils/function-utils";
|
|
4
4
|
import { appKeyResolver, actionTypeResolver, actionKeyResolver, authenticationIdResolver, inputsAllOptionalResolver, } from "../../resolvers";
|
|
5
5
|
import { RootFieldItemSchema } from "../../schemas/Field";
|
|
6
6
|
import { toTitleCase } from "../../utils/string-utils";
|
|
7
|
+
import { fetchImplementationNeeds } from "../../services/implementations";
|
|
7
8
|
// Enums for input field transformation
|
|
8
9
|
var InputFieldType;
|
|
9
10
|
(function (InputFieldType) {
|
|
@@ -147,7 +148,7 @@ export const listInputFieldsPlugin = ({ sdk, context }) => {
|
|
|
147
148
|
// Note: This function ignores pageSize and cursor since it's not actually paginated internally
|
|
148
149
|
const { api, getVersionedImplementationId } = context;
|
|
149
150
|
// Extract parameters
|
|
150
|
-
const { appKey, actionKey, actionType, authenticationId, inputs } = options;
|
|
151
|
+
const { appKey, actionKey, actionType, authenticationId = null, inputs, } = options;
|
|
151
152
|
// Use the manifest plugin
|
|
152
153
|
const selectedApi = await getVersionedImplementationId(appKey);
|
|
153
154
|
if (!selectedApi) {
|
|
@@ -158,21 +159,15 @@ export const listInputFieldsPlugin = ({ sdk, context }) => {
|
|
|
158
159
|
actionType,
|
|
159
160
|
actionKey,
|
|
160
161
|
});
|
|
161
|
-
//
|
|
162
|
-
const
|
|
163
|
-
|
|
162
|
+
// Use service layer to fetch implementation needs
|
|
163
|
+
const needsData = await fetchImplementationNeeds({
|
|
164
|
+
api,
|
|
165
|
+
selectedApi,
|
|
164
166
|
action: action.key,
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
if (authenticationId !== null) {
|
|
170
|
-
needsRequest.authentication_id = authenticationId;
|
|
171
|
-
}
|
|
172
|
-
const needsData = await api.post("/api/v4/implementations/needs/", needsRequest);
|
|
173
|
-
if (!needsData.success) {
|
|
174
|
-
throw new ZapierApiError(`Failed to get action fields: ${needsData.errors?.join(", ") || "Unknown error"}`);
|
|
175
|
-
}
|
|
167
|
+
actionType,
|
|
168
|
+
authenticationId,
|
|
169
|
+
inputs,
|
|
170
|
+
});
|
|
176
171
|
// Transform Need objects to Root Fieldset with proper nesting
|
|
177
172
|
const rootFieldset = transformNeedsToFields(needsData.needs || []);
|
|
178
173
|
return {
|
|
@@ -208,7 +208,7 @@ describe("listInputFields plugin", () => {
|
|
|
208
208
|
placeholder: "Enter your message",
|
|
209
209
|
default_value: "",
|
|
210
210
|
}));
|
|
211
|
-
// Check channel field with SELECT format
|
|
211
|
+
// Check channel field with SELECT format (choices should NOT be exposed)
|
|
212
212
|
expect(result.data[1]).toEqual(expect.objectContaining({
|
|
213
213
|
key: "channel",
|
|
214
214
|
title: "Channel",
|
|
@@ -217,6 +217,8 @@ describe("listInputFields plugin", () => {
|
|
|
217
217
|
value_type: "STRING",
|
|
218
218
|
format: "SELECT",
|
|
219
219
|
}));
|
|
220
|
+
// Verify choices are NOT exposed in listInputFields output
|
|
221
|
+
expect(result.data[1]).not.toHaveProperty("choices");
|
|
220
222
|
// Check array field
|
|
221
223
|
expect(result.data[2]).toEqual(expect.objectContaining({
|
|
222
224
|
key: "tags",
|
|
@@ -298,7 +300,7 @@ describe("listInputFields plugin", () => {
|
|
|
298
300
|
appKey: "slack",
|
|
299
301
|
actionType: "write",
|
|
300
302
|
actionKey: "send_message", // Use valid action so we get to the POST call
|
|
301
|
-
})).rejects.toThrow("Failed to get
|
|
303
|
+
})).rejects.toThrow("Failed to get input fields: Authentication failed, Invalid credentials");
|
|
302
304
|
});
|
|
303
305
|
it("should handle API errors gracefully", async () => {
|
|
304
306
|
mockApiClient.post = vi
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Implementation Services
|
|
3
|
+
*
|
|
4
|
+
* This module provides domain-specific service functions for interacting with
|
|
5
|
+
* the /api/v4/implementations/* endpoints. These services handle request building,
|
|
6
|
+
* validation, error handling, and authentication for implementation-related API calls.
|
|
7
|
+
*
|
|
8
|
+
* Services are consumed by plugins to avoid code duplication while maintaining
|
|
9
|
+
* separation between the generic HTTP client layer and business logic.
|
|
10
|
+
*/
|
|
11
|
+
import type { ApiClient } from "../api";
|
|
12
|
+
import type { NeedsResponse, NeedChoicesResponse } from "../api/types";
|
|
13
|
+
/**
|
|
14
|
+
* Fetches implementation needs (input fields) for a specific action.
|
|
15
|
+
*
|
|
16
|
+
* This service calls the /api/v4/implementations/needs/ endpoint and returns
|
|
17
|
+
* the raw response after validating success. The response includes all field
|
|
18
|
+
* metadata including static choices, field types, and validation rules.
|
|
19
|
+
*
|
|
20
|
+
* @param params - Request parameters
|
|
21
|
+
* @param params.api - API client instance
|
|
22
|
+
* @param params.selectedApi - Versioned implementation ID (e.g., "SlackCLIAPI@1.21.1")
|
|
23
|
+
* @param params.action - Action key
|
|
24
|
+
* @param params.actionType - Action type (read, write, etc.)
|
|
25
|
+
* @param params.authenticationId - Authentication ID (null to skip authentication)
|
|
26
|
+
* @param params.inputs - Input values that may affect available fields
|
|
27
|
+
* @returns Promise resolving to NeedsResponse
|
|
28
|
+
* @throws {ZapierApiError} When the API request fails or returns success: false
|
|
29
|
+
*/
|
|
30
|
+
export declare function fetchImplementationNeeds({ api, selectedApi, action, actionType, authenticationId, inputs, }: {
|
|
31
|
+
api: ApiClient;
|
|
32
|
+
selectedApi: string;
|
|
33
|
+
action: string;
|
|
34
|
+
actionType: string;
|
|
35
|
+
authenticationId: number | null;
|
|
36
|
+
inputs?: Record<string, unknown>;
|
|
37
|
+
}): Promise<NeedsResponse>;
|
|
38
|
+
/**
|
|
39
|
+
* Fetches dynamic choices for a specific input field.
|
|
40
|
+
*
|
|
41
|
+
* This service calls the /api/v4/implementations/choices/ endpoint and returns
|
|
42
|
+
* the raw response after validating success. The response includes available
|
|
43
|
+
* choices for dropdown fields with pagination support.
|
|
44
|
+
*
|
|
45
|
+
* @param params - Request parameters
|
|
46
|
+
* @param params.api - API client instance
|
|
47
|
+
* @param params.actionId - Action ID (e.g., "core:123")
|
|
48
|
+
* @param params.inputFieldId - Input field key
|
|
49
|
+
* @param params.authenticationId - Authentication ID (null to skip authentication)
|
|
50
|
+
* @param params.inputs - Input values that may affect available choices
|
|
51
|
+
* @param params.page - Page number for pagination (0-indexed)
|
|
52
|
+
* @returns Promise resolving to NeedChoicesResponse
|
|
53
|
+
* @throws {ZapierApiError} When the API request fails or returns success: false
|
|
54
|
+
*/
|
|
55
|
+
export declare function fetchImplementationChoices({ api, actionId, inputFieldId, authenticationId, inputs, page, }: {
|
|
56
|
+
api: ApiClient;
|
|
57
|
+
actionId: string;
|
|
58
|
+
inputFieldId: string;
|
|
59
|
+
authenticationId: number | null;
|
|
60
|
+
inputs?: Record<string, unknown>;
|
|
61
|
+
page: number;
|
|
62
|
+
}): Promise<NeedChoicesResponse>;
|
|
63
|
+
//# sourceMappingURL=implementations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"implementations.d.ts","sourceRoot":"","sources":["../../src/services/implementations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,QAAQ,CAAC;AACxC,OAAO,KAAK,EAEV,aAAa,EAEb,mBAAmB,EACpB,MAAM,cAAc,CAAC;AAGtB;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,wBAAwB,CAAC,EAC7C,GAAG,EACH,WAAW,EACX,MAAM,EACN,UAAU,EACV,gBAAgB,EAChB,MAAM,GACP,EAAE;IACD,GAAG,EAAE,SAAS,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,GAAG,OAAO,CAAC,aAAa,CAAC,CAyBzB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,0BAA0B,CAAC,EAC/C,GAAG,EACH,QAAQ,EACR,YAAY,EACZ,gBAAgB,EAChB,MAAM,EACN,IAAI,GACL,EAAE;IACD,GAAG,EAAE,SAAS,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAyB/B"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Implementation Services
|
|
3
|
+
*
|
|
4
|
+
* This module provides domain-specific service functions for interacting with
|
|
5
|
+
* the /api/v4/implementations/* endpoints. These services handle request building,
|
|
6
|
+
* validation, error handling, and authentication for implementation-related API calls.
|
|
7
|
+
*
|
|
8
|
+
* Services are consumed by plugins to avoid code duplication while maintaining
|
|
9
|
+
* separation between the generic HTTP client layer and business logic.
|
|
10
|
+
*/
|
|
11
|
+
import { ZapierApiError } from "../types/errors";
|
|
12
|
+
/**
|
|
13
|
+
* Fetches implementation needs (input fields) for a specific action.
|
|
14
|
+
*
|
|
15
|
+
* This service calls the /api/v4/implementations/needs/ endpoint and returns
|
|
16
|
+
* the raw response after validating success. The response includes all field
|
|
17
|
+
* metadata including static choices, field types, and validation rules.
|
|
18
|
+
*
|
|
19
|
+
* @param params - Request parameters
|
|
20
|
+
* @param params.api - API client instance
|
|
21
|
+
* @param params.selectedApi - Versioned implementation ID (e.g., "SlackCLIAPI@1.21.1")
|
|
22
|
+
* @param params.action - Action key
|
|
23
|
+
* @param params.actionType - Action type (read, write, etc.)
|
|
24
|
+
* @param params.authenticationId - Authentication ID (null to skip authentication)
|
|
25
|
+
* @param params.inputs - Input values that may affect available fields
|
|
26
|
+
* @returns Promise resolving to NeedsResponse
|
|
27
|
+
* @throws {ZapierApiError} When the API request fails or returns success: false
|
|
28
|
+
*/
|
|
29
|
+
export async function fetchImplementationNeeds({ api, selectedApi, action, actionType, authenticationId, inputs, }) {
|
|
30
|
+
const request = {
|
|
31
|
+
selected_api: selectedApi,
|
|
32
|
+
action,
|
|
33
|
+
type_of: actionType,
|
|
34
|
+
params: inputs || {},
|
|
35
|
+
};
|
|
36
|
+
// Only include authentication_id if it's not null (skip authentication when null)
|
|
37
|
+
if (authenticationId !== null) {
|
|
38
|
+
request.authentication_id = authenticationId;
|
|
39
|
+
}
|
|
40
|
+
const response = await api.post("/api/v4/implementations/needs/", request);
|
|
41
|
+
if (!response.success) {
|
|
42
|
+
throw new ZapierApiError(`Failed to get input fields: ${response.errors?.join(", ") || "Unknown error"}`);
|
|
43
|
+
}
|
|
44
|
+
return response;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Fetches dynamic choices for a specific input field.
|
|
48
|
+
*
|
|
49
|
+
* This service calls the /api/v4/implementations/choices/ endpoint and returns
|
|
50
|
+
* the raw response after validating success. The response includes available
|
|
51
|
+
* choices for dropdown fields with pagination support.
|
|
52
|
+
*
|
|
53
|
+
* @param params - Request parameters
|
|
54
|
+
* @param params.api - API client instance
|
|
55
|
+
* @param params.actionId - Action ID (e.g., "core:123")
|
|
56
|
+
* @param params.inputFieldId - Input field key
|
|
57
|
+
* @param params.authenticationId - Authentication ID (null to skip authentication)
|
|
58
|
+
* @param params.inputs - Input values that may affect available choices
|
|
59
|
+
* @param params.page - Page number for pagination (0-indexed)
|
|
60
|
+
* @returns Promise resolving to NeedChoicesResponse
|
|
61
|
+
* @throws {ZapierApiError} When the API request fails or returns success: false
|
|
62
|
+
*/
|
|
63
|
+
export async function fetchImplementationChoices({ api, actionId, inputFieldId, authenticationId, inputs, page, }) {
|
|
64
|
+
const request = {
|
|
65
|
+
action_id: actionId,
|
|
66
|
+
input_field_id: inputFieldId,
|
|
67
|
+
page,
|
|
68
|
+
params: inputs || {},
|
|
69
|
+
};
|
|
70
|
+
// Only include authentication_id if it's not null (skip authentication when null)
|
|
71
|
+
if (authenticationId !== null) {
|
|
72
|
+
request.authentication_id = authenticationId;
|
|
73
|
+
}
|
|
74
|
+
const response = await api.post("/api/v4/implementations/choices/", request);
|
|
75
|
+
if (!response.success) {
|
|
76
|
+
throw new ZapierApiError(`Failed to get input field choices: ${response.errors?.join(", ") || "Unknown error"}`);
|
|
77
|
+
}
|
|
78
|
+
return response;
|
|
79
|
+
}
|