clefbase 1.4.1 → 1.5.1
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/app.d.ts +19 -1
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +25 -1
- package/dist/app.js.map +1 -1
- package/dist/cli-src/cli/api.js +33 -11
- package/dist/cli-src/cli/commands/functions.js +331 -0
- package/dist/cli-src/cli/commands/init.js +53 -16
- package/dist/cli-src/cli/config.js +7 -2
- package/dist/cli-src/cli/index.js +102 -11
- package/dist/cli.js +469 -66
- package/dist/functions.d.ts +209 -0
- package/dist/functions.d.ts.map +1 -0
- package/dist/functions.js +307 -0
- package/dist/functions.js.map +1 -0
- package/dist/index.d.ts +48 -29
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +62 -29
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +164 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +4 -2
package/dist/cli.js
CHANGED
|
@@ -959,8 +959,8 @@ var require_command = __commonJS({
|
|
|
959
959
|
"node_modules/commander/lib/command.js"(exports2) {
|
|
960
960
|
var EventEmitter = require("node:events").EventEmitter;
|
|
961
961
|
var childProcess = require("node:child_process");
|
|
962
|
-
var
|
|
963
|
-
var
|
|
962
|
+
var path6 = require("node:path");
|
|
963
|
+
var fs5 = require("node:fs");
|
|
964
964
|
var process11 = require("node:process");
|
|
965
965
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
966
966
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -1893,11 +1893,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1893
1893
|
let launchWithNode = false;
|
|
1894
1894
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1895
1895
|
function findFile(baseDir, baseName) {
|
|
1896
|
-
const localBin =
|
|
1897
|
-
if (
|
|
1898
|
-
if (sourceExt.includes(
|
|
1896
|
+
const localBin = path6.resolve(baseDir, baseName);
|
|
1897
|
+
if (fs5.existsSync(localBin)) return localBin;
|
|
1898
|
+
if (sourceExt.includes(path6.extname(baseName))) return void 0;
|
|
1899
1899
|
const foundExt = sourceExt.find(
|
|
1900
|
-
(ext) =>
|
|
1900
|
+
(ext) => fs5.existsSync(`${localBin}${ext}`)
|
|
1901
1901
|
);
|
|
1902
1902
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
1903
1903
|
return void 0;
|
|
@@ -1909,21 +1909,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1909
1909
|
if (this._scriptPath) {
|
|
1910
1910
|
let resolvedScriptPath;
|
|
1911
1911
|
try {
|
|
1912
|
-
resolvedScriptPath =
|
|
1912
|
+
resolvedScriptPath = fs5.realpathSync(this._scriptPath);
|
|
1913
1913
|
} catch (err) {
|
|
1914
1914
|
resolvedScriptPath = this._scriptPath;
|
|
1915
1915
|
}
|
|
1916
|
-
executableDir =
|
|
1917
|
-
|
|
1916
|
+
executableDir = path6.resolve(
|
|
1917
|
+
path6.dirname(resolvedScriptPath),
|
|
1918
1918
|
executableDir
|
|
1919
1919
|
);
|
|
1920
1920
|
}
|
|
1921
1921
|
if (executableDir) {
|
|
1922
1922
|
let localFile = findFile(executableDir, executableFile);
|
|
1923
1923
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
1924
|
-
const legacyName =
|
|
1924
|
+
const legacyName = path6.basename(
|
|
1925
1925
|
this._scriptPath,
|
|
1926
|
-
|
|
1926
|
+
path6.extname(this._scriptPath)
|
|
1927
1927
|
);
|
|
1928
1928
|
if (legacyName !== this._name) {
|
|
1929
1929
|
localFile = findFile(
|
|
@@ -1934,7 +1934,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1934
1934
|
}
|
|
1935
1935
|
executableFile = localFile || executableFile;
|
|
1936
1936
|
}
|
|
1937
|
-
launchWithNode = sourceExt.includes(
|
|
1937
|
+
launchWithNode = sourceExt.includes(path6.extname(executableFile));
|
|
1938
1938
|
let proc;
|
|
1939
1939
|
if (process11.platform !== "win32") {
|
|
1940
1940
|
if (launchWithNode) {
|
|
@@ -2776,7 +2776,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2776
2776
|
* @return {Command}
|
|
2777
2777
|
*/
|
|
2778
2778
|
nameFromFilename(filename) {
|
|
2779
|
-
this._name =
|
|
2779
|
+
this._name = path6.basename(filename, path6.extname(filename));
|
|
2780
2780
|
return this;
|
|
2781
2781
|
}
|
|
2782
2782
|
/**
|
|
@@ -2790,9 +2790,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2790
2790
|
* @param {string} [path]
|
|
2791
2791
|
* @return {(string|null|Command)}
|
|
2792
2792
|
*/
|
|
2793
|
-
executableDir(
|
|
2794
|
-
if (
|
|
2795
|
-
this._executableDir =
|
|
2793
|
+
executableDir(path7) {
|
|
2794
|
+
if (path7 === void 0) return this._executableDir;
|
|
2795
|
+
this._executableDir = path7;
|
|
2796
2796
|
return this;
|
|
2797
2797
|
}
|
|
2798
2798
|
/**
|
|
@@ -13742,15 +13742,15 @@ var require_route = __commonJS({
|
|
|
13742
13742
|
};
|
|
13743
13743
|
}
|
|
13744
13744
|
function wrapConversion(toModel, graph) {
|
|
13745
|
-
const
|
|
13745
|
+
const path6 = [graph[toModel].parent, toModel];
|
|
13746
13746
|
let fn = conversions[graph[toModel].parent][toModel];
|
|
13747
13747
|
let cur = graph[toModel].parent;
|
|
13748
13748
|
while (graph[cur].parent) {
|
|
13749
|
-
|
|
13749
|
+
path6.unshift(graph[cur].parent);
|
|
13750
13750
|
fn = link(conversions[graph[cur].parent][cur], fn);
|
|
13751
13751
|
cur = graph[cur].parent;
|
|
13752
13752
|
}
|
|
13753
|
-
fn.conversion =
|
|
13753
|
+
fn.conversion = path6;
|
|
13754
13754
|
return fn;
|
|
13755
13755
|
}
|
|
13756
13756
|
module2.exports = function(fromModel) {
|
|
@@ -25890,10 +25890,10 @@ var require_lib = __commonJS({
|
|
|
25890
25890
|
exports2.analyse = analyse;
|
|
25891
25891
|
var detectFile = (filepath, opts = {}) => new Promise((resolve, reject) => {
|
|
25892
25892
|
let fd;
|
|
25893
|
-
const
|
|
25893
|
+
const fs5 = (0, node_1.default)();
|
|
25894
25894
|
const handler = (err, buffer) => {
|
|
25895
25895
|
if (fd) {
|
|
25896
|
-
|
|
25896
|
+
fs5.closeSync(fd);
|
|
25897
25897
|
}
|
|
25898
25898
|
if (err) {
|
|
25899
25899
|
reject(err);
|
|
@@ -25905,9 +25905,9 @@ var require_lib = __commonJS({
|
|
|
25905
25905
|
};
|
|
25906
25906
|
const sampleSize = (opts === null || opts === void 0 ? void 0 : opts.sampleSize) || 0;
|
|
25907
25907
|
if (sampleSize > 0) {
|
|
25908
|
-
fd =
|
|
25908
|
+
fd = fs5.openSync(filepath, "r");
|
|
25909
25909
|
let sample = Buffer.allocUnsafe(sampleSize);
|
|
25910
|
-
|
|
25910
|
+
fs5.read(fd, sample, 0, sampleSize, opts.offset, (err, bytesRead) => {
|
|
25911
25911
|
if (err) {
|
|
25912
25912
|
handler(err, null);
|
|
25913
25913
|
} else {
|
|
@@ -25919,22 +25919,22 @@ var require_lib = __commonJS({
|
|
|
25919
25919
|
});
|
|
25920
25920
|
return;
|
|
25921
25921
|
}
|
|
25922
|
-
|
|
25922
|
+
fs5.readFile(filepath, handler);
|
|
25923
25923
|
});
|
|
25924
25924
|
exports2.detectFile = detectFile;
|
|
25925
25925
|
var detectFileSync = (filepath, opts = {}) => {
|
|
25926
|
-
const
|
|
25926
|
+
const fs5 = (0, node_1.default)();
|
|
25927
25927
|
if (opts && opts.sampleSize) {
|
|
25928
|
-
const fd =
|
|
25928
|
+
const fd = fs5.openSync(filepath, "r");
|
|
25929
25929
|
let sample = Buffer.allocUnsafe(opts.sampleSize);
|
|
25930
|
-
const bytesRead =
|
|
25930
|
+
const bytesRead = fs5.readSync(fd, sample, 0, opts.sampleSize, opts.offset);
|
|
25931
25931
|
if (bytesRead < opts.sampleSize) {
|
|
25932
25932
|
sample = sample.subarray(0, bytesRead);
|
|
25933
25933
|
}
|
|
25934
|
-
|
|
25934
|
+
fs5.closeSync(fd);
|
|
25935
25935
|
return (0, exports2.detect)(sample);
|
|
25936
25936
|
}
|
|
25937
|
-
return (0, exports2.detect)(
|
|
25937
|
+
return (0, exports2.detect)(fs5.readFileSync(filepath));
|
|
25938
25938
|
};
|
|
25939
25939
|
exports2.detectFileSync = detectFileSync;
|
|
25940
25940
|
exports2.default = {
|
|
@@ -32520,9 +32520,9 @@ var fetchAsyncQuestionProperty = function(question, prop, answers) {
|
|
|
32520
32520
|
|
|
32521
32521
|
// node_modules/inquirer/lib/ui/prompt.js
|
|
32522
32522
|
var _ = {
|
|
32523
|
-
set: (obj,
|
|
32523
|
+
set: (obj, path6 = "", value) => {
|
|
32524
32524
|
let pointer = obj;
|
|
32525
|
-
|
|
32525
|
+
path6.split(".").forEach((key, index, arr) => {
|
|
32526
32526
|
if (key === "__proto__" || key === "constructor") return;
|
|
32527
32527
|
if (index === arr.length - 1) {
|
|
32528
32528
|
pointer[key] = value;
|
|
@@ -32532,8 +32532,8 @@ var _ = {
|
|
|
32532
32532
|
pointer = pointer[key];
|
|
32533
32533
|
});
|
|
32534
32534
|
},
|
|
32535
|
-
get: (obj,
|
|
32536
|
-
const travel = (regexp) => String.prototype.split.call(
|
|
32535
|
+
get: (obj, path6 = "", defaultValue) => {
|
|
32536
|
+
const travel = (regexp) => String.prototype.split.call(path6, regexp).filter(Boolean).reduce(
|
|
32537
32537
|
// @ts-expect-error implicit any on res[key]
|
|
32538
32538
|
(res, key) => res !== null && res !== void 0 ? res[key] : res,
|
|
32539
32539
|
obj
|
|
@@ -33637,7 +33637,11 @@ function loadConfig(cwd = process.cwd()) {
|
|
|
33637
33637
|
const p = findConfigPath(cwd);
|
|
33638
33638
|
if (!p) return null;
|
|
33639
33639
|
try {
|
|
33640
|
-
|
|
33640
|
+
const raw = JSON.parse(import_fs2.default.readFileSync(p, "utf-8"));
|
|
33641
|
+
if (raw.services && raw.services.functions === void 0) {
|
|
33642
|
+
raw.services.functions = false;
|
|
33643
|
+
}
|
|
33644
|
+
return raw;
|
|
33641
33645
|
} catch {
|
|
33642
33646
|
return null;
|
|
33643
33647
|
}
|
|
@@ -33720,6 +33724,9 @@ function base(cfg) {
|
|
|
33720
33724
|
function adminHeaders(cfg) {
|
|
33721
33725
|
return { "Content-Type": "application/json", "x-admin-secret": cfg.adminSecret };
|
|
33722
33726
|
}
|
|
33727
|
+
function cfxHeaders(cfg) {
|
|
33728
|
+
return { "Content-Type": "application/json", "x-cfx-key": cfg.apiKey };
|
|
33729
|
+
}
|
|
33723
33730
|
async function listSites(cfg) {
|
|
33724
33731
|
return apiFetch(
|
|
33725
33732
|
`${base(cfg)}/api/hosting/databases/${cfg.projectId}/sites`,
|
|
@@ -33729,11 +33736,7 @@ async function listSites(cfg) {
|
|
|
33729
33736
|
async function createSite(cfg, name, description) {
|
|
33730
33737
|
return apiFetch(
|
|
33731
33738
|
`${base(cfg)}/api/hosting/databases/${cfg.projectId}/sites`,
|
|
33732
|
-
{
|
|
33733
|
-
method: "POST",
|
|
33734
|
-
headers: adminHeaders(cfg),
|
|
33735
|
-
body: JSON.stringify({ name, description })
|
|
33736
|
-
}
|
|
33739
|
+
{ method: "POST", headers: adminHeaders(cfg), body: JSON.stringify({ name, description }) }
|
|
33737
33740
|
);
|
|
33738
33741
|
}
|
|
33739
33742
|
async function getDnsStatus(cfg, siteId) {
|
|
@@ -33825,6 +33828,36 @@ async function getActiveDeploy(cfg, siteId) {
|
|
|
33825
33828
|
throw err;
|
|
33826
33829
|
}
|
|
33827
33830
|
}
|
|
33831
|
+
async function apiFnList(cfg) {
|
|
33832
|
+
return apiFetch(
|
|
33833
|
+
`${base(cfg)}/functions/`,
|
|
33834
|
+
{ headers: cfxHeaders(cfg) }
|
|
33835
|
+
);
|
|
33836
|
+
}
|
|
33837
|
+
async function apiFnDeploy(cfg, options) {
|
|
33838
|
+
return apiFetch(
|
|
33839
|
+
`${base(cfg)}/functions/deploy`,
|
|
33840
|
+
{ method: "POST", headers: cfxHeaders(cfg), body: JSON.stringify(options) }
|
|
33841
|
+
);
|
|
33842
|
+
}
|
|
33843
|
+
async function apiFnDelete(cfg, name) {
|
|
33844
|
+
return apiFetch(
|
|
33845
|
+
`${base(cfg)}/functions/${encodeURIComponent(name)}`,
|
|
33846
|
+
{ method: "DELETE", headers: cfxHeaders(cfg) }
|
|
33847
|
+
);
|
|
33848
|
+
}
|
|
33849
|
+
async function apiFnCall(cfg, name, data) {
|
|
33850
|
+
return apiFetch(
|
|
33851
|
+
`${base(cfg)}/functions/call/${encodeURIComponent(name)}`,
|
|
33852
|
+
{ method: "POST", headers: cfxHeaders(cfg), body: JSON.stringify({ data: data ?? null }) }
|
|
33853
|
+
);
|
|
33854
|
+
}
|
|
33855
|
+
async function apiFnExecutions(cfg, name, limit = 30) {
|
|
33856
|
+
return apiFetch(
|
|
33857
|
+
`${base(cfg)}/functions/${encodeURIComponent(name)}/executions?limit=${Math.min(limit, 100)}`,
|
|
33858
|
+
{ headers: cfxHeaders(cfg) }
|
|
33859
|
+
);
|
|
33860
|
+
}
|
|
33828
33861
|
async function testConnection(cfg) {
|
|
33829
33862
|
try {
|
|
33830
33863
|
const fetchFn = await getFetch();
|
|
@@ -33882,7 +33915,7 @@ async function runInit(cwd = process.cwd()) {
|
|
|
33882
33915
|
projectId: projectId.trim(),
|
|
33883
33916
|
apiKey: apiKey.trim(),
|
|
33884
33917
|
adminSecret: adminSecret.trim(),
|
|
33885
|
-
services: { database: false, auth: false, storage: false, hosting: false }
|
|
33918
|
+
services: { database: false, auth: false, storage: false, hosting: false, functions: false }
|
|
33886
33919
|
};
|
|
33887
33920
|
const connSpinner = ora2("Testing connection\u2026").start();
|
|
33888
33921
|
const ok = await testConnection(cfg);
|
|
@@ -33897,17 +33930,19 @@ async function runInit(cwd = process.cwd()) {
|
|
|
33897
33930
|
name: "services",
|
|
33898
33931
|
message: "Which services will you use?",
|
|
33899
33932
|
choices: [
|
|
33900
|
-
{ name: "Database
|
|
33901
|
-
{ name: "Auth
|
|
33902
|
-
{ name: "Storage
|
|
33903
|
-
{ name: "Hosting
|
|
33933
|
+
{ name: "Database \u2014 store and query documents", value: "database", checked: true },
|
|
33934
|
+
{ name: "Auth \u2014 user sign-up / sign-in", value: "auth", checked: true },
|
|
33935
|
+
{ name: "Storage \u2014 file uploads", value: "storage", checked: false },
|
|
33936
|
+
{ name: "Hosting \u2014 deploy static sites", value: "hosting", checked: false },
|
|
33937
|
+
{ name: "Functions \u2014 serverless JS/TS & Python functions", value: "functions", checked: false }
|
|
33904
33938
|
]
|
|
33905
33939
|
}]);
|
|
33906
33940
|
cfg.services = {
|
|
33907
33941
|
database: services.includes("database"),
|
|
33908
33942
|
auth: services.includes("auth"),
|
|
33909
33943
|
storage: services.includes("storage"),
|
|
33910
|
-
hosting: services.includes("hosting")
|
|
33944
|
+
hosting: services.includes("hosting"),
|
|
33945
|
+
functions: services.includes("functions")
|
|
33911
33946
|
};
|
|
33912
33947
|
if (cfg.services.hosting) {
|
|
33913
33948
|
await setupHosting(cfg, cwd);
|
|
@@ -33936,7 +33971,6 @@ function scaffoldLib(cfg, cwd = process.cwd()) {
|
|
|
33936
33971
|
serverUrl: cfg.serverUrl,
|
|
33937
33972
|
projectId: cfg.projectId,
|
|
33938
33973
|
apiKey: cfg.apiKey,
|
|
33939
|
-
// adminSecret intentionally omitted — not needed in client code
|
|
33940
33974
|
services: cfg.services,
|
|
33941
33975
|
...cfg.hosting ? { hosting: cfg.hosting } : {}
|
|
33942
33976
|
};
|
|
@@ -33950,22 +33984,31 @@ function scaffoldLib(cfg, cwd = process.cwd()) {
|
|
|
33950
33984
|
};
|
|
33951
33985
|
}
|
|
33952
33986
|
function buildLibTs(cfg) {
|
|
33953
|
-
const { database, auth, storage } = cfg.services;
|
|
33987
|
+
const { database, auth, storage, functions: fns } = cfg.services;
|
|
33954
33988
|
const sdkImports = ["initClefbase"];
|
|
33955
33989
|
if (database) sdkImports.push("getDatabase");
|
|
33956
33990
|
if (auth) sdkImports.push("getAuth");
|
|
33957
33991
|
if (storage) sdkImports.push("getStorage");
|
|
33992
|
+
if (fns) sdkImports.push("getFunctions", "httpsCallable");
|
|
33958
33993
|
const typeImports = [];
|
|
33959
33994
|
if (database) typeImports.push("Database");
|
|
33960
33995
|
if (auth) typeImports.push("Auth");
|
|
33961
33996
|
if (storage) typeImports.push("ClefbaseStorage");
|
|
33997
|
+
if (fns) typeImports.push("ClefbaseFunctions");
|
|
33962
33998
|
const lines = [
|
|
33963
33999
|
`/**`,
|
|
33964
34000
|
` * Clefbase \u2014 pre-initialised service exports`,
|
|
33965
34001
|
` *`,
|
|
33966
34002
|
` * Usage:`,
|
|
33967
|
-
` * import { db
|
|
33968
|
-
` * import
|
|
34003
|
+
...database ? [` * import { db } from "@lib/clefBase";`] : [],
|
|
34004
|
+
...auth ? [` * import { auth } from "@lib/clefBase";`] : [],
|
|
34005
|
+
...storage ? [` * import { storage } from "@lib/clefBase";`] : [],
|
|
34006
|
+
...fns ? [
|
|
34007
|
+
` * import { fns, httpsCallable } from "@lib/clefBase";`,
|
|
34008
|
+
` *`,
|
|
34009
|
+
` * const greet = httpsCallable<{ name: string }, { message: string }>(fns, "greetUser");`,
|
|
34010
|
+
` * const { data } = await greet({ name: "Alice" });`
|
|
34011
|
+
] : [],
|
|
33969
34012
|
` */`,
|
|
33970
34013
|
``,
|
|
33971
34014
|
`import { ${sdkImports.join(", ")} } from "clefbase";`,
|
|
@@ -33982,7 +34025,8 @@ function buildLibTs(cfg) {
|
|
|
33982
34025
|
`});`,
|
|
33983
34026
|
``
|
|
33984
34027
|
];
|
|
33985
|
-
|
|
34028
|
+
const hasServices = database || auth || storage || fns;
|
|
34029
|
+
if (hasServices) {
|
|
33986
34030
|
lines.push("// \u2500\u2500\u2500 Services \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
33987
34031
|
lines.push("");
|
|
33988
34032
|
}
|
|
@@ -34001,6 +34045,20 @@ function buildLibTs(cfg) {
|
|
|
34001
34045
|
lines.push(`export const storage: ClefbaseStorage = getStorage(app);`);
|
|
34002
34046
|
lines.push("");
|
|
34003
34047
|
}
|
|
34048
|
+
if (fns) {
|
|
34049
|
+
lines.push(`/** Clefbase Functions \u2014 deploy and call serverless functions. */`);
|
|
34050
|
+
lines.push(`export const fns: ClefbaseFunctions = getFunctions(app);`);
|
|
34051
|
+
lines.push("");
|
|
34052
|
+
lines.push(`/**`);
|
|
34053
|
+
lines.push(` * Create a typed callable reference to an HTTP-triggered function.`);
|
|
34054
|
+
lines.push(` *`);
|
|
34055
|
+
lines.push(` * @example`);
|
|
34056
|
+
lines.push(` * const greet = httpsCallable<{ name: string }, { message: string }>(fns, "greetUser");`);
|
|
34057
|
+
lines.push(` * const { data } = await greet({ name: "Alice" });`);
|
|
34058
|
+
lines.push(` */`);
|
|
34059
|
+
lines.push(`export { httpsCallable };`);
|
|
34060
|
+
lines.push("");
|
|
34061
|
+
}
|
|
34004
34062
|
lines.push(
|
|
34005
34063
|
`// \u2500\u2500\u2500 Advanced \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`,
|
|
34006
34064
|
``,
|
|
@@ -34008,7 +34066,6 @@ function buildLibTs(cfg) {
|
|
|
34008
34066
|
`export { app };`,
|
|
34009
34067
|
``
|
|
34010
34068
|
);
|
|
34011
|
-
lines.push("");
|
|
34012
34069
|
return lines.join("\n");
|
|
34013
34070
|
}
|
|
34014
34071
|
async function setupHosting(cfg, cwd) {
|
|
@@ -34095,12 +34152,11 @@ function printUsageHint(cfg) {
|
|
|
34095
34152
|
if (cfg.services.database) namedImports.push("db");
|
|
34096
34153
|
if (cfg.services.auth) namedImports.push("auth");
|
|
34097
34154
|
if (cfg.services.storage) namedImports.push("storage");
|
|
34155
|
+
if (cfg.services.functions) namedImports.push("fns", "httpsCallable");
|
|
34098
34156
|
console.log(source_default.bold(" Quick start:"));
|
|
34099
34157
|
console.log();
|
|
34100
34158
|
if (namedImports.length > 0) {
|
|
34101
|
-
console.log(
|
|
34102
|
-
source_default.cyan(` import { ${namedImports.join(", ")} } from "@lib/clefBase";`)
|
|
34103
|
-
);
|
|
34159
|
+
console.log(source_default.cyan(` import { ${namedImports.join(", ")} } from "@lib/clefBase";`));
|
|
34104
34160
|
} else {
|
|
34105
34161
|
console.log(source_default.cyan(` import app from "@lib/clefBase";`));
|
|
34106
34162
|
}
|
|
@@ -34116,6 +34172,16 @@ function printUsageHint(cfg) {
|
|
|
34116
34172
|
console.log();
|
|
34117
34173
|
console.log(source_default.cyan(` await storage.ref("uploads/photo.jpg").upload(file);`));
|
|
34118
34174
|
}
|
|
34175
|
+
if (cfg.services.functions) {
|
|
34176
|
+
console.log();
|
|
34177
|
+
console.log(source_default.bold(" Functions:"));
|
|
34178
|
+
console.log(source_default.cyan(` // Deploy from a file`));
|
|
34179
|
+
console.log(source_default.cyan(` $ clefbase functions:deploy -f ./src/functions/hello.ts`));
|
|
34180
|
+
console.log();
|
|
34181
|
+
console.log(source_default.cyan(` // Call from your app`));
|
|
34182
|
+
console.log(source_default.cyan(` const greet = httpsCallable(fns, "greetUser");`));
|
|
34183
|
+
console.log(source_default.cyan(` const { data } = await greet({ name: "Alice" });`));
|
|
34184
|
+
}
|
|
34119
34185
|
if (cfg.services.hosting && cfg.hosting) {
|
|
34120
34186
|
console.log();
|
|
34121
34187
|
console.log(source_default.bold(" Deploy:"));
|
|
@@ -34522,12 +34588,301 @@ async function runSitesList(cwd = process.cwd()) {
|
|
|
34522
34588
|
}
|
|
34523
34589
|
}
|
|
34524
34590
|
|
|
34591
|
+
// src/cli/commands/functions.ts
|
|
34592
|
+
var import_fs5 = __toESM(require("fs"));
|
|
34593
|
+
var import_path4 = __toESM(require("path"));
|
|
34594
|
+
function fmtDuration(ms) {
|
|
34595
|
+
return ms < 1e3 ? `${ms}ms` : `${(ms / 1e3).toFixed(2)}s`;
|
|
34596
|
+
}
|
|
34597
|
+
function fmtDate(iso) {
|
|
34598
|
+
return new Date(iso).toLocaleString(void 0, {
|
|
34599
|
+
month: "short",
|
|
34600
|
+
day: "numeric",
|
|
34601
|
+
year: "numeric",
|
|
34602
|
+
hour: "2-digit",
|
|
34603
|
+
minute: "2-digit"
|
|
34604
|
+
});
|
|
34605
|
+
}
|
|
34606
|
+
function triggerLabel(fn) {
|
|
34607
|
+
const t = fn.trigger;
|
|
34608
|
+
if (t.type === "schedule") return `schedule ${source_default.dim(t.cron ?? "")}`;
|
|
34609
|
+
if (t.collection) return `${t.type} ${source_default.dim(t.collection)}`;
|
|
34610
|
+
if (t.bucket) return `${t.type} ${source_default.dim(t.bucket)}`;
|
|
34611
|
+
return t.type;
|
|
34612
|
+
}
|
|
34613
|
+
function statusColor(status) {
|
|
34614
|
+
if (status === "active" || status === "success") return source_default.green(status);
|
|
34615
|
+
if (status === "error" || status === "timeout") return source_default.red(status);
|
|
34616
|
+
if (status === "disabled") return source_default.dim(status);
|
|
34617
|
+
return status;
|
|
34618
|
+
}
|
|
34619
|
+
async function runFunctionsList(cwd = process.cwd()) {
|
|
34620
|
+
const cfg = requireConfig(cwd);
|
|
34621
|
+
const sp = ora2("Fetching functions\u2026").start();
|
|
34622
|
+
let fns;
|
|
34623
|
+
try {
|
|
34624
|
+
fns = await apiFnList(cfg);
|
|
34625
|
+
sp.succeed(`${fns.length} function${fns.length !== 1 ? "s" : ""}`);
|
|
34626
|
+
} catch (err) {
|
|
34627
|
+
sp.fail(err.message);
|
|
34628
|
+
return;
|
|
34629
|
+
}
|
|
34630
|
+
if (fns.length === 0) {
|
|
34631
|
+
console.log(source_default.dim("\n No functions deployed yet. Run `clefbase functions:deploy` to get started.\n"));
|
|
34632
|
+
return;
|
|
34633
|
+
}
|
|
34634
|
+
console.log();
|
|
34635
|
+
for (const fn of fns) {
|
|
34636
|
+
const err = fn.errorCount > 0 ? source_default.red(` ${fn.errorCount} err`) : "";
|
|
34637
|
+
console.log(
|
|
34638
|
+
` ${source_default.bold(fn.name.padEnd(28))}${RUNTIME_BADGE[fn.runtime] ?? fn.runtime} ${statusColor(fn.status).padEnd(14)} ${triggerLabel(fn)}`
|
|
34639
|
+
);
|
|
34640
|
+
console.log(
|
|
34641
|
+
` ${source_default.dim("".padEnd(28))}invocations: ${fn.invocationCount}${err} last: ${fn.lastInvokedAt ? fmtDate(fn.lastInvokedAt) : "\u2014"}`
|
|
34642
|
+
);
|
|
34643
|
+
console.log();
|
|
34644
|
+
}
|
|
34645
|
+
}
|
|
34646
|
+
var RUNTIME_BADGE = {
|
|
34647
|
+
node: source_default.green("[JS/TS]"),
|
|
34648
|
+
python: source_default.blue("[PY] ")
|
|
34649
|
+
};
|
|
34650
|
+
async function runFunctionsDeploy(opts) {
|
|
34651
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
34652
|
+
const cfg = requireConfig(cwd);
|
|
34653
|
+
console.log();
|
|
34654
|
+
console.log(source_default.bold.cyan(" Deploy Function"));
|
|
34655
|
+
console.log();
|
|
34656
|
+
const name = opts.name ?? await promptRequired("Function name");
|
|
34657
|
+
let source;
|
|
34658
|
+
if (opts.file) {
|
|
34659
|
+
const absFile = import_path4.default.isAbsolute(opts.file) ? opts.file : import_path4.default.join(cwd, opts.file);
|
|
34660
|
+
if (!import_fs5.default.existsSync(absFile)) {
|
|
34661
|
+
console.error(source_default.red(`
|
|
34662
|
+
File not found: ${absFile}
|
|
34663
|
+
`));
|
|
34664
|
+
process.exit(1);
|
|
34665
|
+
}
|
|
34666
|
+
source = import_fs5.default.readFileSync(absFile, "utf-8");
|
|
34667
|
+
} else {
|
|
34668
|
+
const { inputMode } = await lib_default.prompt([{
|
|
34669
|
+
type: "list",
|
|
34670
|
+
name: "inputMode",
|
|
34671
|
+
message: "Source code",
|
|
34672
|
+
choices: [
|
|
34673
|
+
{ name: "From a file (recommended)", value: "file" },
|
|
34674
|
+
{ name: "Inline snippet (paste in terminal)", value: "inline" }
|
|
34675
|
+
]
|
|
34676
|
+
}]);
|
|
34677
|
+
if (inputMode === "file") {
|
|
34678
|
+
const { filePath } = await lib_default.prompt([{
|
|
34679
|
+
type: "input",
|
|
34680
|
+
name: "filePath",
|
|
34681
|
+
message: "Path to source file (.js, .ts, .py)",
|
|
34682
|
+
validate: (v) => {
|
|
34683
|
+
if (!v.trim()) return "Required";
|
|
34684
|
+
const abs2 = import_path4.default.isAbsolute(v) ? v : import_path4.default.join(cwd, v);
|
|
34685
|
+
return import_fs5.default.existsSync(abs2) || `File not found: ${abs2}`;
|
|
34686
|
+
}
|
|
34687
|
+
}]);
|
|
34688
|
+
const abs = import_path4.default.isAbsolute(filePath) ? filePath : import_path4.default.join(cwd, filePath.trim());
|
|
34689
|
+
source = import_fs5.default.readFileSync(abs, "utf-8");
|
|
34690
|
+
} else {
|
|
34691
|
+
const { snippet } = await lib_default.prompt([{
|
|
34692
|
+
type: "editor",
|
|
34693
|
+
name: "snippet",
|
|
34694
|
+
message: "Paste your function source (opens $EDITOR)"
|
|
34695
|
+
}]);
|
|
34696
|
+
source = snippet;
|
|
34697
|
+
}
|
|
34698
|
+
}
|
|
34699
|
+
let runtime = opts.runtime;
|
|
34700
|
+
if (!runtime) {
|
|
34701
|
+
if (opts.file) {
|
|
34702
|
+
const ext = import_path4.default.extname(opts.file).toLowerCase();
|
|
34703
|
+
if (ext === ".py") runtime = "python";
|
|
34704
|
+
else runtime = "node";
|
|
34705
|
+
} else {
|
|
34706
|
+
const { rt } = await lib_default.prompt([{
|
|
34707
|
+
type: "list",
|
|
34708
|
+
name: "rt",
|
|
34709
|
+
message: "Runtime",
|
|
34710
|
+
choices: [
|
|
34711
|
+
{ name: "Node.js / TypeScript (JS/TS)", value: "node" },
|
|
34712
|
+
{ name: "Python 3 (PY)", value: "python" }
|
|
34713
|
+
]
|
|
34714
|
+
}]);
|
|
34715
|
+
runtime = rt;
|
|
34716
|
+
}
|
|
34717
|
+
}
|
|
34718
|
+
let triggerType = opts.trigger;
|
|
34719
|
+
if (!triggerType) {
|
|
34720
|
+
const { tt } = await lib_default.prompt([{
|
|
34721
|
+
type: "list",
|
|
34722
|
+
name: "tt",
|
|
34723
|
+
message: "Trigger type",
|
|
34724
|
+
choices: [
|
|
34725
|
+
{ name: "HTTP (POST /functions/call/:name)", value: "http" },
|
|
34726
|
+
{ name: "Schedule (cron timer)", value: "schedule" },
|
|
34727
|
+
{ name: "onDocumentCreate", value: "onDocumentCreate" },
|
|
34728
|
+
{ name: "onDocumentUpdate", value: "onDocumentUpdate" },
|
|
34729
|
+
{ name: "onDocumentDelete", value: "onDocumentDelete" },
|
|
34730
|
+
{ name: "onDocumentWrite (create + update + delete)", value: "onDocumentWrite" },
|
|
34731
|
+
{ name: "onUserCreate", value: "onUserCreate" },
|
|
34732
|
+
{ name: "onUserDelete", value: "onUserDelete" },
|
|
34733
|
+
{ name: "onFileUpload", value: "onFileUpload" },
|
|
34734
|
+
{ name: "onFileDelete", value: "onFileDelete" }
|
|
34735
|
+
]
|
|
34736
|
+
}]);
|
|
34737
|
+
triggerType = tt;
|
|
34738
|
+
}
|
|
34739
|
+
const trigger = { type: triggerType };
|
|
34740
|
+
if (triggerType === "schedule") {
|
|
34741
|
+
trigger.cron = opts.cron ?? await promptRequired("Cron expression (e.g. 0 * * * *)");
|
|
34742
|
+
}
|
|
34743
|
+
if (["onDocumentWrite", "onDocumentCreate", "onDocumentUpdate", "onDocumentDelete"].includes(triggerType)) {
|
|
34744
|
+
trigger.collection = opts.collection ?? await promptRequired("Collection path (e.g. users)");
|
|
34745
|
+
}
|
|
34746
|
+
if (["onFileUpload", "onFileDelete"].includes(triggerType)) {
|
|
34747
|
+
const { bucket } = await lib_default.prompt([{
|
|
34748
|
+
type: "input",
|
|
34749
|
+
name: "bucket",
|
|
34750
|
+
message: "Bucket name filter (leave blank = all buckets)"
|
|
34751
|
+
}]);
|
|
34752
|
+
if (bucket.trim()) trigger.bucket = bucket.trim();
|
|
34753
|
+
}
|
|
34754
|
+
const entryPoint = opts.entry ?? "handler";
|
|
34755
|
+
const timeoutMs = opts.timeout ? parseInt(opts.timeout, 10) : 3e4;
|
|
34756
|
+
const env2 = {};
|
|
34757
|
+
for (const pair of opts.env ?? []) {
|
|
34758
|
+
const idx = pair.indexOf("=");
|
|
34759
|
+
if (idx > 0) env2[pair.slice(0, idx)] = pair.slice(idx + 1);
|
|
34760
|
+
}
|
|
34761
|
+
const payload = { name, runtime, trigger, source, entryPoint, timeoutMs, env: env2 };
|
|
34762
|
+
const sp = ora2(`Deploying "${name}"\u2026`).start();
|
|
34763
|
+
try {
|
|
34764
|
+
const result = await apiFnDeploy(cfg, payload);
|
|
34765
|
+
sp.succeed(source_default.green(`Deployed "${result.name}" \u2192 ${statusColor(result.status)}`));
|
|
34766
|
+
console.log();
|
|
34767
|
+
console.log(` ${source_default.bold("Name:")} ${result.name}`);
|
|
34768
|
+
console.log(` ${source_default.bold("Runtime:")} ${runtime}`);
|
|
34769
|
+
console.log(` ${source_default.bold("Trigger:")} ${triggerLabel({ trigger })}`);
|
|
34770
|
+
if (trigger.type === "http") {
|
|
34771
|
+
console.log(` ${source_default.bold("Call:")} POST ${cfg.serverUrl.replace(/\/+$/, "")}/functions/call/${name}`);
|
|
34772
|
+
}
|
|
34773
|
+
console.log();
|
|
34774
|
+
} catch (err) {
|
|
34775
|
+
sp.fail(err.message);
|
|
34776
|
+
process.exit(1);
|
|
34777
|
+
}
|
|
34778
|
+
}
|
|
34779
|
+
async function runFunctionsCall(name, opts) {
|
|
34780
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
34781
|
+
const cfg = requireConfig(cwd);
|
|
34782
|
+
let data = null;
|
|
34783
|
+
if (opts.data) {
|
|
34784
|
+
try {
|
|
34785
|
+
data = JSON.parse(opts.data);
|
|
34786
|
+
} catch {
|
|
34787
|
+
console.error(source_default.red(`
|
|
34788
|
+
--data must be valid JSON. Got: ${opts.data}
|
|
34789
|
+
`));
|
|
34790
|
+
process.exit(1);
|
|
34791
|
+
}
|
|
34792
|
+
}
|
|
34793
|
+
const sp = ora2(`Calling "${name}"\u2026`).start();
|
|
34794
|
+
try {
|
|
34795
|
+
const result = await apiFnCall(cfg, name, data);
|
|
34796
|
+
sp.succeed(`${source_default.green("\u2713")} ${name} ${source_default.dim(fmtDuration(result.durationMs))}`);
|
|
34797
|
+
console.log();
|
|
34798
|
+
console.log(JSON.stringify(result.data, null, 2));
|
|
34799
|
+
console.log();
|
|
34800
|
+
} catch (err) {
|
|
34801
|
+
sp.fail(err.message);
|
|
34802
|
+
process.exit(1);
|
|
34803
|
+
}
|
|
34804
|
+
}
|
|
34805
|
+
async function runFunctionsDelete(name, opts) {
|
|
34806
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
34807
|
+
const cfg = requireConfig(cwd);
|
|
34808
|
+
if (!opts.force) {
|
|
34809
|
+
const { confirmed } = await lib_default.prompt([{
|
|
34810
|
+
type: "confirm",
|
|
34811
|
+
name: "confirmed",
|
|
34812
|
+
message: `Delete function "${name}"? This cannot be undone.`,
|
|
34813
|
+
default: false
|
|
34814
|
+
}]);
|
|
34815
|
+
if (!confirmed) {
|
|
34816
|
+
console.log(source_default.dim("\n Cancelled.\n"));
|
|
34817
|
+
return;
|
|
34818
|
+
}
|
|
34819
|
+
}
|
|
34820
|
+
const sp = ora2(`Deleting "${name}"\u2026`).start();
|
|
34821
|
+
try {
|
|
34822
|
+
await apiFnDelete(cfg, name);
|
|
34823
|
+
sp.succeed(source_default.green(`"${name}" deleted`));
|
|
34824
|
+
console.log();
|
|
34825
|
+
} catch (err) {
|
|
34826
|
+
sp.fail(err.message);
|
|
34827
|
+
process.exit(1);
|
|
34828
|
+
}
|
|
34829
|
+
}
|
|
34830
|
+
async function runFunctionsLogs(name, opts) {
|
|
34831
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
34832
|
+
const cfg = requireConfig(cwd);
|
|
34833
|
+
const limit = opts.limit ? parseInt(opts.limit, 10) : 20;
|
|
34834
|
+
const sp = ora2(`Fetching logs for "${name}"\u2026`).start();
|
|
34835
|
+
let execs;
|
|
34836
|
+
try {
|
|
34837
|
+
execs = await apiFnExecutions(cfg, name, limit);
|
|
34838
|
+
sp.succeed(`${execs.length} execution${execs.length !== 1 ? "s" : ""}`);
|
|
34839
|
+
} catch (err) {
|
|
34840
|
+
sp.fail(err.message);
|
|
34841
|
+
return;
|
|
34842
|
+
}
|
|
34843
|
+
if (execs.length === 0) {
|
|
34844
|
+
console.log(source_default.dim(`
|
|
34845
|
+
No executions recorded yet for "${name}".
|
|
34846
|
+
`));
|
|
34847
|
+
return;
|
|
34848
|
+
}
|
|
34849
|
+
console.log();
|
|
34850
|
+
for (const ex of execs) {
|
|
34851
|
+
const statusStr = statusColor(ex.status);
|
|
34852
|
+
console.log(
|
|
34853
|
+
` ${statusStr.padEnd(16)}${source_default.dim(fmtDate(ex.startedAt))} ${source_default.dim(fmtDuration(ex.durationMs))} ${source_default.dim("via")} ${ex.triggeredBy}`
|
|
34854
|
+
);
|
|
34855
|
+
if (ex.error) {
|
|
34856
|
+
console.log(source_default.red(` \u2717 ${ex.error.split("\n")[0]}`));
|
|
34857
|
+
}
|
|
34858
|
+
if (ex.logs.length > 0) {
|
|
34859
|
+
for (const line of ex.logs) {
|
|
34860
|
+
console.log(source_default.dim(` \u25B6 ${line}`));
|
|
34861
|
+
}
|
|
34862
|
+
}
|
|
34863
|
+
if (ex.result !== void 0 && ex.result !== null) {
|
|
34864
|
+
const preview = JSON.stringify(ex.result);
|
|
34865
|
+
console.log(source_default.dim(` \u2190 ${preview.length > 120 ? preview.slice(0, 120) + "\u2026" : preview}`));
|
|
34866
|
+
}
|
|
34867
|
+
console.log();
|
|
34868
|
+
}
|
|
34869
|
+
}
|
|
34870
|
+
async function promptRequired(message) {
|
|
34871
|
+
const { value } = await lib_default.prompt([{
|
|
34872
|
+
type: "input",
|
|
34873
|
+
name: "value",
|
|
34874
|
+
message,
|
|
34875
|
+
validate: (v) => v.trim().length > 0 || "Required"
|
|
34876
|
+
}]);
|
|
34877
|
+
return value.trim();
|
|
34878
|
+
}
|
|
34879
|
+
|
|
34525
34880
|
// package.json
|
|
34526
|
-
var version = "1.
|
|
34881
|
+
var version = "1.5.1";
|
|
34527
34882
|
|
|
34528
34883
|
// src/cli/index.ts
|
|
34529
34884
|
var program2 = new Command();
|
|
34530
|
-
program2.name("clefbase").description("Clefbase CLI \u2014 initialise projects, deploy sites, manage
|
|
34885
|
+
program2.name("clefbase").description("Clefbase CLI \u2014 initialise projects, deploy sites, manage functions").version(version);
|
|
34531
34886
|
program2.command("init").description("Initialise a Clefbase project in the current directory").action(async () => {
|
|
34532
34887
|
try {
|
|
34533
34888
|
await runInit();
|
|
@@ -34577,6 +34932,41 @@ program2.command("hosting:dns:reprovision").alias("dns:reprovision").description
|
|
|
34577
34932
|
fatal(err);
|
|
34578
34933
|
}
|
|
34579
34934
|
});
|
|
34935
|
+
program2.command("functions:list").alias("fn:list").description("List all deployed functions for this project").action(async () => {
|
|
34936
|
+
try {
|
|
34937
|
+
await runFunctionsList();
|
|
34938
|
+
} catch (err) {
|
|
34939
|
+
fatal(err);
|
|
34940
|
+
}
|
|
34941
|
+
});
|
|
34942
|
+
program2.command("functions:deploy").alias("fn:deploy").description("Deploy (or redeploy) a function from a source file or interactively").option("-n, --name <name>", "Function name").option("-f, --file <path>", "Path to source file (.js, .ts, .py)").option("-r, --runtime <runtime>", "Runtime: node | python (auto-detected from file ext)").option("-t, --trigger <type>", "Trigger type (http, schedule, onDocumentCreate, \u2026)").option("-c, --cron <expr>", "Cron expression for schedule triggers").option("-C, --collection <path>", "Collection path for document triggers").option("-T, --timeout <ms>", "Execution timeout in milliseconds (default: 30000)").option("-e, --entry <name>", "Exported function name to call (default: handler)").option("--env <KEY=VALUE...>", "Environment variable(s) \u2014 repeatable").action(async (opts) => {
|
|
34943
|
+
try {
|
|
34944
|
+
await runFunctionsDeploy(opts);
|
|
34945
|
+
} catch (err) {
|
|
34946
|
+
fatal(err);
|
|
34947
|
+
}
|
|
34948
|
+
});
|
|
34949
|
+
program2.command("functions:call <name>").alias("fn:call").description("Call an HTTP-triggered function and print its return value").option("-d, --data <json>", "JSON payload to pass as ctx.data").action(async (name, opts) => {
|
|
34950
|
+
try {
|
|
34951
|
+
await runFunctionsCall(name, opts);
|
|
34952
|
+
} catch (err) {
|
|
34953
|
+
fatal(err);
|
|
34954
|
+
}
|
|
34955
|
+
});
|
|
34956
|
+
program2.command("functions:delete <name>").alias("fn:delete").description("Delete a deployed function").option("-y, --force", "Skip confirmation prompt").action(async (name, opts) => {
|
|
34957
|
+
try {
|
|
34958
|
+
await runFunctionsDelete(name, opts);
|
|
34959
|
+
} catch (err) {
|
|
34960
|
+
fatal(err);
|
|
34961
|
+
}
|
|
34962
|
+
});
|
|
34963
|
+
program2.command("functions:logs <name>").alias("fn:logs").description("Show recent execution history for a function").option("-l, --limit <n>", "Number of executions to show (default: 20, max: 100)").action(async (name, opts) => {
|
|
34964
|
+
try {
|
|
34965
|
+
await runFunctionsLogs(name, opts);
|
|
34966
|
+
} catch (err) {
|
|
34967
|
+
fatal(err);
|
|
34968
|
+
}
|
|
34969
|
+
});
|
|
34580
34970
|
program2.command("info").description("Show project config and server connectivity").action(async () => {
|
|
34581
34971
|
try {
|
|
34582
34972
|
await runInfo();
|
|
@@ -34586,16 +34976,29 @@ program2.command("info").description("Show project config and server connectivit
|
|
|
34586
34976
|
});
|
|
34587
34977
|
program2.addHelpText("after", `
|
|
34588
34978
|
${source_default.bold("Examples:")}
|
|
34589
|
-
${source_default.
|
|
34590
|
-
${source_default.cyan("clefbase
|
|
34591
|
-
${source_default.cyan("clefbase
|
|
34592
|
-
|
|
34593
|
-
${source_default.
|
|
34594
|
-
${source_default.cyan("clefbase
|
|
34595
|
-
${source_default.cyan(
|
|
34596
|
-
${source_default.cyan("clefbase hosting:
|
|
34597
|
-
${source_default.cyan("clefbase hosting:
|
|
34598
|
-
${source_default.cyan("clefbase
|
|
34979
|
+
${source_default.bold("Project:")}
|
|
34980
|
+
${source_default.cyan("clefbase init")} Set up a new project
|
|
34981
|
+
${source_default.cyan("clefbase info")} Show config & connection status
|
|
34982
|
+
|
|
34983
|
+
${source_default.bold("Hosting:")}
|
|
34984
|
+
${source_default.cyan("clefbase deploy")} Deploy your built site
|
|
34985
|
+
${source_default.cyan('clefbase deploy -d ./dist -m "v2"')} Deploy from a dir with a note
|
|
34986
|
+
${source_default.cyan("clefbase hosting:init")} Link or create a hosted site
|
|
34987
|
+
${source_default.cyan("clefbase hosting:status")} Show current live deploy
|
|
34988
|
+
${source_default.cyan("clefbase hosting:sites")} List all sites
|
|
34989
|
+
${source_default.cyan("clefbase hosting:dns")} Show DNS status
|
|
34990
|
+
${source_default.cyan("clefbase hosting:dns:reprovision")} Fix / create the preview CNAME
|
|
34991
|
+
|
|
34992
|
+
${source_default.bold("Functions:")}
|
|
34993
|
+
${source_default.cyan("clefbase functions:list")} List all deployed functions
|
|
34994
|
+
${source_default.cyan("clefbase functions:deploy")} Interactive deploy wizard
|
|
34995
|
+
${source_default.cyan("clefbase functions:deploy -f ./fn.ts")} Deploy from a file (auto-detects runtime)
|
|
34996
|
+
${source_default.cyan("clefbase functions:deploy -n greet -f fn.ts --trigger http")}
|
|
34997
|
+
${source_default.cyan("clefbase functions:call greetUser")} Call an HTTP function
|
|
34998
|
+
${source_default.cyan(`clefbase functions:call greetUser -d '{"name":"Alice"}'}`)}
|
|
34999
|
+
${source_default.cyan("clefbase functions:logs greetUser")} View execution history
|
|
35000
|
+
${source_default.cyan("clefbase functions:logs greetUser -l 50")} View last 50 executions
|
|
35001
|
+
${source_default.cyan("clefbase functions:delete oldFunction")} Delete a function
|
|
34599
35002
|
`);
|
|
34600
35003
|
program2.parse(process.argv);
|
|
34601
35004
|
function fatal(err) {
|