@fluxbase/sdk 0.0.1-rc.41 → 0.0.1-rc.43
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 +1360 -56
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1423 -70
- package/dist/index.d.ts +1423 -70
- package/dist/index.js +1357 -57
- package/dist/index.js.map +1 -1
- package/package.json +10 -1
package/dist/index.js
CHANGED
|
@@ -899,6 +899,7 @@ var RealtimeChannel = class {
|
|
|
899
899
|
this.presenceCallbacks = /* @__PURE__ */ new Map();
|
|
900
900
|
this.broadcastCallbacks = /* @__PURE__ */ new Map();
|
|
901
901
|
this.subscriptionConfig = null;
|
|
902
|
+
this.subscriptionId = null;
|
|
902
903
|
this._presenceState = {};
|
|
903
904
|
this.myPresenceKey = null;
|
|
904
905
|
this.reconnectAttempts = 0;
|
|
@@ -988,7 +989,8 @@ var RealtimeChannel = class {
|
|
|
988
989
|
if (this.ws) {
|
|
989
990
|
this.sendMessage({
|
|
990
991
|
type: "unsubscribe",
|
|
991
|
-
channel: this.channelName
|
|
992
|
+
channel: this.channelName,
|
|
993
|
+
subscription_id: this.subscriptionId || void 0
|
|
992
994
|
});
|
|
993
995
|
const startTime = Date.now();
|
|
994
996
|
const maxWait = timeout || 5e3;
|
|
@@ -1247,7 +1249,12 @@ var RealtimeChannel = class {
|
|
|
1247
1249
|
ackHandler.resolve(message.status || "ok");
|
|
1248
1250
|
}
|
|
1249
1251
|
} else {
|
|
1250
|
-
|
|
1252
|
+
if (message.payload && typeof message.payload === "object" && "subscription_id" in message.payload) {
|
|
1253
|
+
this.subscriptionId = message.payload.subscription_id;
|
|
1254
|
+
console.log("[Fluxbase Realtime] Subscription ID received:", this.subscriptionId);
|
|
1255
|
+
} else {
|
|
1256
|
+
console.log("[Fluxbase Realtime] Acknowledged:", message);
|
|
1257
|
+
}
|
|
1251
1258
|
}
|
|
1252
1259
|
break;
|
|
1253
1260
|
case "error":
|
|
@@ -1844,16 +1851,22 @@ var FluxbaseFunctions = class {
|
|
|
1844
1851
|
* This method is fully compatible with Supabase's functions.invoke() API.
|
|
1845
1852
|
*
|
|
1846
1853
|
* @param functionName - The name of the function to invoke
|
|
1847
|
-
* @param options - Invocation options including body, headers,
|
|
1854
|
+
* @param options - Invocation options including body, headers, HTTP method, and namespace
|
|
1848
1855
|
* @returns Promise resolving to { data, error } tuple
|
|
1849
1856
|
*
|
|
1850
1857
|
* @example
|
|
1851
1858
|
* ```typescript
|
|
1852
|
-
* // Simple invocation
|
|
1859
|
+
* // Simple invocation (uses first matching function by namespace alphabetically)
|
|
1853
1860
|
* const { data, error } = await client.functions.invoke('hello', {
|
|
1854
1861
|
* body: { name: 'World' }
|
|
1855
1862
|
* })
|
|
1856
1863
|
*
|
|
1864
|
+
* // Invoke a specific namespace's function
|
|
1865
|
+
* const { data, error } = await client.functions.invoke('hello', {
|
|
1866
|
+
* body: { name: 'World' },
|
|
1867
|
+
* namespace: 'my-app'
|
|
1868
|
+
* })
|
|
1869
|
+
*
|
|
1857
1870
|
* // With GET method
|
|
1858
1871
|
* const { data, error } = await client.functions.invoke('get-data', {
|
|
1859
1872
|
* method: 'GET'
|
|
@@ -1872,7 +1885,8 @@ var FluxbaseFunctions = class {
|
|
|
1872
1885
|
const method = options?.method || "POST";
|
|
1873
1886
|
const headers = options?.headers || {};
|
|
1874
1887
|
const body = options?.body;
|
|
1875
|
-
const
|
|
1888
|
+
const namespace = options?.namespace;
|
|
1889
|
+
const endpoint = namespace ? `/api/v1/functions/${functionName}/invoke?namespace=${encodeURIComponent(namespace)}` : `/api/v1/functions/${functionName}/invoke`;
|
|
1876
1890
|
let response;
|
|
1877
1891
|
switch (method) {
|
|
1878
1892
|
case "GET":
|
|
@@ -1898,136 +1912,209 @@ var FluxbaseFunctions = class {
|
|
|
1898
1912
|
}
|
|
1899
1913
|
}
|
|
1900
1914
|
/**
|
|
1901
|
-
*
|
|
1915
|
+
* List all public edge functions
|
|
1902
1916
|
*
|
|
1903
|
-
* @
|
|
1904
|
-
* @returns Promise resolving to { data, error } tuple with created function metadata
|
|
1917
|
+
* @returns Promise resolving to { data, error } tuple with array of public functions
|
|
1905
1918
|
*
|
|
1906
1919
|
* @example
|
|
1907
1920
|
* ```typescript
|
|
1908
|
-
* const { data, error } = await client.functions.
|
|
1909
|
-
*
|
|
1910
|
-
*
|
|
1911
|
-
*
|
|
1912
|
-
* })
|
|
1921
|
+
* const { data, error } = await client.functions.list()
|
|
1922
|
+
* if (data) {
|
|
1923
|
+
* console.log('Functions:', data.map(f => f.name))
|
|
1924
|
+
* }
|
|
1913
1925
|
* ```
|
|
1914
1926
|
*/
|
|
1915
|
-
async
|
|
1927
|
+
async list() {
|
|
1916
1928
|
try {
|
|
1917
|
-
const data = await this.fetch.
|
|
1929
|
+
const data = await this.fetch.get("/api/v1/functions");
|
|
1918
1930
|
return { data, error: null };
|
|
1919
1931
|
} catch (error) {
|
|
1920
1932
|
return { data: null, error };
|
|
1921
1933
|
}
|
|
1922
1934
|
}
|
|
1923
1935
|
/**
|
|
1924
|
-
*
|
|
1936
|
+
* Get details of a specific edge function
|
|
1925
1937
|
*
|
|
1926
|
-
* @
|
|
1938
|
+
* @param name - Function name
|
|
1939
|
+
* @returns Promise resolving to { data, error } tuple with function metadata
|
|
1927
1940
|
*
|
|
1928
1941
|
* @example
|
|
1929
1942
|
* ```typescript
|
|
1930
|
-
* const { data, error } = await client.functions.
|
|
1943
|
+
* const { data, error } = await client.functions.get('my-function')
|
|
1931
1944
|
* if (data) {
|
|
1932
|
-
* console.log('
|
|
1945
|
+
* console.log('Function version:', data.version)
|
|
1933
1946
|
* }
|
|
1934
1947
|
* ```
|
|
1935
1948
|
*/
|
|
1936
|
-
async
|
|
1949
|
+
async get(name) {
|
|
1937
1950
|
try {
|
|
1938
|
-
const data = await this.fetch.get(
|
|
1951
|
+
const data = await this.fetch.get(`/api/v1/functions/${name}`);
|
|
1939
1952
|
return { data, error: null };
|
|
1940
1953
|
} catch (error) {
|
|
1941
1954
|
return { data: null, error };
|
|
1942
1955
|
}
|
|
1943
1956
|
}
|
|
1957
|
+
};
|
|
1958
|
+
|
|
1959
|
+
// src/jobs.ts
|
|
1960
|
+
var FluxbaseJobs = class {
|
|
1961
|
+
constructor(fetch2) {
|
|
1962
|
+
this.fetch = fetch2;
|
|
1963
|
+
}
|
|
1944
1964
|
/**
|
|
1945
|
-
*
|
|
1965
|
+
* Submit a new job for execution
|
|
1946
1966
|
*
|
|
1947
|
-
* @param
|
|
1948
|
-
* @
|
|
1967
|
+
* @param jobName - Name of the job function to execute
|
|
1968
|
+
* @param payload - Job input data
|
|
1969
|
+
* @param options - Additional options (priority, namespace, scheduled time)
|
|
1970
|
+
* @returns Promise resolving to { data, error } tuple with submitted job details
|
|
1949
1971
|
*
|
|
1950
1972
|
* @example
|
|
1951
1973
|
* ```typescript
|
|
1952
|
-
*
|
|
1974
|
+
* // Submit a simple job
|
|
1975
|
+
* const { data, error } = await client.jobs.submit('send-email', {
|
|
1976
|
+
* to: 'user@example.com',
|
|
1977
|
+
* subject: 'Hello',
|
|
1978
|
+
* body: 'Welcome!'
|
|
1979
|
+
* })
|
|
1980
|
+
*
|
|
1953
1981
|
* if (data) {
|
|
1954
|
-
* console.log('
|
|
1982
|
+
* console.log('Job submitted:', data.id)
|
|
1983
|
+
* console.log('Status:', data.status)
|
|
1955
1984
|
* }
|
|
1985
|
+
*
|
|
1986
|
+
* // Submit with priority
|
|
1987
|
+
* const { data } = await client.jobs.submit('high-priority-task', payload, {
|
|
1988
|
+
* priority: 10
|
|
1989
|
+
* })
|
|
1990
|
+
*
|
|
1991
|
+
* // Schedule for later
|
|
1992
|
+
* const { data } = await client.jobs.submit('scheduled-task', payload, {
|
|
1993
|
+
* scheduled: '2025-01-01T00:00:00Z'
|
|
1994
|
+
* })
|
|
1956
1995
|
* ```
|
|
1957
1996
|
*/
|
|
1958
|
-
async
|
|
1997
|
+
async submit(jobName, payload, options) {
|
|
1959
1998
|
try {
|
|
1960
|
-
const
|
|
1999
|
+
const request = {
|
|
2000
|
+
job_name: jobName,
|
|
2001
|
+
payload,
|
|
2002
|
+
...options
|
|
2003
|
+
};
|
|
2004
|
+
const data = await this.fetch.post("/api/v1/jobs/submit", request);
|
|
1961
2005
|
return { data, error: null };
|
|
1962
2006
|
} catch (error) {
|
|
1963
2007
|
return { data: null, error };
|
|
1964
2008
|
}
|
|
1965
2009
|
}
|
|
1966
2010
|
/**
|
|
1967
|
-
*
|
|
2011
|
+
* Get status and details of a specific job
|
|
1968
2012
|
*
|
|
1969
|
-
* @param
|
|
1970
|
-
* @
|
|
1971
|
-
* @returns Promise resolving to { data, error } tuple with updated function metadata
|
|
2013
|
+
* @param jobId - Job ID
|
|
2014
|
+
* @returns Promise resolving to { data, error } tuple with job details
|
|
1972
2015
|
*
|
|
1973
2016
|
* @example
|
|
1974
2017
|
* ```typescript
|
|
1975
|
-
* const { data, error } = await client.
|
|
1976
|
-
*
|
|
1977
|
-
*
|
|
2018
|
+
* const { data: job, error } = await client.jobs.get('550e8400-e29b-41d4-a716-446655440000')
|
|
2019
|
+
*
|
|
2020
|
+
* if (job) {
|
|
2021
|
+
* console.log('Status:', job.status)
|
|
2022
|
+
* console.log('Progress:', job.progress_percent + '%')
|
|
2023
|
+
* console.log('Result:', job.result)
|
|
2024
|
+
* console.log('Logs:', job.logs)
|
|
2025
|
+
* }
|
|
2026
|
+
* ```
|
|
2027
|
+
*/
|
|
2028
|
+
async get(jobId) {
|
|
2029
|
+
try {
|
|
2030
|
+
const data = await this.fetch.get(`/api/v1/jobs/${jobId}`);
|
|
2031
|
+
return { data, error: null };
|
|
2032
|
+
} catch (error) {
|
|
2033
|
+
return { data: null, error };
|
|
2034
|
+
}
|
|
2035
|
+
}
|
|
2036
|
+
/**
|
|
2037
|
+
* List jobs submitted by the current user
|
|
2038
|
+
*
|
|
2039
|
+
* @param filters - Optional filters (status, namespace, limit, offset)
|
|
2040
|
+
* @returns Promise resolving to { data, error } tuple with array of jobs
|
|
2041
|
+
*
|
|
2042
|
+
* @example
|
|
2043
|
+
* ```typescript
|
|
2044
|
+
* // List all your jobs
|
|
2045
|
+
* const { data: jobs, error } = await client.jobs.list()
|
|
2046
|
+
*
|
|
2047
|
+
* // Filter by status
|
|
2048
|
+
* const { data: running } = await client.jobs.list({
|
|
2049
|
+
* status: 'running'
|
|
2050
|
+
* })
|
|
2051
|
+
*
|
|
2052
|
+
* // Paginate
|
|
2053
|
+
* const { data: page } = await client.jobs.list({
|
|
2054
|
+
* limit: 20,
|
|
2055
|
+
* offset: 40
|
|
1978
2056
|
* })
|
|
1979
2057
|
* ```
|
|
1980
2058
|
*/
|
|
1981
|
-
async
|
|
2059
|
+
async list(filters) {
|
|
1982
2060
|
try {
|
|
1983
|
-
const
|
|
2061
|
+
const params = new URLSearchParams();
|
|
2062
|
+
if (filters?.status) params.append("status", filters.status);
|
|
2063
|
+
if (filters?.namespace) params.append("namespace", filters.namespace);
|
|
2064
|
+
if (filters?.limit) params.append("limit", filters.limit.toString());
|
|
2065
|
+
if (filters?.offset) params.append("offset", filters.offset.toString());
|
|
2066
|
+
const queryString = params.toString();
|
|
2067
|
+
const data = await this.fetch.get(
|
|
2068
|
+
`/api/v1/jobs${queryString ? `?${queryString}` : ""}`
|
|
2069
|
+
);
|
|
1984
2070
|
return { data, error: null };
|
|
1985
2071
|
} catch (error) {
|
|
1986
2072
|
return { data: null, error };
|
|
1987
2073
|
}
|
|
1988
2074
|
}
|
|
1989
2075
|
/**
|
|
1990
|
-
*
|
|
2076
|
+
* Cancel a pending or running job
|
|
1991
2077
|
*
|
|
1992
|
-
* @param
|
|
2078
|
+
* @param jobId - Job ID to cancel
|
|
1993
2079
|
* @returns Promise resolving to { data, error } tuple
|
|
1994
2080
|
*
|
|
1995
2081
|
* @example
|
|
1996
2082
|
* ```typescript
|
|
1997
|
-
* const {
|
|
2083
|
+
* const { error } = await client.jobs.cancel('550e8400-e29b-41d4-a716-446655440000')
|
|
2084
|
+
*
|
|
2085
|
+
* if (!error) {
|
|
2086
|
+
* console.log('Job cancelled successfully')
|
|
2087
|
+
* }
|
|
1998
2088
|
* ```
|
|
1999
2089
|
*/
|
|
2000
|
-
async
|
|
2090
|
+
async cancel(jobId) {
|
|
2001
2091
|
try {
|
|
2002
|
-
await this.fetch.
|
|
2092
|
+
await this.fetch.post(`/api/v1/jobs/${jobId}/cancel`, {});
|
|
2003
2093
|
return { data: null, error: null };
|
|
2004
2094
|
} catch (error) {
|
|
2005
2095
|
return { data: null, error };
|
|
2006
2096
|
}
|
|
2007
2097
|
}
|
|
2008
2098
|
/**
|
|
2009
|
-
*
|
|
2099
|
+
* Retry a failed job
|
|
2010
2100
|
*
|
|
2011
|
-
*
|
|
2012
|
-
*
|
|
2013
|
-
* @
|
|
2101
|
+
* Creates a new job execution with the same parameters
|
|
2102
|
+
*
|
|
2103
|
+
* @param jobId - Job ID to retry
|
|
2104
|
+
* @returns Promise resolving to { data, error } tuple with new job
|
|
2014
2105
|
*
|
|
2015
2106
|
* @example
|
|
2016
2107
|
* ```typescript
|
|
2017
|
-
* const { data, error } = await client.
|
|
2018
|
-
*
|
|
2019
|
-
*
|
|
2020
|
-
*
|
|
2021
|
-
* })
|
|
2108
|
+
* const { data: newJob, error } = await client.jobs.retry('550e8400-e29b-41d4-a716-446655440000')
|
|
2109
|
+
*
|
|
2110
|
+
* if (newJob) {
|
|
2111
|
+
* console.log('Job retried, new ID:', newJob.id)
|
|
2022
2112
|
* }
|
|
2023
2113
|
* ```
|
|
2024
2114
|
*/
|
|
2025
|
-
async
|
|
2115
|
+
async retry(jobId) {
|
|
2026
2116
|
try {
|
|
2027
|
-
const
|
|
2028
|
-
const data = await this.fetch.get(
|
|
2029
|
-
`/api/v1/functions/${name}/executions${params}`
|
|
2030
|
-
);
|
|
2117
|
+
const data = await this.fetch.post(`/api/v1/jobs/${jobId}/retry`, {});
|
|
2031
2118
|
return { data, error: null };
|
|
2032
2119
|
} catch (error) {
|
|
2033
2120
|
return { data: null, error };
|
|
@@ -3852,6 +3939,1215 @@ var FluxbaseManagement = class {
|
|
|
3852
3939
|
}
|
|
3853
3940
|
};
|
|
3854
3941
|
|
|
3942
|
+
// src/admin-functions.ts
|
|
3943
|
+
var FluxbaseAdminFunctions = class {
|
|
3944
|
+
constructor(fetch2) {
|
|
3945
|
+
this.fetch = fetch2;
|
|
3946
|
+
}
|
|
3947
|
+
/**
|
|
3948
|
+
* Create a new edge function
|
|
3949
|
+
*
|
|
3950
|
+
* @param request - Function configuration and code
|
|
3951
|
+
* @returns Promise resolving to { data, error } tuple with created function metadata
|
|
3952
|
+
*
|
|
3953
|
+
* @example
|
|
3954
|
+
* ```typescript
|
|
3955
|
+
* const { data, error } = await client.admin.functions.create({
|
|
3956
|
+
* name: 'my-function',
|
|
3957
|
+
* code: 'export default async function handler(req) { return { hello: "world" } }',
|
|
3958
|
+
* enabled: true
|
|
3959
|
+
* })
|
|
3960
|
+
* ```
|
|
3961
|
+
*/
|
|
3962
|
+
async create(request) {
|
|
3963
|
+
try {
|
|
3964
|
+
const data = await this.fetch.post(
|
|
3965
|
+
"/api/v1/functions",
|
|
3966
|
+
request
|
|
3967
|
+
);
|
|
3968
|
+
return { data, error: null };
|
|
3969
|
+
} catch (error) {
|
|
3970
|
+
return { data: null, error };
|
|
3971
|
+
}
|
|
3972
|
+
}
|
|
3973
|
+
/**
|
|
3974
|
+
* List all namespaces that have edge functions
|
|
3975
|
+
*
|
|
3976
|
+
* @returns Promise resolving to { data, error } tuple with array of namespace strings
|
|
3977
|
+
*
|
|
3978
|
+
* @example
|
|
3979
|
+
* ```typescript
|
|
3980
|
+
* const { data, error } = await client.admin.functions.listNamespaces()
|
|
3981
|
+
* if (data) {
|
|
3982
|
+
* console.log('Available namespaces:', data)
|
|
3983
|
+
* }
|
|
3984
|
+
* ```
|
|
3985
|
+
*/
|
|
3986
|
+
async listNamespaces() {
|
|
3987
|
+
try {
|
|
3988
|
+
const response = await this.fetch.get(
|
|
3989
|
+
"/api/v1/admin/functions/namespaces"
|
|
3990
|
+
);
|
|
3991
|
+
return { data: response.namespaces || ["default"], error: null };
|
|
3992
|
+
} catch (error) {
|
|
3993
|
+
return { data: null, error };
|
|
3994
|
+
}
|
|
3995
|
+
}
|
|
3996
|
+
/**
|
|
3997
|
+
* List all edge functions (admin view)
|
|
3998
|
+
*
|
|
3999
|
+
* @param namespace - Optional namespace filter (if not provided, lists all public functions)
|
|
4000
|
+
* @returns Promise resolving to { data, error } tuple with array of functions
|
|
4001
|
+
*
|
|
4002
|
+
* @example
|
|
4003
|
+
* ```typescript
|
|
4004
|
+
* // List all public functions
|
|
4005
|
+
* const { data, error } = await client.admin.functions.list()
|
|
4006
|
+
*
|
|
4007
|
+
* // List functions in a specific namespace
|
|
4008
|
+
* const { data, error } = await client.admin.functions.list('my-namespace')
|
|
4009
|
+
* if (data) {
|
|
4010
|
+
* console.log('Functions:', data.map(f => f.name))
|
|
4011
|
+
* }
|
|
4012
|
+
* ```
|
|
4013
|
+
*/
|
|
4014
|
+
async list(namespace) {
|
|
4015
|
+
try {
|
|
4016
|
+
const params = namespace ? `?namespace=${namespace}` : "";
|
|
4017
|
+
const data = await this.fetch.get(
|
|
4018
|
+
`/api/v1/functions${params}`
|
|
4019
|
+
);
|
|
4020
|
+
return { data, error: null };
|
|
4021
|
+
} catch (error) {
|
|
4022
|
+
return { data: null, error };
|
|
4023
|
+
}
|
|
4024
|
+
}
|
|
4025
|
+
/**
|
|
4026
|
+
* Get details of a specific edge function
|
|
4027
|
+
*
|
|
4028
|
+
* @param name - Function name
|
|
4029
|
+
* @returns Promise resolving to { data, error } tuple with function metadata
|
|
4030
|
+
*
|
|
4031
|
+
* @example
|
|
4032
|
+
* ```typescript
|
|
4033
|
+
* const { data, error } = await client.admin.functions.get('my-function')
|
|
4034
|
+
* if (data) {
|
|
4035
|
+
* console.log('Function version:', data.version)
|
|
4036
|
+
* }
|
|
4037
|
+
* ```
|
|
4038
|
+
*/
|
|
4039
|
+
async get(name) {
|
|
4040
|
+
try {
|
|
4041
|
+
const data = await this.fetch.get(
|
|
4042
|
+
`/api/v1/functions/${name}`
|
|
4043
|
+
);
|
|
4044
|
+
return { data, error: null };
|
|
4045
|
+
} catch (error) {
|
|
4046
|
+
return { data: null, error };
|
|
4047
|
+
}
|
|
4048
|
+
}
|
|
4049
|
+
/**
|
|
4050
|
+
* Update an existing edge function
|
|
4051
|
+
*
|
|
4052
|
+
* @param name - Function name
|
|
4053
|
+
* @param updates - Fields to update
|
|
4054
|
+
* @returns Promise resolving to { data, error } tuple with updated function metadata
|
|
4055
|
+
*
|
|
4056
|
+
* @example
|
|
4057
|
+
* ```typescript
|
|
4058
|
+
* const { data, error } = await client.admin.functions.update('my-function', {
|
|
4059
|
+
* enabled: false,
|
|
4060
|
+
* description: 'Updated description'
|
|
4061
|
+
* })
|
|
4062
|
+
* ```
|
|
4063
|
+
*/
|
|
4064
|
+
async update(name, updates) {
|
|
4065
|
+
try {
|
|
4066
|
+
const data = await this.fetch.put(
|
|
4067
|
+
`/api/v1/functions/${name}`,
|
|
4068
|
+
updates
|
|
4069
|
+
);
|
|
4070
|
+
return { data, error: null };
|
|
4071
|
+
} catch (error) {
|
|
4072
|
+
return { data: null, error };
|
|
4073
|
+
}
|
|
4074
|
+
}
|
|
4075
|
+
/**
|
|
4076
|
+
* Delete an edge function
|
|
4077
|
+
*
|
|
4078
|
+
* @param name - Function name
|
|
4079
|
+
* @returns Promise resolving to { data, error } tuple
|
|
4080
|
+
*
|
|
4081
|
+
* @example
|
|
4082
|
+
* ```typescript
|
|
4083
|
+
* const { data, error } = await client.admin.functions.delete('my-function')
|
|
4084
|
+
* ```
|
|
4085
|
+
*/
|
|
4086
|
+
async delete(name) {
|
|
4087
|
+
try {
|
|
4088
|
+
await this.fetch.delete(`/api/v1/functions/${name}`);
|
|
4089
|
+
return { data: null, error: null };
|
|
4090
|
+
} catch (error) {
|
|
4091
|
+
return { data: null, error };
|
|
4092
|
+
}
|
|
4093
|
+
}
|
|
4094
|
+
/**
|
|
4095
|
+
* Get execution history for an edge function
|
|
4096
|
+
*
|
|
4097
|
+
* @param name - Function name
|
|
4098
|
+
* @param limit - Maximum number of executions to return (optional)
|
|
4099
|
+
* @returns Promise resolving to { data, error } tuple with execution records
|
|
4100
|
+
*
|
|
4101
|
+
* @example
|
|
4102
|
+
* ```typescript
|
|
4103
|
+
* const { data, error } = await client.admin.functions.getExecutions('my-function', 10)
|
|
4104
|
+
* if (data) {
|
|
4105
|
+
* data.forEach(exec => {
|
|
4106
|
+
* console.log(`${exec.executed_at}: ${exec.status} (${exec.duration_ms}ms)`)
|
|
4107
|
+
* })
|
|
4108
|
+
* }
|
|
4109
|
+
* ```
|
|
4110
|
+
*/
|
|
4111
|
+
async getExecutions(name, limit) {
|
|
4112
|
+
try {
|
|
4113
|
+
const params = limit ? `?limit=${limit}` : "";
|
|
4114
|
+
const data = await this.fetch.get(
|
|
4115
|
+
`/api/v1/functions/${name}/executions${params}`
|
|
4116
|
+
);
|
|
4117
|
+
return { data, error: null };
|
|
4118
|
+
} catch (error) {
|
|
4119
|
+
return { data: null, error };
|
|
4120
|
+
}
|
|
4121
|
+
}
|
|
4122
|
+
/**
|
|
4123
|
+
* Sync multiple functions to a namespace
|
|
4124
|
+
*
|
|
4125
|
+
* Bulk create/update/delete functions in a specific namespace. This is useful for
|
|
4126
|
+
* deploying functions from your application to Fluxbase in Kubernetes or other
|
|
4127
|
+
* container environments.
|
|
4128
|
+
*
|
|
4129
|
+
* Requires service_role or admin authentication.
|
|
4130
|
+
*
|
|
4131
|
+
* @param options - Sync configuration including namespace, functions, and options
|
|
4132
|
+
* @returns Promise resolving to { data, error } tuple with sync results
|
|
4133
|
+
*
|
|
4134
|
+
* @example
|
|
4135
|
+
* ```typescript
|
|
4136
|
+
* // Sync functions to "payment-service" namespace
|
|
4137
|
+
* const { data, error } = await client.admin.functions.sync({
|
|
4138
|
+
* namespace: 'payment-service',
|
|
4139
|
+
* functions: [
|
|
4140
|
+
* {
|
|
4141
|
+
* name: 'process-payment',
|
|
4142
|
+
* code: 'export default async function handler(req) { ... }',
|
|
4143
|
+
* enabled: true,
|
|
4144
|
+
* allow_net: true
|
|
4145
|
+
* },
|
|
4146
|
+
* {
|
|
4147
|
+
* name: 'refund-payment',
|
|
4148
|
+
* code: 'export default async function handler(req) { ... }',
|
|
4149
|
+
* enabled: true
|
|
4150
|
+
* }
|
|
4151
|
+
* ],
|
|
4152
|
+
* options: {
|
|
4153
|
+
* delete_missing: true // Remove functions not in this list
|
|
4154
|
+
* }
|
|
4155
|
+
* })
|
|
4156
|
+
*
|
|
4157
|
+
* if (data) {
|
|
4158
|
+
* console.log(`Synced: ${data.summary.created} created, ${data.summary.updated} updated`)
|
|
4159
|
+
* }
|
|
4160
|
+
*
|
|
4161
|
+
* // Dry run to preview changes
|
|
4162
|
+
* const { data, error } = await client.admin.functions.sync({
|
|
4163
|
+
* namespace: 'myapp',
|
|
4164
|
+
* functions: [...],
|
|
4165
|
+
* options: { dry_run: true }
|
|
4166
|
+
* })
|
|
4167
|
+
* ```
|
|
4168
|
+
*/
|
|
4169
|
+
async sync(options) {
|
|
4170
|
+
try {
|
|
4171
|
+
const data = await this.fetch.post(
|
|
4172
|
+
"/api/v1/admin/functions/sync",
|
|
4173
|
+
options
|
|
4174
|
+
);
|
|
4175
|
+
return { data, error: null };
|
|
4176
|
+
} catch (error) {
|
|
4177
|
+
return { data: null, error };
|
|
4178
|
+
}
|
|
4179
|
+
}
|
|
4180
|
+
};
|
|
4181
|
+
|
|
4182
|
+
// src/admin-migrations.ts
|
|
4183
|
+
var FluxbaseAdminMigrations = class {
|
|
4184
|
+
constructor(fetch2) {
|
|
4185
|
+
this.localMigrations = /* @__PURE__ */ new Map();
|
|
4186
|
+
this.fetch = fetch2;
|
|
4187
|
+
}
|
|
4188
|
+
/**
|
|
4189
|
+
* Register a migration locally for smart sync
|
|
4190
|
+
*
|
|
4191
|
+
* Call this method to register migrations in your application code.
|
|
4192
|
+
* When you call sync(), only new or changed migrations will be sent to the server.
|
|
4193
|
+
*
|
|
4194
|
+
* @param migration - Migration definition
|
|
4195
|
+
* @returns { error } tuple (always succeeds unless validation fails)
|
|
4196
|
+
*
|
|
4197
|
+
* @example
|
|
4198
|
+
* ```typescript
|
|
4199
|
+
* // In your app initialization
|
|
4200
|
+
* const { error: err1 } = client.admin.migrations.register({
|
|
4201
|
+
* name: '001_create_users_table',
|
|
4202
|
+
* namespace: 'myapp',
|
|
4203
|
+
* up_sql: 'CREATE TABLE app.users (...)',
|
|
4204
|
+
* down_sql: 'DROP TABLE app.users',
|
|
4205
|
+
* description: 'Initial users table'
|
|
4206
|
+
* })
|
|
4207
|
+
*
|
|
4208
|
+
* const { error: err2 } = client.admin.migrations.register({
|
|
4209
|
+
* name: '002_add_posts_table',
|
|
4210
|
+
* namespace: 'myapp',
|
|
4211
|
+
* up_sql: 'CREATE TABLE app.posts (...)',
|
|
4212
|
+
* down_sql: 'DROP TABLE app.posts'
|
|
4213
|
+
* })
|
|
4214
|
+
*
|
|
4215
|
+
* // Sync all registered migrations
|
|
4216
|
+
* await client.admin.migrations.sync()
|
|
4217
|
+
* ```
|
|
4218
|
+
*/
|
|
4219
|
+
register(migration) {
|
|
4220
|
+
try {
|
|
4221
|
+
if (!migration.name || !migration.up_sql) {
|
|
4222
|
+
return {
|
|
4223
|
+
error: new Error("Migration name and up_sql are required")
|
|
4224
|
+
};
|
|
4225
|
+
}
|
|
4226
|
+
const key = `${migration.namespace || "default"}:${migration.name}`;
|
|
4227
|
+
this.localMigrations.set(key, migration);
|
|
4228
|
+
return { error: null };
|
|
4229
|
+
} catch (error) {
|
|
4230
|
+
return { error };
|
|
4231
|
+
}
|
|
4232
|
+
}
|
|
4233
|
+
/**
|
|
4234
|
+
* Trigger schema refresh which will restart the server
|
|
4235
|
+
* Handles the restart gracefully by waiting for the server to come back online
|
|
4236
|
+
*
|
|
4237
|
+
* @private
|
|
4238
|
+
*/
|
|
4239
|
+
async triggerSchemaRefreshWithRestart() {
|
|
4240
|
+
console.log("Triggering schema refresh (server will restart)...");
|
|
4241
|
+
try {
|
|
4242
|
+
const response = await this.fetch.post(
|
|
4243
|
+
"/api/v1/admin/schema/refresh",
|
|
4244
|
+
{}
|
|
4245
|
+
);
|
|
4246
|
+
console.log("Server restart initiated:", response.message || "Schema refresh in progress");
|
|
4247
|
+
} catch (error) {
|
|
4248
|
+
const isConnectionError = error.message?.includes("fetch failed") || error.message?.includes("ECONNREFUSED") || error.message?.includes("ECONNRESET") || error.code === "ECONNREFUSED" || error.code === "ECONNRESET";
|
|
4249
|
+
if (!isConnectionError) {
|
|
4250
|
+
throw error;
|
|
4251
|
+
}
|
|
4252
|
+
console.log("Connection dropped (expected during restart)...");
|
|
4253
|
+
}
|
|
4254
|
+
console.log("Waiting 6 seconds for server to restart...");
|
|
4255
|
+
await this.sleep(6e3);
|
|
4256
|
+
const maxAttempts = 5;
|
|
4257
|
+
const baseDelay = 1e3;
|
|
4258
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
|
|
4259
|
+
try {
|
|
4260
|
+
await this.fetch.get("/health");
|
|
4261
|
+
console.log("Server is back online and ready");
|
|
4262
|
+
return;
|
|
4263
|
+
} catch (error) {
|
|
4264
|
+
const isLastAttempt = attempt === maxAttempts;
|
|
4265
|
+
if (isLastAttempt) {
|
|
4266
|
+
throw new Error(
|
|
4267
|
+
`Server did not come back online after ${maxAttempts} attempts. Please check server logs and try again.`
|
|
4268
|
+
);
|
|
4269
|
+
}
|
|
4270
|
+
const delay = baseDelay * Math.pow(2, attempt - 1);
|
|
4271
|
+
console.log(`Server not ready yet, retrying in ${delay}ms... (attempt ${attempt}/${maxAttempts})`);
|
|
4272
|
+
await this.sleep(delay);
|
|
4273
|
+
}
|
|
4274
|
+
}
|
|
4275
|
+
}
|
|
4276
|
+
/**
|
|
4277
|
+
* Helper function to sleep for a given duration
|
|
4278
|
+
* @private
|
|
4279
|
+
*/
|
|
4280
|
+
sleep(ms) {
|
|
4281
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
4282
|
+
}
|
|
4283
|
+
/**
|
|
4284
|
+
* Smart sync all registered migrations
|
|
4285
|
+
*
|
|
4286
|
+
* Automatically determines which migrations need to be created or updated by:
|
|
4287
|
+
* 1. Fetching existing migrations from the server
|
|
4288
|
+
* 2. Comparing content hashes to detect changes
|
|
4289
|
+
* 3. Only sending new or changed migrations
|
|
4290
|
+
*
|
|
4291
|
+
* After successful sync, can optionally auto-apply new migrations and refresh
|
|
4292
|
+
* the server's schema cache.
|
|
4293
|
+
*
|
|
4294
|
+
* @param options - Sync options
|
|
4295
|
+
* @returns Promise resolving to { data, error } tuple with sync results
|
|
4296
|
+
*
|
|
4297
|
+
* @example
|
|
4298
|
+
* ```typescript
|
|
4299
|
+
* // Basic sync (idempotent - safe to call on every app startup)
|
|
4300
|
+
* const { data, error } = await client.admin.migrations.sync()
|
|
4301
|
+
* if (data) {
|
|
4302
|
+
* console.log(`Created: ${data.summary.created}, Updated: ${data.summary.updated}`)
|
|
4303
|
+
* }
|
|
4304
|
+
*
|
|
4305
|
+
* // Sync with auto-apply (applies new migrations automatically)
|
|
4306
|
+
* const { data, error } = await client.admin.migrations.sync({
|
|
4307
|
+
* auto_apply: true
|
|
4308
|
+
* })
|
|
4309
|
+
*
|
|
4310
|
+
* // Dry run to preview changes without applying
|
|
4311
|
+
* const { data, error } = await client.admin.migrations.sync({
|
|
4312
|
+
* dry_run: true
|
|
4313
|
+
* })
|
|
4314
|
+
* ```
|
|
4315
|
+
*/
|
|
4316
|
+
async sync(options = {}) {
|
|
4317
|
+
try {
|
|
4318
|
+
const byNamespace = /* @__PURE__ */ new Map();
|
|
4319
|
+
for (const migration of this.localMigrations.values()) {
|
|
4320
|
+
const ns = migration.namespace || "default";
|
|
4321
|
+
if (!byNamespace.has(ns)) {
|
|
4322
|
+
byNamespace.set(ns, []);
|
|
4323
|
+
}
|
|
4324
|
+
byNamespace.get(ns).push(migration);
|
|
4325
|
+
}
|
|
4326
|
+
const results = [];
|
|
4327
|
+
const errors = [];
|
|
4328
|
+
for (const [namespace, migrations] of byNamespace) {
|
|
4329
|
+
try {
|
|
4330
|
+
const result = await this.fetch.post(
|
|
4331
|
+
"/api/v1/admin/migrations/sync",
|
|
4332
|
+
{
|
|
4333
|
+
namespace,
|
|
4334
|
+
migrations: migrations.map((m) => ({
|
|
4335
|
+
name: m.name,
|
|
4336
|
+
description: m.description,
|
|
4337
|
+
up_sql: m.up_sql,
|
|
4338
|
+
down_sql: m.down_sql
|
|
4339
|
+
})),
|
|
4340
|
+
options: {
|
|
4341
|
+
update_if_changed: options.update_if_changed ?? true,
|
|
4342
|
+
auto_apply: options.auto_apply ?? false,
|
|
4343
|
+
dry_run: options.dry_run ?? false
|
|
4344
|
+
}
|
|
4345
|
+
}
|
|
4346
|
+
);
|
|
4347
|
+
results.push(result);
|
|
4348
|
+
} catch (error) {
|
|
4349
|
+
const err = error;
|
|
4350
|
+
if (err.status === 422 && err.details) {
|
|
4351
|
+
results.push(err.details);
|
|
4352
|
+
errors.push(err);
|
|
4353
|
+
} else {
|
|
4354
|
+
throw error;
|
|
4355
|
+
}
|
|
4356
|
+
}
|
|
4357
|
+
}
|
|
4358
|
+
const combined = {
|
|
4359
|
+
message: results.map((r) => r.message).join("; "),
|
|
4360
|
+
namespace: Array.from(byNamespace.keys()).join(", "),
|
|
4361
|
+
summary: {
|
|
4362
|
+
created: results.reduce((sum, r) => sum + r.summary.created, 0),
|
|
4363
|
+
updated: results.reduce((sum, r) => sum + r.summary.updated, 0),
|
|
4364
|
+
unchanged: results.reduce((sum, r) => sum + r.summary.unchanged, 0),
|
|
4365
|
+
skipped: results.reduce((sum, r) => sum + r.summary.skipped, 0),
|
|
4366
|
+
applied: results.reduce((sum, r) => sum + r.summary.applied, 0),
|
|
4367
|
+
errors: results.reduce((sum, r) => sum + r.summary.errors, 0)
|
|
4368
|
+
},
|
|
4369
|
+
details: {
|
|
4370
|
+
created: results.flatMap((r) => r.details.created),
|
|
4371
|
+
updated: results.flatMap((r) => r.details.updated),
|
|
4372
|
+
unchanged: results.flatMap((r) => r.details.unchanged),
|
|
4373
|
+
skipped: results.flatMap((r) => r.details.skipped),
|
|
4374
|
+
applied: results.flatMap((r) => r.details.applied),
|
|
4375
|
+
errors: results.flatMap((r) => r.details.errors)
|
|
4376
|
+
},
|
|
4377
|
+
dry_run: options.dry_run ?? false,
|
|
4378
|
+
warnings: results.flatMap((r) => r.warnings || [])
|
|
4379
|
+
};
|
|
4380
|
+
const hasChanges = combined.summary.created > 0 || combined.summary.updated > 0;
|
|
4381
|
+
if (!combined.dry_run && hasChanges) {
|
|
4382
|
+
try {
|
|
4383
|
+
await this.triggerSchemaRefreshWithRestart();
|
|
4384
|
+
} catch (refreshError) {
|
|
4385
|
+
console.warn("Schema refresh completed with warnings:", refreshError);
|
|
4386
|
+
}
|
|
4387
|
+
}
|
|
4388
|
+
if (errors.length > 0 || combined.summary.errors > 0) {
|
|
4389
|
+
const error = new Error(combined.message);
|
|
4390
|
+
error.syncResult = combined;
|
|
4391
|
+
error.details = combined.details.errors;
|
|
4392
|
+
return { data: combined, error };
|
|
4393
|
+
}
|
|
4394
|
+
return { data: combined, error: null };
|
|
4395
|
+
} catch (error) {
|
|
4396
|
+
return { data: null, error };
|
|
4397
|
+
}
|
|
4398
|
+
}
|
|
4399
|
+
/**
|
|
4400
|
+
* Create a new migration
|
|
4401
|
+
*
|
|
4402
|
+
* @param request - Migration configuration
|
|
4403
|
+
* @returns Promise resolving to { data, error } tuple with created migration
|
|
4404
|
+
*
|
|
4405
|
+
* @example
|
|
4406
|
+
* ```typescript
|
|
4407
|
+
* const { data, error } = await client.admin.migrations.create({
|
|
4408
|
+
* namespace: 'myapp',
|
|
4409
|
+
* name: '001_create_users',
|
|
4410
|
+
* up_sql: 'CREATE TABLE app.users (id UUID PRIMARY KEY, email TEXT)',
|
|
4411
|
+
* down_sql: 'DROP TABLE app.users',
|
|
4412
|
+
* description: 'Create users table'
|
|
4413
|
+
* })
|
|
4414
|
+
* ```
|
|
4415
|
+
*/
|
|
4416
|
+
async create(request) {
|
|
4417
|
+
try {
|
|
4418
|
+
const data = await this.fetch.post("/api/v1/admin/migrations", request);
|
|
4419
|
+
return { data, error: null };
|
|
4420
|
+
} catch (error) {
|
|
4421
|
+
return { data: null, error };
|
|
4422
|
+
}
|
|
4423
|
+
}
|
|
4424
|
+
/**
|
|
4425
|
+
* List migrations in a namespace
|
|
4426
|
+
*
|
|
4427
|
+
* @param namespace - Migration namespace (default: 'default')
|
|
4428
|
+
* @param status - Filter by status: 'pending', 'applied', 'failed', 'rolled_back'
|
|
4429
|
+
* @returns Promise resolving to { data, error } tuple with migrations array
|
|
4430
|
+
*
|
|
4431
|
+
* @example
|
|
4432
|
+
* ```typescript
|
|
4433
|
+
* // List all migrations
|
|
4434
|
+
* const { data, error } = await client.admin.migrations.list('myapp')
|
|
4435
|
+
*
|
|
4436
|
+
* // List only pending migrations
|
|
4437
|
+
* const { data, error } = await client.admin.migrations.list('myapp', 'pending')
|
|
4438
|
+
* ```
|
|
4439
|
+
*/
|
|
4440
|
+
async list(namespace = "default", status) {
|
|
4441
|
+
try {
|
|
4442
|
+
const params = new URLSearchParams({ namespace });
|
|
4443
|
+
if (status) params.append("status", status);
|
|
4444
|
+
const data = await this.fetch.get(
|
|
4445
|
+
`/api/v1/admin/migrations?${params.toString()}`
|
|
4446
|
+
);
|
|
4447
|
+
return { data, error: null };
|
|
4448
|
+
} catch (error) {
|
|
4449
|
+
return { data: null, error };
|
|
4450
|
+
}
|
|
4451
|
+
}
|
|
4452
|
+
/**
|
|
4453
|
+
* Get details of a specific migration
|
|
4454
|
+
*
|
|
4455
|
+
* @param name - Migration name
|
|
4456
|
+
* @param namespace - Migration namespace (default: 'default')
|
|
4457
|
+
* @returns Promise resolving to { data, error } tuple with migration details
|
|
4458
|
+
*
|
|
4459
|
+
* @example
|
|
4460
|
+
* ```typescript
|
|
4461
|
+
* const { data, error } = await client.admin.migrations.get('001_create_users', 'myapp')
|
|
4462
|
+
* ```
|
|
4463
|
+
*/
|
|
4464
|
+
async get(name, namespace = "default") {
|
|
4465
|
+
try {
|
|
4466
|
+
const params = new URLSearchParams({ namespace });
|
|
4467
|
+
const data = await this.fetch.get(
|
|
4468
|
+
`/api/v1/admin/migrations/${name}?${params.toString()}`
|
|
4469
|
+
);
|
|
4470
|
+
return { data, error: null };
|
|
4471
|
+
} catch (error) {
|
|
4472
|
+
return { data: null, error };
|
|
4473
|
+
}
|
|
4474
|
+
}
|
|
4475
|
+
/**
|
|
4476
|
+
* Update a migration (only if status is pending)
|
|
4477
|
+
*
|
|
4478
|
+
* @param name - Migration name
|
|
4479
|
+
* @param updates - Fields to update
|
|
4480
|
+
* @param namespace - Migration namespace (default: 'default')
|
|
4481
|
+
* @returns Promise resolving to { data, error } tuple with updated migration
|
|
4482
|
+
*
|
|
4483
|
+
* @example
|
|
4484
|
+
* ```typescript
|
|
4485
|
+
* const { data, error } = await client.admin.migrations.update(
|
|
4486
|
+
* '001_create_users',
|
|
4487
|
+
* { description: 'Updated description' },
|
|
4488
|
+
* 'myapp'
|
|
4489
|
+
* )
|
|
4490
|
+
* ```
|
|
4491
|
+
*/
|
|
4492
|
+
async update(name, updates, namespace = "default") {
|
|
4493
|
+
try {
|
|
4494
|
+
const params = new URLSearchParams({ namespace });
|
|
4495
|
+
const data = await this.fetch.put(
|
|
4496
|
+
`/api/v1/admin/migrations/${name}?${params.toString()}`,
|
|
4497
|
+
updates
|
|
4498
|
+
);
|
|
4499
|
+
return { data, error: null };
|
|
4500
|
+
} catch (error) {
|
|
4501
|
+
return { data: null, error };
|
|
4502
|
+
}
|
|
4503
|
+
}
|
|
4504
|
+
/**
|
|
4505
|
+
* Delete a migration (only if status is pending)
|
|
4506
|
+
*
|
|
4507
|
+
* @param name - Migration name
|
|
4508
|
+
* @param namespace - Migration namespace (default: 'default')
|
|
4509
|
+
* @returns Promise resolving to { data, error } tuple
|
|
4510
|
+
*
|
|
4511
|
+
* @example
|
|
4512
|
+
* ```typescript
|
|
4513
|
+
* const { data, error } = await client.admin.migrations.delete('001_create_users', 'myapp')
|
|
4514
|
+
* ```
|
|
4515
|
+
*/
|
|
4516
|
+
async delete(name, namespace = "default") {
|
|
4517
|
+
try {
|
|
4518
|
+
const params = new URLSearchParams({ namespace });
|
|
4519
|
+
await this.fetch.delete(`/api/v1/admin/migrations/${name}?${params.toString()}`);
|
|
4520
|
+
return { data: null, error: null };
|
|
4521
|
+
} catch (error) {
|
|
4522
|
+
return { data: null, error };
|
|
4523
|
+
}
|
|
4524
|
+
}
|
|
4525
|
+
/**
|
|
4526
|
+
* Apply a specific migration
|
|
4527
|
+
*
|
|
4528
|
+
* @param name - Migration name
|
|
4529
|
+
* @param namespace - Migration namespace (default: 'default')
|
|
4530
|
+
* @returns Promise resolving to { data, error } tuple with result message
|
|
4531
|
+
*
|
|
4532
|
+
* @example
|
|
4533
|
+
* ```typescript
|
|
4534
|
+
* const { data, error } = await client.admin.migrations.apply('001_create_users', 'myapp')
|
|
4535
|
+
* if (data) {
|
|
4536
|
+
* console.log(data.message) // "Migration applied successfully"
|
|
4537
|
+
* }
|
|
4538
|
+
* ```
|
|
4539
|
+
*/
|
|
4540
|
+
async apply(name, namespace = "default") {
|
|
4541
|
+
try {
|
|
4542
|
+
const data = await this.fetch.post(
|
|
4543
|
+
`/api/v1/admin/migrations/${name}/apply`,
|
|
4544
|
+
{ namespace }
|
|
4545
|
+
);
|
|
4546
|
+
return { data, error: null };
|
|
4547
|
+
} catch (error) {
|
|
4548
|
+
return { data: null, error };
|
|
4549
|
+
}
|
|
4550
|
+
}
|
|
4551
|
+
/**
|
|
4552
|
+
* Rollback a specific migration
|
|
4553
|
+
*
|
|
4554
|
+
* @param name - Migration name
|
|
4555
|
+
* @param namespace - Migration namespace (default: 'default')
|
|
4556
|
+
* @returns Promise resolving to { data, error } tuple with result message
|
|
4557
|
+
*
|
|
4558
|
+
* @example
|
|
4559
|
+
* ```typescript
|
|
4560
|
+
* const { data, error } = await client.admin.migrations.rollback('001_create_users', 'myapp')
|
|
4561
|
+
* ```
|
|
4562
|
+
*/
|
|
4563
|
+
async rollback(name, namespace = "default") {
|
|
4564
|
+
try {
|
|
4565
|
+
const data = await this.fetch.post(
|
|
4566
|
+
`/api/v1/admin/migrations/${name}/rollback`,
|
|
4567
|
+
{ namespace }
|
|
4568
|
+
);
|
|
4569
|
+
return { data, error: null };
|
|
4570
|
+
} catch (error) {
|
|
4571
|
+
return { data: null, error };
|
|
4572
|
+
}
|
|
4573
|
+
}
|
|
4574
|
+
/**
|
|
4575
|
+
* Apply all pending migrations in order
|
|
4576
|
+
*
|
|
4577
|
+
* @param namespace - Migration namespace (default: 'default')
|
|
4578
|
+
* @returns Promise resolving to { data, error } tuple with applied/failed counts
|
|
4579
|
+
*
|
|
4580
|
+
* @example
|
|
4581
|
+
* ```typescript
|
|
4582
|
+
* const { data, error } = await client.admin.migrations.applyPending('myapp')
|
|
4583
|
+
* if (data) {
|
|
4584
|
+
* console.log(`Applied: ${data.applied.length}, Failed: ${data.failed.length}`)
|
|
4585
|
+
* }
|
|
4586
|
+
* ```
|
|
4587
|
+
*/
|
|
4588
|
+
async applyPending(namespace = "default") {
|
|
4589
|
+
try {
|
|
4590
|
+
const data = await this.fetch.post("/api/v1/admin/migrations/apply-pending", { namespace });
|
|
4591
|
+
return { data, error: null };
|
|
4592
|
+
} catch (error) {
|
|
4593
|
+
return { data: null, error };
|
|
4594
|
+
}
|
|
4595
|
+
}
|
|
4596
|
+
/**
|
|
4597
|
+
* Get execution history for a migration
|
|
4598
|
+
*
|
|
4599
|
+
* @param name - Migration name
|
|
4600
|
+
* @param namespace - Migration namespace (default: 'default')
|
|
4601
|
+
* @param limit - Maximum number of executions to return (default: 50, max: 100)
|
|
4602
|
+
* @returns Promise resolving to { data, error } tuple with execution records
|
|
4603
|
+
*
|
|
4604
|
+
* @example
|
|
4605
|
+
* ```typescript
|
|
4606
|
+
* const { data, error } = await client.admin.migrations.getExecutions(
|
|
4607
|
+
* '001_create_users',
|
|
4608
|
+
* 'myapp',
|
|
4609
|
+
* 10
|
|
4610
|
+
* )
|
|
4611
|
+
* if (data) {
|
|
4612
|
+
* data.forEach(exec => {
|
|
4613
|
+
* console.log(`${exec.executed_at}: ${exec.action} - ${exec.status}`)
|
|
4614
|
+
* })
|
|
4615
|
+
* }
|
|
4616
|
+
* ```
|
|
4617
|
+
*/
|
|
4618
|
+
async getExecutions(name, namespace = "default", limit = 50) {
|
|
4619
|
+
try {
|
|
4620
|
+
const params = new URLSearchParams({ namespace, limit: limit.toString() });
|
|
4621
|
+
const data = await this.fetch.get(
|
|
4622
|
+
`/api/v1/admin/migrations/${name}/executions?${params.toString()}`
|
|
4623
|
+
);
|
|
4624
|
+
return { data, error: null };
|
|
4625
|
+
} catch (error) {
|
|
4626
|
+
return { data: null, error };
|
|
4627
|
+
}
|
|
4628
|
+
}
|
|
4629
|
+
};
|
|
4630
|
+
|
|
4631
|
+
// src/admin-jobs.ts
|
|
4632
|
+
var esbuild = null;
|
|
4633
|
+
async function loadEsbuild() {
|
|
4634
|
+
if (esbuild) return true;
|
|
4635
|
+
try {
|
|
4636
|
+
esbuild = await import('esbuild');
|
|
4637
|
+
return true;
|
|
4638
|
+
} catch {
|
|
4639
|
+
return false;
|
|
4640
|
+
}
|
|
4641
|
+
}
|
|
4642
|
+
var FluxbaseAdminJobs = class _FluxbaseAdminJobs {
|
|
4643
|
+
constructor(fetch2) {
|
|
4644
|
+
this.fetch = fetch2;
|
|
4645
|
+
}
|
|
4646
|
+
/**
|
|
4647
|
+
* Create a new job function
|
|
4648
|
+
*
|
|
4649
|
+
* @param request - Job function configuration and code
|
|
4650
|
+
* @returns Promise resolving to { data, error } tuple with created job function metadata
|
|
4651
|
+
*
|
|
4652
|
+
* @example
|
|
4653
|
+
* ```typescript
|
|
4654
|
+
* const { data, error } = await client.admin.jobs.create({
|
|
4655
|
+
* name: 'process-data',
|
|
4656
|
+
* code: 'export async function handler(req) { return { success: true } }',
|
|
4657
|
+
* enabled: true,
|
|
4658
|
+
* timeout_seconds: 300
|
|
4659
|
+
* })
|
|
4660
|
+
* ```
|
|
4661
|
+
*/
|
|
4662
|
+
async create(request) {
|
|
4663
|
+
try {
|
|
4664
|
+
const data = await this.fetch.post(
|
|
4665
|
+
"/api/v1/admin/jobs/functions",
|
|
4666
|
+
request
|
|
4667
|
+
);
|
|
4668
|
+
return { data, error: null };
|
|
4669
|
+
} catch (error) {
|
|
4670
|
+
return { data: null, error };
|
|
4671
|
+
}
|
|
4672
|
+
}
|
|
4673
|
+
/**
|
|
4674
|
+
* List all namespaces that have job functions
|
|
4675
|
+
*
|
|
4676
|
+
* @returns Promise resolving to { data, error } tuple with array of namespace strings
|
|
4677
|
+
*
|
|
4678
|
+
* @example
|
|
4679
|
+
* ```typescript
|
|
4680
|
+
* const { data, error } = await client.admin.jobs.listNamespaces()
|
|
4681
|
+
* if (data) {
|
|
4682
|
+
* console.log('Available namespaces:', data)
|
|
4683
|
+
* }
|
|
4684
|
+
* ```
|
|
4685
|
+
*/
|
|
4686
|
+
async listNamespaces() {
|
|
4687
|
+
try {
|
|
4688
|
+
const response = await this.fetch.get(
|
|
4689
|
+
"/api/v1/admin/jobs/namespaces"
|
|
4690
|
+
);
|
|
4691
|
+
return { data: response.namespaces || ["default"], error: null };
|
|
4692
|
+
} catch (error) {
|
|
4693
|
+
return { data: null, error };
|
|
4694
|
+
}
|
|
4695
|
+
}
|
|
4696
|
+
/**
|
|
4697
|
+
* List all job functions (admin view)
|
|
4698
|
+
*
|
|
4699
|
+
* @param namespace - Optional namespace filter
|
|
4700
|
+
* @returns Promise resolving to { data, error } tuple with array of job functions
|
|
4701
|
+
*
|
|
4702
|
+
* @example
|
|
4703
|
+
* ```typescript
|
|
4704
|
+
* const { data, error } = await client.admin.jobs.list('default')
|
|
4705
|
+
* if (data) {
|
|
4706
|
+
* console.log('Job functions:', data.map(f => f.name))
|
|
4707
|
+
* }
|
|
4708
|
+
* ```
|
|
4709
|
+
*/
|
|
4710
|
+
async list(namespace) {
|
|
4711
|
+
try {
|
|
4712
|
+
const params = namespace ? `?namespace=${namespace}` : "";
|
|
4713
|
+
const data = await this.fetch.get(
|
|
4714
|
+
`/api/v1/admin/jobs/functions${params}`
|
|
4715
|
+
);
|
|
4716
|
+
return { data, error: null };
|
|
4717
|
+
} catch (error) {
|
|
4718
|
+
return { data: null, error };
|
|
4719
|
+
}
|
|
4720
|
+
}
|
|
4721
|
+
/**
|
|
4722
|
+
* Get details of a specific job function
|
|
4723
|
+
*
|
|
4724
|
+
* @param namespace - Namespace
|
|
4725
|
+
* @param name - Job function name
|
|
4726
|
+
* @returns Promise resolving to { data, error } tuple with job function metadata
|
|
4727
|
+
*
|
|
4728
|
+
* @example
|
|
4729
|
+
* ```typescript
|
|
4730
|
+
* const { data, error } = await client.admin.jobs.get('default', 'process-data')
|
|
4731
|
+
* if (data) {
|
|
4732
|
+
* console.log('Job function version:', data.version)
|
|
4733
|
+
* }
|
|
4734
|
+
* ```
|
|
4735
|
+
*/
|
|
4736
|
+
async get(namespace, name) {
|
|
4737
|
+
try {
|
|
4738
|
+
const data = await this.fetch.get(
|
|
4739
|
+
`/api/v1/admin/jobs/functions/${namespace}/${name}`
|
|
4740
|
+
);
|
|
4741
|
+
return { data, error: null };
|
|
4742
|
+
} catch (error) {
|
|
4743
|
+
return { data: null, error };
|
|
4744
|
+
}
|
|
4745
|
+
}
|
|
4746
|
+
/**
|
|
4747
|
+
* Update an existing job function
|
|
4748
|
+
*
|
|
4749
|
+
* @param namespace - Namespace
|
|
4750
|
+
* @param name - Job function name
|
|
4751
|
+
* @param updates - Fields to update
|
|
4752
|
+
* @returns Promise resolving to { data, error } tuple with updated job function metadata
|
|
4753
|
+
*
|
|
4754
|
+
* @example
|
|
4755
|
+
* ```typescript
|
|
4756
|
+
* const { data, error } = await client.admin.jobs.update('default', 'process-data', {
|
|
4757
|
+
* enabled: false,
|
|
4758
|
+
* timeout_seconds: 600
|
|
4759
|
+
* })
|
|
4760
|
+
* ```
|
|
4761
|
+
*/
|
|
4762
|
+
async update(namespace, name, updates) {
|
|
4763
|
+
try {
|
|
4764
|
+
const data = await this.fetch.put(
|
|
4765
|
+
`/api/v1/admin/jobs/functions/${namespace}/${name}`,
|
|
4766
|
+
updates
|
|
4767
|
+
);
|
|
4768
|
+
return { data, error: null };
|
|
4769
|
+
} catch (error) {
|
|
4770
|
+
return { data: null, error };
|
|
4771
|
+
}
|
|
4772
|
+
}
|
|
4773
|
+
/**
|
|
4774
|
+
* Delete a job function
|
|
4775
|
+
*
|
|
4776
|
+
* @param namespace - Namespace
|
|
4777
|
+
* @param name - Job function name
|
|
4778
|
+
* @returns Promise resolving to { data, error } tuple
|
|
4779
|
+
*
|
|
4780
|
+
* @example
|
|
4781
|
+
* ```typescript
|
|
4782
|
+
* const { data, error } = await client.admin.jobs.delete('default', 'process-data')
|
|
4783
|
+
* ```
|
|
4784
|
+
*/
|
|
4785
|
+
async delete(namespace, name) {
|
|
4786
|
+
try {
|
|
4787
|
+
await this.fetch.delete(
|
|
4788
|
+
`/api/v1/admin/jobs/functions/${namespace}/${name}`
|
|
4789
|
+
);
|
|
4790
|
+
return { data: null, error: null };
|
|
4791
|
+
} catch (error) {
|
|
4792
|
+
return { data: null, error };
|
|
4793
|
+
}
|
|
4794
|
+
}
|
|
4795
|
+
/**
|
|
4796
|
+
* List all jobs (executions) across all namespaces (admin view)
|
|
4797
|
+
*
|
|
4798
|
+
* @param filters - Optional filters (status, namespace, limit, offset)
|
|
4799
|
+
* @returns Promise resolving to { data, error } tuple with array of jobs
|
|
4800
|
+
*
|
|
4801
|
+
* @example
|
|
4802
|
+
* ```typescript
|
|
4803
|
+
* const { data, error } = await client.admin.jobs.listJobs({
|
|
4804
|
+
* status: 'running',
|
|
4805
|
+
* namespace: 'default',
|
|
4806
|
+
* limit: 50
|
|
4807
|
+
* })
|
|
4808
|
+
* if (data) {
|
|
4809
|
+
* data.forEach(job => {
|
|
4810
|
+
* console.log(`${job.job_name}: ${job.status}`)
|
|
4811
|
+
* })
|
|
4812
|
+
* }
|
|
4813
|
+
* ```
|
|
4814
|
+
*/
|
|
4815
|
+
async listJobs(filters) {
|
|
4816
|
+
try {
|
|
4817
|
+
const params = new URLSearchParams();
|
|
4818
|
+
if (filters?.status) params.append("status", filters.status);
|
|
4819
|
+
if (filters?.namespace) params.append("namespace", filters.namespace);
|
|
4820
|
+
if (filters?.limit) params.append("limit", filters.limit.toString());
|
|
4821
|
+
if (filters?.offset) params.append("offset", filters.offset.toString());
|
|
4822
|
+
const queryString = params.toString();
|
|
4823
|
+
const data = await this.fetch.get(
|
|
4824
|
+
`/api/v1/admin/jobs/queue${queryString ? `?${queryString}` : ""}`
|
|
4825
|
+
);
|
|
4826
|
+
return { data, error: null };
|
|
4827
|
+
} catch (error) {
|
|
4828
|
+
return { data: null, error };
|
|
4829
|
+
}
|
|
4830
|
+
}
|
|
4831
|
+
/**
|
|
4832
|
+
* Get details of a specific job (execution)
|
|
4833
|
+
*
|
|
4834
|
+
* @param jobId - Job ID
|
|
4835
|
+
* @returns Promise resolving to { data, error } tuple with job details
|
|
4836
|
+
*
|
|
4837
|
+
* @example
|
|
4838
|
+
* ```typescript
|
|
4839
|
+
* const { data, error } = await client.admin.jobs.getJob('550e8400-e29b-41d4-a716-446655440000')
|
|
4840
|
+
* if (data) {
|
|
4841
|
+
* console.log(`Job ${data.job_name}: ${data.status}`)
|
|
4842
|
+
* }
|
|
4843
|
+
* ```
|
|
4844
|
+
*/
|
|
4845
|
+
async getJob(jobId) {
|
|
4846
|
+
try {
|
|
4847
|
+
const data = await this.fetch.get(`/api/v1/admin/jobs/queue/${jobId}`);
|
|
4848
|
+
return { data, error: null };
|
|
4849
|
+
} catch (error) {
|
|
4850
|
+
return { data: null, error };
|
|
4851
|
+
}
|
|
4852
|
+
}
|
|
4853
|
+
/**
|
|
4854
|
+
* Cancel a running or pending job
|
|
4855
|
+
*
|
|
4856
|
+
* @param jobId - Job ID
|
|
4857
|
+
* @returns Promise resolving to { data, error } tuple
|
|
4858
|
+
*
|
|
4859
|
+
* @example
|
|
4860
|
+
* ```typescript
|
|
4861
|
+
* const { data, error } = await client.admin.jobs.cancel('550e8400-e29b-41d4-a716-446655440000')
|
|
4862
|
+
* ```
|
|
4863
|
+
*/
|
|
4864
|
+
async cancel(jobId) {
|
|
4865
|
+
try {
|
|
4866
|
+
await this.fetch.post(`/api/v1/admin/jobs/queue/${jobId}/cancel`, {});
|
|
4867
|
+
return { data: null, error: null };
|
|
4868
|
+
} catch (error) {
|
|
4869
|
+
return { data: null, error };
|
|
4870
|
+
}
|
|
4871
|
+
}
|
|
4872
|
+
/**
|
|
4873
|
+
* Terminate a running job immediately
|
|
4874
|
+
*
|
|
4875
|
+
* @param jobId - Job ID
|
|
4876
|
+
* @returns Promise resolving to { data, error } tuple
|
|
4877
|
+
*
|
|
4878
|
+
* @example
|
|
4879
|
+
* ```typescript
|
|
4880
|
+
* const { data, error } = await client.admin.jobs.terminate('550e8400-e29b-41d4-a716-446655440000')
|
|
4881
|
+
* ```
|
|
4882
|
+
*/
|
|
4883
|
+
async terminate(jobId) {
|
|
4884
|
+
try {
|
|
4885
|
+
await this.fetch.post(`/api/v1/admin/jobs/queue/${jobId}/terminate`, {});
|
|
4886
|
+
return { data: null, error: null };
|
|
4887
|
+
} catch (error) {
|
|
4888
|
+
return { data: null, error };
|
|
4889
|
+
}
|
|
4890
|
+
}
|
|
4891
|
+
/**
|
|
4892
|
+
* Retry a failed job
|
|
4893
|
+
*
|
|
4894
|
+
* @param jobId - Job ID
|
|
4895
|
+
* @returns Promise resolving to { data, error } tuple with new job
|
|
4896
|
+
*
|
|
4897
|
+
* @example
|
|
4898
|
+
* ```typescript
|
|
4899
|
+
* const { data, error } = await client.admin.jobs.retry('550e8400-e29b-41d4-a716-446655440000')
|
|
4900
|
+
* ```
|
|
4901
|
+
*/
|
|
4902
|
+
async retry(jobId) {
|
|
4903
|
+
try {
|
|
4904
|
+
const data = await this.fetch.post(
|
|
4905
|
+
`/api/v1/admin/jobs/queue/${jobId}/retry`,
|
|
4906
|
+
{}
|
|
4907
|
+
);
|
|
4908
|
+
return { data, error: null };
|
|
4909
|
+
} catch (error) {
|
|
4910
|
+
return { data: null, error };
|
|
4911
|
+
}
|
|
4912
|
+
}
|
|
4913
|
+
/**
|
|
4914
|
+
* Get job statistics
|
|
4915
|
+
*
|
|
4916
|
+
* @param namespace - Optional namespace filter
|
|
4917
|
+
* @returns Promise resolving to { data, error } tuple with job stats
|
|
4918
|
+
*
|
|
4919
|
+
* @example
|
|
4920
|
+
* ```typescript
|
|
4921
|
+
* const { data, error } = await client.admin.jobs.getStats('default')
|
|
4922
|
+
* if (data) {
|
|
4923
|
+
* console.log(`Pending: ${data.pending}, Running: ${data.running}`)
|
|
4924
|
+
* }
|
|
4925
|
+
* ```
|
|
4926
|
+
*/
|
|
4927
|
+
async getStats(namespace) {
|
|
4928
|
+
try {
|
|
4929
|
+
const params = namespace ? `?namespace=${namespace}` : "";
|
|
4930
|
+
const data = await this.fetch.get(
|
|
4931
|
+
`/api/v1/admin/jobs/stats${params}`
|
|
4932
|
+
);
|
|
4933
|
+
return { data, error: null };
|
|
4934
|
+
} catch (error) {
|
|
4935
|
+
return { data: null, error };
|
|
4936
|
+
}
|
|
4937
|
+
}
|
|
4938
|
+
/**
|
|
4939
|
+
* List active workers
|
|
4940
|
+
*
|
|
4941
|
+
* @returns Promise resolving to { data, error } tuple with array of workers
|
|
4942
|
+
*
|
|
4943
|
+
* @example
|
|
4944
|
+
* ```typescript
|
|
4945
|
+
* const { data, error } = await client.admin.jobs.listWorkers()
|
|
4946
|
+
* if (data) {
|
|
4947
|
+
* data.forEach(worker => {
|
|
4948
|
+
* console.log(`Worker ${worker.id}: ${worker.current_jobs} jobs`)
|
|
4949
|
+
* })
|
|
4950
|
+
* }
|
|
4951
|
+
* ```
|
|
4952
|
+
*/
|
|
4953
|
+
async listWorkers() {
|
|
4954
|
+
try {
|
|
4955
|
+
const data = await this.fetch.get(
|
|
4956
|
+
"/api/v1/admin/jobs/workers"
|
|
4957
|
+
);
|
|
4958
|
+
return { data, error: null };
|
|
4959
|
+
} catch (error) {
|
|
4960
|
+
return { data: null, error };
|
|
4961
|
+
}
|
|
4962
|
+
}
|
|
4963
|
+
/**
|
|
4964
|
+
* Sync multiple job functions to a namespace
|
|
4965
|
+
*
|
|
4966
|
+
* Can sync from:
|
|
4967
|
+
* 1. Filesystem (if no jobs provided) - loads from configured jobs directory
|
|
4968
|
+
* 2. API payload (if jobs array provided) - syncs provided job specifications
|
|
4969
|
+
*
|
|
4970
|
+
* Requires service_role or admin authentication.
|
|
4971
|
+
*
|
|
4972
|
+
* @param options - Sync options including namespace and optional jobs array
|
|
4973
|
+
* @returns Promise resolving to { data, error } tuple with sync results
|
|
4974
|
+
*
|
|
4975
|
+
* @example
|
|
4976
|
+
* ```typescript
|
|
4977
|
+
* // Sync from filesystem
|
|
4978
|
+
* const { data, error } = await client.admin.jobs.sync({ namespace: 'default' })
|
|
4979
|
+
*
|
|
4980
|
+
* // Sync with pre-bundled code (client-side bundling)
|
|
4981
|
+
* const bundled = await FluxbaseAdminJobs.bundleCode({ code: myJobCode })
|
|
4982
|
+
* const { data, error } = await client.admin.jobs.sync({
|
|
4983
|
+
* namespace: 'default',
|
|
4984
|
+
* functions: [{
|
|
4985
|
+
* name: 'my-job',
|
|
4986
|
+
* code: bundled.code,
|
|
4987
|
+
* is_pre_bundled: true,
|
|
4988
|
+
* original_code: myJobCode,
|
|
4989
|
+
* }],
|
|
4990
|
+
* options: {
|
|
4991
|
+
* delete_missing: true, // Remove jobs not in this sync
|
|
4992
|
+
* dry_run: false, // Preview changes without applying
|
|
4993
|
+
* }
|
|
4994
|
+
* })
|
|
4995
|
+
*
|
|
4996
|
+
* if (data) {
|
|
4997
|
+
* console.log(`Synced: ${data.summary.created} created, ${data.summary.updated} updated`)
|
|
4998
|
+
* }
|
|
4999
|
+
* ```
|
|
5000
|
+
*/
|
|
5001
|
+
async sync(options) {
|
|
5002
|
+
try {
|
|
5003
|
+
const syncOptions = typeof options === "string" ? { namespace: options } : options;
|
|
5004
|
+
const data = await this.fetch.post(
|
|
5005
|
+
"/api/v1/admin/jobs/sync",
|
|
5006
|
+
{
|
|
5007
|
+
namespace: syncOptions.namespace,
|
|
5008
|
+
jobs: syncOptions.functions,
|
|
5009
|
+
options: {
|
|
5010
|
+
delete_missing: syncOptions.options?.delete_missing ?? false,
|
|
5011
|
+
dry_run: syncOptions.options?.dry_run ?? false
|
|
5012
|
+
}
|
|
5013
|
+
}
|
|
5014
|
+
);
|
|
5015
|
+
return { data, error: null };
|
|
5016
|
+
} catch (error) {
|
|
5017
|
+
return { data: null, error };
|
|
5018
|
+
}
|
|
5019
|
+
}
|
|
5020
|
+
/**
|
|
5021
|
+
* Sync job functions with automatic client-side bundling
|
|
5022
|
+
*
|
|
5023
|
+
* This is a convenience method that bundles all job code using esbuild
|
|
5024
|
+
* before sending to the server. Requires esbuild as a peer dependency.
|
|
5025
|
+
*
|
|
5026
|
+
* @param options - Sync options including namespace and jobs array
|
|
5027
|
+
* @param bundleOptions - Optional bundling configuration
|
|
5028
|
+
* @returns Promise resolving to { data, error } tuple with sync results
|
|
5029
|
+
*
|
|
5030
|
+
* @example
|
|
5031
|
+
* ```typescript
|
|
5032
|
+
* const { data, error } = await client.admin.jobs.syncWithBundling({
|
|
5033
|
+
* namespace: 'default',
|
|
5034
|
+
* functions: [
|
|
5035
|
+
* { name: 'process-data', code: processDataCode },
|
|
5036
|
+
* { name: 'send-email', code: sendEmailCode },
|
|
5037
|
+
* ],
|
|
5038
|
+
* options: { delete_missing: true }
|
|
5039
|
+
* })
|
|
5040
|
+
* ```
|
|
5041
|
+
*/
|
|
5042
|
+
async syncWithBundling(options, bundleOptions) {
|
|
5043
|
+
if (!options.functions || options.functions.length === 0) {
|
|
5044
|
+
return this.sync(options);
|
|
5045
|
+
}
|
|
5046
|
+
const hasEsbuild = await loadEsbuild();
|
|
5047
|
+
if (!hasEsbuild) {
|
|
5048
|
+
return {
|
|
5049
|
+
data: null,
|
|
5050
|
+
error: new Error(
|
|
5051
|
+
"esbuild is required for client-side bundling. Install it with: npm install esbuild"
|
|
5052
|
+
)
|
|
5053
|
+
};
|
|
5054
|
+
}
|
|
5055
|
+
try {
|
|
5056
|
+
const bundledFunctions = await Promise.all(
|
|
5057
|
+
options.functions.map(async (fn) => {
|
|
5058
|
+
if (fn.is_pre_bundled) {
|
|
5059
|
+
return fn;
|
|
5060
|
+
}
|
|
5061
|
+
const bundled = await _FluxbaseAdminJobs.bundleCode({
|
|
5062
|
+
code: fn.code,
|
|
5063
|
+
...bundleOptions
|
|
5064
|
+
});
|
|
5065
|
+
return {
|
|
5066
|
+
...fn,
|
|
5067
|
+
code: bundled.code,
|
|
5068
|
+
original_code: fn.code,
|
|
5069
|
+
is_pre_bundled: true
|
|
5070
|
+
};
|
|
5071
|
+
})
|
|
5072
|
+
);
|
|
5073
|
+
return this.sync({
|
|
5074
|
+
...options,
|
|
5075
|
+
functions: bundledFunctions
|
|
5076
|
+
});
|
|
5077
|
+
} catch (error) {
|
|
5078
|
+
return { data: null, error };
|
|
5079
|
+
}
|
|
5080
|
+
}
|
|
5081
|
+
/**
|
|
5082
|
+
* Bundle job code using esbuild (client-side)
|
|
5083
|
+
*
|
|
5084
|
+
* Transforms and bundles TypeScript/JavaScript code into a single file
|
|
5085
|
+
* that can be executed by the Fluxbase jobs runtime.
|
|
5086
|
+
*
|
|
5087
|
+
* Requires esbuild as a peer dependency.
|
|
5088
|
+
*
|
|
5089
|
+
* @param options - Bundle options including source code
|
|
5090
|
+
* @returns Promise resolving to bundled code
|
|
5091
|
+
* @throws Error if esbuild is not available
|
|
5092
|
+
*
|
|
5093
|
+
* @example
|
|
5094
|
+
* ```typescript
|
|
5095
|
+
* const bundled = await FluxbaseAdminJobs.bundleCode({
|
|
5096
|
+
* code: `
|
|
5097
|
+
* import { helper } from './utils'
|
|
5098
|
+
* export async function handler(req) {
|
|
5099
|
+
* return helper(req.payload)
|
|
5100
|
+
* }
|
|
5101
|
+
* `,
|
|
5102
|
+
* minify: true,
|
|
5103
|
+
* })
|
|
5104
|
+
*
|
|
5105
|
+
* // Use bundled code in sync
|
|
5106
|
+
* await client.admin.jobs.sync({
|
|
5107
|
+
* namespace: 'default',
|
|
5108
|
+
* functions: [{
|
|
5109
|
+
* name: 'my-job',
|
|
5110
|
+
* code: bundled.code,
|
|
5111
|
+
* is_pre_bundled: true,
|
|
5112
|
+
* }]
|
|
5113
|
+
* })
|
|
5114
|
+
* ```
|
|
5115
|
+
*/
|
|
5116
|
+
static async bundleCode(options) {
|
|
5117
|
+
const hasEsbuild = await loadEsbuild();
|
|
5118
|
+
if (!hasEsbuild || !esbuild) {
|
|
5119
|
+
throw new Error(
|
|
5120
|
+
"esbuild is required for bundling. Install it with: npm install esbuild"
|
|
5121
|
+
);
|
|
5122
|
+
}
|
|
5123
|
+
const result = await esbuild.build({
|
|
5124
|
+
stdin: {
|
|
5125
|
+
contents: options.code,
|
|
5126
|
+
loader: "ts",
|
|
5127
|
+
resolveDir: process.cwd?.() || "/"
|
|
5128
|
+
},
|
|
5129
|
+
bundle: true,
|
|
5130
|
+
write: false,
|
|
5131
|
+
format: "esm",
|
|
5132
|
+
platform: "neutral",
|
|
5133
|
+
target: "esnext",
|
|
5134
|
+
minify: options.minify ?? false,
|
|
5135
|
+
sourcemap: options.sourcemap ? "inline" : false,
|
|
5136
|
+
external: options.external ?? [],
|
|
5137
|
+
// Preserve handler export
|
|
5138
|
+
treeShaking: true
|
|
5139
|
+
});
|
|
5140
|
+
const output = result.outputFiles?.[0];
|
|
5141
|
+
if (!output) {
|
|
5142
|
+
throw new Error("Bundling failed: no output generated");
|
|
5143
|
+
}
|
|
5144
|
+
return {
|
|
5145
|
+
code: output.text,
|
|
5146
|
+
sourceMap: options.sourcemap ? output.text : void 0
|
|
5147
|
+
};
|
|
5148
|
+
}
|
|
5149
|
+
};
|
|
5150
|
+
|
|
3855
5151
|
// src/admin.ts
|
|
3856
5152
|
var FluxbaseAdmin = class {
|
|
3857
5153
|
constructor(fetch2) {
|
|
@@ -3863,6 +5159,9 @@ var FluxbaseAdmin = class {
|
|
|
3863
5159
|
this.impersonation = new ImpersonationManager(fetch2);
|
|
3864
5160
|
this.management = new FluxbaseManagement(fetch2);
|
|
3865
5161
|
this.emailTemplates = new EmailTemplateManager(fetch2);
|
|
5162
|
+
this.functions = new FluxbaseAdminFunctions(fetch2);
|
|
5163
|
+
this.jobs = new FluxbaseAdminJobs(fetch2);
|
|
5164
|
+
this.migrations = new FluxbaseAdminMigrations(fetch2);
|
|
3866
5165
|
}
|
|
3867
5166
|
/**
|
|
3868
5167
|
* Set admin authentication token
|
|
@@ -5059,6 +6358,7 @@ var FluxbaseClient = class {
|
|
|
5059
6358
|
);
|
|
5060
6359
|
this.storage = new FluxbaseStorage(this.fetch);
|
|
5061
6360
|
this.functions = new FluxbaseFunctions(this.fetch);
|
|
6361
|
+
this.jobs = new FluxbaseJobs(this.fetch);
|
|
5062
6362
|
this.admin = new FluxbaseAdmin(this.fetch);
|
|
5063
6363
|
this.management = new FluxbaseManagement(this.fetch);
|
|
5064
6364
|
this.settings = new SettingsClient(this.fetch);
|
|
@@ -5225,6 +6525,6 @@ function createClient(fluxbaseUrl, fluxbaseKey, options) {
|
|
|
5225
6525
|
);
|
|
5226
6526
|
}
|
|
5227
6527
|
|
|
5228
|
-
export { APIKeysManager, AppSettingsManager, AuthSettingsManager, DDLManager, EmailTemplateManager, FluxbaseAdmin, FluxbaseAuth, FluxbaseClient, FluxbaseFetch, FluxbaseFunctions, FluxbaseManagement, FluxbaseOAuth, FluxbaseRealtime, FluxbaseSettings, FluxbaseStorage, ImpersonationManager, InvitationsManager, OAuthProviderManager, QueryBuilder, RealtimeChannel, SettingsClient, StorageBucket, SystemSettingsManager, WebhooksManager, createClient };
|
|
6528
|
+
export { APIKeysManager, AppSettingsManager, AuthSettingsManager, DDLManager, EmailTemplateManager, FluxbaseAdmin, FluxbaseAdminFunctions, FluxbaseAdminJobs, FluxbaseAdminMigrations, FluxbaseAuth, FluxbaseClient, FluxbaseFetch, FluxbaseFunctions, FluxbaseJobs, FluxbaseManagement, FluxbaseOAuth, FluxbaseRealtime, FluxbaseSettings, FluxbaseStorage, ImpersonationManager, InvitationsManager, OAuthProviderManager, QueryBuilder, RealtimeChannel, SettingsClient, StorageBucket, SystemSettingsManager, WebhooksManager, createClient };
|
|
5229
6529
|
//# sourceMappingURL=index.js.map
|
|
5230
6530
|
//# sourceMappingURL=index.js.map
|