@layervai/qurl 0.2.0 → 0.3.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/README.md +157 -20
- package/dist/cjs/client.d.ts +164 -4
- package/dist/cjs/client.js +494 -8
- package/dist/cjs/errors.d.ts +4 -0
- package/dist/cjs/errors.js +5 -1
- package/dist/cjs/index.d.ts +3 -3
- package/dist/cjs/index.js +4 -1
- package/dist/cjs/types.d.ts +93 -1
- package/dist/cjs/version.d.ts +1 -1
- package/dist/cjs/version.js +1 -1
- package/dist/esm/client.d.ts +164 -4
- package/dist/esm/client.d.ts.map +1 -1
- package/dist/esm/client.js +493 -8
- package/dist/esm/client.js.map +1 -1
- package/dist/esm/errors.d.ts +4 -0
- package/dist/esm/errors.d.ts.map +1 -1
- package/dist/esm/errors.js +4 -0
- package/dist/esm/errors.js.map +1 -1
- package/dist/esm/index.d.ts +3 -3
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/types.d.ts +93 -1
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/package.json +1 -1
package/dist/cjs/client.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.QURLClient = void 0;
|
|
3
|
+
exports.ProtectedResource = exports.QURLClient = void 0;
|
|
4
4
|
const errors_js_1 = require("./errors.js");
|
|
5
5
|
const version_js_1 = require("./version.js");
|
|
6
6
|
const DEFAULT_BASE_URL = "https://api.layerv.ai";
|
|
@@ -127,6 +127,28 @@ const CREATE_QURL_FOR_RESOURCE_FIELD_KEYS = [
|
|
|
127
127
|
"session_duration",
|
|
128
128
|
"label",
|
|
129
129
|
"access_policy",
|
|
130
|
+
"target_path",
|
|
131
|
+
];
|
|
132
|
+
assertExhaustive(true);
|
|
133
|
+
/**
|
|
134
|
+
* Options accepted by the portal-verb `protectUrl` / `createPortal`
|
|
135
|
+
* surface. These are camelCase caller-facing options (the portal verbs are
|
|
136
|
+
* the idiomatic layer); the build helpers map them onto the same wire
|
|
137
|
+
* fields the REST-shaped methods send.
|
|
138
|
+
*/
|
|
139
|
+
const PROTECT_URL_OPTION_KEYS = [
|
|
140
|
+
"description",
|
|
141
|
+
"tags",
|
|
142
|
+
"customDomain",
|
|
143
|
+
"alias",
|
|
144
|
+
];
|
|
145
|
+
assertExhaustive(true);
|
|
146
|
+
const CREATE_PORTAL_OPTION_KEYS = [
|
|
147
|
+
"validFor",
|
|
148
|
+
"label",
|
|
149
|
+
"oneTimeUse",
|
|
150
|
+
"maxSessions",
|
|
151
|
+
"sessionDuration",
|
|
130
152
|
];
|
|
131
153
|
assertExhaustive(true);
|
|
132
154
|
const UPDATE_RESOURCE_QURL_FIELD_KEYS = [
|
|
@@ -350,6 +372,7 @@ const MAX_MAX_SESSIONS = 1000;
|
|
|
350
372
|
const MAX_API_KEY_NAME = 100;
|
|
351
373
|
const MAX_ALIAS = 64;
|
|
352
374
|
const MAX_SLUG = 64;
|
|
375
|
+
const MAX_TARGET_PATH = 2048;
|
|
353
376
|
const MAX_TAGS = 10;
|
|
354
377
|
const MAX_TAG_LENGTH = 50;
|
|
355
378
|
const MAX_AUTO_PAGINATION_PAGES = 10_000;
|
|
@@ -377,11 +400,11 @@ function requireNonEmptyIfPresent(value, field) {
|
|
|
377
400
|
throw clientValidationError(`${field}: must not be an empty string`);
|
|
378
401
|
}
|
|
379
402
|
}
|
|
380
|
-
function requireMaxSessionsInRange(value) {
|
|
403
|
+
function requireMaxSessionsInRange(value, field = "max_sessions") {
|
|
381
404
|
if (value === undefined)
|
|
382
405
|
return;
|
|
383
406
|
if (!Number.isInteger(value) || value < 0 || value > MAX_MAX_SESSIONS) {
|
|
384
|
-
throw clientValidationError(
|
|
407
|
+
throw clientValidationError(`${field}: must be an integer between 0 and ${MAX_MAX_SESSIONS} (got ${value})`);
|
|
385
408
|
}
|
|
386
409
|
}
|
|
387
410
|
function requireBooleanIfPresent(value, field) {
|
|
@@ -663,6 +686,13 @@ function validateQurlTokenOptions(input) {
|
|
|
663
686
|
requireNonEmptyIfPresent(input.label, "label");
|
|
664
687
|
requireNonEmptyIfPresent(input.expires_in, "expires_in");
|
|
665
688
|
requireNonEmptyIfPresent(input.session_duration, "session_duration");
|
|
689
|
+
// Mirror the service-documented size cap, but keep host-safety grammar
|
|
690
|
+
// (single leading slash, no scheme/host/backslash/etc.) and the tunnel-only
|
|
691
|
+
// gate server-authoritative (`invalid_target_path`); a client-side regex
|
|
692
|
+
// would create a drift surface. Keep max-before-empty consistent with label;
|
|
693
|
+
// empty strings pass the length check and are rejected by the next guard.
|
|
694
|
+
requireMaxLength(input.target_path, "target_path", MAX_TARGET_PATH);
|
|
695
|
+
requireNonEmptyIfPresent(input.target_path, "target_path");
|
|
666
696
|
requireBooleanIfPresent(input.one_time_use, "one_time_use");
|
|
667
697
|
requireMaxSessionsInRange(input.max_sessions);
|
|
668
698
|
requireValidAccessPolicy(input.access_policy);
|
|
@@ -881,6 +911,195 @@ function batchItemResultValidationReason(entry) {
|
|
|
881
911
|
}
|
|
882
912
|
return "missing/invalid 'success' discriminant (expected boolean)";
|
|
883
913
|
}
|
|
914
|
+
// ---- Portal-verb helpers (mirrors qurl-go) -------------------------------
|
|
915
|
+
// Client-side guardrails for the portal flow (protectUrl → createPortal →
|
|
916
|
+
// enterPortal), kept in lockstep with qurl-go's option validation and
|
|
917
|
+
// qurl-python's port of it.
|
|
918
|
+
/**
|
|
919
|
+
* Client-side floor for portal lifetimes, mirroring qurl-go's `ValidFor`.
|
|
920
|
+
* The LayerV API remains the source of truth for account limits; there is
|
|
921
|
+
* intentionally no SDK-side maximum because an account may allow
|
|
922
|
+
* longer-lived portals.
|
|
923
|
+
*/
|
|
924
|
+
const MIN_PORTAL_VALID_FOR_SECONDS = 60;
|
|
925
|
+
/**
|
|
926
|
+
* Client-side floor for session durations, mirroring qurl-go's
|
|
927
|
+
* `WithSessionDuration` (at least one second; zero is rejected rather than
|
|
928
|
+
* treated as the server default).
|
|
929
|
+
*/
|
|
930
|
+
const MIN_SESSION_DURATION_SECONDS = 1;
|
|
931
|
+
// Shape of qurl-go's offline signed-fragment links: three or more
|
|
932
|
+
// dot-separated base64url parts (<version>.<claims>.<secret>.<sig>).
|
|
933
|
+
// Detected only to give those links a precise error in extractAccessToken.
|
|
934
|
+
const SIGNED_FRAGMENT_RE = /^[A-Za-z0-9_-]+(?:\.[A-Za-z0-9_-]+){2,}$/;
|
|
935
|
+
// Access-token grammar accepted by enterPortal (base64url charset).
|
|
936
|
+
const ACCESS_TOKEN_RE = /^[A-Za-z0-9_-]+$/;
|
|
937
|
+
/**
|
|
938
|
+
* Serialize a duration option to the API's h/m/s duration grammar.
|
|
939
|
+
*
|
|
940
|
+
* Strings pass through unvalidated — the server is authoritative, same as
|
|
941
|
+
* the REST-shaped `expires_in` fields. Numbers are milliseconds and get
|
|
942
|
+
* qurl-go's client-side guardrails: whole seconds only and at least
|
|
943
|
+
* `minimumSeconds` (checked in that order so e.g. 30.5s reports "at least
|
|
944
|
+
* 60s" in every SDK). Serialized with hours as the largest unit so all API
|
|
945
|
+
* duration fields use the same grammar across SDKs.
|
|
946
|
+
*/
|
|
947
|
+
function serializeApiDuration(value, field, minimumSeconds) {
|
|
948
|
+
if (value === undefined)
|
|
949
|
+
return undefined;
|
|
950
|
+
if (typeof value === "string") {
|
|
951
|
+
if (value.trim() === "") {
|
|
952
|
+
throw clientValidationError(`${field}: must be a non-empty duration string`);
|
|
953
|
+
}
|
|
954
|
+
return value;
|
|
955
|
+
}
|
|
956
|
+
if (typeof value === "number") {
|
|
957
|
+
// NaN fails no comparison, so an explicit finite check keeps the
|
|
958
|
+
// error actionable instead of a misleading "whole seconds" report.
|
|
959
|
+
if (!Number.isFinite(value)) {
|
|
960
|
+
throw clientValidationError(`${field}: must be a finite number of milliseconds`);
|
|
961
|
+
}
|
|
962
|
+
if (value < minimumSeconds * 1000) {
|
|
963
|
+
throw clientValidationError(`${field}: must be at least ${minimumSeconds}s`);
|
|
964
|
+
}
|
|
965
|
+
if (value % 1000 !== 0) {
|
|
966
|
+
throw clientValidationError(`${field}: must be whole seconds`);
|
|
967
|
+
}
|
|
968
|
+
const seconds = value / 1000;
|
|
969
|
+
if (seconds % 3600 === 0)
|
|
970
|
+
return `${seconds / 3600}h`;
|
|
971
|
+
if (seconds % 60 === 0)
|
|
972
|
+
return `${seconds / 60}m`;
|
|
973
|
+
return `${seconds}s`;
|
|
974
|
+
}
|
|
975
|
+
throw clientValidationError(`${field}: must be a duration string (e.g. "5m") or a number of milliseconds`);
|
|
976
|
+
}
|
|
977
|
+
/**
|
|
978
|
+
* Portal-verb target URL validation (qurl-go `ProtectURL` parity). On top of
|
|
979
|
+
* the shared scheme/length check, the URL must carry a host and must parse,
|
|
980
|
+
* and embedded credentials (userinfo) are rejected. The added checks never
|
|
981
|
+
* echo the URL — a userinfo URL contains credentials that must stay out of
|
|
982
|
+
* logs and error messages. The REST-shaped compatibility layer keeps its
|
|
983
|
+
* original prefix-only check so its accepted inputs don't change.
|
|
984
|
+
*/
|
|
985
|
+
function requirePortalTargetUrl(targetUrl) {
|
|
986
|
+
requireValidTargetUrl(targetUrl);
|
|
987
|
+
const url = targetUrl; // requireValidTargetUrl only returns for http(s) strings
|
|
988
|
+
// WHATWG URL normalizes away an empty authority ("https:///x" parses
|
|
989
|
+
// with host "x"), so the host-presence check runs on the raw string,
|
|
990
|
+
// mirroring qurl-go's url.Parse which rejects authority-less URLs.
|
|
991
|
+
const afterScheme = url.slice(url.indexOf("://") + 3);
|
|
992
|
+
if (afterScheme === "" || "/?#".includes(afterScheme[0])) {
|
|
993
|
+
throw clientValidationError("target_url: must include a host");
|
|
994
|
+
}
|
|
995
|
+
let parsed;
|
|
996
|
+
try {
|
|
997
|
+
parsed = new URL(url);
|
|
998
|
+
}
|
|
999
|
+
catch {
|
|
1000
|
+
throw clientValidationError("target_url: malformed URL");
|
|
1001
|
+
}
|
|
1002
|
+
if (parsed.username !== "" || parsed.password !== "") {
|
|
1003
|
+
throw clientValidationError("target_url: must not include embedded credentials (userinfo)");
|
|
1004
|
+
}
|
|
1005
|
+
}
|
|
1006
|
+
/**
|
|
1007
|
+
* Extract the access token from a qURL link, or pass a bare token through.
|
|
1008
|
+
*
|
|
1009
|
+
* Platform-issued links carry the access token in the URL fragment
|
|
1010
|
+
* (`https://qurl.link/#at_...`). Error messages deliberately never echo the
|
|
1011
|
+
* input — qURL links are credentials and must stay out of logs.
|
|
1012
|
+
*/
|
|
1013
|
+
function extractAccessToken(qurlLink) {
|
|
1014
|
+
if (typeof qurlLink !== "string" || qurlLink.trim() === "") {
|
|
1015
|
+
throw clientValidationError("qurlLink: must be a non-empty string");
|
|
1016
|
+
}
|
|
1017
|
+
const hashIndex = qurlLink.indexOf("#");
|
|
1018
|
+
const token = hashIndex >= 0 ? qurlLink.slice(hashIndex + 1) : qurlLink;
|
|
1019
|
+
if (SIGNED_FRAGMENT_RE.test(token)) {
|
|
1020
|
+
throw clientValidationError("qurlLink: this is a signed qURL link (offline fragment format), which cannot be " +
|
|
1021
|
+
"opened through the API resolver — enterPortal only accepts platform links " +
|
|
1022
|
+
"(https://qurl.link/#at_...) or bare access tokens");
|
|
1023
|
+
}
|
|
1024
|
+
if (token === "" || !ACCESS_TOKEN_RE.test(token)) {
|
|
1025
|
+
throw clientValidationError("qurlLink: no access token found — pass a platform qURL link " +
|
|
1026
|
+
"(https://qurl.link/#at_...) or a bare access token");
|
|
1027
|
+
}
|
|
1028
|
+
return token;
|
|
1029
|
+
}
|
|
1030
|
+
/**
|
|
1031
|
+
* Parse an RFC 3339 timestamp from the API into a `Date`, or `undefined`
|
|
1032
|
+
* when absent or unparseable. The portal surface exposes `Date` (matching
|
|
1033
|
+
* qurl-go's `time.Time` and qurl-python's `datetime`); the REST-shaped
|
|
1034
|
+
* layer keeps raw wire strings.
|
|
1035
|
+
*/
|
|
1036
|
+
function parseApiDate(value) {
|
|
1037
|
+
if (typeof value !== "string" || value === "")
|
|
1038
|
+
return undefined;
|
|
1039
|
+
const parsed = new Date(value);
|
|
1040
|
+
return Number.isNaN(parsed.getTime()) ? undefined : parsed;
|
|
1041
|
+
}
|
|
1042
|
+
/**
|
|
1043
|
+
* Parse a {@link Portal} from a create-portal API response. `resource_id`
|
|
1044
|
+
* and `qurl_link` are required, mirroring qurl-go's fail-closed response
|
|
1045
|
+
* check; everything else is optional because the two mint endpoints differ
|
|
1046
|
+
* in which ancillary fields they return.
|
|
1047
|
+
*/
|
|
1048
|
+
function parsePortal(data, method) {
|
|
1049
|
+
if (typeof data?.resource_id !== "string" || data.resource_id.trim() === "") {
|
|
1050
|
+
throw unexpectedResponseError(`${method}: response is missing resource_id`);
|
|
1051
|
+
}
|
|
1052
|
+
if (typeof data.qurl_link !== "string" || data.qurl_link.trim() === "") {
|
|
1053
|
+
throw unexpectedResponseError(`${method}: response is missing qurl_link`);
|
|
1054
|
+
}
|
|
1055
|
+
return {
|
|
1056
|
+
resourceId: data.resource_id,
|
|
1057
|
+
link: data.qurl_link,
|
|
1058
|
+
site: data.qurl_site,
|
|
1059
|
+
expiresAt: parseApiDate(data.expires_at),
|
|
1060
|
+
// Same empty-string → absent normalization the REST-shaped layer's
|
|
1061
|
+
// consumers apply to qurl_id.
|
|
1062
|
+
qurlId: data.qurl_id || undefined,
|
|
1063
|
+
label: data.label,
|
|
1064
|
+
};
|
|
1065
|
+
}
|
|
1066
|
+
/**
|
|
1067
|
+
* Validate portal options and build the create-portal wire body, or
|
|
1068
|
+
* `undefined` when every option is omitted so no request body is sent and
|
|
1069
|
+
* the server applies its default lifetime (matching mintLink /
|
|
1070
|
+
* createQurlForResource).
|
|
1071
|
+
*/
|
|
1072
|
+
function buildCreatePortalBody(opts, method) {
|
|
1073
|
+
requireObjectInput(opts, method);
|
|
1074
|
+
requireNoUnknownFields(opts, CREATE_PORTAL_OPTION_KEYS, method);
|
|
1075
|
+
// null → omitted, via the SDK-wide normalizePatchFields convention.
|
|
1076
|
+
const { validFor, label, oneTimeUse, maxSessions, sessionDuration } = normalizePatchFields(opts, CREATE_PORTAL_OPTION_KEYS);
|
|
1077
|
+
if (label !== undefined) {
|
|
1078
|
+
requireMaxLength(label, "label", MAX_LABEL);
|
|
1079
|
+
// qurl-go's WithLabel rejects blank labels; the REST-shaped mintLink
|
|
1080
|
+
// keeps its permissive whitespace behavior, so the check lives here.
|
|
1081
|
+
if (label.trim() === "") {
|
|
1082
|
+
throw clientValidationError("label: must not be empty");
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
requireBooleanIfPresent(oneTimeUse, "oneTimeUse");
|
|
1086
|
+
requireMaxSessionsInRange(maxSessions, "maxSessions");
|
|
1087
|
+
const body = {};
|
|
1088
|
+
const expiresIn = serializeApiDuration(validFor, "validFor", MIN_PORTAL_VALID_FOR_SECONDS);
|
|
1089
|
+
if (expiresIn !== undefined)
|
|
1090
|
+
body.expires_in = expiresIn;
|
|
1091
|
+
if (label !== undefined)
|
|
1092
|
+
body.label = label;
|
|
1093
|
+
if (oneTimeUse !== undefined)
|
|
1094
|
+
body.one_time_use = oneTimeUse;
|
|
1095
|
+
// Explicit 0 means unlimited and must survive body construction.
|
|
1096
|
+
if (maxSessions !== undefined)
|
|
1097
|
+
body.max_sessions = maxSessions;
|
|
1098
|
+
const wireSessionDuration = serializeApiDuration(sessionDuration, "sessionDuration", MIN_SESSION_DURATION_SECONDS);
|
|
1099
|
+
if (wireSessionDuration !== undefined)
|
|
1100
|
+
body.session_duration = wireSessionDuration;
|
|
1101
|
+
return Object.keys(body).length > 0 ? body : undefined;
|
|
1102
|
+
}
|
|
884
1103
|
/** qURL API client. */
|
|
885
1104
|
class QURLClient {
|
|
886
1105
|
baseUrl;
|
|
@@ -1138,8 +1357,214 @@ class QURLClient {
|
|
|
1138
1357
|
}
|
|
1139
1358
|
} while (cursor);
|
|
1140
1359
|
}
|
|
1360
|
+
// --- Portal API (mirrors qurl-go: ProtectURL → CreatePortal → EnterPortal) ---
|
|
1361
|
+
/**
|
|
1362
|
+
* Protect a private URL — create or reuse its LayerV resource.
|
|
1363
|
+
*
|
|
1364
|
+
* The first step of the portal flow (qurl-go: `Client.ProtectURL`).
|
|
1365
|
+
* Protect the URL once, then mint short-lived links for it with
|
|
1366
|
+
* {@link ProtectedResource.createPortal}:
|
|
1367
|
+
*
|
|
1368
|
+
* ```ts
|
|
1369
|
+
* const resource = await client.protectUrl("https://internal.example.com/dashboard");
|
|
1370
|
+
* const portal = await resource.createPortal({ validFor: "5m" });
|
|
1371
|
+
* share(portal.link);
|
|
1372
|
+
* ```
|
|
1373
|
+
*
|
|
1374
|
+
* Protecting the same target URL again returns the existing resource.
|
|
1375
|
+
* Malformed URLs and URLs with embedded credentials (userinfo) are
|
|
1376
|
+
* rejected before any request, mirroring qurl-go. REST-shaped equivalent:
|
|
1377
|
+
* {@link createResource}.
|
|
1378
|
+
*/
|
|
1379
|
+
async protectUrl(targetUrl, opts = {}, requestOptions) {
|
|
1380
|
+
requirePortalTargetUrl(targetUrl);
|
|
1381
|
+
requireObjectInput(opts, "protectUrl");
|
|
1382
|
+
requireNoUnknownFields(opts, PROTECT_URL_OPTION_KEYS, "protectUrl");
|
|
1383
|
+
// camelCase options → wire fields; null is treated as omitted, via the
|
|
1384
|
+
// SDK-wide normalizePatchFields convention.
|
|
1385
|
+
const normalized = normalizePatchFields(opts, PROTECT_URL_OPTION_KEYS);
|
|
1386
|
+
const body = { target_url: targetUrl };
|
|
1387
|
+
if (normalized.description !== undefined)
|
|
1388
|
+
body.description = normalized.description;
|
|
1389
|
+
if (normalized.tags !== undefined)
|
|
1390
|
+
body.tags = normalized.tags;
|
|
1391
|
+
if (normalized.customDomain !== undefined)
|
|
1392
|
+
body.custom_domain = normalized.customDomain;
|
|
1393
|
+
if (normalized.alias !== undefined)
|
|
1394
|
+
body.alias = normalized.alias;
|
|
1395
|
+
validateResourceWriteFields(body);
|
|
1396
|
+
const resource = await this.request("POST", "/v1/resources", body, requestOptions);
|
|
1397
|
+
if (typeof resource?.resource_id !== "string" || resource.resource_id.trim() === "") {
|
|
1398
|
+
throw unexpectedResponseError("protectUrl: response is missing resource_id");
|
|
1399
|
+
}
|
|
1400
|
+
return new ProtectedResource(this, resource.resource_id,
|
|
1401
|
+
// Some resource types redact target_url in responses; fall back to
|
|
1402
|
+
// the caller-supplied URL so the handle stays useful.
|
|
1403
|
+
resource.target_url || targetUrl, resource);
|
|
1404
|
+
}
|
|
1405
|
+
/**
|
|
1406
|
+
* Return a portal-minting handle for a stored resource id, without an API
|
|
1407
|
+
* call.
|
|
1408
|
+
*
|
|
1409
|
+
* Use when you persisted a LayerV resource id and want to mint more
|
|
1410
|
+
* portals for it (qurl-go: `Client.ResourceByID`):
|
|
1411
|
+
*
|
|
1412
|
+
* ```ts
|
|
1413
|
+
* const resource = client.resourceById("r_demo1234567");
|
|
1414
|
+
* const portal = await resource.createPortal({ validFor: "1h" });
|
|
1415
|
+
* ```
|
|
1416
|
+
*
|
|
1417
|
+
* The handle carries no server metadata; use {@link getResource} when you
|
|
1418
|
+
* need the full resource details.
|
|
1419
|
+
*/
|
|
1420
|
+
resourceById(id) {
|
|
1421
|
+
requireNonEmptyId(id, "resourceById");
|
|
1422
|
+
return new ProtectedResource(this, id);
|
|
1423
|
+
}
|
|
1424
|
+
/**
|
|
1425
|
+
* Return the resource qURL Connector created for `connectorId`.
|
|
1426
|
+
*
|
|
1427
|
+
* Use when qURL Connector already protects the service — do not call
|
|
1428
|
+
* {@link protectUrl} again for the same service. The connector id is the
|
|
1429
|
+
* resource slug LayerV stores for that connector; the LayerV API performs
|
|
1430
|
+
* the slug lookup, and the SDK confirms the returned alias matches
|
|
1431
|
+
* `connectorId` before binding the handle (qurl-go:
|
|
1432
|
+
* `Client.ConnectorResource`).
|
|
1433
|
+
*
|
|
1434
|
+
* Throws {@link NotFoundError} (`status: 0`, `code: "resource_not_found"`)
|
|
1435
|
+
* when no resource exists for the connector id, {@link QURLError}
|
|
1436
|
+
* (`code: "ambiguous_resource"`) when the lookup returns more than one
|
|
1437
|
+
* resource, and {@link ValidationError} (`code: "unexpected_response"`)
|
|
1438
|
+
* when the returned resource's alias is missing or does not match.
|
|
1439
|
+
*/
|
|
1440
|
+
async connectorResource(connectorId) {
|
|
1441
|
+
requireNonEmptyId(connectorId, "connectorResource", "connector id");
|
|
1442
|
+
const { resources } = await this.listResources({ slug: connectorId });
|
|
1443
|
+
if (resources.length === 0) {
|
|
1444
|
+
throw new errors_js_1.NotFoundError({
|
|
1445
|
+
status: 0,
|
|
1446
|
+
code: errors_js_1.ERROR_CODE_RESOURCE_NOT_FOUND,
|
|
1447
|
+
title: "Resource Not Found",
|
|
1448
|
+
detail: `connectorResource: no resource found for connector "${connectorId}"`,
|
|
1449
|
+
});
|
|
1450
|
+
}
|
|
1451
|
+
if (resources.length > 1) {
|
|
1452
|
+
throw new errors_js_1.QURLError({
|
|
1453
|
+
status: 0,
|
|
1454
|
+
code: errors_js_1.ERROR_CODE_AMBIGUOUS_RESOURCE,
|
|
1455
|
+
title: "Ambiguous Resource",
|
|
1456
|
+
detail: `connectorResource: connector "${connectorId}" returned ${resources.length} resources`,
|
|
1457
|
+
});
|
|
1458
|
+
}
|
|
1459
|
+
const resource = resources[0];
|
|
1460
|
+
if (resource.alias !== connectorId) {
|
|
1461
|
+
throw unexpectedResponseError(`connectorResource: connector "${connectorId}" returned a resource with a missing or different alias`);
|
|
1462
|
+
}
|
|
1463
|
+
if (typeof resource.resource_id !== "string" || resource.resource_id.trim() === "") {
|
|
1464
|
+
throw unexpectedResponseError("connectorResource: response is missing resource_id");
|
|
1465
|
+
}
|
|
1466
|
+
return new ProtectedResource(this, resource.resource_id, resource.target_url, resource);
|
|
1467
|
+
}
|
|
1468
|
+
/**
|
|
1469
|
+
* Mint a short-lived qURL link (a portal) for a protected resource.
|
|
1470
|
+
*
|
|
1471
|
+
* A portal is cryptographic, just-in-time permission for one actor to
|
|
1472
|
+
* reach one private resource. Recipients open `portal.link` directly and
|
|
1473
|
+
* need no LayerV credentials. Prefer short lifetimes such as
|
|
1474
|
+
* `{ validFor: "5m" }`. Accepts a {@link ProtectedResource} handle or a
|
|
1475
|
+
* resource id (`r_` prefix). REST-shaped equivalents: {@link mintLink} /
|
|
1476
|
+
* {@link createQurlForResource}.
|
|
1477
|
+
*
|
|
1478
|
+
* Duration options take a string (`"5m"`, `"24h"`; server-validated) or a
|
|
1479
|
+
* number of milliseconds with qurl-go's client-side guardrails: whole
|
|
1480
|
+
* seconds only, at least one minute for `validFor` and one second for
|
|
1481
|
+
* `sessionDuration`. `maxSessions: 0` is sent explicitly and means
|
|
1482
|
+
* unlimited; blank labels are rejected.
|
|
1483
|
+
*/
|
|
1484
|
+
async createPortal(resource, opts = {}, requestOptions) {
|
|
1485
|
+
let resourceId;
|
|
1486
|
+
if (typeof resource === "string") {
|
|
1487
|
+
resourceId = resource;
|
|
1488
|
+
}
|
|
1489
|
+
else if (resource instanceof ProtectedResource) {
|
|
1490
|
+
if (!ProtectedResource.isBoundTo(resource, this)) {
|
|
1491
|
+
throw clientValidationError("createPortal: resource is bound to a different client");
|
|
1492
|
+
}
|
|
1493
|
+
resourceId = resource.id;
|
|
1494
|
+
}
|
|
1495
|
+
else {
|
|
1496
|
+
throw clientValidationError(`createPortal: resource must be a ProtectedResource handle or a resource id string (got ${describeShape(resource)})`);
|
|
1497
|
+
}
|
|
1498
|
+
requireNonEmptyId(resourceId, "createPortal", "resource id");
|
|
1499
|
+
const body = buildCreatePortalBody(opts, "createPortal");
|
|
1500
|
+
const data = await this.request("POST", `/v1/resources/${encodeURIComponent(resourceId)}/qurls`, body, requestOptions);
|
|
1501
|
+
return parsePortal(data, "createPortal");
|
|
1502
|
+
}
|
|
1503
|
+
/**
|
|
1504
|
+
* Protect `targetUrl` and mint a portal in one API call.
|
|
1505
|
+
*
|
|
1506
|
+
* Convenience for one-off scripts (qurl-go: `Client.CreatePortalForURL`).
|
|
1507
|
+
* The returned resource handle is reusable for minting more portals but
|
|
1508
|
+
* carries only the resource id and the caller-supplied target URL; use
|
|
1509
|
+
* {@link protectUrl} when you need the full server-populated resource
|
|
1510
|
+
* metadata. Portal options match {@link createPortal}; `targetUrl` gets
|
|
1511
|
+
* the same malformed-URL and embedded-credentials rejection as
|
|
1512
|
+
* {@link protectUrl}. REST-shaped equivalent: {@link create}.
|
|
1513
|
+
*/
|
|
1514
|
+
async createPortalForUrl(targetUrl, opts = {}, requestOptions) {
|
|
1515
|
+
requirePortalTargetUrl(targetUrl);
|
|
1516
|
+
const body = {
|
|
1517
|
+
target_url: targetUrl,
|
|
1518
|
+
...buildCreatePortalBody(opts, "createPortalForUrl"),
|
|
1519
|
+
};
|
|
1520
|
+
const data = await this.request("POST", "/v1/qurls", body, requestOptions);
|
|
1521
|
+
const portal = parsePortal(data, "createPortalForUrl");
|
|
1522
|
+
return {
|
|
1523
|
+
portal,
|
|
1524
|
+
resource: new ProtectedResource(this, portal.resourceId, targetUrl),
|
|
1525
|
+
};
|
|
1526
|
+
}
|
|
1527
|
+
/**
|
|
1528
|
+
* Open a qURL link programmatically and return the reachable resource.
|
|
1529
|
+
*
|
|
1530
|
+
* For services and agents that open received qURL links in code — human
|
|
1531
|
+
* recipients just open the link. Accepts a full platform link
|
|
1532
|
+
* (`https://qurl.link/#at_...`) or a bare access token. Triggers an NHP
|
|
1533
|
+
* knock that grants network access for the caller's IP and returns a
|
|
1534
|
+
* {@link ResourceHandle} with the reachable resource URL and access
|
|
1535
|
+
* lifetime.
|
|
1536
|
+
*
|
|
1537
|
+
* Unlike qurl-go's `EnterPortal` (which verifies links locally and needs
|
|
1538
|
+
* no LayerV credentials), this SDK opens links through the LayerV API:
|
|
1539
|
+
* the client needs an API key with the `qurl:resolve` scope. REST-shaped
|
|
1540
|
+
* equivalent: {@link resolve}.
|
|
1541
|
+
*
|
|
1542
|
+
* Throws {@link ValidationError} (`code: "client_validation"`) when no
|
|
1543
|
+
* access token can be extracted from `qurlLink`, and
|
|
1544
|
+
* (`code: "unexpected_response"`) when access is granted but the API
|
|
1545
|
+
* reports no resource URL — it fails closed rather than returning an
|
|
1546
|
+
* empty handle. Error messages never echo the link; qURL links are
|
|
1547
|
+
* credentials.
|
|
1548
|
+
*/
|
|
1549
|
+
async enterPortal(qurlLink, requestOptions) {
|
|
1550
|
+
const token = extractAccessToken(qurlLink);
|
|
1551
|
+
const resolved = await this.resolve(token, requestOptions);
|
|
1552
|
+
if (typeof resolved?.target_url !== "string" || resolved.target_url === "") {
|
|
1553
|
+
throw unexpectedResponseError("enterPortal: access was granted but the API returned no resource URL");
|
|
1554
|
+
}
|
|
1555
|
+
return {
|
|
1556
|
+
resourceUrl: resolved.target_url,
|
|
1557
|
+
openSeconds: resolved.access_grant?.expires_in ?? 0,
|
|
1558
|
+
resourceId: resolved.resource_id,
|
|
1559
|
+
};
|
|
1560
|
+
}
|
|
1141
1561
|
// --- Public API ---
|
|
1142
|
-
/**
|
|
1562
|
+
/**
|
|
1563
|
+
* Create a new qURL.
|
|
1564
|
+
*
|
|
1565
|
+
* Portal-flow equivalent: {@link createPortalForUrl} (same endpoint,
|
|
1566
|
+
* returns a {@link Portal} plus a reusable resource handle).
|
|
1567
|
+
*/
|
|
1143
1568
|
async create(input, options) {
|
|
1144
1569
|
validateCreateInput(input);
|
|
1145
1570
|
return this.request("POST", "/v1/qurls", input, options);
|
|
@@ -1366,8 +1791,8 @@ class QURLClient {
|
|
|
1366
1791
|
}
|
|
1367
1792
|
if (!id.startsWith(RESOURCE_ID_PREFIX)) {
|
|
1368
1793
|
// Wrong-prefix branch: the input is long enough to plausibly be
|
|
1369
|
-
// an ID but has the wrong prefix (e.g. `q_3a7f2c8e91b
|
|
1370
|
-
//
|
|
1794
|
+
// an ID but has the wrong prefix (e.g. `q_3a7f2c8e91b`).
|
|
1795
|
+
// Echo only the 2-char prefix — never the raw ID
|
|
1371
1796
|
// — so observability pipelines don't end up with caller-supplied
|
|
1372
1797
|
// identifiers in error logs.
|
|
1373
1798
|
const observedPrefix = id.slice(0, RESOURCE_ID_PREFIX.length);
|
|
@@ -1436,6 +1861,8 @@ class QURLClient {
|
|
|
1436
1861
|
/**
|
|
1437
1862
|
* Mint a new access link for a qURL.
|
|
1438
1863
|
*
|
|
1864
|
+
* Portal-flow equivalent: {@link createPortal}.
|
|
1865
|
+
*
|
|
1439
1866
|
* Accepts either a resource ID (`r_` prefix) or a qURL display ID (`q_`
|
|
1440
1867
|
* prefix); the API resolves `q_` IDs to the parent resource automatically.
|
|
1441
1868
|
*
|
|
@@ -1492,6 +1919,9 @@ class QURLClient {
|
|
|
1492
1919
|
/**
|
|
1493
1920
|
* Resolve a qURL access token (headless).
|
|
1494
1921
|
*
|
|
1922
|
+
* Portal-flow equivalent: {@link enterPortal} (also accepts full qURL
|
|
1923
|
+
* links and fails closed when no resource URL is returned).
|
|
1924
|
+
*
|
|
1495
1925
|
* Triggers an NHP knock to grant network access for the caller's IP.
|
|
1496
1926
|
* Requires `qurl:resolve` scope on the API key.
|
|
1497
1927
|
*
|
|
@@ -1546,7 +1976,12 @@ class QURLClient {
|
|
|
1546
1976
|
validateListAllInput(input, RESOURCE_LIST_PARAM_KEYS, "listAllResources");
|
|
1547
1977
|
return this.paginateAll("listAllResources", input, (pageInput) => this.listResources(pageInput), (page) => page.resources);
|
|
1548
1978
|
}
|
|
1549
|
-
/**
|
|
1979
|
+
/**
|
|
1980
|
+
* Create a resource directly.
|
|
1981
|
+
*
|
|
1982
|
+
* Portal-flow equivalent for URL resources: {@link protectUrl} (returns
|
|
1983
|
+
* a portal-minting handle).
|
|
1984
|
+
*/
|
|
1550
1985
|
async createResource(input, options) {
|
|
1551
1986
|
requireObjectInput(input, "createResource");
|
|
1552
1987
|
requireNoUnknownFields(input, CREATE_RESOURCE_FIELD_KEYS, "createResource");
|
|
@@ -1581,7 +2016,11 @@ class QURLClient {
|
|
|
1581
2016
|
requireNonEmptyId(id, "deleteResource");
|
|
1582
2017
|
await this.rawRequest("DELETE", `/v1/resources/${encodeURIComponent(id)}`);
|
|
1583
2018
|
}
|
|
1584
|
-
/**
|
|
2019
|
+
/**
|
|
2020
|
+
* Mint a qURL against an existing resource.
|
|
2021
|
+
*
|
|
2022
|
+
* Portal-flow equivalent: {@link createPortal} (same endpoint).
|
|
2023
|
+
*/
|
|
1585
2024
|
async createQurlForResource(id, input, options) {
|
|
1586
2025
|
requireNonEmptyId(id, "createQurlForResource");
|
|
1587
2026
|
let normalized = input;
|
|
@@ -2202,3 +2641,50 @@ class QURLClient {
|
|
|
2202
2641
|
}
|
|
2203
2642
|
}
|
|
2204
2643
|
exports.QURLClient = QURLClient;
|
|
2644
|
+
/**
|
|
2645
|
+
* A LayerV-protected resource, bound to the client that produced it.
|
|
2646
|
+
*
|
|
2647
|
+
* Obtained from {@link QURLClient.protectUrl},
|
|
2648
|
+
* {@link QURLClient.connectorResource}, or {@link QURLClient.resourceById} —
|
|
2649
|
+
* not constructed directly. Mint short-lived access links for the resource
|
|
2650
|
+
* with {@link createPortal} (qurl-go: `qurl.Resource`).
|
|
2651
|
+
*/
|
|
2652
|
+
class ProtectedResource {
|
|
2653
|
+
// A true private field (not a module-scope WeakMap registry, which
|
|
2654
|
+
// CONTRIBUTING.md's dual-build rule bars) so the binding stays on the
|
|
2655
|
+
// instance and out of Object.keys/JSON.stringify output.
|
|
2656
|
+
#client;
|
|
2657
|
+
/** The LayerV resource id (`r_` prefix). */
|
|
2658
|
+
id;
|
|
2659
|
+
/** The private URL protected by this resource, when known. */
|
|
2660
|
+
targetUrl;
|
|
2661
|
+
/**
|
|
2662
|
+
* Full server-populated {@link Resource} metadata when the handle came
|
|
2663
|
+
* from an API response; `undefined` for {@link QURLClient.resourceById}
|
|
2664
|
+
* handles and for the one-call {@link QURLClient.createPortalForUrl} path.
|
|
2665
|
+
*/
|
|
2666
|
+
details;
|
|
2667
|
+
constructor(client, id, targetUrl, details) {
|
|
2668
|
+
this.#client = client;
|
|
2669
|
+
this.id = id;
|
|
2670
|
+
this.targetUrl = targetUrl;
|
|
2671
|
+
this.details = details;
|
|
2672
|
+
}
|
|
2673
|
+
/**
|
|
2674
|
+
* Whether `resource` was produced by `client`. A static because the
|
|
2675
|
+
* binding lives in a private field that only this class can read; used
|
|
2676
|
+
* by {@link QURLClient.createPortal} to refuse handles bound to a
|
|
2677
|
+
* different client.
|
|
2678
|
+
*/
|
|
2679
|
+
static isBoundTo(resource, client) {
|
|
2680
|
+
return resource.#client === client;
|
|
2681
|
+
}
|
|
2682
|
+
/**
|
|
2683
|
+
* Mint a short-lived qURL link (a portal) for this resource. See
|
|
2684
|
+
* {@link QURLClient.createPortal} for the option reference.
|
|
2685
|
+
*/
|
|
2686
|
+
async createPortal(opts = {}, requestOptions) {
|
|
2687
|
+
return this.#client.createPortal(this, opts, requestOptions);
|
|
2688
|
+
}
|
|
2689
|
+
}
|
|
2690
|
+
exports.ProtectedResource = ProtectedResource;
|
package/dist/cjs/errors.d.ts
CHANGED
|
@@ -14,6 +14,10 @@ export declare const ERROR_CODE_UNEXPECTED_RESPONSE = "unexpected_response";
|
|
|
14
14
|
export declare const ERROR_CODE_NETWORK = "network_error";
|
|
15
15
|
export declare const ERROR_CODE_TIMEOUT = "timeout";
|
|
16
16
|
export declare const ERROR_CODE_RUNTIME = "runtime_error";
|
|
17
|
+
/** `connectorResource` found no resource for the connector id (client-detected, `status: 0`). */
|
|
18
|
+
export declare const ERROR_CODE_RESOURCE_NOT_FOUND = "resource_not_found";
|
|
19
|
+
/** `connectorResource` matched more than one resource where exactly one is required (client-detected, `status: 0`). */
|
|
20
|
+
export declare const ERROR_CODE_AMBIGUOUS_RESOURCE = "ambiguous_resource";
|
|
17
21
|
/** Fallback `.code` when the server returns a non-RFC-7807 response (HTML proxy page, plaintext gateway error, JSON without `error` envelope). */
|
|
18
22
|
export declare const ERROR_CODE_UNKNOWN = "unknown";
|
|
19
23
|
/**
|
package/dist/cjs/errors.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RuntimeError = exports.TimeoutError = exports.NetworkError = exports.ServerError = exports.RateLimitError = exports.ValidationError = exports.NotFoundError = exports.AuthorizationError = exports.AuthenticationError = exports.QURLError = exports.ERROR_CODE_UNKNOWN = exports.ERROR_CODE_RUNTIME = exports.ERROR_CODE_TIMEOUT = exports.ERROR_CODE_NETWORK = exports.ERROR_CODE_UNEXPECTED_RESPONSE = exports.ERROR_CODE_CLIENT_VALIDATION = void 0;
|
|
3
|
+
exports.RuntimeError = exports.TimeoutError = exports.NetworkError = exports.ServerError = exports.RateLimitError = exports.ValidationError = exports.NotFoundError = exports.AuthorizationError = exports.AuthenticationError = exports.QURLError = exports.ERROR_CODE_UNKNOWN = exports.ERROR_CODE_AMBIGUOUS_RESOURCE = exports.ERROR_CODE_RESOURCE_NOT_FOUND = exports.ERROR_CODE_RUNTIME = exports.ERROR_CODE_TIMEOUT = exports.ERROR_CODE_NETWORK = exports.ERROR_CODE_UNEXPECTED_RESPONSE = exports.ERROR_CODE_CLIENT_VALIDATION = void 0;
|
|
4
4
|
exports.createError = createError;
|
|
5
5
|
/**
|
|
6
6
|
* Sentinel `.code` values for SDK-internal failure modes (no real HTTP
|
|
@@ -17,6 +17,10 @@ exports.ERROR_CODE_UNEXPECTED_RESPONSE = "unexpected_response";
|
|
|
17
17
|
exports.ERROR_CODE_NETWORK = "network_error";
|
|
18
18
|
exports.ERROR_CODE_TIMEOUT = "timeout";
|
|
19
19
|
exports.ERROR_CODE_RUNTIME = "runtime_error";
|
|
20
|
+
/** `connectorResource` found no resource for the connector id (client-detected, `status: 0`). */
|
|
21
|
+
exports.ERROR_CODE_RESOURCE_NOT_FOUND = "resource_not_found";
|
|
22
|
+
/** `connectorResource` matched more than one resource where exactly one is required (client-detected, `status: 0`). */
|
|
23
|
+
exports.ERROR_CODE_AMBIGUOUS_RESOURCE = "ambiguous_resource";
|
|
20
24
|
/** Fallback `.code` when the server returns a non-RFC-7807 response (HTML proxy page, plaintext gateway error, JSON without `error` envelope). */
|
|
21
25
|
exports.ERROR_CODE_UNKNOWN = "unknown";
|
|
22
26
|
/**
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { QURLClient } from "./client.js";
|
|
2
|
-
export { AuthenticationError, AuthorizationError, createError, ERROR_CODE_CLIENT_VALIDATION, ERROR_CODE_NETWORK, ERROR_CODE_RUNTIME, ERROR_CODE_TIMEOUT, ERROR_CODE_UNEXPECTED_RESPONSE, ERROR_CODE_UNKNOWN, NetworkError, NotFoundError, QURLError, RateLimitError, RuntimeError, ServerError, TimeoutError, ValidationError, } from "./errors.js";
|
|
1
|
+
export { ProtectedResource, QURLClient } from "./client.js";
|
|
2
|
+
export { AuthenticationError, AuthorizationError, createError, ERROR_CODE_AMBIGUOUS_RESOURCE, ERROR_CODE_CLIENT_VALIDATION, ERROR_CODE_NETWORK, ERROR_CODE_RESOURCE_NOT_FOUND, ERROR_CODE_RUNTIME, ERROR_CODE_TIMEOUT, ERROR_CODE_UNEXPECTED_RESPONSE, ERROR_CODE_UNKNOWN, NetworkError, NotFoundError, QURLError, RateLimitError, RuntimeError, ServerError, TimeoutError, ValidationError, } from "./errors.js";
|
|
3
3
|
export { VERSION } from "./version.js";
|
|
4
|
-
export type { AccessCode, AccessCodeListOutput, AccessGrant, AccessPolicy, AccessToken, AgentBootstrapInput, AgentBootstrapOutput, AIAgentCategory, AIAgentPolicy, ApiKey, ApiKeyListOutput, ApiKeyScope, BatchCreateInput, BatchCreateOutput, BatchItemFailure, BatchItemResult, BatchItemSuccess, BillingInvoiceListOutput, ClientOptions, ConnectorInstallation, ConnectorInstallationCapabilities, ConnectorInstallationListOutput, ConnectorInstallationStats, CreateAccessCodeInput, CreateAccessCodeOutput, CreateApiKeyInput, CreateApiKeyOutput, CreateBillingCheckoutInput, CreateInput, CreateOutput, CreateQurlForResourceInput, CreateResourceInput, CreateWebhookInput, Customer, CheckoutSession, DnsRecord, Domain, DomainCheckDetail, DomainListOutput, DomainVerifyResult, ExtendInput, Invoice, ListApiKeysInput, ListBillingInvoicesInput, ListConnectorInstallationsInput, ListDomainsInput, ListInput, ListOutput, ListWebhooksInput, ListWebhookDeliveriesInput, Meta, MintInput, MintOutput, NHPServerPeerInfo, PaginatedOutput, PortalSession, QURL, QURLErrorData, QurlSummary, Quota, RedeemAccessCodeInput, RedeemAccessCodeOutput, RegisterDomainInput, Resource, ResourceDetail, ResourceListInput, ResourceListOutput, ResourceType, RequestOptions, ResolveInput, ResolveOutput, Session, SessionListOutput, SessionTerminateOutput, TombstoneInfo, UnpaginatedOutput, UpdateApiKeyInput, UpdateCustomerInput, UpdateInput, UpdateResourceInput, UpdateResourceQurlInput, UpdateWebhookInput, UsageCostEstimate, UsageCurrentPeriod, UsageDaily, UsageDailyEntry, Webhook, WebhookDelivery, WebhookDeliveryListOutput, WebhookEventType, WebhookEventTypeInfo, WebhookListOutput, WebhookPayload, WebhookWithSecret, } from "./types.js";
|
|
4
|
+
export type { AccessCode, AccessCodeListOutput, AccessGrant, AccessPolicy, AccessToken, AgentBootstrapInput, AgentBootstrapOutput, AIAgentCategory, AIAgentPolicy, ApiKey, ApiKeyListOutput, ApiKeyScope, BatchCreateInput, BatchCreateOutput, BatchItemFailure, BatchItemResult, BatchItemSuccess, BillingInvoiceListOutput, ClientOptions, ConnectorInstallation, ConnectorInstallationCapabilities, ConnectorInstallationListOutput, ConnectorInstallationStats, CreateAccessCodeInput, CreateAccessCodeOutput, CreateApiKeyInput, CreateApiKeyOutput, CreateBillingCheckoutInput, CreateInput, CreateOutput, CreatePortalOptions, CreateQurlForResourceInput, CreateResourceInput, CreateWebhookInput, Customer, CheckoutSession, DnsRecord, Domain, DomainCheckDetail, DomainListOutput, DomainVerifyResult, ExtendInput, Invoice, ListApiKeysInput, ListBillingInvoicesInput, ListConnectorInstallationsInput, ListDomainsInput, ListInput, ListOutput, ListWebhooksInput, ListWebhookDeliveriesInput, Meta, MintInput, MintOutput, NHPServerPeerInfo, PaginatedOutput, Portal, PortalSession, ProtectUrlOptions, QURL, QURLErrorData, QurlSummary, Quota, RedeemAccessCodeInput, RedeemAccessCodeOutput, RegisterDomainInput, Resource, ResourceDetail, ResourceHandle, ResourceListInput, ResourceListOutput, ResourceType, RequestOptions, ResolveInput, ResolveOutput, Session, SessionListOutput, SessionTerminateOutput, TombstoneInfo, UnpaginatedOutput, UpdateApiKeyInput, UpdateCustomerInput, UpdateInput, UpdateResourceInput, UpdateResourceQurlInput, UpdateWebhookInput, UsageCostEstimate, UsageCurrentPeriod, UsageDaily, UsageDailyEntry, Webhook, WebhookDelivery, WebhookDeliveryListOutput, WebhookEventType, WebhookEventTypeInfo, WebhookListOutput, WebhookPayload, WebhookWithSecret, } from "./types.js";
|
package/dist/cjs/index.js
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.VERSION = exports.ValidationError = exports.TimeoutError = exports.ServerError = exports.RuntimeError = exports.RateLimitError = exports.QURLError = exports.NotFoundError = exports.NetworkError = exports.ERROR_CODE_UNKNOWN = exports.ERROR_CODE_UNEXPECTED_RESPONSE = exports.ERROR_CODE_TIMEOUT = exports.ERROR_CODE_RUNTIME = exports.ERROR_CODE_NETWORK = exports.ERROR_CODE_CLIENT_VALIDATION = exports.createError = exports.AuthorizationError = exports.AuthenticationError = exports.QURLClient = void 0;
|
|
3
|
+
exports.VERSION = exports.ValidationError = exports.TimeoutError = exports.ServerError = exports.RuntimeError = exports.RateLimitError = exports.QURLError = exports.NotFoundError = exports.NetworkError = exports.ERROR_CODE_UNKNOWN = exports.ERROR_CODE_UNEXPECTED_RESPONSE = exports.ERROR_CODE_TIMEOUT = exports.ERROR_CODE_RUNTIME = exports.ERROR_CODE_RESOURCE_NOT_FOUND = exports.ERROR_CODE_NETWORK = exports.ERROR_CODE_CLIENT_VALIDATION = exports.ERROR_CODE_AMBIGUOUS_RESOURCE = exports.createError = exports.AuthorizationError = exports.AuthenticationError = exports.QURLClient = exports.ProtectedResource = void 0;
|
|
4
4
|
var client_js_1 = require("./client.js");
|
|
5
|
+
Object.defineProperty(exports, "ProtectedResource", { enumerable: true, get: function () { return client_js_1.ProtectedResource; } });
|
|
5
6
|
Object.defineProperty(exports, "QURLClient", { enumerable: true, get: function () { return client_js_1.QURLClient; } });
|
|
6
7
|
var errors_js_1 = require("./errors.js");
|
|
7
8
|
Object.defineProperty(exports, "AuthenticationError", { enumerable: true, get: function () { return errors_js_1.AuthenticationError; } });
|
|
8
9
|
Object.defineProperty(exports, "AuthorizationError", { enumerable: true, get: function () { return errors_js_1.AuthorizationError; } });
|
|
9
10
|
Object.defineProperty(exports, "createError", { enumerable: true, get: function () { return errors_js_1.createError; } });
|
|
11
|
+
Object.defineProperty(exports, "ERROR_CODE_AMBIGUOUS_RESOURCE", { enumerable: true, get: function () { return errors_js_1.ERROR_CODE_AMBIGUOUS_RESOURCE; } });
|
|
10
12
|
Object.defineProperty(exports, "ERROR_CODE_CLIENT_VALIDATION", { enumerable: true, get: function () { return errors_js_1.ERROR_CODE_CLIENT_VALIDATION; } });
|
|
11
13
|
Object.defineProperty(exports, "ERROR_CODE_NETWORK", { enumerable: true, get: function () { return errors_js_1.ERROR_CODE_NETWORK; } });
|
|
14
|
+
Object.defineProperty(exports, "ERROR_CODE_RESOURCE_NOT_FOUND", { enumerable: true, get: function () { return errors_js_1.ERROR_CODE_RESOURCE_NOT_FOUND; } });
|
|
12
15
|
Object.defineProperty(exports, "ERROR_CODE_RUNTIME", { enumerable: true, get: function () { return errors_js_1.ERROR_CODE_RUNTIME; } });
|
|
13
16
|
Object.defineProperty(exports, "ERROR_CODE_TIMEOUT", { enumerable: true, get: function () { return errors_js_1.ERROR_CODE_TIMEOUT; } });
|
|
14
17
|
Object.defineProperty(exports, "ERROR_CODE_UNEXPECTED_RESPONSE", { enumerable: true, get: function () { return errors_js_1.ERROR_CODE_UNEXPECTED_RESPONSE; } });
|