oneclient 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -0
- package/dist/artifact-create.d.ts +15 -0
- package/dist/artifact-create.d.ts.map +1 -0
- package/dist/artifact-create.js +130 -0
- package/dist/client.d.ts +2 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +1 -0
- package/dist/credential-routing.d.ts +5 -0
- package/dist/credential-routing.d.ts.map +1 -0
- package/dist/credential-routing.js +32 -0
- package/dist/credentials.d.ts +10 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +88 -0
- package/dist/deployment-wait.d.ts +16 -0
- package/dist/deployment-wait.d.ts.map +1 -0
- package/dist/deployment-wait.js +31 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +624 -0
- package/dist/platform-auth.d.ts +4 -0
- package/dist/platform-auth.d.ts.map +1 -0
- package/dist/platform-auth.js +61 -0
- package/dist/presenter.d.ts +9 -0
- package/dist/presenter.d.ts.map +1 -0
- package/dist/presenter.js +106 -0
- package/dist/secret-input.d.ts +8 -0
- package/dist/secret-input.d.ts.map +1 -0
- package/dist/secret-input.js +33 -0
- package/dist/slug.d.ts +2 -0
- package/dist/slug.d.ts.map +1 -0
- package/dist/slug.js +10 -0
- package/llms.txt +17 -0
- package/package.json +56 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { validateApiUrl } from "./credentials.js";
|
|
2
|
+
export async function sendDeveloperOtp(apiUrl, email, fetcher = globalThis.fetch) {
|
|
3
|
+
await authRequest(fetcher, apiUrl, "/v1/platform/auth/email-otp/send-verification-otp", {
|
|
4
|
+
email: normalizeEmail(email),
|
|
5
|
+
type: "sign-in",
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
export async function verifyDeveloperOtp(apiUrl, email, otp, fetcher = globalThis.fetch) {
|
|
9
|
+
const response = await authRequest(fetcher, apiUrl, "/v1/platform/auth/sign-in/email-otp", {
|
|
10
|
+
email: normalizeEmail(email),
|
|
11
|
+
otp: normalizeOtp(otp),
|
|
12
|
+
});
|
|
13
|
+
const token = response.headers.get("set-auth-token");
|
|
14
|
+
if (!token)
|
|
15
|
+
throw new Error("The control plane did not return a signed CLI session token");
|
|
16
|
+
return token;
|
|
17
|
+
}
|
|
18
|
+
export async function revokeDeveloperSession(apiUrl, sessionToken, fetcher = globalThis.fetch) {
|
|
19
|
+
await authRequest(fetcher, apiUrl, "/v1/platform/auth/sign-out", {}, sessionToken);
|
|
20
|
+
}
|
|
21
|
+
async function authRequest(fetcher, apiUrl, path, body, sessionToken) {
|
|
22
|
+
const response = await fetcher(`${validateApiUrl(apiUrl)}${path}`, {
|
|
23
|
+
method: "POST",
|
|
24
|
+
headers: {
|
|
25
|
+
Accept: "application/json",
|
|
26
|
+
"Content-Type": "application/json",
|
|
27
|
+
...(sessionToken ? { Authorization: `Bearer ${sessionToken}` } : {}),
|
|
28
|
+
},
|
|
29
|
+
body: JSON.stringify(body),
|
|
30
|
+
});
|
|
31
|
+
if (response.ok)
|
|
32
|
+
return response;
|
|
33
|
+
const value = await response.json().catch(() => ({}));
|
|
34
|
+
const payload = isAuthErrorPayload(value) ? value : {};
|
|
35
|
+
throw new Error(payload.error?.message ??
|
|
36
|
+
payload.message ??
|
|
37
|
+
`Authentication failed with HTTP ${response.status}`);
|
|
38
|
+
}
|
|
39
|
+
function isAuthErrorPayload(value) {
|
|
40
|
+
if (typeof value !== "object" || value === null)
|
|
41
|
+
return false;
|
|
42
|
+
const payload = value;
|
|
43
|
+
return ((payload.message === undefined || typeof payload.message === "string") &&
|
|
44
|
+
(payload.error === undefined ||
|
|
45
|
+
(typeof payload.error === "object" &&
|
|
46
|
+
payload.error !== null &&
|
|
47
|
+
(!("message" in payload.error) ||
|
|
48
|
+
typeof payload.error.message === "string"))));
|
|
49
|
+
}
|
|
50
|
+
function normalizeEmail(value) {
|
|
51
|
+
const email = value.trim().toLowerCase();
|
|
52
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email))
|
|
53
|
+
throw new Error("Enter a valid email address");
|
|
54
|
+
return email;
|
|
55
|
+
}
|
|
56
|
+
function normalizeOtp(value) {
|
|
57
|
+
const otp = value.trim();
|
|
58
|
+
if (!/^\d{6}$/.test(otp))
|
|
59
|
+
throw new Error("The email OTP must contain exactly six digits");
|
|
60
|
+
return otp;
|
|
61
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface PresentationOptions {
|
|
2
|
+
color: boolean;
|
|
3
|
+
json: boolean;
|
|
4
|
+
title?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function formatOutput(value: unknown, options: PresentationOptions): string;
|
|
7
|
+
export declare function brand(color: boolean): string;
|
|
8
|
+
export declare function statusLine(state: "done" | "working" | "error", message: string, color: boolean): string;
|
|
9
|
+
//# sourceMappingURL=presenter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"presenter.d.ts","sourceRoot":"","sources":["../src/presenter.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,OAAO,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA6ED,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,mBAAmB,GAAG,MAAM,CAyBjF;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAE5C;AAED,wBAAgB,UAAU,CACxB,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,EACnC,OAAO,EAAE,MAAM,EACf,KAAK,EAAE,OAAO,GACb,MAAM,CAIR"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
const ansi = {
|
|
2
|
+
reset: "\u001b[0m",
|
|
3
|
+
bold: "\u001b[1m",
|
|
4
|
+
dim: "\u001b[2m",
|
|
5
|
+
green: "\u001b[38;2;88;206;145m",
|
|
6
|
+
mint: "\u001b[38;2;108;222;163m",
|
|
7
|
+
amber: "\u001b[38;2;229;187;111m",
|
|
8
|
+
red: "\u001b[38;2;224;106;99m",
|
|
9
|
+
gray: "\u001b[38;2;137;149;140m",
|
|
10
|
+
};
|
|
11
|
+
function paint(value, code, enabled) {
|
|
12
|
+
return enabled ? `${code}${value}${ansi.reset}` : value;
|
|
13
|
+
}
|
|
14
|
+
function label(value) {
|
|
15
|
+
return value
|
|
16
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1 $2")
|
|
17
|
+
.replaceAll("_", " ")
|
|
18
|
+
.replace(/^./, (character) => character.toUpperCase());
|
|
19
|
+
}
|
|
20
|
+
function scalar(value, color) {
|
|
21
|
+
if (value === null || value === undefined)
|
|
22
|
+
return paint("—", ansi.gray, color);
|
|
23
|
+
if (typeof value === "boolean")
|
|
24
|
+
return value ? paint("yes", ansi.green, color) : paint("no", ansi.gray, color);
|
|
25
|
+
if (typeof value === "number")
|
|
26
|
+
return value.toLocaleString("en-US");
|
|
27
|
+
if (typeof value === "string") {
|
|
28
|
+
if (/^-?[0-9]+$/.test(value) && /micros/i.test(value))
|
|
29
|
+
return value;
|
|
30
|
+
if (/^(ready|active|complete|completed|promoted|true)$/i.test(value))
|
|
31
|
+
return paint(value, ansi.green, color);
|
|
32
|
+
if (/^(failed|suspended|revoked|false)$/i.test(value))
|
|
33
|
+
return paint(value, ansi.red, color);
|
|
34
|
+
if (/^(queued|building|provisioning|pending|warning)$/i.test(value))
|
|
35
|
+
return paint(value, ansi.amber, color);
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
return JSON.stringify(value);
|
|
39
|
+
}
|
|
40
|
+
function compactValue(value, color) {
|
|
41
|
+
if (Array.isArray(value))
|
|
42
|
+
return `${value.length} item${value.length === 1 ? "" : "s"}`;
|
|
43
|
+
if (value && typeof value === "object")
|
|
44
|
+
return Object.keys(value).join(", ");
|
|
45
|
+
return scalar(value, color);
|
|
46
|
+
}
|
|
47
|
+
function objectLines(value, color, indent = "") {
|
|
48
|
+
const lines = [];
|
|
49
|
+
for (const [key, item] of Object.entries(value)) {
|
|
50
|
+
if (item && typeof item === "object" && !Array.isArray(item)) {
|
|
51
|
+
lines.push(`${indent}${paint(label(key), ansi.gray, color)}`);
|
|
52
|
+
lines.push(...objectLines(item, color, `${indent} `));
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
lines.push(`${indent}${paint(label(key).padEnd(22), ansi.gray, color)} ${compactValue(item, color)}`);
|
|
56
|
+
}
|
|
57
|
+
return lines;
|
|
58
|
+
}
|
|
59
|
+
function table(rows, color) {
|
|
60
|
+
if (!rows.length)
|
|
61
|
+
return paint("No results", ansi.gray, color);
|
|
62
|
+
const keys = [...new Set(rows.flatMap((row) => Object.keys(row)))].slice(0, 6);
|
|
63
|
+
const widths = keys.map((key) => Math.min(36, Math.max(label(key).length, ...rows.map((row) => compactValue(row[key], false).length))));
|
|
64
|
+
const header = keys
|
|
65
|
+
.map((key, index) => paint(label(key).padEnd(widths[index] ?? 0), ansi.gray, color))
|
|
66
|
+
.join(" ");
|
|
67
|
+
const divider = widths.map((width) => "─".repeat(width)).join("──");
|
|
68
|
+
const body = rows.map((row) => keys
|
|
69
|
+
.map((key, index) => {
|
|
70
|
+
const raw = compactValue(row[key], false);
|
|
71
|
+
const width = widths[index] ?? 0;
|
|
72
|
+
const clipped = raw.length > width ? `${raw.slice(0, Math.max(0, width - 1))}…` : raw;
|
|
73
|
+
return scalar(clipped.padEnd(width), color);
|
|
74
|
+
})
|
|
75
|
+
.join(" "));
|
|
76
|
+
return [header, paint(divider, ansi.dim, color), ...body].join("\n");
|
|
77
|
+
}
|
|
78
|
+
export function formatOutput(value, options) {
|
|
79
|
+
if (options.json)
|
|
80
|
+
return `${JSON.stringify(value, null, 2)}\n`;
|
|
81
|
+
const heading = options.title
|
|
82
|
+
? `${paint("◆", ansi.mint, options.color)} ${paint(options.title, ansi.bold, options.color)}\n\n`
|
|
83
|
+
: "";
|
|
84
|
+
if (Array.isArray(value)) {
|
|
85
|
+
const rows = value.filter((item) => Boolean(item) && typeof item === "object");
|
|
86
|
+
return `${heading}${rows.length === value.length ? table(rows, options.color) : value.map((item) => scalar(item, options.color)).join("\n")}\n`;
|
|
87
|
+
}
|
|
88
|
+
if (value && typeof value === "object") {
|
|
89
|
+
const record = value;
|
|
90
|
+
const singleArray = Object.entries(record).find(([, item]) => Array.isArray(item) && Object.keys(record).length === 1);
|
|
91
|
+
if (singleArray) {
|
|
92
|
+
const rows = singleArray[1].filter((item) => Boolean(item) && typeof item === "object");
|
|
93
|
+
return `${heading}${paint(label(singleArray[0]), ansi.bold, options.color)}\n${table(rows, options.color)}\n`;
|
|
94
|
+
}
|
|
95
|
+
return `${heading}${objectLines(record, options.color).join("\n")}\n`;
|
|
96
|
+
}
|
|
97
|
+
return `${heading}${scalar(value, options.color)}\n`;
|
|
98
|
+
}
|
|
99
|
+
export function brand(color) {
|
|
100
|
+
return `${paint("◇", ansi.mint, color)} ${paint("oneclient", ansi.bold, color)} ${paint("— build the product, run everything else", ansi.gray, color)}`;
|
|
101
|
+
}
|
|
102
|
+
export function statusLine(state, message, color) {
|
|
103
|
+
const symbol = state === "done" ? "✓" : state === "error" ? "×" : "◌";
|
|
104
|
+
const tone = state === "done" ? ansi.green : state === "error" ? ansi.red : ansi.amber;
|
|
105
|
+
return `${paint(symbol, tone, color)} ${message}`;
|
|
106
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Readable } from "node:stream";
|
|
2
|
+
export interface SecretInputOptions {
|
|
3
|
+
fromEnv?: string;
|
|
4
|
+
stdin?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function secretValueFromOptions(options: SecretInputOptions, environment?: NodeJS.ProcessEnv, input?: Readable): Promise<string>;
|
|
7
|
+
export declare function readSecretFromStdin(input: Readable, maximumBytes?: number): Promise<string>;
|
|
8
|
+
//# sourceMappingURL=secret-input.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secret-input.d.ts","sourceRoot":"","sources":["../src/secret-input.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,kBAAkB,EAC3B,WAAW,GAAE,MAAM,CAAC,UAAwB,EAC5C,KAAK,GAAE,QAAwB,GAC9B,OAAO,CAAC,MAAM,CAAC,CAajB;AAED,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,QAAQ,EACf,YAAY,SAAY,GACvB,OAAO,CAAC,MAAM,CAAC,CAajB"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
export async function secretValueFromOptions(options, environment = process.env, input = process.stdin) {
|
|
3
|
+
if (Boolean(options.fromEnv) === Boolean(options.stdin)) {
|
|
4
|
+
throw new Error("Choose exactly one of --from-env <name> or --stdin");
|
|
5
|
+
}
|
|
6
|
+
if (options.fromEnv) {
|
|
7
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(options.fromEnv))
|
|
8
|
+
throw new Error("from-env must name a valid environment variable");
|
|
9
|
+
const value = environment[options.fromEnv];
|
|
10
|
+
if (value === undefined)
|
|
11
|
+
throw new Error(`Environment variable ${options.fromEnv} is not set`);
|
|
12
|
+
if (!value)
|
|
13
|
+
throw new Error("Secret values cannot be empty");
|
|
14
|
+
return value;
|
|
15
|
+
}
|
|
16
|
+
return readSecretFromStdin(input);
|
|
17
|
+
}
|
|
18
|
+
export async function readSecretFromStdin(input, maximumBytes = 64 * 1024) {
|
|
19
|
+
if ("isTTY" in input && input.isTTY)
|
|
20
|
+
throw new Error("--stdin requires piped input; secret values are never prompted or echoed");
|
|
21
|
+
const chunks = [];
|
|
22
|
+
let bytes = 0;
|
|
23
|
+
for await (const chunk of input) {
|
|
24
|
+
const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
|
|
25
|
+
bytes += buffer.byteLength;
|
|
26
|
+
if (bytes > maximumBytes)
|
|
27
|
+
throw new Error(`Secret value exceeds ${maximumBytes} bytes`);
|
|
28
|
+
chunks.push(buffer);
|
|
29
|
+
}
|
|
30
|
+
if (bytes === 0)
|
|
31
|
+
throw new Error("Secret values cannot be empty");
|
|
32
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
33
|
+
}
|
package/dist/slug.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slug.d.ts","sourceRoot":"","sources":["../src/slug.ts"],"names":[],"mappings":"AAAA,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAS7C"}
|
package/dist/slug.js
ADDED
package/llms.txt
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# OneClient
|
|
2
|
+
|
|
3
|
+
OneClient is a managed application platform for auth, data, storage, jobs, email, AI, analytics,
|
|
4
|
+
hosting, domains, and prepaid spend control.
|
|
5
|
+
|
|
6
|
+
Human docs: https://one-client.com/docs
|
|
7
|
+
Quickstart: https://one-client.com/docs/quickstart
|
|
8
|
+
AI guide: https://one-client.com/docs/ai
|
|
9
|
+
OpenAPI: https://console.one-client.com/openapi.yaml
|
|
10
|
+
MCP: https://control.one-client.com/mcp
|
|
11
|
+
|
|
12
|
+
Install: npm install oneclient
|
|
13
|
+
CLI login: npx oneclient login --email you@company.com
|
|
14
|
+
|
|
15
|
+
Use pk_* only in browser/mobile clients, sk_* only on trusted servers, and dp_* only for deploys.
|
|
16
|
+
Never expose sk_* or dp_* values in client bundles or model output. Every mutation is idempotent and
|
|
17
|
+
every costly operation is prepaid or bounded by a funded reservation.
|
package/package.json
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "oneclient",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "One package for the complete OneClient TypeScript SDK and developer CLI.",
|
|
5
|
+
"license": "UNLICENSED",
|
|
6
|
+
"homepage": "https://one-client.com",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"oneclient",
|
|
9
|
+
"cli",
|
|
10
|
+
"sdk",
|
|
11
|
+
"backend",
|
|
12
|
+
"deployment",
|
|
13
|
+
"ai"
|
|
14
|
+
],
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"README.md",
|
|
18
|
+
"llms.txt"
|
|
19
|
+
],
|
|
20
|
+
"publishConfig": {
|
|
21
|
+
"access": "public",
|
|
22
|
+
"provenance": true
|
|
23
|
+
},
|
|
24
|
+
"type": "module",
|
|
25
|
+
"bin": {
|
|
26
|
+
"oneclient": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"exports": {
|
|
29
|
+
".": {
|
|
30
|
+
"types": "./dist/client.d.ts",
|
|
31
|
+
"import": "./dist/client.js"
|
|
32
|
+
},
|
|
33
|
+
"./sdk": {
|
|
34
|
+
"types": "./dist/client.d.ts",
|
|
35
|
+
"import": "./dist/client.js"
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"commander": "15.0.0",
|
|
40
|
+
"tar": "7.5.22",
|
|
41
|
+
"@oneclient/contracts": "0.1.0",
|
|
42
|
+
"@oneclient/sdk": "0.1.0"
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"@types/node": "26.4.0",
|
|
46
|
+
"tsx": "4.23.12",
|
|
47
|
+
"typescript": "5.9.3",
|
|
48
|
+
"vitest": "4.1.11"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsc -p tsconfig.build.json",
|
|
52
|
+
"dev": "tsx src/index.ts",
|
|
53
|
+
"test": "vitest run src --passWithNoTests",
|
|
54
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
55
|
+
}
|
|
56
|
+
}
|