@tinycloud/sdk-core 2.0.4 → 2.1.0-beta.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/index.cjs +453 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +436 -63
- package/dist/index.d.ts +436 -63
- package/dist/index.js +428 -0
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/dist/index.cjs
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -24,6 +34,8 @@ __export(index_exports, {
|
|
|
24
34
|
CapabilityKeyRegistry: () => CapabilityKeyRegistry,
|
|
25
35
|
CapabilityKeyRegistryErrorCodes: () => CapabilityKeyRegistryErrorCodes,
|
|
26
36
|
ClientSessionSchema: () => ClientSessionSchema,
|
|
37
|
+
DEFAULT_DEFAULTS: () => DEFAULT_DEFAULTS,
|
|
38
|
+
DEFAULT_EXPIRY: () => DEFAULT_EXPIRY,
|
|
27
39
|
DataVaultService: () => import_sdk_services4.DataVaultService,
|
|
28
40
|
DatabaseHandle: () => import_sdk_services4.DatabaseHandle,
|
|
29
41
|
DelegationErrorCodes: () => DelegationErrorCodes,
|
|
@@ -33,12 +45,18 @@ __export(index_exports, {
|
|
|
33
45
|
DuckDbService: () => import_sdk_services4.DuckDbService,
|
|
34
46
|
EnsDataSchema: () => EnsDataSchema,
|
|
35
47
|
ErrorCodes: () => import_sdk_services4.ErrorCodes,
|
|
48
|
+
HooksService: () => import_sdk_services4.HooksService,
|
|
36
49
|
KVService: () => import_sdk_services4.KVService,
|
|
50
|
+
ManifestValidationError: () => ManifestValidationError,
|
|
51
|
+
PermissionNotInManifestError: () => PermissionNotInManifestError,
|
|
37
52
|
PrefixedKVService: () => import_sdk_services4.PrefixedKVService,
|
|
38
53
|
ProtocolMismatchError: () => ProtocolMismatchError,
|
|
54
|
+
SERVICE_LONG_TO_SHORT: () => SERVICE_LONG_TO_SHORT,
|
|
55
|
+
SERVICE_SHORT_TO_LONG: () => SERVICE_SHORT_TO_LONG,
|
|
39
56
|
SQLAction: () => import_sdk_services4.SQLAction,
|
|
40
57
|
SQLService: () => import_sdk_services4.SQLService,
|
|
41
58
|
ServiceContext: () => import_sdk_services4.ServiceContext,
|
|
59
|
+
SessionExpiredError: () => SessionExpiredError,
|
|
42
60
|
SharingService: () => SharingService,
|
|
43
61
|
SilentNotificationHandler: () => SilentNotificationHandler,
|
|
44
62
|
SiweConfigSchema: () => SiweConfigSchema,
|
|
@@ -52,6 +70,7 @@ __export(index_exports, {
|
|
|
52
70
|
VaultPublicSpaceKVActions: () => import_sdk_services4.VaultPublicSpaceKVActions,
|
|
53
71
|
VersionCheckError: () => VersionCheckError,
|
|
54
72
|
activateSessionWithHost: () => activateSessionWithHost,
|
|
73
|
+
applyPrefix: () => applyPrefix,
|
|
55
74
|
buildSpaceUri: () => buildSpaceUri,
|
|
56
75
|
checkNodeInfo: () => checkNodeInfo,
|
|
57
76
|
createCapabilityKeyRegistry: () => createCapabilityKeyRegistry,
|
|
@@ -62,13 +81,21 @@ __export(index_exports, {
|
|
|
62
81
|
defaultSignStrategy: () => defaultSignStrategy,
|
|
63
82
|
defaultSpaceCreationHandler: () => defaultSpaceCreationHandler,
|
|
64
83
|
err: () => import_sdk_services4.err,
|
|
84
|
+
expandActionShortNames: () => expandActionShortNames,
|
|
65
85
|
fetchPeerId: () => fetchPeerId,
|
|
86
|
+
isCapabilitySubset: () => isCapabilitySubset,
|
|
87
|
+
loadManifest: () => loadManifest,
|
|
66
88
|
makePublicSpaceId: () => makePublicSpaceId,
|
|
89
|
+
normalizeDefaults: () => normalizeDefaults,
|
|
67
90
|
ok: () => import_sdk_services4.ok,
|
|
91
|
+
parseExpiry: () => parseExpiry,
|
|
92
|
+
parseRecapCapabilities: () => parseRecapCapabilities,
|
|
68
93
|
parseSpaceUri: () => parseSpaceUri,
|
|
94
|
+
resolveManifest: () => resolveManifest,
|
|
69
95
|
serviceError: () => import_sdk_services4.serviceError,
|
|
70
96
|
submitHostDelegation: () => submitHostDelegation,
|
|
71
97
|
validateClientSession: () => validateClientSession,
|
|
98
|
+
validateManifest: () => validateManifest,
|
|
72
99
|
validatePersistedSessionData: () => validatePersistedSessionData
|
|
73
100
|
});
|
|
74
101
|
module.exports = __toCommonJS(index_exports);
|
|
@@ -1554,6 +1581,7 @@ var TinyCloud = class _TinyCloud {
|
|
|
1554
1581
|
}
|
|
1555
1582
|
this._serviceContext = new import_sdk_services2.ServiceContext({
|
|
1556
1583
|
invoke: effectiveInvoke,
|
|
1584
|
+
invokeAny: this.config.invokeAny,
|
|
1557
1585
|
fetch: fetchFn ?? this.config.fetch ?? globalThis.fetch.bind(globalThis),
|
|
1558
1586
|
hosts: effectiveHosts,
|
|
1559
1587
|
retryPolicy: this.config.retryPolicy
|
|
@@ -1562,6 +1590,7 @@ var TinyCloud = class _TinyCloud {
|
|
|
1562
1590
|
kv: import_sdk_services2.KVService,
|
|
1563
1591
|
sql: import_sdk_services2.SQLService,
|
|
1564
1592
|
duckdb: import_sdk_services2.DuckDbService,
|
|
1593
|
+
hooks: import_sdk_services2.HooksService,
|
|
1565
1594
|
...this.config.services
|
|
1566
1595
|
};
|
|
1567
1596
|
for (const [name, ServiceClass] of Object.entries(serviceConstructors)) {
|
|
@@ -1642,6 +1671,22 @@ var TinyCloud = class _TinyCloud {
|
|
|
1642
1671
|
}
|
|
1643
1672
|
return service;
|
|
1644
1673
|
}
|
|
1674
|
+
/**
|
|
1675
|
+
* Get the Hooks service.
|
|
1676
|
+
* @throws Error if services are not initialized
|
|
1677
|
+
*/
|
|
1678
|
+
get hooks() {
|
|
1679
|
+
if (!this._servicesInitialized) {
|
|
1680
|
+
throw new Error(
|
|
1681
|
+
"Services not initialized. Call initializeServices() first, or use TinyCloudWeb/TinyCloudNode which handles this automatically."
|
|
1682
|
+
);
|
|
1683
|
+
}
|
|
1684
|
+
const service = this._services.get("hooks");
|
|
1685
|
+
if (!service) {
|
|
1686
|
+
throw new Error("Hooks service is not registered.");
|
|
1687
|
+
}
|
|
1688
|
+
return service;
|
|
1689
|
+
}
|
|
1645
1690
|
/**
|
|
1646
1691
|
* Get the Data Vault service.
|
|
1647
1692
|
* @throws Error if services are not initialized or vault service is not registered
|
|
@@ -3760,12 +3805,405 @@ async function checkNodeInfo(host, sdkProtocol, fetchFn = globalThis.fetch.bind(
|
|
|
3760
3805
|
quotaUrl: data.quota_url
|
|
3761
3806
|
};
|
|
3762
3807
|
}
|
|
3808
|
+
|
|
3809
|
+
// src/manifest.ts
|
|
3810
|
+
var import_ms = __toESM(require("ms"), 1);
|
|
3811
|
+
var ManifestValidationError = class extends Error {
|
|
3812
|
+
constructor(message) {
|
|
3813
|
+
super(`Manifest validation failed: ${message}`);
|
|
3814
|
+
this.name = "ManifestValidationError";
|
|
3815
|
+
}
|
|
3816
|
+
};
|
|
3817
|
+
var DEFAULT_EXPIRY = "30d";
|
|
3818
|
+
var DEFAULT_DEFAULTS = true;
|
|
3819
|
+
var SERVICE_SHORT_TO_LONG = Object.freeze({
|
|
3820
|
+
kv: "tinycloud.kv",
|
|
3821
|
+
sql: "tinycloud.sql",
|
|
3822
|
+
duckdb: "tinycloud.duckdb",
|
|
3823
|
+
capabilities: "tinycloud.capabilities",
|
|
3824
|
+
hooks: "tinycloud.hooks"
|
|
3825
|
+
});
|
|
3826
|
+
var SERVICE_LONG_TO_SHORT = Object.freeze(
|
|
3827
|
+
Object.fromEntries(
|
|
3828
|
+
Object.entries(SERVICE_SHORT_TO_LONG).map(([s, l]) => [l, s])
|
|
3829
|
+
)
|
|
3830
|
+
);
|
|
3831
|
+
var DEFAULT_STANDARD_ENTRIES = [
|
|
3832
|
+
{
|
|
3833
|
+
service: "tinycloud.kv",
|
|
3834
|
+
space: "default",
|
|
3835
|
+
path: "/",
|
|
3836
|
+
actions: ["get", "put", "del", "list", "metadata"]
|
|
3837
|
+
},
|
|
3838
|
+
{
|
|
3839
|
+
service: "tinycloud.sql",
|
|
3840
|
+
space: "default",
|
|
3841
|
+
path: "/",
|
|
3842
|
+
actions: ["read", "write"]
|
|
3843
|
+
},
|
|
3844
|
+
{
|
|
3845
|
+
service: "tinycloud.capabilities",
|
|
3846
|
+
space: "default",
|
|
3847
|
+
path: "/",
|
|
3848
|
+
actions: ["read"]
|
|
3849
|
+
}
|
|
3850
|
+
];
|
|
3851
|
+
var DEFAULT_ADMIN_ENTRIES = [
|
|
3852
|
+
{
|
|
3853
|
+
service: "tinycloud.kv",
|
|
3854
|
+
space: "default",
|
|
3855
|
+
path: "/",
|
|
3856
|
+
actions: ["get", "put", "del", "list", "metadata"]
|
|
3857
|
+
},
|
|
3858
|
+
{
|
|
3859
|
+
service: "tinycloud.sql",
|
|
3860
|
+
space: "default",
|
|
3861
|
+
path: "/",
|
|
3862
|
+
actions: ["read", "write", "ddl"]
|
|
3863
|
+
},
|
|
3864
|
+
{
|
|
3865
|
+
service: "tinycloud.capabilities",
|
|
3866
|
+
space: "default",
|
|
3867
|
+
path: "/",
|
|
3868
|
+
actions: ["read", "admin"]
|
|
3869
|
+
}
|
|
3870
|
+
];
|
|
3871
|
+
var DEFAULT_ALL_ENTRIES = [
|
|
3872
|
+
{
|
|
3873
|
+
service: "tinycloud.kv",
|
|
3874
|
+
space: "default",
|
|
3875
|
+
path: "/",
|
|
3876
|
+
actions: ["get", "put", "del", "list", "metadata"]
|
|
3877
|
+
},
|
|
3878
|
+
{
|
|
3879
|
+
service: "tinycloud.sql",
|
|
3880
|
+
space: "default",
|
|
3881
|
+
path: "/",
|
|
3882
|
+
actions: ["read", "write", "ddl"]
|
|
3883
|
+
},
|
|
3884
|
+
{
|
|
3885
|
+
service: "tinycloud.duckdb",
|
|
3886
|
+
space: "default",
|
|
3887
|
+
path: "/",
|
|
3888
|
+
actions: ["read", "write"]
|
|
3889
|
+
},
|
|
3890
|
+
{
|
|
3891
|
+
service: "tinycloud.capabilities",
|
|
3892
|
+
space: "default",
|
|
3893
|
+
path: "/",
|
|
3894
|
+
actions: ["read", "admin"]
|
|
3895
|
+
}
|
|
3896
|
+
];
|
|
3897
|
+
function parseExpiry(duration) {
|
|
3898
|
+
if (typeof duration !== "string" || duration.length === 0) {
|
|
3899
|
+
throw new ManifestValidationError(
|
|
3900
|
+
`expiry must be a non-empty duration string (got ${JSON.stringify(duration)})`
|
|
3901
|
+
);
|
|
3902
|
+
}
|
|
3903
|
+
const parsed = (0, import_ms.default)(
|
|
3904
|
+
duration
|
|
3905
|
+
);
|
|
3906
|
+
if (typeof parsed !== "number" || !Number.isFinite(parsed) || parsed <= 0) {
|
|
3907
|
+
throw new ManifestValidationError(
|
|
3908
|
+
`invalid expiry duration: ${JSON.stringify(duration)}`
|
|
3909
|
+
);
|
|
3910
|
+
}
|
|
3911
|
+
return parsed;
|
|
3912
|
+
}
|
|
3913
|
+
function expandActionShortNames(service, actions) {
|
|
3914
|
+
return actions.map((a) => {
|
|
3915
|
+
if (a.includes("/")) {
|
|
3916
|
+
return a;
|
|
3917
|
+
}
|
|
3918
|
+
return `${service}/${a}`;
|
|
3919
|
+
});
|
|
3920
|
+
}
|
|
3921
|
+
function applyPrefix(prefix, path, skipPrefix) {
|
|
3922
|
+
if (skipPrefix) {
|
|
3923
|
+
return path;
|
|
3924
|
+
}
|
|
3925
|
+
if (prefix === "") {
|
|
3926
|
+
return path;
|
|
3927
|
+
}
|
|
3928
|
+
if (path.startsWith("/")) {
|
|
3929
|
+
return `${prefix}${path}`;
|
|
3930
|
+
}
|
|
3931
|
+
return `${prefix}/${path}`;
|
|
3932
|
+
}
|
|
3933
|
+
async function loadManifest(url) {
|
|
3934
|
+
const fetchFn = globalThis.fetch;
|
|
3935
|
+
if (typeof fetchFn !== "function") {
|
|
3936
|
+
throw new ManifestValidationError(
|
|
3937
|
+
"loadManifest requires a global fetch; pass the manifest object directly on runtimes without fetch"
|
|
3938
|
+
);
|
|
3939
|
+
}
|
|
3940
|
+
const res = await fetchFn(url);
|
|
3941
|
+
if (!res.ok) {
|
|
3942
|
+
throw new ManifestValidationError(
|
|
3943
|
+
`failed to fetch manifest from ${url}: HTTP ${res.status}`
|
|
3944
|
+
);
|
|
3945
|
+
}
|
|
3946
|
+
const json = await res.json();
|
|
3947
|
+
return validateManifest(json);
|
|
3948
|
+
}
|
|
3949
|
+
function validateManifest(input) {
|
|
3950
|
+
if (input === null || typeof input !== "object") {
|
|
3951
|
+
throw new ManifestValidationError("manifest must be an object");
|
|
3952
|
+
}
|
|
3953
|
+
const m = input;
|
|
3954
|
+
if (typeof m.id !== "string" || m.id.length === 0) {
|
|
3955
|
+
throw new ManifestValidationError("manifest.id is required and must be a non-empty string");
|
|
3956
|
+
}
|
|
3957
|
+
if (typeof m.name !== "string" || m.name.length === 0) {
|
|
3958
|
+
throw new ManifestValidationError("manifest.name is required and must be a non-empty string");
|
|
3959
|
+
}
|
|
3960
|
+
if (m.expiry !== void 0) {
|
|
3961
|
+
parseExpiry(m.expiry);
|
|
3962
|
+
}
|
|
3963
|
+
if (m.permissions !== void 0) {
|
|
3964
|
+
if (!Array.isArray(m.permissions)) {
|
|
3965
|
+
throw new ManifestValidationError("manifest.permissions must be an array");
|
|
3966
|
+
}
|
|
3967
|
+
m.permissions.forEach(
|
|
3968
|
+
(p, i) => validatePermissionEntry(p, `permissions[${i}]`)
|
|
3969
|
+
);
|
|
3970
|
+
}
|
|
3971
|
+
if (m.delegations !== void 0) {
|
|
3972
|
+
if (!Array.isArray(m.delegations)) {
|
|
3973
|
+
throw new ManifestValidationError("manifest.delegations must be an array");
|
|
3974
|
+
}
|
|
3975
|
+
m.delegations.forEach((d, i) => {
|
|
3976
|
+
if (typeof d?.to !== "string" || d.to.length === 0) {
|
|
3977
|
+
throw new ManifestValidationError(
|
|
3978
|
+
`delegations[${i}].to is required and must be a non-empty DID string`
|
|
3979
|
+
);
|
|
3980
|
+
}
|
|
3981
|
+
if (d.expiry !== void 0) {
|
|
3982
|
+
parseExpiry(d.expiry);
|
|
3983
|
+
}
|
|
3984
|
+
if (!Array.isArray(d.permissions)) {
|
|
3985
|
+
throw new ManifestValidationError(
|
|
3986
|
+
`delegations[${i}].permissions must be an array`
|
|
3987
|
+
);
|
|
3988
|
+
}
|
|
3989
|
+
d.permissions.forEach(
|
|
3990
|
+
(p, j) => validatePermissionEntry(p, `delegations[${i}].permissions[${j}]`)
|
|
3991
|
+
);
|
|
3992
|
+
});
|
|
3993
|
+
}
|
|
3994
|
+
return m;
|
|
3995
|
+
}
|
|
3996
|
+
function validatePermissionEntry(p, path) {
|
|
3997
|
+
if (p === null || typeof p !== "object") {
|
|
3998
|
+
throw new ManifestValidationError(`${path} must be an object`);
|
|
3999
|
+
}
|
|
4000
|
+
const entry = p;
|
|
4001
|
+
if (typeof entry.service !== "string" || entry.service.length === 0) {
|
|
4002
|
+
throw new ManifestValidationError(`${path}.service is required`);
|
|
4003
|
+
}
|
|
4004
|
+
if (typeof entry.space !== "string" || entry.space.length === 0) {
|
|
4005
|
+
throw new ManifestValidationError(`${path}.space is required`);
|
|
4006
|
+
}
|
|
4007
|
+
if (typeof entry.path !== "string") {
|
|
4008
|
+
throw new ManifestValidationError(
|
|
4009
|
+
`${path}.path is required (use "" or "/" for root)`
|
|
4010
|
+
);
|
|
4011
|
+
}
|
|
4012
|
+
if (!Array.isArray(entry.actions) || entry.actions.length === 0) {
|
|
4013
|
+
throw new ManifestValidationError(
|
|
4014
|
+
`${path}.actions must be a non-empty array`
|
|
4015
|
+
);
|
|
4016
|
+
}
|
|
4017
|
+
if (entry.expiry !== void 0) {
|
|
4018
|
+
parseExpiry(entry.expiry);
|
|
4019
|
+
}
|
|
4020
|
+
}
|
|
4021
|
+
function normalizeDefaults(value) {
|
|
4022
|
+
if (value === void 0) {
|
|
4023
|
+
return DEFAULT_DEFAULTS;
|
|
4024
|
+
}
|
|
4025
|
+
if (typeof value === "boolean") {
|
|
4026
|
+
return value;
|
|
4027
|
+
}
|
|
4028
|
+
if (typeof value !== "string") {
|
|
4029
|
+
return true;
|
|
4030
|
+
}
|
|
4031
|
+
const normalized = value.trim().toLowerCase();
|
|
4032
|
+
if (normalized === "admin" || normalized === "all") {
|
|
4033
|
+
return normalized;
|
|
4034
|
+
}
|
|
4035
|
+
return true;
|
|
4036
|
+
}
|
|
4037
|
+
function defaultEntriesForTier(tier) {
|
|
4038
|
+
if (tier === false) {
|
|
4039
|
+
return [];
|
|
4040
|
+
}
|
|
4041
|
+
const source = tier === "admin" ? DEFAULT_ADMIN_ENTRIES : tier === "all" ? DEFAULT_ALL_ENTRIES : DEFAULT_STANDARD_ENTRIES;
|
|
4042
|
+
return source.map((e) => ({
|
|
4043
|
+
service: e.service,
|
|
4044
|
+
space: e.space,
|
|
4045
|
+
path: e.path,
|
|
4046
|
+
actions: [...e.actions]
|
|
4047
|
+
}));
|
|
4048
|
+
}
|
|
4049
|
+
function resolveManifest(input) {
|
|
4050
|
+
const manifest = validateManifest(input);
|
|
4051
|
+
const prefix = manifest.prefix !== void 0 ? manifest.prefix : manifest.id;
|
|
4052
|
+
const expiryMs = parseExpiry(manifest.expiry ?? DEFAULT_EXPIRY);
|
|
4053
|
+
const includePublicSpace = manifest.includePublicSpace ?? true;
|
|
4054
|
+
const tier = normalizeDefaults(manifest.defaults);
|
|
4055
|
+
const defaultEntries = defaultEntriesForTier(tier);
|
|
4056
|
+
const explicitEntries = manifest.permissions ?? [];
|
|
4057
|
+
const allEntries = [...defaultEntries, ...explicitEntries];
|
|
4058
|
+
const resources = allEntries.map(
|
|
4059
|
+
(entry) => resolveEntry(entry, prefix, expiryMs)
|
|
4060
|
+
);
|
|
4061
|
+
const additionalDelegates = (manifest.delegations ?? []).map((d) => ({
|
|
4062
|
+
did: d.to,
|
|
4063
|
+
name: d.name,
|
|
4064
|
+
expiryMs: parseExpiry(d.expiry ?? manifest.expiry ?? DEFAULT_EXPIRY),
|
|
4065
|
+
permissions: d.permissions.map(
|
|
4066
|
+
(entry) => resolveEntry(
|
|
4067
|
+
entry,
|
|
4068
|
+
prefix,
|
|
4069
|
+
parseExpiry(d.expiry ?? manifest.expiry ?? DEFAULT_EXPIRY)
|
|
4070
|
+
)
|
|
4071
|
+
)
|
|
4072
|
+
}));
|
|
4073
|
+
return {
|
|
4074
|
+
id: manifest.id,
|
|
4075
|
+
resources,
|
|
4076
|
+
expiryMs,
|
|
4077
|
+
includePublicSpace,
|
|
4078
|
+
additionalDelegates
|
|
4079
|
+
};
|
|
4080
|
+
}
|
|
4081
|
+
function resolveEntry(entry, prefix, _inheritedExpiryMs) {
|
|
4082
|
+
const resolvedPath = applyPrefix(
|
|
4083
|
+
prefix,
|
|
4084
|
+
entry.path,
|
|
4085
|
+
entry.skipPrefix === true
|
|
4086
|
+
);
|
|
4087
|
+
const resolvedActions = expandActionShortNames(entry.service, entry.actions);
|
|
4088
|
+
const entryExpiryMs = entry.expiry !== void 0 ? parseExpiry(entry.expiry) : void 0;
|
|
4089
|
+
return {
|
|
4090
|
+
service: entry.service,
|
|
4091
|
+
space: entry.space,
|
|
4092
|
+
path: resolvedPath,
|
|
4093
|
+
actions: resolvedActions,
|
|
4094
|
+
// Only populate `expiryMs` when the entry had its own expiry override.
|
|
4095
|
+
// When absent, callers use the parent (delegation or manifest) expiry
|
|
4096
|
+
// which is carried on ResolvedDelegate.expiryMs / ResolvedCapabilities.expiryMs.
|
|
4097
|
+
...entryExpiryMs !== void 0 ? { expiryMs: entryExpiryMs } : {}
|
|
4098
|
+
};
|
|
4099
|
+
}
|
|
4100
|
+
|
|
4101
|
+
// src/capabilities.ts
|
|
4102
|
+
var PermissionNotInManifestError = class extends Error {
|
|
4103
|
+
constructor(missing, granted) {
|
|
4104
|
+
super(
|
|
4105
|
+
`Requested capabilities exceed current session. Missing ${missing.length} entries.`
|
|
4106
|
+
);
|
|
4107
|
+
this.name = "PermissionNotInManifestError";
|
|
4108
|
+
this.missing = missing;
|
|
4109
|
+
this.granted = granted;
|
|
4110
|
+
}
|
|
4111
|
+
};
|
|
4112
|
+
var SessionExpiredError = class extends Error {
|
|
4113
|
+
constructor(expiredAt) {
|
|
4114
|
+
super(`Session expired at ${expiredAt.toISOString()}`);
|
|
4115
|
+
this.name = "SessionExpiredError";
|
|
4116
|
+
this.expiredAt = expiredAt;
|
|
4117
|
+
}
|
|
4118
|
+
};
|
|
4119
|
+
function isCapabilitySubset(requested, granted) {
|
|
4120
|
+
const missing = [];
|
|
4121
|
+
for (const req of requested) {
|
|
4122
|
+
const match = granted.find((g) => canonicalizeEntryMatches(req, g));
|
|
4123
|
+
if (match === void 0) {
|
|
4124
|
+
missing.push(cloneEntry(req));
|
|
4125
|
+
continue;
|
|
4126
|
+
}
|
|
4127
|
+
}
|
|
4128
|
+
return { subset: missing.length === 0, missing };
|
|
4129
|
+
}
|
|
4130
|
+
function canonicalizeEntryMatches(requested, granted) {
|
|
4131
|
+
if (requested.service !== granted.service) {
|
|
4132
|
+
return false;
|
|
4133
|
+
}
|
|
4134
|
+
if (requested.space !== granted.space) {
|
|
4135
|
+
return false;
|
|
4136
|
+
}
|
|
4137
|
+
if (!pathContains(granted.path, requested.path)) {
|
|
4138
|
+
return false;
|
|
4139
|
+
}
|
|
4140
|
+
const reqActions = new Set(
|
|
4141
|
+
expandActionShortNames(requested.service, requested.actions)
|
|
4142
|
+
);
|
|
4143
|
+
const grantedActions = new Set(
|
|
4144
|
+
expandActionShortNames(granted.service, granted.actions)
|
|
4145
|
+
);
|
|
4146
|
+
for (const a of reqActions) {
|
|
4147
|
+
if (!grantedActions.has(a)) {
|
|
4148
|
+
return false;
|
|
4149
|
+
}
|
|
4150
|
+
}
|
|
4151
|
+
return true;
|
|
4152
|
+
}
|
|
4153
|
+
function pathContains(grantedPath, requestedPath) {
|
|
4154
|
+
if (grantedPath === "" || grantedPath === "/") {
|
|
4155
|
+
return true;
|
|
4156
|
+
}
|
|
4157
|
+
if (grantedPath.endsWith("/")) {
|
|
4158
|
+
return requestedPath.startsWith(grantedPath);
|
|
4159
|
+
}
|
|
4160
|
+
return requestedPath === grantedPath;
|
|
4161
|
+
}
|
|
4162
|
+
function cloneEntry(entry) {
|
|
4163
|
+
return {
|
|
4164
|
+
service: entry.service,
|
|
4165
|
+
space: entry.space,
|
|
4166
|
+
path: entry.path,
|
|
4167
|
+
actions: [...entry.actions],
|
|
4168
|
+
...entry.skipPrefix !== void 0 ? { skipPrefix: entry.skipPrefix } : {},
|
|
4169
|
+
...entry.expiry !== void 0 ? { expiry: entry.expiry } : {}
|
|
4170
|
+
};
|
|
4171
|
+
}
|
|
4172
|
+
function parseRecapCapabilities(parseWasm, siwe) {
|
|
4173
|
+
const raw = parseWasm(siwe);
|
|
4174
|
+
if (!Array.isArray(raw)) {
|
|
4175
|
+
throw new Error(
|
|
4176
|
+
"parseRecapFromSiwe returned a non-array value; wasm binding may be out of sync"
|
|
4177
|
+
);
|
|
4178
|
+
}
|
|
4179
|
+
const normalized = raw.map((entry) => {
|
|
4180
|
+
const longService = SERVICE_SHORT_TO_LONG[entry.service] ?? // Unknown short names pass through. If the recap already contained a
|
|
4181
|
+
// long-form service (e.g. a future tinycloud-node version emits long
|
|
4182
|
+
// form directly), don't double-prefix.
|
|
4183
|
+
(entry.service.startsWith("tinycloud.") ? entry.service : `tinycloud.${entry.service}`);
|
|
4184
|
+
return {
|
|
4185
|
+
service: longService,
|
|
4186
|
+
space: entry.space,
|
|
4187
|
+
path: entry.path,
|
|
4188
|
+
actions: [...entry.actions]
|
|
4189
|
+
};
|
|
4190
|
+
});
|
|
4191
|
+
normalized.sort((a, b) => {
|
|
4192
|
+
if (a.space !== b.space) return a.space < b.space ? -1 : 1;
|
|
4193
|
+
if (a.service !== b.service) return a.service < b.service ? -1 : 1;
|
|
4194
|
+
if (a.path !== b.path) return a.path < b.path ? -1 : 1;
|
|
4195
|
+
return 0;
|
|
4196
|
+
});
|
|
4197
|
+
return normalized;
|
|
4198
|
+
}
|
|
3763
4199
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3764
4200
|
0 && (module.exports = {
|
|
3765
4201
|
AutoApproveSpaceCreationHandler,
|
|
3766
4202
|
CapabilityKeyRegistry,
|
|
3767
4203
|
CapabilityKeyRegistryErrorCodes,
|
|
3768
4204
|
ClientSessionSchema,
|
|
4205
|
+
DEFAULT_DEFAULTS,
|
|
4206
|
+
DEFAULT_EXPIRY,
|
|
3769
4207
|
DataVaultService,
|
|
3770
4208
|
DatabaseHandle,
|
|
3771
4209
|
DelegationErrorCodes,
|
|
@@ -3775,12 +4213,18 @@ async function checkNodeInfo(host, sdkProtocol, fetchFn = globalThis.fetch.bind(
|
|
|
3775
4213
|
DuckDbService,
|
|
3776
4214
|
EnsDataSchema,
|
|
3777
4215
|
ErrorCodes,
|
|
4216
|
+
HooksService,
|
|
3778
4217
|
KVService,
|
|
4218
|
+
ManifestValidationError,
|
|
4219
|
+
PermissionNotInManifestError,
|
|
3779
4220
|
PrefixedKVService,
|
|
3780
4221
|
ProtocolMismatchError,
|
|
4222
|
+
SERVICE_LONG_TO_SHORT,
|
|
4223
|
+
SERVICE_SHORT_TO_LONG,
|
|
3781
4224
|
SQLAction,
|
|
3782
4225
|
SQLService,
|
|
3783
4226
|
ServiceContext,
|
|
4227
|
+
SessionExpiredError,
|
|
3784
4228
|
SharingService,
|
|
3785
4229
|
SilentNotificationHandler,
|
|
3786
4230
|
SiweConfigSchema,
|
|
@@ -3794,6 +4238,7 @@ async function checkNodeInfo(host, sdkProtocol, fetchFn = globalThis.fetch.bind(
|
|
|
3794
4238
|
VaultPublicSpaceKVActions,
|
|
3795
4239
|
VersionCheckError,
|
|
3796
4240
|
activateSessionWithHost,
|
|
4241
|
+
applyPrefix,
|
|
3797
4242
|
buildSpaceUri,
|
|
3798
4243
|
checkNodeInfo,
|
|
3799
4244
|
createCapabilityKeyRegistry,
|
|
@@ -3804,13 +4249,21 @@ async function checkNodeInfo(host, sdkProtocol, fetchFn = globalThis.fetch.bind(
|
|
|
3804
4249
|
defaultSignStrategy,
|
|
3805
4250
|
defaultSpaceCreationHandler,
|
|
3806
4251
|
err,
|
|
4252
|
+
expandActionShortNames,
|
|
3807
4253
|
fetchPeerId,
|
|
4254
|
+
isCapabilitySubset,
|
|
4255
|
+
loadManifest,
|
|
3808
4256
|
makePublicSpaceId,
|
|
4257
|
+
normalizeDefaults,
|
|
3809
4258
|
ok,
|
|
4259
|
+
parseExpiry,
|
|
4260
|
+
parseRecapCapabilities,
|
|
3810
4261
|
parseSpaceUri,
|
|
4262
|
+
resolveManifest,
|
|
3811
4263
|
serviceError,
|
|
3812
4264
|
submitHostDelegation,
|
|
3813
4265
|
validateClientSession,
|
|
4266
|
+
validateManifest,
|
|
3814
4267
|
validatePersistedSessionData
|
|
3815
4268
|
});
|
|
3816
4269
|
//# sourceMappingURL=index.cjs.map
|