@asteby/metacore-runtime-react 39.2.6 → 39.2.7
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/CHANGELOG.md +6 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/query-batch.d.ts +26 -0
- package/dist/query-batch.d.ts.map +1 -0
- package/dist/query-batch.js +109 -0
- package/dist/use-options-resolver.d.ts.map +1 -1
- package/dist/use-options-resolver.js +28 -2
- package/package.json +1 -1
- package/src/index.ts +7 -0
- package/src/query-batch.test.ts +24 -0
- package/src/query-batch.ts +136 -0
- package/src/use-options-resolver.ts +29 -2
package/CHANGELOG.md
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -74,6 +74,7 @@ export { DynamicRelation, type DynamicRelationProps, type DynamicRelationStrings
|
|
|
74
74
|
export { DynamicRelations, resolveParentId, buildRelationFilters, isEmbedded, type DynamicRelationsProps, } from './dynamic-relations';
|
|
75
75
|
export { registerModelExtension, getModelExtension, clearModelExtensions, type ModelExtension, type ModelExtensionProps, } from './model-extension-registry';
|
|
76
76
|
export { isColumnVisibleInTable, isColumnVisibleInModal, isColumnVisibleInLineSubtable, AUDIT_SUBTABLE_COLUMN_KEYS, getSearchableColumnKeys, } from './column-visibility';
|
|
77
|
+
export { loadQueryPart, nameBatchTokens, optionsBatchToken, optionsModelFromUrl, type QueryPart, } from './query-batch';
|
|
77
78
|
export { useOptionsResolver, projectOption, type ResolvedOption, type OptionsMeta, type UseOptionsResolverArgs, type UseOptionsResolverResult, } from './use-options-resolver';
|
|
78
79
|
export { setOrgConfigBridge, getOrgConfigBridge, resolveValidatorToken, type OrgConfigBridge, } from './use-org-config-bridge';
|
|
79
80
|
export { registerValidator, getDependsOn, resolveDependsValue, getOptionsConfig, resolveOptionsSource, getVisibleWhen, evaluateVisibleWhen, scopeValueFromFilterToken, buildListScopeValues, evaluateVisibleWhenForListScope, applyLineItemRowFormulas, computeLineItemTotals, toNumber, } from './dynamic-form-schema';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,cAAc,SAAS,CAAA;AACvB,cAAc,wBAAwB,CAAA;AACtC,OAAO,EACH,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACd,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,eAAe,GACvB,MAAM,WAAW,CAAA;AAClB,cAAc,mBAAmB,CAAA;AACjC,OAAO,EACH,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,KAAK,UAAU,GAClB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACH,eAAe,EACf,iBAAiB,EACjB,UAAU,EACV,cAAc,EACd,YAAY,EACZ,yBAAyB,EACzB,KAAK,cAAc,GACtB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAA;AACnG,OAAO,EACH,sBAAsB,EACtB,yBAAyB,EACzB,4BAA4B,EAC5B,mBAAmB,EACnB,iBAAiB,GACpB,MAAM,uBAAuB,CAAA;AAC9B,cAAc,iBAAiB,CAAA;AAC/B,OAAO,EACH,aAAa,EACb,KAAK,kBAAkB,EACvB,YAAY,EACZ,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,GAClB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACH,mBAAmB,EACnB,sBAAsB,EACtB,WAAW,EACX,sBAAsB,EACtB,uBAAuB,EACvB,qBAAqB,EACrB,KAAK,eAAe,EACpB,KAAK,qBAAqB,EAC1B,KAAK,yBAAyB,EAC9B,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,2BAA2B,GACnC,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,iBAAiB,EACjB,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,EACvB,eAAe,EACf,sBAAsB,EACtB,cAAc,EACd,mBAAmB,EACnB,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,EACrB,iBAAiB,EACjB,mBAAmB,EACnB,SAAS,EACT,mBAAmB,EACnB,uBAAuB,EACvB,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,qBAAqB,EAC1B,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,0BAA0B,EAC/B,KAAK,sBAAsB,GAC9B,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACH,cAAc,EACd,KAAK,WAAW,EAChB,KAAK,oBAAoB,GAC5B,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACH,iBAAiB,EACjB,KAAK,kBAAkB,EACvB,KAAK,uBAAuB,GAC/B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACH,WAAW,EACX,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,KAAK,gBAAgB,GACxB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EACH,iBAAiB,EACjB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,GAC/B,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAA;AAC7E,OAAO,EACH,WAAW,EACX,WAAW,EACX,KAAK,aAAa,EAClB,KAAK,aAAa,GACrB,MAAM,gBAAgB,CAAA;AACvB,cAAc,gBAAgB,CAAA;AAC9B,OAAO,EACH,cAAc,EACd,KAAK,mBAAmB,GAC3B,MAAM,oBAAoB,CAAA;AAC3B,cAAc,mBAAmB,CAAA;AACjC,cAAc,eAAe,CAAA;AAC7B,cAAc,kBAAkB,CAAA;AAChC,OAAO,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAC/D,OAAO,EACH,qBAAqB,EACrB,KAAK,gBAAgB,GACxB,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACH,kBAAkB,EAClB,eAAe,EACf,KAAK,uBAAuB,EAC5B,KAAK,eAAe,GACvB,MAAM,wBAAwB,CAAA;AAC/B,cAAc,gBAAgB,CAAA;AAC9B,OAAO,EACH,mBAAmB,EACnB,uBAAuB,EACvB,uBAAuB,EACvB,oBAAoB,EACpB,kBAAkB,EAClB,UAAU,EACV,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,EACxB,KAAK,cAAc,GACtB,MAAM,eAAe,CAAA;AACtB,OAAO,EACH,mBAAmB,EACnB,cAAc,EACd,qBAAqB,EACrB,qBAAqB,EACrB,KAAK,WAAW,EAChB,KAAK,wBAAwB,GAChC,MAAM,wBAAwB,CAAA;AAC/B,cAAc,QAAQ,CAAA;AACtB,cAAc,mBAAmB,CAAA;AACjC,OAAO,EACH,mBAAmB,EACnB,MAAM,EACN,oBAAoB,EACpB,OAAO,EACP,sBAAsB,EACtB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,KAAK,EACV,KAAK,wBAAwB,GAChC,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,oBAAoB,EACpB,KAAK,0BAA0B,EAC/B,KAAK,iBAAiB,GACzB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AACzF,OAAO,EACH,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,sBAAsB,EACtB,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAClB,KAAK,uBAAuB,EAC5B,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,KAAK,WAAW,EAChB,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,OAAO,EACZ,KAAK,SAAS,GACjB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,kBAAkB,EAClB,iBAAiB,EACjB,sBAAsB,EACtB,UAAU,EACV,gBAAgB,EAChB,cAAc,EACd,SAAS,EACT,UAAU,EACV,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,EAChB,uBAAuB,EACvB,KAAK,WAAW,EAChB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,eAAe,EACpB,KAAK,cAAc,GACtB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACH,oBAAoB,EACpB,KAAK,yBAAyB,GACjC,MAAM,0BAA0B,CAAA;AACjC,cAAc,uBAAuB,CAAA;AACrC,cAAc,wBAAwB,CAAA;AACtC,cAAc,sBAAsB,CAAA;AACpC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,sBAAsB,CAAA;AACpC,cAAc,mBAAmB,CAAA;AACjC,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA;AACvC,cAAc,8BAA8B,CAAA;AAC5C,cAAc,4BAA4B,CAAA;AAC1C,cAAc,kBAAkB,CAAA;AAChC,OAAO,EACH,gBAAgB,EAChB,iBAAiB,EACjB,kBAAkB,EAClB,WAAW,EACX,iBAAiB,EACjB,qBAAqB,EACrB,eAAe,EACf,oBAAoB,EACpB,KAAK,oBAAoB,EACzB,KAAK,qBAAqB,EAC1B,KAAK,kBAAkB,EACvB,KAAK,4BAA4B,EACjC,KAAK,sBAAsB,GAC9B,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACH,2BAA2B,EAC3B,uBAAuB,EACvB,4BAA4B,EAC5B,KAAK,2BAA2B,EAChC,KAAK,qBAAqB,EAC1B,KAAK,8BAA8B,GACtC,MAAM,+BAA+B,CAAA;AACtC,OAAO,EACH,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,wBAAwB,EACxB,WAAW,EACX,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,EACxB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,sBAAsB,GAC9B,MAAM,yBAAyB,CAAA;AAChC,cAAc,gBAAgB,CAAA;AAC9B,YAAY,EACR,kBAAkB,EAClB,YAAY,IAAI,yBAAyB,EACzC,iBAAiB,EACjB,oBAAoB,GACvB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACH,wBAAwB,EACxB,4BAA4B,EAC5B,cAAc,EACd,gBAAgB,EAChB,wBAAwB,EACxB,uBAAuB,EACvB,oBAAoB,EACpB,KAAK,qBAAqB,GAC7B,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,aAAa,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAA;AACjF,YAAY,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AACnE,OAAO,EACH,OAAO,EACP,QAAQ,EACR,cAAc,EACd,UAAU,EACV,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,SAAS,EACT,UAAU,EACV,aAAa,EACb,eAAe,EACf,kBAAkB,EAClB,KAAK,OAAO,EACZ,KAAK,cAAc,GACtB,MAAM,YAAY,CAAA;AACnB,OAAO,EACH,UAAU,EACV,WAAW,EACX,cAAc,EACd,cAAc,GACjB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACH,cAAc,EACd,YAAY,EACZ,WAAW,EACX,UAAU,EACV,KAAK,mBAAmB,EACxB,KAAK,SAAS,IAAI,uBAAuB,GAC5C,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAClE,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACzE,OAAO,EAAE,2BAA2B,EAAE,MAAM,4BAA4B,CAAA;AACxE,YAAY,EAAE,wBAAwB,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAC5G,OAAO,EAAE,kBAAkB,EAAE,MAAM,gCAAgC,CAAA;AACnE,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC9C,YAAY,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AAC5E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAA;AAC/D,YAAY,EACR,QAAQ,EACR,WAAW,EACX,YAAY,EACZ,iBAAiB,EACjB,uBAAuB,EACvB,qBAAqB,GACxB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAC/C,OAAO,EACH,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,sBAAsB,GAC9B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,eAAe,EACf,KAAK,oBAAoB,EACzB,KAAK,sBAAsB,EAC3B,KAAK,mBAAmB,EACxB,yBAAyB,EACzB,kBAAkB,EAClB,wBAAwB,EACxB,cAAc,GACjB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EACH,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,UAAU,EACV,KAAK,qBAAqB,GAC7B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,sBAAsB,EACtB,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,cAAc,EACnB,KAAK,mBAAmB,GAC3B,MAAM,4BAA4B,CAAA;AACnC,OAAO,EACH,sBAAsB,EACtB,sBAAsB,EACtB,6BAA6B,EAC7B,0BAA0B,EAC1B,uBAAuB,GAC1B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,SAAS,GACjB,MAAM,eAAe,CAAA;AACtB,OAAO,EACH,kBAAkB,EAClB,aAAa,EACb,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,sBAAsB,EAC3B,KAAK,wBAAwB,GAChC,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EACH,kBAAkB,EAClB,kBAAkB,EAClB,qBAAqB,EACrB,KAAK,eAAe,GACvB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACH,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,mBAAmB,EACnB,yBAAyB,EACzB,oBAAoB,EACpB,+BAA+B,EAC/B,wBAAwB,EACxB,qBAAqB,EACrB,QAAQ,GACX,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,wBAAwB,EACxB,mBAAmB,EACnB,KAAK,mBAAmB,GAC3B,MAAM,sBAAsB,CAAA;AAC7B,OAAO,EACH,qBAAqB,EACrB,KAAK,0BAA0B,GAClC,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACH,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,iBAAiB,GACzB,MAAM,iBAAiB,CAAA;AACxB,OAAO,EACH,aAAa,EACb,KAAK,kBAAkB,GAC1B,MAAM,kBAAkB,CAAA;AACzB,OAAO,EACH,gBAAgB,EAChB,KAAK,qBAAqB,GAC7B,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,aAAa,EACb,eAAe,GAClB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAA;AAC/D,YAAY,EACR,UAAU,EACV,UAAU,EACV,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,EACV,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EAClB,oBAAoB,GACvB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EACH,UAAU,EACV,SAAS,EACT,UAAU,EACV,UAAU,EACV,SAAS,EACT,WAAW,EACX,UAAU,EACV,cAAc,EACd,KAAK,iBAAiB,GACzB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EACH,cAAc,EACd,cAAc,EACd,SAAS,EACT,UAAU,EACV,KAAK,mBAAmB,GAC3B,MAAM,2BAA2B,CAAA;AAClC,OAAO,EACH,UAAU,EACV,SAAS,EACT,WAAW,EACX,WAAW,EACX,KAAK,eAAe,GACvB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EACH,iBAAiB,EACjB,cAAc,EACd,WAAW,EACX,aAAa,EACb,YAAY,EACZ,aAAa,EACb,KAAK,aAAa,EAClB,KAAK,eAAe,GACvB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AACpE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,UAAU,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -74,6 +74,7 @@ export { DynamicRelation, buildRelationFilterParams, buildCreatePayload, deriveR
|
|
|
74
74
|
export { DynamicRelations, resolveParentId, buildRelationFilters, isEmbedded, } from './dynamic-relations';
|
|
75
75
|
export { registerModelExtension, getModelExtension, clearModelExtensions, } from './model-extension-registry';
|
|
76
76
|
export { isColumnVisibleInTable, isColumnVisibleInModal, isColumnVisibleInLineSubtable, AUDIT_SUBTABLE_COLUMN_KEYS, getSearchableColumnKeys, } from './column-visibility';
|
|
77
|
+
export { loadQueryPart, nameBatchTokens, optionsBatchToken, optionsModelFromUrl, } from './query-batch';
|
|
77
78
|
export { useOptionsResolver, projectOption, } from './use-options-resolver';
|
|
78
79
|
export { setOrgConfigBridge, getOrgConfigBridge, resolveValidatorToken, } from './use-org-config-bridge';
|
|
79
80
|
export { registerValidator, getDependsOn, resolveDependsValue, getOptionsConfig, resolveOptionsSource, getVisibleWhen, evaluateVisibleWhen, scopeValueFromFilterToken, buildListScopeValues, evaluateVisibleWhenForListScope, applyLineItemRowFormulas, computeLineItemTotals, toNumber, } from './dynamic-form-schema';
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coalesces concurrent reads into one POST /api/q.
|
|
3
|
+
*
|
|
4
|
+
* Callers enqueue a batch token (`o:Customer?field=id&q=lop`). Tokens that
|
|
5
|
+
* arrive inside an 8ms window share one request. Each part keeps its own
|
|
6
|
+
* success, data and etag. A failed part does not reject the others.
|
|
7
|
+
*/
|
|
8
|
+
import type { ApiClient } from './api-context';
|
|
9
|
+
export interface QueryPart {
|
|
10
|
+
success: boolean;
|
|
11
|
+
data?: unknown;
|
|
12
|
+
meta?: unknown;
|
|
13
|
+
message?: string;
|
|
14
|
+
etag?: string;
|
|
15
|
+
not_modified?: boolean;
|
|
16
|
+
}
|
|
17
|
+
export declare function optionsModelFromUrl(url: string): string | null;
|
|
18
|
+
export declare function optionsBatchToken(model: string, field: string, query: string, limit: number | undefined, filter: string | undefined): string;
|
|
19
|
+
/** Names each distinct token so the server can key the response. */
|
|
20
|
+
export declare function nameBatchTokens(tokens: string[]): {
|
|
21
|
+
name: string;
|
|
22
|
+
token: string;
|
|
23
|
+
plan: string;
|
|
24
|
+
}[];
|
|
25
|
+
export declare function loadQueryPart(api: ApiClient, token: string): Promise<QueryPart>;
|
|
26
|
+
//# sourceMappingURL=query-batch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query-batch.d.ts","sourceRoot":"","sources":["../src/query-batch.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AAE9C,MAAM,WAAW,SAAS;IACtB,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,YAAY,CAAC,EAAE,OAAO,CAAA;CACzB;AA6BD,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG9D;AAED,wBAAgB,iBAAiB,CAC7B,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,MAAM,EAAE,MAAM,GAAG,SAAS,GAC3B,MAAM,CAOR;AAED,oEAAoE;AACpE,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAYjG;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAU/E"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
const WINDOW_MS = 8;
|
|
2
|
+
const PART_TTL_MS = 30_000;
|
|
3
|
+
const partCache = new Map();
|
|
4
|
+
let waiters = [];
|
|
5
|
+
let timer = null;
|
|
6
|
+
let transport = null;
|
|
7
|
+
function cacheScope() {
|
|
8
|
+
if (typeof localStorage === 'undefined')
|
|
9
|
+
return '';
|
|
10
|
+
try {
|
|
11
|
+
const raw = localStorage.getItem('auth_user');
|
|
12
|
+
if (!raw)
|
|
13
|
+
return '';
|
|
14
|
+
return String(JSON.parse(raw).organization_id ?? '');
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return '';
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export function optionsModelFromUrl(url) {
|
|
21
|
+
const match = url.match(/^\/options\/([A-Za-z][A-Za-z0-9_]*)$/);
|
|
22
|
+
return match ? match[1] : null;
|
|
23
|
+
}
|
|
24
|
+
export function optionsBatchToken(model, field, query, limit, filter) {
|
|
25
|
+
const params = new URLSearchParams();
|
|
26
|
+
params.set('field', field);
|
|
27
|
+
if (query)
|
|
28
|
+
params.set('q', query);
|
|
29
|
+
if (typeof limit === 'number' && limit > 0)
|
|
30
|
+
params.set('limit', String(limit));
|
|
31
|
+
if (filter)
|
|
32
|
+
params.set('filter_value', filter);
|
|
33
|
+
return `o:${model}?${params.toString()}`;
|
|
34
|
+
}
|
|
35
|
+
/** Names each distinct token so the server can key the response. */
|
|
36
|
+
export function nameBatchTokens(tokens) {
|
|
37
|
+
const unique = [];
|
|
38
|
+
const seen = new Set();
|
|
39
|
+
for (const token of tokens) {
|
|
40
|
+
if (seen.has(token))
|
|
41
|
+
continue;
|
|
42
|
+
seen.add(token);
|
|
43
|
+
unique.push(token);
|
|
44
|
+
}
|
|
45
|
+
return unique.map((token, index) => {
|
|
46
|
+
const name = `q${index + 1}`;
|
|
47
|
+
return { name, token, plan: `${name}=${token}` };
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
export function loadQueryPart(api, token) {
|
|
51
|
+
const cached = partCache.get(`${cacheScope()}\n${token}`);
|
|
52
|
+
if (cached && Date.now() - cached.at < PART_TTL_MS && cached.part.success) {
|
|
53
|
+
return Promise.resolve(cached.part);
|
|
54
|
+
}
|
|
55
|
+
return new Promise((resolve, reject) => {
|
|
56
|
+
transport = api;
|
|
57
|
+
waiters.push({ token, resolve, reject });
|
|
58
|
+
if (timer == null)
|
|
59
|
+
timer = setTimeout(() => void flushQueryBatch(), WINDOW_MS);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
async function flushQueryBatch() {
|
|
63
|
+
timer = null;
|
|
64
|
+
const batch = waiters;
|
|
65
|
+
waiters = [];
|
|
66
|
+
const api = transport;
|
|
67
|
+
if (!api || batch.length === 0)
|
|
68
|
+
return;
|
|
69
|
+
const named = nameBatchTokens(batch.map((waiter) => waiter.token));
|
|
70
|
+
const byToken = new Map(named.map((part) => [part.token, part.name]));
|
|
71
|
+
const inm = {};
|
|
72
|
+
const scope = cacheScope();
|
|
73
|
+
for (const part of named) {
|
|
74
|
+
const cached = partCache.get(`${scope}\n${part.token}`);
|
|
75
|
+
if (cached?.part.etag)
|
|
76
|
+
inm[part.name] = cached.part.etag;
|
|
77
|
+
}
|
|
78
|
+
try {
|
|
79
|
+
const res = await api.post('/q', { parts: named.map((part) => part.plan), inm });
|
|
80
|
+
const body = res?.data;
|
|
81
|
+
if (!body || body.success !== true || !body.parts) {
|
|
82
|
+
throw new Error('batch unavailable');
|
|
83
|
+
}
|
|
84
|
+
for (const waiter of batch) {
|
|
85
|
+
const name = byToken.get(waiter.token);
|
|
86
|
+
const part = name ? body.parts[name] : undefined;
|
|
87
|
+
if (!part) {
|
|
88
|
+
waiter.reject(new Error('batch part missing'));
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
if (part.not_modified) {
|
|
92
|
+
const cached = partCache.get(`${scope}\n${waiter.token}`);
|
|
93
|
+
if (cached) {
|
|
94
|
+
waiter.resolve(cached.part);
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
if (part.success) {
|
|
99
|
+
partCache.set(`${scope}\n${waiter.token}`, { part, at: Date.now() });
|
|
100
|
+
}
|
|
101
|
+
waiter.resolve(part);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
106
|
+
for (const waiter of batch)
|
|
107
|
+
waiter.reject(error);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-options-resolver.d.ts","sourceRoot":"","sources":["../src/use-options-resolver.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"use-options-resolver.d.ts","sourceRoot":"","sources":["../src/use-options-resolver.ts"],"names":[],"mappings":"AAgBA,MAAM,WAAW,cAAc;IAC3B,8CAA8C;IAC9C,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,2DAA2D;IAC3D,KAAK,EAAE,MAAM,GAAG,MAAM,CAAA;IACtB,sBAAsB;IACtB,KAAK,EAAE,MAAM,CAAA;IACb,8DAA8D;IAC9D,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACvB;AAED,MAAM,WAAW,WAAW;IACxB,oEAAoE;IACpE,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,MAAM,CAAA;IACnC,2DAA2D;IAC3D,KAAK,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,sBAAsB;IACnC;;;;OAIG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAA;IAChB;;;;;OAKG;IACH,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;;;;;OAOG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAA;IACd;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,WAAW,wBAAwB;IACrC,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,IAAI,EAAE,WAAW,GAAG,IAAI,CAAA;IACxB,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAA;IACnB,8DAA8D;IAC9D,OAAO,EAAE,MAAM,IAAI,CAAA;CACtB;AAoBD,wBAAgB,iBAAiB,CAC7B,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,MAAM,EAAE,MAAM,GAAG,SAAS,GAC3B,MAAM,CAER;AA8BD,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,sBAAsB,GAAG,wBAAwB,CA4JzF;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,GAAG,GAAG,cAAc,CAatD"}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
// free; legacy callers that still ship `searchEndpoint` keep working.
|
|
13
13
|
import { useEffect, useMemo, useRef, useState } from 'react';
|
|
14
14
|
import { useApi } from './api-context';
|
|
15
|
+
import { loadQueryPart, optionsBatchToken, optionsModelFromUrl } from './query-batch';
|
|
15
16
|
/**
|
|
16
17
|
* Resolves select options for a field via the canonical
|
|
17
18
|
* `/api/options/:model?field=…` endpoint. Returns the v0.9.0 envelope
|
|
@@ -126,7 +127,32 @@ export function useOptionsResolver(args) {
|
|
|
126
127
|
params.limit = limit;
|
|
127
128
|
if (filterValue)
|
|
128
129
|
params.filter_value = filterValue;
|
|
129
|
-
|
|
130
|
+
const model = optionsModelFromUrl(url);
|
|
131
|
+
pending = (async () => {
|
|
132
|
+
if (model) {
|
|
133
|
+
try {
|
|
134
|
+
const part = await loadQueryPart(api, optionsBatchToken(model, effectiveField, query ?? '', limit, filterValue));
|
|
135
|
+
if (!part.success) {
|
|
136
|
+
throw new Error(part.message || 'options resolver: unsuccessful response');
|
|
137
|
+
}
|
|
138
|
+
const payload = readOptionsEnvelope({
|
|
139
|
+
success: true,
|
|
140
|
+
data: part.data,
|
|
141
|
+
meta: part.meta,
|
|
142
|
+
});
|
|
143
|
+
if ((optionsEpoch.get(key) ?? 0) === epoch) {
|
|
144
|
+
optionsCache.set(key, { payload, at: Date.now() });
|
|
145
|
+
}
|
|
146
|
+
return payload;
|
|
147
|
+
}
|
|
148
|
+
catch (err) {
|
|
149
|
+
const msg = err instanceof Error ? err.message : '';
|
|
150
|
+
const batchMiss = msg === 'batch unavailable' || msg === 'batch part missing';
|
|
151
|
+
if (!batchMiss)
|
|
152
|
+
throw err;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
const res = await api.get(url, { params });
|
|
130
156
|
const body = res.data;
|
|
131
157
|
if (!body || body.success !== true) {
|
|
132
158
|
throw new Error(body?.message || 'options resolver: unsuccessful response');
|
|
@@ -136,7 +162,7 @@ export function useOptionsResolver(args) {
|
|
|
136
162
|
optionsCache.set(key, { payload, at: Date.now() });
|
|
137
163
|
}
|
|
138
164
|
return payload;
|
|
139
|
-
}).finally(() => {
|
|
165
|
+
})().finally(() => {
|
|
140
166
|
if (optionsInflight.get(key) === pending)
|
|
141
167
|
optionsInflight.delete(key);
|
|
142
168
|
});
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -392,6 +392,13 @@ export {
|
|
|
392
392
|
AUDIT_SUBTABLE_COLUMN_KEYS,
|
|
393
393
|
getSearchableColumnKeys,
|
|
394
394
|
} from './column-visibility'
|
|
395
|
+
export {
|
|
396
|
+
loadQueryPart,
|
|
397
|
+
nameBatchTokens,
|
|
398
|
+
optionsBatchToken,
|
|
399
|
+
optionsModelFromUrl,
|
|
400
|
+
type QueryPart,
|
|
401
|
+
} from './query-batch'
|
|
395
402
|
export {
|
|
396
403
|
useOptionsResolver,
|
|
397
404
|
projectOption,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest'
|
|
2
|
+
import { nameBatchTokens, optionsBatchToken, optionsModelFromUrl } from './query-batch'
|
|
3
|
+
|
|
4
|
+
describe('query batch tokens', () => {
|
|
5
|
+
it('names distinct tokens and keeps duplicates as one part', () => {
|
|
6
|
+
const named = nameBatchTokens([
|
|
7
|
+
'o:Customer?field=id',
|
|
8
|
+
'o:Product?field=id',
|
|
9
|
+
'o:Customer?field=id',
|
|
10
|
+
])
|
|
11
|
+
expect(named).toEqual([
|
|
12
|
+
{ name: 'q1', token: 'o:Customer?field=id', plan: 'q1=o:Customer?field=id' },
|
|
13
|
+
{ name: 'q2', token: 'o:Product?field=id', plan: 'q2=o:Product?field=id' },
|
|
14
|
+
])
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
it('builds an options token from the canonical url', () => {
|
|
18
|
+
expect(optionsModelFromUrl('/options/Customer')).toBe('Customer')
|
|
19
|
+
expect(optionsModelFromUrl('/data/Customer')).toBeNull()
|
|
20
|
+
expect(optionsBatchToken('Customer', 'id', 'lop', 20, undefined)).toBe(
|
|
21
|
+
'o:Customer?field=id&q=lop&limit=20',
|
|
22
|
+
)
|
|
23
|
+
})
|
|
24
|
+
})
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Coalesces concurrent reads into one POST /api/q.
|
|
3
|
+
*
|
|
4
|
+
* Callers enqueue a batch token (`o:Customer?field=id&q=lop`). Tokens that
|
|
5
|
+
* arrive inside an 8ms window share one request. Each part keeps its own
|
|
6
|
+
* success, data and etag. A failed part does not reject the others.
|
|
7
|
+
*/
|
|
8
|
+
import type { ApiClient } from './api-context'
|
|
9
|
+
|
|
10
|
+
export interface QueryPart {
|
|
11
|
+
success: boolean
|
|
12
|
+
data?: unknown
|
|
13
|
+
meta?: unknown
|
|
14
|
+
message?: string
|
|
15
|
+
etag?: string
|
|
16
|
+
not_modified?: boolean
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const WINDOW_MS = 8
|
|
20
|
+
const PART_TTL_MS = 30_000
|
|
21
|
+
|
|
22
|
+
type Waiter = {
|
|
23
|
+
token: string
|
|
24
|
+
resolve: (part: QueryPart) => void
|
|
25
|
+
reject: (error: Error) => void
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
type CachedPart = { part: QueryPart; at: number }
|
|
29
|
+
|
|
30
|
+
const partCache = new Map<string, CachedPart>()
|
|
31
|
+
let waiters: Waiter[] = []
|
|
32
|
+
let timer: ReturnType<typeof setTimeout> | null = null
|
|
33
|
+
let transport: ApiClient | null = null
|
|
34
|
+
|
|
35
|
+
function cacheScope(): string {
|
|
36
|
+
if (typeof localStorage === 'undefined') return ''
|
|
37
|
+
try {
|
|
38
|
+
const raw = localStorage.getItem('auth_user')
|
|
39
|
+
if (!raw) return ''
|
|
40
|
+
return String((JSON.parse(raw) as { organization_id?: string }).organization_id ?? '')
|
|
41
|
+
} catch {
|
|
42
|
+
return ''
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export function optionsModelFromUrl(url: string): string | null {
|
|
47
|
+
const match = url.match(/^\/options\/([A-Za-z][A-Za-z0-9_]*)$/)
|
|
48
|
+
return match ? match[1] : null
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function optionsBatchToken(
|
|
52
|
+
model: string,
|
|
53
|
+
field: string,
|
|
54
|
+
query: string,
|
|
55
|
+
limit: number | undefined,
|
|
56
|
+
filter: string | undefined,
|
|
57
|
+
): string {
|
|
58
|
+
const params = new URLSearchParams()
|
|
59
|
+
params.set('field', field)
|
|
60
|
+
if (query) params.set('q', query)
|
|
61
|
+
if (typeof limit === 'number' && limit > 0) params.set('limit', String(limit))
|
|
62
|
+
if (filter) params.set('filter_value', filter)
|
|
63
|
+
return `o:${model}?${params.toString()}`
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/** Names each distinct token so the server can key the response. */
|
|
67
|
+
export function nameBatchTokens(tokens: string[]): { name: string; token: string; plan: string }[] {
|
|
68
|
+
const unique: string[] = []
|
|
69
|
+
const seen = new Set<string>()
|
|
70
|
+
for (const token of tokens) {
|
|
71
|
+
if (seen.has(token)) continue
|
|
72
|
+
seen.add(token)
|
|
73
|
+
unique.push(token)
|
|
74
|
+
}
|
|
75
|
+
return unique.map((token, index) => {
|
|
76
|
+
const name = `q${index + 1}`
|
|
77
|
+
return { name, token, plan: `${name}=${token}` }
|
|
78
|
+
})
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function loadQueryPart(api: ApiClient, token: string): Promise<QueryPart> {
|
|
82
|
+
const cached = partCache.get(`${cacheScope()}\n${token}`)
|
|
83
|
+
if (cached && Date.now() - cached.at < PART_TTL_MS && cached.part.success) {
|
|
84
|
+
return Promise.resolve(cached.part)
|
|
85
|
+
}
|
|
86
|
+
return new Promise((resolve, reject) => {
|
|
87
|
+
transport = api
|
|
88
|
+
waiters.push({ token, resolve, reject })
|
|
89
|
+
if (timer == null) timer = setTimeout(() => void flushQueryBatch(), WINDOW_MS)
|
|
90
|
+
})
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async function flushQueryBatch() {
|
|
94
|
+
timer = null
|
|
95
|
+
const batch = waiters
|
|
96
|
+
waiters = []
|
|
97
|
+
const api = transport
|
|
98
|
+
if (!api || batch.length === 0) return
|
|
99
|
+
const named = nameBatchTokens(batch.map((waiter) => waiter.token))
|
|
100
|
+
const byToken = new Map(named.map((part) => [part.token, part.name]))
|
|
101
|
+
const inm: Record<string, string> = {}
|
|
102
|
+
const scope = cacheScope()
|
|
103
|
+
for (const part of named) {
|
|
104
|
+
const cached = partCache.get(`${scope}\n${part.token}`)
|
|
105
|
+
if (cached?.part.etag) inm[part.name] = cached.part.etag
|
|
106
|
+
}
|
|
107
|
+
try {
|
|
108
|
+
const res = await api.post('/q', { parts: named.map((part) => part.plan), inm })
|
|
109
|
+
const body = res?.data
|
|
110
|
+
if (!body || body.success !== true || !body.parts) {
|
|
111
|
+
throw new Error('batch unavailable')
|
|
112
|
+
}
|
|
113
|
+
for (const waiter of batch) {
|
|
114
|
+
const name = byToken.get(waiter.token)
|
|
115
|
+
const part = name ? (body.parts[name] as QueryPart | undefined) : undefined
|
|
116
|
+
if (!part) {
|
|
117
|
+
waiter.reject(new Error('batch part missing'))
|
|
118
|
+
continue
|
|
119
|
+
}
|
|
120
|
+
if (part.not_modified) {
|
|
121
|
+
const cached = partCache.get(`${scope}\n${waiter.token}`)
|
|
122
|
+
if (cached) {
|
|
123
|
+
waiter.resolve(cached.part)
|
|
124
|
+
continue
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (part.success) {
|
|
128
|
+
partCache.set(`${scope}\n${waiter.token}`, { part, at: Date.now() })
|
|
129
|
+
}
|
|
130
|
+
waiter.resolve(part)
|
|
131
|
+
}
|
|
132
|
+
} catch (err) {
|
|
133
|
+
const error = err instanceof Error ? err : new Error(String(err))
|
|
134
|
+
for (const waiter of batch) waiter.reject(error)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
// free; legacy callers that still ship `searchEndpoint` keep working.
|
|
13
13
|
import { useEffect, useMemo, useRef, useState } from 'react'
|
|
14
14
|
import { useApi } from './api-context'
|
|
15
|
+
import { loadQueryPart, optionsBatchToken, optionsModelFromUrl } from './query-batch'
|
|
15
16
|
|
|
16
17
|
export interface ResolvedOption {
|
|
17
18
|
/** Canonical id (server-side primary key). */
|
|
@@ -237,7 +238,33 @@ export function useOptionsResolver(args: UseOptionsResolverArgs): UseOptionsReso
|
|
|
237
238
|
if (query) params.q = query
|
|
238
239
|
if (typeof limit === 'number' && limit > 0) params.limit = limit
|
|
239
240
|
if (filterValue) params.filter_value = filterValue
|
|
240
|
-
|
|
241
|
+
const model = optionsModelFromUrl(url)
|
|
242
|
+
pending = (async () => {
|
|
243
|
+
if (model) {
|
|
244
|
+
try {
|
|
245
|
+
const part = await loadQueryPart(
|
|
246
|
+
api,
|
|
247
|
+
optionsBatchToken(model, effectiveField, query ?? '', limit, filterValue),
|
|
248
|
+
)
|
|
249
|
+
if (!part.success) {
|
|
250
|
+
throw new Error(part.message || 'options resolver: unsuccessful response')
|
|
251
|
+
}
|
|
252
|
+
const payload = readOptionsEnvelope({
|
|
253
|
+
success: true,
|
|
254
|
+
data: part.data,
|
|
255
|
+
meta: part.meta,
|
|
256
|
+
})
|
|
257
|
+
if ((optionsEpoch.get(key) ?? 0) === epoch) {
|
|
258
|
+
optionsCache.set(key, { payload, at: Date.now() })
|
|
259
|
+
}
|
|
260
|
+
return payload
|
|
261
|
+
} catch (err) {
|
|
262
|
+
const msg = err instanceof Error ? err.message : ''
|
|
263
|
+
const batchMiss = msg === 'batch unavailable' || msg === 'batch part missing'
|
|
264
|
+
if (!batchMiss) throw err
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
const res = await api.get(url, { params })
|
|
241
268
|
const body = (res as { data: any }).data
|
|
242
269
|
if (!body || body.success !== true) {
|
|
243
270
|
throw new Error(body?.message || 'options resolver: unsuccessful response')
|
|
@@ -247,7 +274,7 @@ export function useOptionsResolver(args: UseOptionsResolverArgs): UseOptionsReso
|
|
|
247
274
|
optionsCache.set(key, { payload, at: Date.now() })
|
|
248
275
|
}
|
|
249
276
|
return payload
|
|
250
|
-
}).finally(() => {
|
|
277
|
+
})().finally(() => {
|
|
251
278
|
if (optionsInflight.get(key) === pending) optionsInflight.delete(key)
|
|
252
279
|
})
|
|
253
280
|
optionsInflight.set(key, pending)
|