@teamkeel/functions-runtime 0.427.0 → 0.429.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/index.cjs CHANGED
@@ -46,6 +46,7 @@ __export(index_exports, {
46
46
  RetryConstant: () => RetryConstant,
47
47
  STEP_STATUS: () => STEP_STATUS,
48
48
  STEP_TYPE: () => STEP_TYPE,
49
+ TaskAPI: () => TaskAPI,
49
50
  checkBuiltInPermissions: () => checkBuiltInPermissions,
50
51
  createFlowContext: () => createFlowContext,
51
52
  handleFlow: () => handleFlow,
@@ -848,24 +849,34 @@ async function storeFile(contents, key, filename, contentType, size, expires) {
848
849
  __name(storeFile, "storeFile");
849
850
 
850
851
  // src/parsing.js
852
+ var dateFormat = /^\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:?\d{2})?)?$/;
851
853
  function parseInputs(inputs) {
852
854
  if (inputs != null && typeof inputs === "object") {
853
855
  for (const k of Object.keys(inputs)) {
854
- if (inputs[k] !== null && typeof inputs[k] === "object") {
855
- if (Array.isArray(inputs[k])) {
856
- inputs[k] = inputs[k].map((item) => {
856
+ const value = inputs[k];
857
+ if (value === null) {
858
+ continue;
859
+ }
860
+ if (typeof value === "string" && dateFormat.test(value)) {
861
+ inputs[k] = new Date(value);
862
+ } else if (typeof value === "object") {
863
+ if (Array.isArray(value)) {
864
+ inputs[k] = value.map((item) => {
857
865
  if (item && typeof item === "object") {
858
866
  if ("__typename" in item) {
859
867
  return parseComplexInputType(item);
860
868
  }
861
869
  return parseInputs(item);
862
870
  }
871
+ if (typeof item === "string" && dateFormat.test(item)) {
872
+ return new Date(item);
873
+ }
863
874
  return item;
864
875
  });
865
- } else if ("__typename" in inputs[k]) {
866
- inputs[k] = parseComplexInputType(inputs[k]);
876
+ } else if ("__typename" in value) {
877
+ inputs[k] = parseComplexInputType(value);
867
878
  } else {
868
- inputs[k] = parseInputs(inputs[k]);
879
+ inputs[k] = parseInputs(value);
869
880
  }
870
881
  }
871
882
  }
@@ -1800,6 +1811,284 @@ async function create(conn, tableName, tableConfigs, values) {
1800
1811
  }
1801
1812
  __name(create, "create");
1802
1813
 
1814
+ // src/TaskAPI.js
1815
+ var import_jsonwebtoken = __toESM(require("jsonwebtoken"), 1);
1816
+ function buildHeaders(identity, authToken) {
1817
+ const headers = { "Content-Type": "application/json" };
1818
+ if (identity !== null) {
1819
+ const base64pk = process.env.KEEL_PRIVATE_KEY;
1820
+ let privateKey = void 0;
1821
+ if (base64pk) {
1822
+ privateKey = Buffer.from(base64pk, "base64").toString("utf8");
1823
+ }
1824
+ headers["Authorization"] = "Bearer " + import_jsonwebtoken.default.sign({}, privateKey, {
1825
+ algorithm: privateKey ? "RS256" : "none",
1826
+ expiresIn: 60 * 60 * 24,
1827
+ subject: identity.id,
1828
+ issuer: "https://keel.so"
1829
+ });
1830
+ }
1831
+ if (authToken !== null) {
1832
+ headers["Authorization"] = "Bearer " + authToken;
1833
+ }
1834
+ return headers;
1835
+ }
1836
+ __name(buildHeaders, "buildHeaders");
1837
+ function getApiUrl() {
1838
+ const apiUrl = process.env.KEEL_API_URL;
1839
+ if (!apiUrl) {
1840
+ throw new Error("KEEL_API_URL environment variable is not set");
1841
+ }
1842
+ return apiUrl;
1843
+ }
1844
+ __name(getApiUrl, "getApiUrl");
1845
+ var Task = class _Task {
1846
+ static {
1847
+ __name(this, "Task");
1848
+ }
1849
+ /**
1850
+ * @param {Object} data The task data from the API
1851
+ * @param {string} taskName The name of the task/topic
1852
+ * @param {Object|null} identity Optional identity object for authentication
1853
+ * @param {string|null} authToken Optional auth token for authentication
1854
+ */
1855
+ constructor(data, taskName, identity = null, authToken = null) {
1856
+ this.id = data.id;
1857
+ this.topic = data.name;
1858
+ this.status = data.status;
1859
+ this.deferredUntil = data.deferredUntil ? new Date(data.deferredUntil) : void 0;
1860
+ this.createdAt = new Date(data.createdAt);
1861
+ this.updatedAt = new Date(data.updatedAt);
1862
+ this.assignedTo = data.assignedTo;
1863
+ this.assignedAt = data.assignedAt ? new Date(data.assignedAt) : void 0;
1864
+ this.resolvedAt = data.resolvedAt ? new Date(data.resolvedAt) : void 0;
1865
+ this.flowRunId = data.flowRunId;
1866
+ this._taskName = taskName;
1867
+ this._identity = identity;
1868
+ this._authToken = authToken;
1869
+ }
1870
+ /**
1871
+ * Returns a new Task instance that will use the given identity for authentication.
1872
+ * @param {Object} identity The identity object
1873
+ * @returns {Task} A new Task instance with the identity set
1874
+ */
1875
+ withIdentity(identity) {
1876
+ const data = this._toApiData();
1877
+ return new _Task(data, this._taskName, identity, null);
1878
+ }
1879
+ /**
1880
+ * Returns a new Task instance that will use the given auth token for authentication.
1881
+ * @param {string} token The auth token to use
1882
+ * @returns {Task} A new Task instance with the auth token set
1883
+ */
1884
+ withAuthToken(token) {
1885
+ const data = this._toApiData();
1886
+ return new _Task(data, this._taskName, null, token);
1887
+ }
1888
+ /**
1889
+ * Converts the task back to API data format for creating new instances.
1890
+ * @returns {Object} The task data in API format
1891
+ */
1892
+ _toApiData() {
1893
+ return {
1894
+ id: this.id,
1895
+ name: this.topic,
1896
+ status: this.status,
1897
+ deferredUntil: this.deferredUntil?.toISOString(),
1898
+ createdAt: this.createdAt.toISOString(),
1899
+ updatedAt: this.updatedAt.toISOString(),
1900
+ assignedTo: this.assignedTo,
1901
+ assignedAt: this.assignedAt?.toISOString(),
1902
+ resolvedAt: this.resolvedAt?.toISOString(),
1903
+ flowRunId: this.flowRunId
1904
+ };
1905
+ }
1906
+ /**
1907
+ * Assigns the task to an identity.
1908
+ * @param {Object} options Options containing identityId
1909
+ * @param {string} options.identityId The ID of the identity to assign the task to
1910
+ * @returns {Promise<Task>} The updated task
1911
+ */
1912
+ async assign({ identityId }) {
1913
+ const name = spanNameForModelAPI(this._taskName, "assign");
1914
+ return withSpan(name, async () => {
1915
+ const apiUrl = getApiUrl();
1916
+ const url = `${apiUrl}/topics/json/${this._taskName}/tasks/${this.id}/assign`;
1917
+ const response = await fetch(url, {
1918
+ method: "PUT",
1919
+ headers: buildHeaders(this._identity, this._authToken),
1920
+ body: JSON.stringify({ assigned_to: identityId })
1921
+ });
1922
+ if (!response.ok) {
1923
+ const errorBody = await response.json().catch(() => ({}));
1924
+ throw new Error(
1925
+ `Failed to assign task: ${response.status} ${response.statusText} - ${errorBody.message || JSON.stringify(errorBody)}`
1926
+ );
1927
+ }
1928
+ const result = await response.json();
1929
+ return new _Task(result, this._taskName, this._identity, this._authToken);
1930
+ });
1931
+ }
1932
+ /**
1933
+ * Starts the task, creating and running the associated flow.
1934
+ * @returns {Promise<Task>} The updated task with flowRunId
1935
+ */
1936
+ async start() {
1937
+ const name = spanNameForModelAPI(this._taskName, "start");
1938
+ return withSpan(name, async () => {
1939
+ const apiUrl = getApiUrl();
1940
+ const url = `${apiUrl}/topics/json/${this._taskName}/tasks/${this.id}/start`;
1941
+ const response = await fetch(url, {
1942
+ method: "PUT",
1943
+ headers: buildHeaders(this._identity, this._authToken)
1944
+ });
1945
+ if (!response.ok) {
1946
+ const errorBody = await response.json().catch(() => ({}));
1947
+ throw new Error(
1948
+ `Failed to start task: ${response.status} ${response.statusText} - ${errorBody.message || JSON.stringify(errorBody)}`
1949
+ );
1950
+ }
1951
+ const result = await response.json();
1952
+ return new _Task(result, this._taskName, this._identity, this._authToken);
1953
+ });
1954
+ }
1955
+ /**
1956
+ * Completes the task.
1957
+ * @returns {Promise<Task>} The updated task
1958
+ */
1959
+ async complete() {
1960
+ const name = spanNameForModelAPI(this._taskName, "complete");
1961
+ return withSpan(name, async () => {
1962
+ const apiUrl = getApiUrl();
1963
+ const url = `${apiUrl}/topics/json/${this._taskName}/tasks/${this.id}/complete`;
1964
+ const response = await fetch(url, {
1965
+ method: "PUT",
1966
+ headers: buildHeaders(this._identity, this._authToken)
1967
+ });
1968
+ if (!response.ok) {
1969
+ const errorBody = await response.json().catch(() => ({}));
1970
+ throw new Error(
1971
+ `Failed to complete task: ${response.status} ${response.statusText} - ${errorBody.message || JSON.stringify(errorBody)}`
1972
+ );
1973
+ }
1974
+ const result = await response.json();
1975
+ return new _Task(result, this._taskName, this._identity, this._authToken);
1976
+ });
1977
+ }
1978
+ /**
1979
+ * Defers the task until a specified date.
1980
+ * @param {Object} options Options containing deferUntil
1981
+ * @param {Date} options.deferUntil The date to defer the task until
1982
+ * @returns {Promise<Task>} The updated task
1983
+ */
1984
+ async defer({ deferUntil }) {
1985
+ const name = spanNameForModelAPI(this._taskName, "defer");
1986
+ return withSpan(name, async () => {
1987
+ const apiUrl = getApiUrl();
1988
+ const url = `${apiUrl}/topics/json/${this._taskName}/tasks/${this.id}/defer`;
1989
+ const response = await fetch(url, {
1990
+ method: "PUT",
1991
+ headers: buildHeaders(this._identity, this._authToken),
1992
+ body: JSON.stringify({ defer_until: deferUntil.toISOString() })
1993
+ });
1994
+ if (!response.ok) {
1995
+ const errorBody = await response.json().catch(() => ({}));
1996
+ throw new Error(
1997
+ `Failed to defer task: ${response.status} ${response.statusText} - ${errorBody.message || JSON.stringify(errorBody)}`
1998
+ );
1999
+ }
2000
+ const result = await response.json();
2001
+ return new _Task(result, this._taskName, this._identity, this._authToken);
2002
+ });
2003
+ }
2004
+ /**
2005
+ * Cancels the task.
2006
+ * @returns {Promise<Task>} The updated task
2007
+ */
2008
+ async cancel() {
2009
+ const name = spanNameForModelAPI(this._taskName, "cancel");
2010
+ return withSpan(name, async () => {
2011
+ const apiUrl = getApiUrl();
2012
+ const url = `${apiUrl}/topics/json/${this._taskName}/tasks/${this.id}/cancel`;
2013
+ const response = await fetch(url, {
2014
+ method: "PUT",
2015
+ headers: buildHeaders(this._identity, this._authToken)
2016
+ });
2017
+ if (!response.ok) {
2018
+ const errorBody = await response.json().catch(() => ({}));
2019
+ throw new Error(
2020
+ `Failed to cancel task: ${response.status} ${response.statusText} - ${errorBody.message || JSON.stringify(errorBody)}`
2021
+ );
2022
+ }
2023
+ const result = await response.json();
2024
+ return new _Task(result, this._taskName, this._identity, this._authToken);
2025
+ });
2026
+ }
2027
+ };
2028
+ var TaskAPI = class _TaskAPI {
2029
+ static {
2030
+ __name(this, "TaskAPI");
2031
+ }
2032
+ /**
2033
+ * @param {string} taskName The name of the task/topic
2034
+ * @param {Object|null} identity Optional identity object for authentication
2035
+ * @param {string|null} authToken Optional auth token for authentication
2036
+ */
2037
+ constructor(taskName, identity = null, authToken = null) {
2038
+ this._taskName = taskName;
2039
+ this._identity = identity;
2040
+ this._authToken = authToken;
2041
+ }
2042
+ /**
2043
+ * Returns a new TaskAPI instance that will use the given identity for authentication.
2044
+ * @param {Object} identity The identity object
2045
+ * @returns {TaskAPI} A new TaskAPI instance with the identity set
2046
+ */
2047
+ withIdentity(identity) {
2048
+ return new _TaskAPI(this._taskName, identity, null);
2049
+ }
2050
+ /**
2051
+ * Returns a new TaskAPI instance that will use the given auth token for authentication.
2052
+ * @param {string} token The auth token to use
2053
+ * @returns {TaskAPI} A new TaskAPI instance with the auth token set
2054
+ */
2055
+ withAuthToken(token) {
2056
+ return new _TaskAPI(this._taskName, null, token);
2057
+ }
2058
+ /**
2059
+ * Creates a new task with the given data by calling the tasks API.
2060
+ * @param {Object} data The task data fields
2061
+ * @param {Object} options Optional settings like deferredUntil
2062
+ * @returns {Promise<Task>} The created task
2063
+ */
2064
+ async create(data = {}, options = {}) {
2065
+ const name = spanNameForModelAPI(this._taskName, "create");
2066
+ return withSpan(name, async () => {
2067
+ const apiUrl = getApiUrl();
2068
+ const url = `${apiUrl}/topics/json/${this._taskName}/tasks`;
2069
+ const body = {
2070
+ data
2071
+ };
2072
+ if (options.deferredUntil) {
2073
+ body.defer_until = options.deferredUntil.toISOString();
2074
+ }
2075
+ const response = await fetch(url, {
2076
+ method: "POST",
2077
+ headers: buildHeaders(this._identity, this._authToken),
2078
+ body: JSON.stringify(body)
2079
+ });
2080
+ if (!response.ok) {
2081
+ const errorBody = await response.json().catch(() => ({}));
2082
+ throw new Error(
2083
+ `Failed to create task: ${response.status} ${response.statusText} - ${errorBody.message || JSON.stringify(errorBody)}`
2084
+ );
2085
+ }
2086
+ const result = await response.json();
2087
+ return new Task(result, this._taskName, this._identity, this._authToken);
2088
+ });
2089
+ }
2090
+ };
2091
+
1803
2092
  // src/RequestHeaders.ts
1804
2093
  var RequestHeaders = class {
1805
2094
  /**
@@ -2978,7 +3267,8 @@ var print = /* @__PURE__ */ __name(async (options) => {
2978
3267
  description: options.description,
2979
3268
  data,
2980
3269
  autoPrint: options.autoPrint ?? false,
2981
- autoContinue: options.autoContinue ?? false
3270
+ autoContinue: options.autoContinue ?? false,
3271
+ allowReprint: options.allowReprint ?? true
2982
3272
  }
2983
3273
  };
2984
3274
  }, "print");
@@ -3591,6 +3881,7 @@ __name(ksuid, "ksuid");
3591
3881
  RetryConstant,
3592
3882
  STEP_STATUS,
3593
3883
  STEP_TYPE,
3884
+ TaskAPI,
3594
3885
  checkBuiltInPermissions,
3595
3886
  createFlowContext,
3596
3887
  handleFlow,