@ada-support/web-storage 1.4.6 → 1.4.8
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/biome.json +11 -0
- package/dist/cli/generate-html.js +41 -7
- package/dist/create-storage.js +6 -6
- package/dist/index.js +1 -1
- package/dist/storage-keys.d.ts +25 -24
- package/package.json +10 -7
- package/src/cli/generate-html.ts +79 -32
- package/src/create-storage.ts +62 -54
- package/src/functional-storage.ts +21 -21
- package/src/index.ts +8 -8
- package/src/storage-keys.ts +77 -76
- package/src/third-party-items.ts +212 -205
- package/.eslintignore +0 -2
- package/.eslintrc +0 -10
- package/.github/PULL_REQUEST_TEMPLATE.md +0 -13
- package/.github/dependabot.yml +0 -11
- package/.github/workflows/dependabot-jira.yml +0 -26
- package/.github/workflows/deploy-html.yml +0 -44
- package/.github/workflows/flag-cleanup.yml +0 -45
- package/.github/workflows/notify-people.yml +0 -42
- package/.github/workflows/npm-publish.yml +0 -45
- package/.github/workflows/verify-code.yml +0 -34
package/biome.json
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://biomejs.dev/schemas/2.4.10/schema.json",
|
|
3
|
+
"extends": ["../biome-config/biome.json"],
|
|
4
|
+
"vcs": {
|
|
5
|
+
"enabled": true,
|
|
6
|
+
"clientKind": "git",
|
|
7
|
+
"useIgnoreFile": true,
|
|
8
|
+
"defaultBranch": "main"
|
|
9
|
+
},
|
|
10
|
+
"files": { "includes": ["src/**/*.ts"] }
|
|
11
|
+
}
|
|
@@ -9,20 +9,41 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
|
9
9
|
return to.concat(ar || Array.prototype.slice.call(from));
|
|
10
10
|
};
|
|
11
11
|
exports.__esModule = true;
|
|
12
|
-
var
|
|
12
|
+
var node_fs_1 = require("node:fs");
|
|
13
13
|
var third_party_items_1 = require("../third-party-items");
|
|
14
14
|
var OUTPUT_DIR = "dist";
|
|
15
15
|
var OUTPUT_FILENAME = "ada-web-storage-list.html";
|
|
16
16
|
var PARSE_ERROR_MESSAGE = "Could not parse StorageValueByKey interface";
|
|
17
|
+
// KEY_LINES is /g only so `.match` returns every key line for the declared list;
|
|
18
|
+
// KEY_LINE must stay non-global so `.match` returns capture groups and [1] is the
|
|
19
|
+
// key name. Don't merge them: with a global regex `[1]` is the second matched line
|
|
20
|
+
// instead, so keyName silently becomes garbage in the published registry.
|
|
21
|
+
// Both need `m` — a key sits on its own line after the entry's doc comment.
|
|
22
|
+
var KEY_LINE = /^\s*"?([\w-]+)"?:\s/m;
|
|
23
|
+
var KEY_LINES = /^\s*"?([\w-]+)"?:\s/gm;
|
|
24
|
+
var INTERFACE_DECL = "export interface StorageValueByKey {";
|
|
17
25
|
function runScript() {
|
|
18
|
-
var
|
|
26
|
+
var _a;
|
|
27
|
+
var data = (0, node_fs_1.readFileSync)("./src/storage-keys.ts", "utf-8");
|
|
19
28
|
var matches = data.match(/StorageValueByKey \{([^}]+)}/);
|
|
20
29
|
if (!matches) {
|
|
21
30
|
throw new Error(PARSE_ERROR_MESSAGE);
|
|
22
31
|
}
|
|
23
32
|
var items = matches[0].split("\n\n").map(function (item) { return item.trim(); });
|
|
24
|
-
|
|
25
|
-
|
|
33
|
+
// Read the declared keys from the interface's real extent — its declaration to
|
|
34
|
+
// its own column-0 closing brace — NOT from `matches`. The `[^}]+` above stops
|
|
35
|
+
// at the first `}`, so an inline object value truncates it, and anything derived
|
|
36
|
+
// from that same match would shrink in step and hide the loss.
|
|
37
|
+
var declStart = data.indexOf(INTERFACE_DECL);
|
|
38
|
+
var declEnd = declStart === -1 ? -1 : data.indexOf("\n}", declStart);
|
|
39
|
+
if (declStart === -1 || declEnd === -1) {
|
|
40
|
+
throw new Error(PARSE_ERROR_MESSAGE);
|
|
41
|
+
}
|
|
42
|
+
var declaredNames = ((_a = data.slice(declStart, declEnd).match(KEY_LINES)) !== null && _a !== void 0 ? _a : []).map(function (line) { var _a, _b; return (_b = (_a = line.match(KEY_LINE)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : line.trim(); });
|
|
43
|
+
var storageRecords = items.map(function (item) {
|
|
44
|
+
// Quotes are optional: the formatter strips redundant ones from
|
|
45
|
+
// identifier-safe key names, so only hyphenated keys keep them.
|
|
46
|
+
var nameMatches = item.match(KEY_LINE);
|
|
26
47
|
var descriptionMatches = item.match(/\/\*\*([^}]+)\*\//);
|
|
27
48
|
if (!nameMatches || !descriptionMatches) {
|
|
28
49
|
throw new Error(PARSE_ERROR_MESSAGE);
|
|
@@ -34,11 +55,24 @@ function runScript() {
|
|
|
34
55
|
duration: "Persistent",
|
|
35
56
|
purpose: ["Functional"]
|
|
36
57
|
};
|
|
37
|
-
})
|
|
38
|
-
|
|
58
|
+
});
|
|
59
|
+
// Compare the key SETS, not their sizes: a size check passes whenever two
|
|
60
|
+
// defects cancel out, and it can't name what went missing. This can, and it is
|
|
61
|
+
// the assertion a golden-file test would make.
|
|
62
|
+
var parsedNames = storageRecords.map(function (record) { return record.keyName; });
|
|
63
|
+
var missing = declaredNames.filter(function (n) { return parsedNames.indexOf(n) === -1; });
|
|
64
|
+
var unexpected = parsedNames.filter(function (n) { return declaredNames.indexOf(n) === -1; });
|
|
65
|
+
if (missing.length > 0 || unexpected.length > 0) {
|
|
66
|
+
throw new Error("".concat(PARSE_ERROR_MESSAGE, ": declared but not parsed: [").concat(missing.join(", "), "]; parsed but not declared: [").concat(unexpected.join(", "), "]. Each key needs its own entry separated by an empty line, and no entry may contain a brace (see storage-keys.ts)."));
|
|
67
|
+
}
|
|
68
|
+
var records = __spreadArray(__spreadArray([], storageRecords, true), third_party_items_1.THIRD_PARTY_ITEMS, true).sort(function (a, b) { return a.keyName.localeCompare(b.keyName); });
|
|
69
|
+
var html = "\n <html lang=\"en\">\n <head>\n <title>Ada client-side storage</title>\n <meta charset=\"utf-8\">\n <style>\n body {\n font-family: sans-serif;\n }\n \n h1 {\n font-size: 1.4em;\n }\n \n table {\n border-collapse: collapse;\n }\n \n table th, table td {\n text-align: left;\n padding: 10px;\n border: 1px solid;\n } \n </style>\n </head>\n <body>\n <h1>Ada client-side storage (\u201Ccookies\u201D)</h1>\n <table>\n <thead>\n <tr>\n <th>Name</th><th>Description</th><th>Type</th><th>Duration</th>\n <tr>\n </thead>\n <tbody>\n ".concat(records
|
|
70
|
+
.map(function (record) { return "\n <tr>\n <td>".concat(record.keyName, "</td>\n <td>").concat(record.description, "</td>\n <td>").concat(record.type, " (").concat(record.purpose.map(function (i) { return i.toLocaleLowerCase(); }).join(", "), ")</td>\n <td>").concat(record.duration, "</td>\n </tr>\n "); })
|
|
71
|
+
.join("\n")
|
|
72
|
+
.trim(), "\n </tbody>\n </table>\n </body>\n </html>\n ")
|
|
39
73
|
.trim()
|
|
40
74
|
.replace(/ {2}/g, "")
|
|
41
75
|
.replace(/\n+/g, "\n");
|
|
42
|
-
(0,
|
|
76
|
+
(0, node_fs_1.writeFileSync)("./".concat(OUTPUT_DIR, "/").concat(OUTPUT_FILENAME), html);
|
|
43
77
|
}
|
|
44
78
|
runScript();
|
package/dist/create-storage.js
CHANGED
|
@@ -19,7 +19,7 @@ var createStorage = function (storageType) {
|
|
|
19
19
|
try {
|
|
20
20
|
storageProvider = storageType === "local" ? localStorage : sessionStorage;
|
|
21
21
|
}
|
|
22
|
-
catch (
|
|
22
|
+
catch (_a) {
|
|
23
23
|
console.warn(WEB_STORAGE_ACCESS_ERROR_MESSAGE);
|
|
24
24
|
}
|
|
25
25
|
var storage = {
|
|
@@ -27,7 +27,7 @@ var createStorage = function (storageType) {
|
|
|
27
27
|
try {
|
|
28
28
|
storageProvider.setItem(key, JSON.stringify(value));
|
|
29
29
|
}
|
|
30
|
-
catch (
|
|
30
|
+
catch (_a) {
|
|
31
31
|
console.warn(WEB_STORAGE_ACCESS_ERROR_MESSAGE);
|
|
32
32
|
}
|
|
33
33
|
},
|
|
@@ -36,7 +36,7 @@ var createStorage = function (storageType) {
|
|
|
36
36
|
var rawStorageValue = storageProvider.getItem(key);
|
|
37
37
|
return rawStorageValue && JSON.parse(rawStorageValue);
|
|
38
38
|
}
|
|
39
|
-
catch (
|
|
39
|
+
catch (_a) {
|
|
40
40
|
console.warn(WEB_STORAGE_ACCESS_ERROR_MESSAGE);
|
|
41
41
|
return null;
|
|
42
42
|
}
|
|
@@ -45,7 +45,7 @@ var createStorage = function (storageType) {
|
|
|
45
45
|
try {
|
|
46
46
|
storageProvider.removeItem(key);
|
|
47
47
|
}
|
|
48
|
-
catch (
|
|
48
|
+
catch (_a) {
|
|
49
49
|
console.warn(WEB_STORAGE_ACCESS_ERROR_MESSAGE);
|
|
50
50
|
}
|
|
51
51
|
},
|
|
@@ -53,7 +53,7 @@ var createStorage = function (storageType) {
|
|
|
53
53
|
try {
|
|
54
54
|
storageProvider.clear();
|
|
55
55
|
}
|
|
56
|
-
catch (
|
|
56
|
+
catch (_a) {
|
|
57
57
|
console.warn(WEB_STORAGE_ACCESS_ERROR_MESSAGE);
|
|
58
58
|
}
|
|
59
59
|
},
|
|
@@ -67,7 +67,7 @@ var createStorage = function (storageType) {
|
|
|
67
67
|
/** Gets a value under `ada-functional-storage` Storage key */
|
|
68
68
|
getFnItem: function (key) {
|
|
69
69
|
var value = storage.getItem("ada-functional-storage");
|
|
70
|
-
return (value
|
|
70
|
+
return (value === null || value === void 0 ? void 0 : value[key]) || null;
|
|
71
71
|
}
|
|
72
72
|
};
|
|
73
73
|
return storage;
|
package/dist/index.js
CHANGED
package/dist/storage-keys.d.ts
CHANGED
|
@@ -18,7 +18,8 @@ export interface MessagingAuthState {
|
|
|
18
18
|
*
|
|
19
19
|
* The interface is being parsed by `./src/cli/generate-html.ts` script.
|
|
20
20
|
* The format of code here must be consistent, i.e.
|
|
21
|
-
* each key should have a comment,
|
|
21
|
+
* each key should have a comment, and keys must be separated by an empty line.
|
|
22
|
+
* Quoting the key name is optional — the parser accepts either form.
|
|
22
23
|
*/
|
|
23
24
|
export interface StorageValueByKey {
|
|
24
25
|
/** Used to store the Web SDK version assigned to a user. */
|
|
@@ -44,52 +45,52 @@ export interface StorageValueByKey {
|
|
|
44
45
|
/** Used to store general information about Ada application state. */
|
|
45
46
|
"ada-functional-storage": Partial<AdaFunctionalStorageValue>;
|
|
46
47
|
/** Used to identify the user within Ada. */
|
|
47
|
-
|
|
48
|
+
chatter: string;
|
|
48
49
|
/** Used to determine whether chatter session is expired. This is stored on Ada domain. */
|
|
49
|
-
|
|
50
|
+
created: string;
|
|
50
51
|
/** Used for live chat messaging functionality. */
|
|
51
|
-
|
|
52
|
+
delayMessageAfterLiveChatEndTimeStamp: number;
|
|
52
53
|
/** Indicates whether user is connected to a live agent. */
|
|
53
|
-
|
|
54
|
+
inLiveChat: boolean;
|
|
54
55
|
/** Indicates whether user is waiting to connect to a live agent. */
|
|
55
|
-
|
|
56
|
+
liveChatPending: boolean;
|
|
56
57
|
/** Used to implement Chat reconnection after an interruption. */
|
|
57
|
-
|
|
58
|
+
netDisruptionMsgStartTime: number;
|
|
58
59
|
/** Stores Chat iFrame parent window origin. */
|
|
59
|
-
|
|
60
|
+
parentOrigin: string;
|
|
60
61
|
/** Used to cache Zendesk tags assigned to a conversation. This is stored on Ada domain. */
|
|
61
|
-
|
|
62
|
+
previousZDTags: string;
|
|
62
63
|
/** Used for Zendesk authentication functionality. */
|
|
63
|
-
|
|
64
|
+
previouslyAuthenticated: boolean;
|
|
64
65
|
/** Used for chatter authentication. */
|
|
65
66
|
"ada-embed_session-token": string;
|
|
66
67
|
/** Stores the messaging authentication state (its owner chatter, a short-lived messaging access token and expiry, a rotating session refresh token, and a refresh counter) used to authenticate the visitor's generative chat session with Ada. Set on the bot's Ada subdomain. */
|
|
67
|
-
|
|
68
|
+
messagingAuthState: MessagingAuthState;
|
|
68
69
|
/** Used to implement Chat reconnection after an interruption. */
|
|
69
|
-
|
|
70
|
+
backoffTimeout: number;
|
|
70
71
|
/** Used during Oracle handoffs to indicate whether the agent has sent a request for a secret message. Allows the state to persist between page changes. */
|
|
71
|
-
|
|
72
|
+
secretButton: string;
|
|
72
73
|
/** Used to keep the builder session active for 24 hours before authentication is required again. Note this is only added if a chatter has logged into the dashboard. */
|
|
73
|
-
|
|
74
|
+
session: string;
|
|
74
75
|
/** Used for chatter authentication. This is stored on Ada domain. */
|
|
75
|
-
|
|
76
|
+
sessionToken: string;
|
|
76
77
|
/** Used to default the test bot to the previously tested modality */
|
|
77
|
-
|
|
78
|
+
testBotModality: "messaging" | "voice" | undefined;
|
|
78
79
|
/** Used for voice chat functionality in the bot builder dashboard */
|
|
79
|
-
|
|
80
|
+
testBotPhoneNumber: string;
|
|
80
81
|
/** Used for Zendesk authentication functionality. */
|
|
81
|
-
|
|
82
|
+
zdAuthChatPending: boolean;
|
|
82
83
|
/** Used for Zendesk SDK functionality. */
|
|
83
|
-
|
|
84
|
+
zdCid: string;
|
|
84
85
|
/** Used for Zendesk SDK functionality. */
|
|
85
|
-
|
|
86
|
+
zdCStore: string;
|
|
86
87
|
/** Used for Zendesk SDK functionality. */
|
|
87
|
-
|
|
88
|
+
zdMessagingExternalUserId: string;
|
|
88
89
|
/** Used for Zendesk SDK functionality. */
|
|
89
|
-
|
|
90
|
+
zdMessagingChatterCreated: string;
|
|
90
91
|
/** Used for Zendesk SDK functionality. */
|
|
91
|
-
|
|
92
|
+
zdSessionId: string;
|
|
92
93
|
/** Used for Zendesk authentication functionality. */
|
|
93
|
-
|
|
94
|
+
zd_isChatterAuthenticated: boolean;
|
|
94
95
|
}
|
|
95
96
|
export declare type StorageKey = keyof StorageValueByKey;
|
package/package.json
CHANGED
|
@@ -1,30 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ada-support/web-storage",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.8",
|
|
4
4
|
"description": "A package to provide access to Web Storage API",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"lint": "
|
|
10
|
+
"lint": "biome check",
|
|
11
|
+
"lint:fix": "biome check --write",
|
|
12
|
+
"lint:ci": "biome ci --error-on-warnings",
|
|
13
|
+
"typecheck": "tsc --noEmit",
|
|
11
14
|
"check-package-version": "./ci-tools/check-package-version.sh",
|
|
12
15
|
"compile": "rm -rf dist && npx tsc && npx ts-node ./src/cli/generate-html.ts"
|
|
13
16
|
},
|
|
14
17
|
"repository": {
|
|
15
18
|
"type": "git",
|
|
16
|
-
"url": "git+https://github.com/AdaSupport/
|
|
19
|
+
"url": "git+https://github.com/AdaSupport/monorepo.git",
|
|
20
|
+
"directory": "web-storage"
|
|
17
21
|
},
|
|
18
22
|
"author": "",
|
|
19
23
|
"license": "ISC",
|
|
20
|
-
"homepage": "https://github.com/AdaSupport/web-storage#readme",
|
|
24
|
+
"homepage": "https://github.com/AdaSupport/monorepo/tree/main/web-storage#readme",
|
|
21
25
|
"dependencies": {
|
|
22
26
|
"ts-node": "^10.9.1",
|
|
23
27
|
"typescript": "^4.8.4"
|
|
24
28
|
},
|
|
25
29
|
"devDependencies": {
|
|
26
|
-
"@
|
|
27
|
-
"@types/node": "^18.8.2"
|
|
28
|
-
"eslint": "^8.24.0"
|
|
30
|
+
"@biomejs/biome": "2.4.10",
|
|
31
|
+
"@types/node": "^18.8.2"
|
|
29
32
|
}
|
|
30
33
|
}
|
package/src/cli/generate-html.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync } from "fs";
|
|
1
|
+
import { readFileSync, writeFileSync } from "node:fs";
|
|
2
2
|
|
|
3
3
|
import { THIRD_PARTY_ITEMS } from "../third-party-items";
|
|
4
4
|
|
|
@@ -7,38 +7,80 @@ const OUTPUT_FILENAME = "ada-web-storage-list.html";
|
|
|
7
7
|
|
|
8
8
|
const PARSE_ERROR_MESSAGE = "Could not parse StorageValueByKey interface";
|
|
9
9
|
|
|
10
|
+
// KEY_LINES is /g only so `.match` returns every key line for the declared list;
|
|
11
|
+
// KEY_LINE must stay non-global so `.match` returns capture groups and [1] is the
|
|
12
|
+
// key name. Don't merge them: with a global regex `[1]` is the second matched line
|
|
13
|
+
// instead, so keyName silently becomes garbage in the published registry.
|
|
14
|
+
// Both need `m` — a key sits on its own line after the entry's doc comment.
|
|
15
|
+
const KEY_LINE = /^\s*"?([\w-]+)"?:\s/m;
|
|
16
|
+
const KEY_LINES = /^\s*"?([\w-]+)"?:\s/gm;
|
|
17
|
+
|
|
18
|
+
const INTERFACE_DECL = "export interface StorageValueByKey {";
|
|
19
|
+
|
|
10
20
|
function runScript() {
|
|
11
|
-
|
|
21
|
+
const data = readFileSync("./src/storage-keys.ts", "utf-8");
|
|
22
|
+
|
|
23
|
+
const matches = data.match(/StorageValueByKey \{([^}]+)}/);
|
|
24
|
+
|
|
25
|
+
if (!matches) {
|
|
26
|
+
throw new Error(PARSE_ERROR_MESSAGE);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const items = matches[0].split("\n\n").map((item) => item.trim());
|
|
30
|
+
|
|
31
|
+
// Read the declared keys from the interface's real extent — its declaration to
|
|
32
|
+
// its own column-0 closing brace — NOT from `matches`. The `[^}]+` above stops
|
|
33
|
+
// at the first `}`, so an inline object value truncates it, and anything derived
|
|
34
|
+
// from that same match would shrink in step and hide the loss.
|
|
35
|
+
const declStart = data.indexOf(INTERFACE_DECL);
|
|
36
|
+
const declEnd = declStart === -1 ? -1 : data.indexOf("\n}", declStart);
|
|
37
|
+
|
|
38
|
+
if (declStart === -1 || declEnd === -1) {
|
|
39
|
+
throw new Error(PARSE_ERROR_MESSAGE);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const declaredNames = (
|
|
43
|
+
data.slice(declStart, declEnd).match(KEY_LINES) ?? []
|
|
44
|
+
).map((line) => line.match(KEY_LINE)?.[1] ?? line.trim());
|
|
12
45
|
|
|
13
|
-
|
|
46
|
+
const storageRecords: typeof THIRD_PARTY_ITEMS = items.map((item) => {
|
|
47
|
+
// Quotes are optional: the formatter strips redundant ones from
|
|
48
|
+
// identifier-safe key names, so only hyphenated keys keep them.
|
|
49
|
+
const nameMatches = item.match(KEY_LINE);
|
|
50
|
+
const descriptionMatches = item.match(/\/\*\*([^}]+)\*\//);
|
|
14
51
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
52
|
+
if (!nameMatches || !descriptionMatches) {
|
|
53
|
+
throw new Error(PARSE_ERROR_MESSAGE);
|
|
54
|
+
}
|
|
18
55
|
|
|
19
|
-
|
|
56
|
+
return {
|
|
57
|
+
keyName: nameMatches[1],
|
|
58
|
+
description: descriptionMatches[1].trim(),
|
|
59
|
+
type: "Web Storage",
|
|
60
|
+
duration: "Persistent",
|
|
61
|
+
purpose: ["Functional"],
|
|
62
|
+
} as const;
|
|
63
|
+
});
|
|
20
64
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
65
|
+
// Compare the key SETS, not their sizes: a size check passes whenever two
|
|
66
|
+
// defects cancel out, and it can't name what went missing. This can, and it is
|
|
67
|
+
// the assertion a golden-file test would make.
|
|
68
|
+
const parsedNames = storageRecords.map((record) => record.keyName);
|
|
69
|
+
const missing = declaredNames.filter((n) => parsedNames.indexOf(n) === -1);
|
|
70
|
+
const unexpected = parsedNames.filter((n) => declaredNames.indexOf(n) === -1);
|
|
25
71
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
72
|
+
if (missing.length > 0 || unexpected.length > 0) {
|
|
73
|
+
throw new Error(
|
|
74
|
+
`${PARSE_ERROR_MESSAGE}: declared but not parsed: [${missing.join(", ")}]; parsed but not declared: [${unexpected.join(", ")}]. Each key needs its own entry separated by an empty line, and no entry may contain a brace (see storage-keys.ts).`,
|
|
75
|
+
);
|
|
76
|
+
}
|
|
29
77
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
duration: "Persistent",
|
|
35
|
-
purpose: ["Functional"],
|
|
36
|
-
} as const;
|
|
37
|
-
}),
|
|
38
|
-
...THIRD_PARTY_ITEMS,
|
|
39
|
-
].sort((a, b) => a.keyName.localeCompare(b.keyName));
|
|
78
|
+
const records: typeof THIRD_PARTY_ITEMS = [
|
|
79
|
+
...storageRecords,
|
|
80
|
+
...THIRD_PARTY_ITEMS,
|
|
81
|
+
].sort((a, b) => a.keyName.localeCompare(b.keyName));
|
|
40
82
|
|
|
41
|
-
|
|
83
|
+
const html = `
|
|
42
84
|
<html lang="en">
|
|
43
85
|
<head>
|
|
44
86
|
<title>Ada client-side storage</title>
|
|
@@ -72,24 +114,29 @@ function runScript() {
|
|
|
72
114
|
<tr>
|
|
73
115
|
</thead>
|
|
74
116
|
<tbody>
|
|
75
|
-
${records
|
|
117
|
+
${records
|
|
118
|
+
.map(
|
|
119
|
+
(record) => `
|
|
76
120
|
<tr>
|
|
77
121
|
<td>${record.keyName}</td>
|
|
78
122
|
<td>${record.description}</td>
|
|
79
|
-
<td>${record.type} (${record.purpose.map(i => i.toLocaleLowerCase()).join(", ")})</td>
|
|
123
|
+
<td>${record.type} (${record.purpose.map((i) => i.toLocaleLowerCase()).join(", ")})</td>
|
|
80
124
|
<td>${record.duration}</td>
|
|
81
125
|
</tr>
|
|
82
|
-
|
|
126
|
+
`,
|
|
127
|
+
)
|
|
128
|
+
.join("\n")
|
|
129
|
+
.trim()}
|
|
83
130
|
</tbody>
|
|
84
131
|
</table>
|
|
85
132
|
</body>
|
|
86
133
|
</html>
|
|
87
134
|
`
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
135
|
+
.trim()
|
|
136
|
+
.replace(/ {2}/g, "")
|
|
137
|
+
.replace(/\n+/g, "\n");
|
|
91
138
|
|
|
92
|
-
|
|
139
|
+
writeFileSync(`./${OUTPUT_DIR}/${OUTPUT_FILENAME}`, html);
|
|
93
140
|
}
|
|
94
141
|
|
|
95
142
|
runScript();
|
package/src/create-storage.ts
CHANGED
|
@@ -4,70 +4,78 @@ import type { StorageKey, StorageValueByKey } from "./storage-keys";
|
|
|
4
4
|
const WEB_STORAGE_ACCESS_ERROR_MESSAGE = "Cannot access Web Storage API";
|
|
5
5
|
|
|
6
6
|
export const createStorage = (storageType: "local" | "session") => {
|
|
7
|
-
|
|
7
|
+
let storageProvider: Storage;
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
// To handle incognito mode. Calling localStorage throws an error when in incognito
|
|
10
|
+
try {
|
|
11
|
+
storageProvider = storageType === "local" ? localStorage : sessionStorage;
|
|
12
|
+
} catch {
|
|
13
|
+
console.warn(WEB_STORAGE_ACCESS_ERROR_MESSAGE);
|
|
14
|
+
}
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
16
|
+
const storage = {
|
|
17
|
+
setItem: <K extends StorageKey>(
|
|
18
|
+
key: K,
|
|
19
|
+
value: StorageValueByKey[K],
|
|
20
|
+
): void => {
|
|
21
|
+
try {
|
|
22
|
+
storageProvider.setItem(key, JSON.stringify(value));
|
|
23
|
+
} catch {
|
|
24
|
+
console.warn(WEB_STORAGE_ACCESS_ERROR_MESSAGE);
|
|
25
|
+
}
|
|
26
|
+
},
|
|
24
27
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
+
getItem: <K extends StorageKey>(key: K): StorageValueByKey[K] | null => {
|
|
29
|
+
try {
|
|
30
|
+
const rawStorageValue = storageProvider.getItem(key);
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
return rawStorageValue && JSON.parse(rawStorageValue);
|
|
33
|
+
} catch {
|
|
34
|
+
console.warn(WEB_STORAGE_ACCESS_ERROR_MESSAGE);
|
|
32
35
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
},
|
|
36
39
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
40
|
+
removeItem: <K extends StorageKey>(key: K): void => {
|
|
41
|
+
try {
|
|
42
|
+
storageProvider.removeItem(key);
|
|
43
|
+
} catch {
|
|
44
|
+
console.warn(WEB_STORAGE_ACCESS_ERROR_MESSAGE);
|
|
45
|
+
}
|
|
46
|
+
},
|
|
44
47
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
clear: () => {
|
|
49
|
+
try {
|
|
50
|
+
storageProvider.clear();
|
|
51
|
+
} catch {
|
|
52
|
+
console.warn(WEB_STORAGE_ACCESS_ERROR_MESSAGE);
|
|
53
|
+
}
|
|
54
|
+
},
|
|
52
55
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
56
|
+
/** Stores a key/value pair within `ada-functional-storage` Storage key */
|
|
57
|
+
setFnItem: <K extends keyof AdaFunctionalStorageValue>(
|
|
58
|
+
key: K,
|
|
59
|
+
value: AdaFunctionalStorageValue[K],
|
|
60
|
+
): void => {
|
|
61
|
+
const currentValue = storage.getItem("ada-functional-storage") || {};
|
|
62
|
+
const newValue = {
|
|
63
|
+
...currentValue,
|
|
64
|
+
[key]: value,
|
|
65
|
+
};
|
|
60
66
|
|
|
61
|
-
|
|
62
|
-
|
|
67
|
+
storage.setItem("ada-functional-storage", newValue);
|
|
68
|
+
},
|
|
63
69
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
70
|
+
/** Gets a value under `ada-functional-storage` Storage key */
|
|
71
|
+
getFnItem: <K extends keyof AdaFunctionalStorageValue>(
|
|
72
|
+
key: K,
|
|
73
|
+
): AdaFunctionalStorageValue[K] | null => {
|
|
74
|
+
const value = storage.getItem("ada-functional-storage");
|
|
67
75
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
76
|
+
return value?.[key] || null;
|
|
77
|
+
},
|
|
78
|
+
} as const;
|
|
71
79
|
|
|
72
|
-
|
|
80
|
+
return storage;
|
|
73
81
|
};
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
export interface AdaFunctionalStorageValue {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
2
|
+
rolloutGroup: {
|
|
3
|
+
[clientHandle: string]: "A" | "B" | undefined;
|
|
4
|
+
};
|
|
5
|
+
rolloutLastValue: {
|
|
6
|
+
[clientHandle: string]: number | undefined;
|
|
7
|
+
};
|
|
8
|
+
marketing_campaigns_shown: {
|
|
9
|
+
[clientHandle: string]: string | undefined;
|
|
10
|
+
};
|
|
11
|
+
zdmChatResetCount: {
|
|
12
|
+
[clientHandle: string]: number | undefined;
|
|
13
|
+
};
|
|
14
|
+
botAssignment: {
|
|
15
|
+
[clientHandle: string]: "primary" | "alternative" | undefined;
|
|
16
|
+
};
|
|
17
|
+
proactive_conversations_shown: {
|
|
18
|
+
[clientHandle: string]: string | undefined;
|
|
19
|
+
};
|
|
20
|
+
proactive_conversations_shown_user: {
|
|
21
|
+
[clientHandle: string]: string | undefined;
|
|
22
|
+
};
|
|
23
23
|
}
|
package/src/index.ts
CHANGED
|
@@ -8,13 +8,13 @@ export type AdaStorageValueByKey = StorageValueByKey;
|
|
|
8
8
|
|
|
9
9
|
/** Checks if Web Storage API is supported */
|
|
10
10
|
export const isWebStorageSupported = (): boolean => {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
11
|
+
try {
|
|
12
|
+
const key = "key_to_test_local_storage";
|
|
13
|
+
localStorage.setItem(key, key);
|
|
14
|
+
localStorage.removeItem(key);
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
16
|
+
return true;
|
|
17
|
+
} catch {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
20
|
};
|