@form-engine-ts/storage-localstorage 7.18.1 → 8.0.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 +32 -0
- package/dist/index.js +34 -1
- package/package.json +3 -3
package/dist/index.cjs
CHANGED
|
@@ -123,6 +123,30 @@ function createLocalStorageAdapter(storagePrefix = "pf_", injectedStorage, optio
|
|
|
123
123
|
if (storage.getItem(key) !== null) throw new Error(`A submission with ID "${submission.id}" already exists.`);
|
|
124
124
|
storage.setItem(key, JSON.stringify(submission));
|
|
125
125
|
},
|
|
126
|
+
async saveSubmissionWithinLimit(submission, maxResponses, saveOptions = {}) {
|
|
127
|
+
if (!Number.isInteger(maxResponses) || maxResponses < 1)
|
|
128
|
+
throw new RangeError("maxResponses must be a positive integer.");
|
|
129
|
+
const key = submissionKey(submission.id);
|
|
130
|
+
const payloadHash = await (0, import_core.hashFormSubmissionPayload)(submission);
|
|
131
|
+
const existingValue = storage.getItem(key);
|
|
132
|
+
if (existingValue !== null) {
|
|
133
|
+
if (saveOptions.idempotent !== true) throw new Error(`A submission with ID "${submission.id}" already exists.`);
|
|
134
|
+
const existing = parseSubmission(existingValue, key);
|
|
135
|
+
const existingPayloadHash = await (0, import_core.hashFormSubmissionPayload)(existing);
|
|
136
|
+
if (existingPayloadHash === payloadHash)
|
|
137
|
+
return { status: "duplicate", submission: cloneJson(existing), payloadHash };
|
|
138
|
+
return { status: "conflict", submissionId: submission.id, payloadHash, existingPayloadHash };
|
|
139
|
+
}
|
|
140
|
+
const count = prefixedKeys(submissionPrefix).reduce((total, key2) => {
|
|
141
|
+
const value = storage.getItem(key2);
|
|
142
|
+
if (value === null) return total;
|
|
143
|
+
const candidate = parseSubmission(value, key2);
|
|
144
|
+
return total + (candidate.formId === submission.formId && candidate.formVersion === submission.formVersion ? 1 : 0);
|
|
145
|
+
}, 0);
|
|
146
|
+
if (count >= maxResponses) return { status: "limit_reached" };
|
|
147
|
+
storage.setItem(key, JSON.stringify(submission));
|
|
148
|
+
if (saveOptions.idempotent === true) return { status: "created", submission: cloneJson(submission), payloadHash };
|
|
149
|
+
},
|
|
126
150
|
async listSubmissions(formId, formVersion, options2) {
|
|
127
151
|
return prefixedKeys(submissionPrefix).map((key) => {
|
|
128
152
|
const value = storage.getItem(key);
|
|
@@ -132,6 +156,14 @@ function createLocalStorageAdapter(storagePrefix = "pf_", injectedStorage, optio
|
|
|
132
156
|
(submission) => submission.formId === formId && (formVersion === void 0 || submission.formVersion === formVersion) && (options2?.since === void 0 || submission.submittedAt >= options2.since) && (options2?.until === void 0 || submission.submittedAt <= options2.until)
|
|
133
157
|
).sort((left, right) => left.submittedAt.localeCompare(right.submittedAt) || left.id.localeCompare(right.id)).map(cloneJson);
|
|
134
158
|
},
|
|
159
|
+
async countSubmissions(formId, formVersion, options2) {
|
|
160
|
+
return prefixedKeys(submissionPrefix).reduce((count, key) => {
|
|
161
|
+
const value = storage.getItem(key);
|
|
162
|
+
if (value === null) throw new Error(`Stored submission at "${key}" disappeared during reading.`);
|
|
163
|
+
const submission = parseSubmission(value, key);
|
|
164
|
+
return count + (submission.formId === formId && (formVersion === void 0 || submission.formVersion === formVersion) && (options2?.since === void 0 || submission.submittedAt >= options2.since) && (options2?.until === void 0 || submission.submittedAt <= options2.until) ? 1 : 0);
|
|
165
|
+
}, 0);
|
|
166
|
+
},
|
|
135
167
|
async deleteSubmission(submissionId) {
|
|
136
168
|
storage.removeItem(submissionKey(submissionId));
|
|
137
169
|
},
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import {
|
|
3
3
|
assertValidFormSchema,
|
|
4
|
-
createFormLifecycleAdapter
|
|
4
|
+
createFormLifecycleAdapter,
|
|
5
|
+
hashFormSubmissionPayload
|
|
5
6
|
} from "@form-engine-ts/core";
|
|
6
7
|
function isRecord(value) {
|
|
7
8
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -102,6 +103,30 @@ function createLocalStorageAdapter(storagePrefix = "pf_", injectedStorage, optio
|
|
|
102
103
|
if (storage.getItem(key) !== null) throw new Error(`A submission with ID "${submission.id}" already exists.`);
|
|
103
104
|
storage.setItem(key, JSON.stringify(submission));
|
|
104
105
|
},
|
|
106
|
+
async saveSubmissionWithinLimit(submission, maxResponses, saveOptions = {}) {
|
|
107
|
+
if (!Number.isInteger(maxResponses) || maxResponses < 1)
|
|
108
|
+
throw new RangeError("maxResponses must be a positive integer.");
|
|
109
|
+
const key = submissionKey(submission.id);
|
|
110
|
+
const payloadHash = await hashFormSubmissionPayload(submission);
|
|
111
|
+
const existingValue = storage.getItem(key);
|
|
112
|
+
if (existingValue !== null) {
|
|
113
|
+
if (saveOptions.idempotent !== true) throw new Error(`A submission with ID "${submission.id}" already exists.`);
|
|
114
|
+
const existing = parseSubmission(existingValue, key);
|
|
115
|
+
const existingPayloadHash = await hashFormSubmissionPayload(existing);
|
|
116
|
+
if (existingPayloadHash === payloadHash)
|
|
117
|
+
return { status: "duplicate", submission: cloneJson(existing), payloadHash };
|
|
118
|
+
return { status: "conflict", submissionId: submission.id, payloadHash, existingPayloadHash };
|
|
119
|
+
}
|
|
120
|
+
const count = prefixedKeys(submissionPrefix).reduce((total, key2) => {
|
|
121
|
+
const value = storage.getItem(key2);
|
|
122
|
+
if (value === null) return total;
|
|
123
|
+
const candidate = parseSubmission(value, key2);
|
|
124
|
+
return total + (candidate.formId === submission.formId && candidate.formVersion === submission.formVersion ? 1 : 0);
|
|
125
|
+
}, 0);
|
|
126
|
+
if (count >= maxResponses) return { status: "limit_reached" };
|
|
127
|
+
storage.setItem(key, JSON.stringify(submission));
|
|
128
|
+
if (saveOptions.idempotent === true) return { status: "created", submission: cloneJson(submission), payloadHash };
|
|
129
|
+
},
|
|
105
130
|
async listSubmissions(formId, formVersion, options2) {
|
|
106
131
|
return prefixedKeys(submissionPrefix).map((key) => {
|
|
107
132
|
const value = storage.getItem(key);
|
|
@@ -111,6 +136,14 @@ function createLocalStorageAdapter(storagePrefix = "pf_", injectedStorage, optio
|
|
|
111
136
|
(submission) => submission.formId === formId && (formVersion === void 0 || submission.formVersion === formVersion) && (options2?.since === void 0 || submission.submittedAt >= options2.since) && (options2?.until === void 0 || submission.submittedAt <= options2.until)
|
|
112
137
|
).sort((left, right) => left.submittedAt.localeCompare(right.submittedAt) || left.id.localeCompare(right.id)).map(cloneJson);
|
|
113
138
|
},
|
|
139
|
+
async countSubmissions(formId, formVersion, options2) {
|
|
140
|
+
return prefixedKeys(submissionPrefix).reduce((count, key) => {
|
|
141
|
+
const value = storage.getItem(key);
|
|
142
|
+
if (value === null) throw new Error(`Stored submission at "${key}" disappeared during reading.`);
|
|
143
|
+
const submission = parseSubmission(value, key);
|
|
144
|
+
return count + (submission.formId === formId && (formVersion === void 0 || submission.formVersion === formVersion) && (options2?.since === void 0 || submission.submittedAt >= options2.since) && (options2?.until === void 0 || submission.submittedAt <= options2.until) ? 1 : 0);
|
|
145
|
+
}, 0);
|
|
146
|
+
},
|
|
114
147
|
async deleteSubmission(submissionId) {
|
|
115
148
|
storage.removeItem(submissionKey(submissionId));
|
|
116
149
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@form-engine-ts/storage-localstorage",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "8.0.1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"typescript"
|
|
40
40
|
],
|
|
41
41
|
"dependencies": {
|
|
42
|
-
"@form-engine-ts/core": "
|
|
42
|
+
"@form-engine-ts/core": "8.0.1"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
|
-
"@form-engine-ts/storage": "
|
|
45
|
+
"@form-engine-ts/storage": "8.0.1"
|
|
46
46
|
},
|
|
47
47
|
"scripts": {
|
|
48
48
|
"build": "tsup src/index.ts --format esm,cjs --dts --clean --external @form-engine-ts/core",
|