monoidentity 0.10.2 → 0.11.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.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { getLoginRecognized, getVerification, useVerification, getStorage } from "./storage.js";
1
+ export { getLoginRecognized, getVerification, useVerification, getStorage, getScopedFS, } from "./storage.js";
2
2
  export { retrieveVerification } from "./storage-attest.js";
3
3
  export { default as rawAttest } from "./verification/attest-remote.js";
4
4
  export { trackReady } from "./trackready.js";
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { getLoginRecognized, getVerification, useVerification, getStorage } from "./storage.js";
1
+ export { getLoginRecognized, getVerification, useVerification, getStorage, getScopedFS, } from "./storage.js";
2
2
  export { retrieveVerification } from "./storage-attest.js";
3
3
  export { default as rawAttest } from "./verification/attest-remote.js";
4
4
  export { trackReady } from "./trackready.js";
@@ -23,17 +23,14 @@ export const wrapWithReplay = (storage) => {
23
23
  const paths = Object.keys(modifications);
24
24
  const tasks = paths.map((path) => (async () => {
25
25
  const mod = modifications[path];
26
+ delete modifications[path];
26
27
  if (mod.type == "set" && mod.old == mod.new) {
27
- delete modifications[path];
28
28
  return;
29
29
  }
30
30
  await tx(path, mod);
31
31
  })()
32
32
  .catch((err) => {
33
33
  console.warn(`[monoidentity] transmitting "${path}" failed`, err);
34
- })
35
- .finally(() => {
36
- delete modifications[path];
37
34
  }));
38
35
  await Promise.all(tasks);
39
36
  }
