@form-engine-ts/storage 6.5.0 → 6.7.0

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 CHANGED
@@ -11,3 +11,7 @@ pnpm add @form-engine-ts/storage
11
11
  The package exports `StorageCursor`, cursor payload contracts, cursor encoders/decoders, and
12
12
  `paginateWithFilter` for adapters that need to scan native pages until enough filtered items are collected.
13
13
  `maxScanPages` bounds low-density scans, and `totalScannedCount` reports the amount of source data inspected.
14
+
15
+ `TypedPagedSubmissionStorageAdapter<TMeta>` and `iterateTypedSubmissionPages` preserve application metadata types
16
+ through page fetching. The Azure Table and MongoDB factories expose a typed `fetchPage` when called as
17
+ `createAzureTableStorage<TMeta>(...)` or `createMongoDbStorage<TMeta>(...)`.
@@ -5,6 +5,23 @@ import {
5
5
  encodeStorageSubmissionCursor,
6
6
  encodeStorageTextAnswerCursor
7
7
  } from "@form-engine-ts/core";
8
+ async function* iterateTypedSubmissionPages(adapter, formId, options = {}) {
9
+ let currentCursor = options.cursor;
10
+ const seenCursors = /* @__PURE__ */ new Set();
11
+ do {
12
+ if (currentCursor !== void 0) {
13
+ if (seenCursors.has(currentCursor)) throw new TypeError("Typed submission pagination cursor cycle detected.");
14
+ seenCursors.add(currentCursor);
15
+ }
16
+ const queryOptions = {
17
+ ...options,
18
+ ...currentCursor === void 0 ? {} : { cursor: currentCursor }
19
+ };
20
+ const page = await adapter.fetchPage(formId, queryOptions);
21
+ yield page.items;
22
+ currentCursor = page.nextCursor;
23
+ } while (currentCursor !== void 0 && currentCursor.length > 0);
24
+ }
8
25
  async function paginateWithFilter(params) {
9
26
  const { pageSize, cursor, maxScanPages = 5, fetchPage, filterPredicate, encodeCursor } = params;
10
27
  if (!Number.isSafeInteger(pageSize) || pageSize < 1) {
@@ -42,6 +59,7 @@ async function paginateWithFilter(params) {
42
59
  }
43
60
 
44
61
  export {
62
+ iterateTypedSubmissionPages,
45
63
  paginateWithFilter,
46
64
  decodeStorageSubmissionCursor,
47
65
  decodeStorageTextAnswerCursor,
package/dist/index.cjs CHANGED
@@ -24,12 +24,30 @@ __export(index_exports, {
24
24
  decodeStorageTextAnswerCursor: () => import_core.decodeStorageTextAnswerCursor,
25
25
  encodeStorageSubmissionCursor: () => import_core.encodeStorageSubmissionCursor,
26
26
  encodeStorageTextAnswerCursor: () => import_core.encodeStorageTextAnswerCursor,
27
+ iterateTypedSubmissionPages: () => iterateTypedSubmissionPages,
27
28
  paginateWithFilter: () => paginateWithFilter
28
29
  });
29
30
  module.exports = __toCommonJS(index_exports);
30
31
 
31
32
  // src/pagination.ts
32
33
  var import_core = require("@form-engine-ts/core");
34
+ async function* iterateTypedSubmissionPages(adapter, formId, options = {}) {
35
+ let currentCursor = options.cursor;
36
+ const seenCursors = /* @__PURE__ */ new Set();
37
+ do {
38
+ if (currentCursor !== void 0) {
39
+ if (seenCursors.has(currentCursor)) throw new TypeError("Typed submission pagination cursor cycle detected.");
40
+ seenCursors.add(currentCursor);
41
+ }
42
+ const queryOptions = {
43
+ ...options,
44
+ ...currentCursor === void 0 ? {} : { cursor: currentCursor }
45
+ };
46
+ const page = await adapter.fetchPage(formId, queryOptions);
47
+ yield page.items;
48
+ currentCursor = page.nextCursor;
49
+ } while (currentCursor !== void 0 && currentCursor.length > 0);
50
+ }
33
51
  async function paginateWithFilter(params) {
34
52
  const { pageSize, cursor, maxScanPages = 5, fetchPage, filterPredicate, encodeCursor } = params;
35
53
  if (!Number.isSafeInteger(pageSize) || pageSize < 1) {
@@ -71,5 +89,6 @@ async function paginateWithFilter(params) {
71
89
  decodeStorageTextAnswerCursor,
72
90
  encodeStorageSubmissionCursor,
73
91
  encodeStorageTextAnswerCursor,
92
+ iterateTypedSubmissionPages,
74
93
  paginateWithFilter
75
94
  });
package/dist/index.d.cts CHANGED
@@ -1,3 +1,3 @@
1
- export { paginateWithFilter } from './pagination.cjs';
1
+ export { TypedPagedSubmissionStorageAdapter, TypedSubmissionPage, TypedSubmissionPageQueryOptions, iterateTypedSubmissionPages, paginateWithFilter } from './pagination.cjs';
2
2
  export { StorageFilterPushdownContract, TenantIsolationOptions } from './types.cjs';
3
3
  export { CursorPagingOptions, PaginatedResult, StorageCursor, StorageFilterCriteria, SubmissionCursorPayload, TextAnswerCursorPayload, decodeStorageSubmissionCursor, decodeStorageTextAnswerCursor, encodeStorageSubmissionCursor, encodeStorageTextAnswerCursor } from '@form-engine-ts/core';
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
- export { paginateWithFilter } from './pagination.js';
1
+ export { TypedPagedSubmissionStorageAdapter, TypedSubmissionPage, TypedSubmissionPageQueryOptions, iterateTypedSubmissionPages, paginateWithFilter } from './pagination.js';
2
2
  export { StorageFilterPushdownContract, TenantIsolationOptions } from './types.js';
3
3
  export { CursorPagingOptions, PaginatedResult, StorageCursor, StorageFilterCriteria, SubmissionCursorPayload, TextAnswerCursorPayload, decodeStorageSubmissionCursor, decodeStorageTextAnswerCursor, encodeStorageSubmissionCursor, encodeStorageTextAnswerCursor } from '@form-engine-ts/core';
package/dist/index.js CHANGED
@@ -3,13 +3,15 @@ import {
3
3
  decodeStorageTextAnswerCursor,
4
4
  encodeStorageSubmissionCursor,
5
5
  encodeStorageTextAnswerCursor,
6
+ iterateTypedSubmissionPages,
6
7
  paginateWithFilter
7
- } from "./chunk-RT2I36BE.js";
8
+ } from "./chunk-5UFB7AZ4.js";
8
9
  import "./chunk-6F4PWJZI.js";
9
10
  export {
10
11
  decodeStorageSubmissionCursor,
11
12
  decodeStorageTextAnswerCursor,
12
13
  encodeStorageSubmissionCursor,
13
14
  encodeStorageTextAnswerCursor,
15
+ iterateTypedSubmissionPages,
14
16
  paginateWithFilter
15
17
  };
@@ -24,10 +24,28 @@ __export(pagination_exports, {
24
24
  decodeStorageTextAnswerCursor: () => import_core.decodeStorageTextAnswerCursor,
25
25
  encodeStorageSubmissionCursor: () => import_core.encodeStorageSubmissionCursor,
26
26
  encodeStorageTextAnswerCursor: () => import_core.encodeStorageTextAnswerCursor,
27
+ iterateTypedSubmissionPages: () => iterateTypedSubmissionPages,
27
28
  paginateWithFilter: () => paginateWithFilter
28
29
  });
29
30
  module.exports = __toCommonJS(pagination_exports);
30
31
  var import_core = require("@form-engine-ts/core");
32
+ async function* iterateTypedSubmissionPages(adapter, formId, options = {}) {
33
+ let currentCursor = options.cursor;
34
+ const seenCursors = /* @__PURE__ */ new Set();
35
+ do {
36
+ if (currentCursor !== void 0) {
37
+ if (seenCursors.has(currentCursor)) throw new TypeError("Typed submission pagination cursor cycle detected.");
38
+ seenCursors.add(currentCursor);
39
+ }
40
+ const queryOptions = {
41
+ ...options,
42
+ ...currentCursor === void 0 ? {} : { cursor: currentCursor }
43
+ };
44
+ const page = await adapter.fetchPage(formId, queryOptions);
45
+ yield page.items;
46
+ currentCursor = page.nextCursor;
47
+ } while (currentCursor !== void 0 && currentCursor.length > 0);
48
+ }
31
49
  async function paginateWithFilter(params) {
32
50
  const { pageSize, cursor, maxScanPages = 5, fetchPage, filterPredicate, encodeCursor } = params;
33
51
  if (!Number.isSafeInteger(pageSize) || pageSize < 1) {
@@ -69,5 +87,6 @@ async function paginateWithFilter(params) {
69
87
  decodeStorageTextAnswerCursor,
70
88
  encodeStorageSubmissionCursor,
71
89
  encodeStorageTextAnswerCursor,
90
+ iterateTypedSubmissionPages,
72
91
  paginateWithFilter
73
92
  });
@@ -1,6 +1,22 @@
1
- import { StorageCursor, PaginatedResult } from '@form-engine-ts/core';
1
+ import { BaseSubmissionMetadata, FormSubmission, StorageCursor, PaginatedResult } from '@form-engine-ts/core';
2
2
  export { CursorPagingOptions, PaginatedResult, StorageCursor, decodeStorageSubmissionCursor, decodeStorageTextAnswerCursor, encodeStorageSubmissionCursor, encodeStorageTextAnswerCursor } from '@form-engine-ts/core';
3
3
 
4
+ interface TypedSubmissionPageQueryOptions<TMeta extends BaseSubmissionMetadata> {
5
+ readonly pageSize?: number;
6
+ readonly fromSubmittedAt?: string;
7
+ readonly toSubmittedAt?: string;
8
+ readonly locale?: string;
9
+ readonly metadataFilters?: Partial<TMeta>;
10
+ readonly cursor?: string;
11
+ }
12
+ interface TypedSubmissionPage<TMeta extends BaseSubmissionMetadata> {
13
+ readonly items: readonly FormSubmission<TMeta>[];
14
+ readonly nextCursor?: string;
15
+ }
16
+ interface TypedPagedSubmissionStorageAdapter<TMeta extends BaseSubmissionMetadata> {
17
+ readonly fetchPage: (formId: string, options?: TypedSubmissionPageQueryOptions<TMeta>) => Promise<TypedSubmissionPage<TMeta>>;
18
+ }
19
+ declare function iterateTypedSubmissionPages<TMeta extends BaseSubmissionMetadata>(adapter: TypedPagedSubmissionStorageAdapter<TMeta>, formId: string, options?: TypedSubmissionPageQueryOptions<TMeta>): AsyncIterable<readonly FormSubmission<TMeta>[]>;
4
20
  declare function paginateWithFilter<T>(params: {
5
21
  readonly pageSize: number;
6
22
  readonly cursor?: StorageCursor;
@@ -13,4 +29,4 @@ declare function paginateWithFilter<T>(params: {
13
29
  readonly encodeCursor: (lastItem: T) => StorageCursor;
14
30
  }): Promise<PaginatedResult<T>>;
15
31
 
16
- export { paginateWithFilter };
32
+ export { type TypedPagedSubmissionStorageAdapter, type TypedSubmissionPage, type TypedSubmissionPageQueryOptions, iterateTypedSubmissionPages, paginateWithFilter };
@@ -1,6 +1,22 @@
1
- import { StorageCursor, PaginatedResult } from '@form-engine-ts/core';
1
+ import { BaseSubmissionMetadata, FormSubmission, StorageCursor, PaginatedResult } from '@form-engine-ts/core';
2
2
  export { CursorPagingOptions, PaginatedResult, StorageCursor, decodeStorageSubmissionCursor, decodeStorageTextAnswerCursor, encodeStorageSubmissionCursor, encodeStorageTextAnswerCursor } from '@form-engine-ts/core';
3
3
 
4
+ interface TypedSubmissionPageQueryOptions<TMeta extends BaseSubmissionMetadata> {
5
+ readonly pageSize?: number;
6
+ readonly fromSubmittedAt?: string;
7
+ readonly toSubmittedAt?: string;
8
+ readonly locale?: string;
9
+ readonly metadataFilters?: Partial<TMeta>;
10
+ readonly cursor?: string;
11
+ }
12
+ interface TypedSubmissionPage<TMeta extends BaseSubmissionMetadata> {
13
+ readonly items: readonly FormSubmission<TMeta>[];
14
+ readonly nextCursor?: string;
15
+ }
16
+ interface TypedPagedSubmissionStorageAdapter<TMeta extends BaseSubmissionMetadata> {
17
+ readonly fetchPage: (formId: string, options?: TypedSubmissionPageQueryOptions<TMeta>) => Promise<TypedSubmissionPage<TMeta>>;
18
+ }
19
+ declare function iterateTypedSubmissionPages<TMeta extends BaseSubmissionMetadata>(adapter: TypedPagedSubmissionStorageAdapter<TMeta>, formId: string, options?: TypedSubmissionPageQueryOptions<TMeta>): AsyncIterable<readonly FormSubmission<TMeta>[]>;
4
20
  declare function paginateWithFilter<T>(params: {
5
21
  readonly pageSize: number;
6
22
  readonly cursor?: StorageCursor;
@@ -13,4 +29,4 @@ declare function paginateWithFilter<T>(params: {
13
29
  readonly encodeCursor: (lastItem: T) => StorageCursor;
14
30
  }): Promise<PaginatedResult<T>>;
15
31
 
16
- export { paginateWithFilter };
32
+ export { type TypedPagedSubmissionStorageAdapter, type TypedSubmissionPage, type TypedSubmissionPageQueryOptions, iterateTypedSubmissionPages, paginateWithFilter };
@@ -3,12 +3,14 @@ import {
3
3
  decodeStorageTextAnswerCursor,
4
4
  encodeStorageSubmissionCursor,
5
5
  encodeStorageTextAnswerCursor,
6
+ iterateTypedSubmissionPages,
6
7
  paginateWithFilter
7
- } from "./chunk-RT2I36BE.js";
8
+ } from "./chunk-5UFB7AZ4.js";
8
9
  export {
9
10
  decodeStorageSubmissionCursor,
10
11
  decodeStorageTextAnswerCursor,
11
12
  encodeStorageSubmissionCursor,
12
13
  encodeStorageTextAnswerCursor,
14
+ iterateTypedSubmissionPages,
13
15
  paginateWithFilter
14
16
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@form-engine-ts/storage",
3
- "version": "6.5.0",
3
+ "version": "6.7.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -37,7 +37,7 @@
37
37
  "url": "git+https://github.com/nitta-a/form-engine-ts.git"
38
38
  },
39
39
  "dependencies": {
40
- "@form-engine-ts/core": "6.5.0"
40
+ "@form-engine-ts/core": "6.7.0"
41
41
  },
42
42
  "scripts": {
43
43
  "build": "tsup src/index.ts src/types.ts src/pagination.ts --format esm,cjs --dts --clean --external @form-engine-ts/core",