@@ -13,24 +13,18 @@ export const createLocalStorage = () => createStore({
13
13
  get(key) {
14
14
  if (typeof key != "string")
15
15
  return undefined;
16
- const value = localStorage[prefixed(key)];
17
- if (value == null)
18
- return undefined;
19
- return value;
16
+ return localStorage[prefixed(key)];
20
17
  },
21
18
  set(key, value) {
22
- if (typeof key == "string") {
23
- localStorage[prefixed(key)] = value;
24
- return true;
25
- }
26
- return false;
19
+ if (typeof key != "string")
20
+ return false;
21
+ localStorage[prefixed(key)] = value;
22
+ return true;
27
23
  },
28
24
  deleteProperty(key) {
29
- if (typeof key == "string") {
30
- delete localStorage[prefixed(key)];
31
- return true;
32
- }
33
- return false;
25
+ if (typeof key != "string")
26
+ return false;
27
+ return delete localStorage[prefixed(key)];
34
28
  },
35
29
  ownKeys() {
36
30
  const keys = [];
@@ -42,4 +36,7 @@ export const createLocalStorage = () => createStore({
42
36
  }
43
37
  return keys;
44
38
  },
39
+ getOwnPropertyDescriptor(key) {
40
+ return Reflect.getOwnPropertyDescriptor(localStorage, prefixed(key));
41
+ },
45
42
  });
@@ -5,6 +5,7 @@ type ProxyHandlerWithoutTarget = {
5
5
  set?(p: string | symbol, newValue: any, receiver: any): boolean;
6
6
  deleteProperty?(p: string | symbol): boolean;
7
7
  ownKeys?(): ArrayLike<string | symbol>;
8
+ getOwnPropertyDescriptor?(p: string | symbol): PropertyDescriptor | undefined;
8
9
  };
9
10
  export declare const createStore: <T>(implementation: ProxyHandlerWithoutTarget) => Record<string, T>;
10
11
  export {};
@@ -1,3 +1,3 @@
1
1
  import type { Dict } from "./createstore.js";
2
2
  import type { Bucket } from "../utils-bucket.js";
3
- export declare const wrapCloud: (storage: Dict, bucket: Bucket) => Dict;
3
+ export declare const wrapCloud: (storage: Dict, bucket: Bucket) => Promise<Dict>;
@@ -2,7 +2,7 @@ import { wrapWithReplay } from "./_replay.js";
2
2
  import { AwsClient } from "aws4fetch";
3
3
  import { CLOUD_CACHE_KEY, loadCloud } from "./_cloud.js";
4
4
  import { md5 } from "./_md5.js";
5
- export const wrapCloud = (storage, bucket) => {
5
+ export const wrapCloud = async (storage, bucket) => {
6
6
  const client = new AwsClient({
7
7
  accessKeyId: bucket.accessKeyId,
8
8
  secretAccessKey: bucket.secretAccessKey,
@@ -10,43 +10,41 @@ export const wrapCloud = (storage, bucket) => {
10
10
  const { proxy, setTransmit, flush, load } = wrapWithReplay(storage);
11
11
  const isFirstLoad = !localStorage[CLOUD_CACHE_KEY];
12
12
  if (isFirstLoad) {
13
- loadCloud(bucket.base, client).then((data) => {
14
- load(data);
15
- location.reload();
16
- });
13
+ const data = await loadCloud(bucket.base, client);
14
+ load(data);
17
15
  }
18
- else {
19
- setTransmit(async (path, mod) => {
20
- if (mod.type == "set") {
21
- const url = `${bucket.base}/${path}`;
22
- const headers = new Headers();
23
- if (mod.old) {
24
- // Update only if current matches our known prior content
25
- const etagFromOld = md5(mod.old);
26
- headers.set("If-Match", `"${etagFromOld}"`);
27
- }
28
- else {
29
- // Create only if it does not already exist
30
- headers.set("If-None-Match", "*");
31
- }
32
- const r = await client.fetch(url, {
33
- method: "PUT",
34
- headers,
35
- body: mod.new,
36
- });
37
- if (!r.ok) {
38
- throw new Error(`Cloud is ${r.status}ing`);
39
- }
16
+ setTransmit(async (path, mod) => {
17
+ if (mod.type == "set") {
18
+ const url = `${bucket.base}/${path}`;
19
+ const headers = new Headers();
20
+ if (mod.old) {
21
+ // Update only if current matches our known prior content
22
+ const etagFromOld = md5(mod.old);
23
+ headers.set("If-Match", `"${etagFromOld}"`);
40
24
  }
41
- else if (mod.type == "delete") {
42
- const url = `${bucket.base}/${path}`;
43
- const r = await client.fetch(url, {
44
- method: "DELETE",
45
- });
46
- if (!r.ok)
47
- throw new Error(`Cloud is ${r.status}ing`);
25
+ else {
26
+ // Create only if it does not already exist
27
+ headers.set("If-None-Match", "*");
48
28
  }
49
- });
29
+ const r = await client.fetch(url, {
30
+ method: "PUT",
31
+ headers,
32
+ body: mod.new,
33
+ });
34
+ if (!r.ok) {
35
+ throw new Error(`Cloud is ${r.status}ing`);
36
+ }
37
+ }
38
+ else if (mod.type == "delete") {
39
+ const url = `${bucket.base}/${path}`;
40
+ const r = await client.fetch(url, {
41
+ method: "DELETE",
42
+ });
43
+ if (!r.ok)
44
+ throw new Error(`Cloud is ${r.status}ing`);
45
+ }
46
+ });
47
+ if (!isFirstLoad) {
50
48
  flush().then(async () => {
51
49
  const data = await loadCloud(bucket.base, client);
52
50
  load(data);
package/dist/storage.d.ts CHANGED
@@ -9,3 +9,4 @@ export declare const getVerification: () => Promise<string>;
9
9
  export declare const setVerification: (jwt: string) => void;
10
10
  export declare const useVerification: (jwt: string) => Promise<import("@tsndr/cloudflare-worker-jwt").JwtData<{}, {}>>;
11
11
  export declare const getStorage: (realm: "config" | "cache") => Record<string, any>;
12
+ export declare const getScopedFS: (dir: string) => Record<string, string>;
package/dist/storage.js CHANGED
@@ -39,37 +39,90 @@ export const useVerification = async (jwt) => {
39
39
  const result = await verify(jwt, publicKey, { algorithm: "ES256", throwError: true });
40
40
  return result;
41
41
  };
42
- export const getStorage = (realm) => {
43
- const prefix = (text) => {
44
- if (!app)
45
- throw new Error("No app set");
46
- return `.${realm}/${app}/${text}.devalue`;
47
- };
48
- return createStore({
49
- get(key) {
50
- if (!implementation)
51
- throw new Error("No implementation set");
52
- const item = implementation[prefix(key)];
53
- if (!item)
54
- return undefined;
55
- return parse(item);
56
- },
57
- set(key, value) {
58
- if (!implementation)
59
- throw new Error("No implementation set");
60
- implementation[prefix(key)] = stringify(value);
61
- return true;
62
- },
63
- has(key) {
64
- if (!implementation)
65
- throw new Error("No implementation set");
66
- return prefix(key) in implementation;
67
- },
68
- deleteProperty(key) {
69
- if (!implementation)
70
- throw new Error("No implementation set");
71
- const k = prefix(key);
72
- return delete implementation[k];
73
- },
74
- });
75
- };
42
+ const withPrefix = (obj, prefix, unprefix) => new Proxy(obj, {
43
+ get(target, prop) {
44
+ return target[prefix(prop)];
45
+ },
46
+ set(target, prop, value) {
47
+ target[prefix(prop)] = value;
48
+ return true;
49
+ },
50
+ has(target, prop) {
51
+ return prefix(prop) in target;
52
+ },
53
+ deleteProperty(target, prop) {
54
+ return delete target[prefix(prop)];
55
+ },
56
+ ownKeys(target) {
57
+ if (typeof unprefix != "function") {
58
+ throw new Error("unprefix must be a function");
59
+ }
60
+ return Object.keys(target)
61
+ .map((key) => unprefix(key))
62
+ .filter((key) => typeof key == "string");
63
+ },
64
+ getOwnPropertyDescriptor(target, prop) {
65
+ return Reflect.getOwnPropertyDescriptor(target, prefix(prop));
66
+ },
67
+ });
68
+ export const getStorage = (realm) => withPrefix(createStore({
69
+ get(key) {
70
+ if (!implementation)
71
+ throw new Error("No implementation set");
72
+ const item = implementation[key];
73
+ return item ? parse(item) : undefined;
74
+ },
75
+ set(key, value) {
76
+ if (!implementation)
77
+ throw new Error("No implementation set");
78
+ implementation[key] = stringify(value);
79
+ return true;
80
+ },
81
+ has(key) {
82
+ if (!implementation)
83
+ throw new Error("No implementation set");
84
+ return key in implementation;
85
+ },
86
+ deleteProperty(key) {
87
+ if (!implementation)
88
+ throw new Error("No implementation set");
89
+ return delete implementation[key];
90
+ },
91
+ }), (text) => {
92
+ if (!app)
93
+ throw new Error("No app set");
94
+ return `.${realm}/${app}/${text}.devalue`;
95
+ });
96
+ export const getScopedFS = (dir) => withPrefix(createStore({
97
+ get(key) {
98
+ if (!implementation)
99
+ throw new Error("No implementation set");
100
+ return implementation[key];
101
+ },
102
+ set(key, value) {
103
+ if (!implementation)
104
+ throw new Error("No implementation set");
105
+ implementation[key] = value;
106
+ return true;
107
+ },
108
+ has(key) {
109
+ if (!implementation)
110
+ throw new Error("No implementation set");
111
+ return key in implementation;
112
+ },
113
+ deleteProperty(key) {
114
+ if (!implementation)
115
+ throw new Error("No implementation set");
116
+ return delete implementation[key];
117
+ },
118
+ ownKeys() {
119
+ if (!implementation)
120
+ throw new Error("No implementation set");
121
+ return Object.keys(implementation);
122
+ },
123
+ getOwnPropertyDescriptor(key) {
124
+ if (!implementation)
125
+ throw new Error("No implementation set");
126
+ return Reflect.getOwnPropertyDescriptor(implementation, key);
127
+ },
128
+ }), (text) => `${dir}/${text}`, (text) => (text.startsWith(`${dir}/`) ? text.slice(dir.length + 1) : undefined));
@@ -32,7 +32,7 @@ export const trackReady = async (app, intents, requestBackup) => {
32
32
  let storage;
33
33
  if (setup.method == "cloud") {
34
34
  storage = createLocalStorage();
35
- storage = wrapCloud(storage, setup);
35
+ storage = await wrapCloud(storage, setup);
36
36
  }
37
37
  else if (setup.method == "localStorage") {
38
38
  storage = createLocalStorage();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "monoidentity",
3
- "version": "0.10.2",
3
+ "version": "0.11.1",
4
4
  "repository": "KTibow/monoidentity",
5
5
  "author": {
6
6
  "name": "KTibow"