@resistdesign/voltra 3.0.0-alpha.44 → 3.0.0-alpha.46

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
@@ -242,6 +242,7 @@ const coords = layout.computeNativeCoords({
242
242
 
243
243
  Voltra routing uses the same `Route` API across app/web/native.
244
244
  Use the platform barrel for root `Route` so runtime mechanics are auto-wired.
245
+ The routing model is path/history based on every platform.
245
246
 
246
247
  Reference example: `examples/routing/app-routing.ts`
247
248
 
@@ -271,10 +272,22 @@ import { Route } from "@resistdesign/voltra/native";
271
272
  </Route>;
272
273
  ```
273
274
 
275
+ On native, Voltra provides the missing browser-like pieces:
276
+
277
+ - history-style path state for environments without the browser History API
278
+ - deep-link URL ingress so app opens behave like web navigations
279
+ - hardware back wiring into that same history model
280
+ - the `native` barrel auto-selects browser behavior on React Native web targets
281
+ and native-history behavior on mobile targets
282
+
274
283
  How it works:
275
284
 
276
285
  - Root `<Route>` (no `path`) is provider mode.
277
286
  - Nested `<Route path="...">` entries are matcher mode.
287
+ - Shared app routing matches normalized path strings on every platform.
288
+ - Web already receives a browser pathname.
289
+ - Native provides the browser-like history/path source that mobile lacks.
290
+ - Native deep-link ingress is mapped into that same path/history model.
278
291
  - Strategy is auto-selected:
279
292
  - DOM + History API => browser history strategy.
280
293
  - Otherwise => in-memory native strategy.
@@ -17,6 +17,17 @@
17
17
  import { BaseTypeInfoORMServiceConfig, TypeInfoORMDACConfig } from "./TypeInfoORMService";
18
18
  import { AuthInfo, RouteAuthConfig, RouteMap } from "../Router/Types";
19
19
  import { TypeInfoORMAPI } from "../../common/TypeInfoORM";
20
+ /**
21
+ * Optional configuration for Type Info ORM route-map behavior.
22
+ */
23
+ export type TypeInfoORMRouteMapConfig = {
24
+ /**
25
+ * Whether update handlers should forward field operators from request args.
26
+ *
27
+ * Defaults to `true`.
28
+ */
29
+ allowUpdateFieldOperators?: boolean;
30
+ };
20
31
  /**
21
32
  * A collection of errors that can occur when creating or using a Type Info ORM Route Map.
22
33
  * */
@@ -52,4 +63,8 @@ getAccessingRoleId?: (authInfo: AuthInfo) => string,
52
63
  /**
53
64
  * Optional route-level auth configuration.
54
65
  */
55
- authConfig?: RouteAuthConfig) => RouteMap;
66
+ authConfig?: RouteAuthConfig,
67
+ /**
68
+ * Optional route-map behavior config.
69
+ */
70
+ routeMapConfig?: TypeInfoORMRouteMapConfig) => RouteMap;
@@ -8,7 +8,7 @@
8
8
  import { LiteralValue, TypeInfo, TypeInfoDataItem, TypeInfoField, TypeInfoMap, TypeOperation } from "../../common/TypeParsing/TypeInfo";
9
9
  import { CustomTypeInfoFieldValidatorMap } from "../../common/TypeParsing/Validation";
10
10
  import { ComparisonOperators, FieldCriterion, ListItemsConfig, ListItemsResults, ListRelationshipsConfig, SearchCriteria } from "../../common/SearchTypes";
11
- import { DeleteRelationshipResults, RelationshipOperation, TypeInfoORMAPI, TypeInfoORMContext } from "../../common/TypeInfoORM";
11
+ import { DeleteRelationshipResults, RelationshipOperation, TypeInfoORMAPI, TypeInfoORMContext, TypeInfoORMUpdateConfig } from "../../common/TypeInfoORM";
12
12
  import { DataItemDBDriver, IndexingRelationshipDriver, ItemRelationshipDBDriver } from "./drivers";
13
13
  import { BaseItemRelationshipInfo, ItemRelationshipInfo, ItemRelationshipInfoKeys, ItemRelationshipInfoType, ItemRelationshipOriginatingItemInfo } from "../../common/ItemRelationshipInfoTypes";
14
14
  import { DACAccessResult, DACDataItemResourceAccessResultMap, DACRole } from "../DataAccessControl";
@@ -738,6 +738,10 @@ export declare class TypeInfoORMService implements TypeInfoORMAPI {
738
738
  * Whether the item is a partial update.
739
739
  */
740
740
  itemIsPartial?: boolean) => void;
741
+ /**
742
+ * Validate update operator config against the target TypeInfo fields.
743
+ */
744
+ protected validateUpdateConfig: (typeName: string, item: TypeInfoDataItem, updateConfig?: TypeInfoORMUpdateConfig) => void;
741
745
  /**
742
746
  * @returns Cleaned item with selected fields and DAC constraints applied.
743
747
  */
@@ -853,9 +857,10 @@ export declare class TypeInfoORMService implements TypeInfoORMAPI {
853
857
  * The `item` **must always** contain its **primary field value**.
854
858
  * @param typeName Type name to update.
855
859
  * @param item Item payload to update.
860
+ * @param updateConfig Optional per-field operator config.
856
861
  * @returns True when the update succeeded.
857
862
  * */
858
- update: (typeName: string, item: TypeInfoDataItem, context?: TypeInfoORMContext) => Promise<boolean>;
863
+ update: (typeName: string, item: TypeInfoDataItem, updateConfig?: TypeInfoORMUpdateConfig, context?: TypeInfoORMContext) => Promise<boolean>;
859
864
  /**
860
865
  * Delete an existing item of the given type.
861
866
  * @param typeName Type name to delete.
@@ -7,6 +7,7 @@
7
7
  import { DataItemDBDriver, DataItemDBDriverConfig, SupportedDataItemDBDriverEntry } from "./common/Types";
8
8
  import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
9
9
  import { TypeInfoDataItem } from "../../../common/TypeParsing/TypeInfo";
10
+ import { TypeInfoORMUpdateConfig } from "../../../common/TypeInfoORM";
10
11
  import { ListItemsConfig, ListItemsResults } from "../../../common/SearchTypes";
11
12
  /**
12
13
  * A {@link DataItemDBDriver} that uses DynamoDB as its database.
@@ -59,7 +60,7 @@ export declare class DynamoDBDataItemDBDriver<ItemType extends TypeInfoDataItem,
59
60
  /**
60
61
  * Partial update payload for the item.
61
62
  */
62
- updatedItem: Partial<ItemType>) => Promise<boolean>;
63
+ updatedItem: Partial<ItemType>, updateConfig?: TypeInfoORMUpdateConfig) => Promise<boolean>;
63
64
  /**
64
65
  * Delete an item from the database.
65
66
  * @returns True when an item was deleted.
@@ -1,6 +1,7 @@
1
1
  import { DataItemDBDriver, DataItemDBDriverConfig, SupportedDataItemDBDriverEntry } from "./common/Types";
2
2
  import type { TypeInfoDataItem } from "../../../common/TypeParsing/TypeInfo";
3
3
  import type { ListItemsConfig, ListItemsResults } from "../../../common/SearchTypes";
4
+ import { TypeInfoORMUpdateConfig } from "../../../common/TypeInfoORM";
4
5
  /**
5
6
  * In-memory data item driver for testing and local usage.
6
7
  */
@@ -34,7 +35,7 @@ export declare class InMemoryDataItemDBDriver<ItemType extends TypeInfoDataItem,
34
35
  * @param updatedItem Partial update payload for the item.
35
36
  * @returns True when the item was updated.
36
37
  */
37
- updateItem: (uniqueIdentifier: ItemType[UniquelyIdentifyingFieldName], updatedItem: Partial<ItemType>) => Promise<boolean>;
38
+ updateItem: (uniqueIdentifier: ItemType[UniquelyIdentifyingFieldName], updatedItem: Partial<ItemType>, updateConfig?: TypeInfoORMUpdateConfig) => Promise<boolean>;
38
39
  /**
39
40
  * Delete an item from memory.
40
41
  * @param uniqueIdentifier Unique identifier value for the item.
@@ -1,6 +1,7 @@
1
1
  import { TypeInfoDataItem, TypeInfoPack } from "../../../../common/TypeParsing/TypeInfo";
2
2
  import { ItemRelationshipInfo, ItemRelationshipInfoIdentifyingKeys } from "../../../../common/ItemRelationshipInfoTypes";
3
3
  import { ListItemsConfig, ListItemsResults } from "../../../../common/SearchTypes";
4
+ import type { TypeInfoORMUpdateConfig } from "../../../../common/TypeInfoORM/Types";
4
5
  /**
5
6
  * The errors that can be thrown by a {@link DataItemDBDriver}.
6
7
  * */
@@ -24,7 +25,11 @@ export declare enum DATA_ITEM_DB_DRIVER_ERRORS {
24
25
  /**
25
26
  * Search operator is not supported by the driver.
26
27
  */
27
- SEARCH_COMPARISON_OPERATOR_NOT_SUPPORTED = "SEARCH_COMPARISON_OPERATOR_NOT_SUPPORTED"
28
+ SEARCH_COMPARISON_OPERATOR_NOT_SUPPORTED = "SEARCH_COMPARISON_OPERATOR_NOT_SUPPORTED",
29
+ /**
30
+ * Update operator is not supported by the driver.
31
+ */
32
+ UPDATE_OPERATOR_NOT_SUPPORTED = "UPDATE_OPERATOR_NOT_SUPPORTED"
28
33
  }
29
34
  /**
30
35
  * The generic type for a database driver configuration.
@@ -70,7 +75,7 @@ export type DataItemDBDriver<ItemType extends TypeInfoDataItem, UniquelyIdentify
70
75
  * @param updatedItem Partial update payload for the item.
71
76
  * @returns True when the item was updated.
72
77
  */
73
- updateItem: (uniqueIdentifier: ItemType[UniquelyIdentifyingFieldName], updatedItem: Partial<ItemType>) => Promise<boolean>;
78
+ updateItem: (uniqueIdentifier: ItemType[UniquelyIdentifyingFieldName], updatedItem: Partial<ItemType>, updateConfig?: TypeInfoORMUpdateConfig) => Promise<boolean>;
74
79
  /**
75
80
  * Delete an item from the data store.
76
81
  * @param uniqueIdentifier Unique identifier value for the item.
package/api/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ITEM_RELATIONSHIP_DAC_RESOURCE_NAME, ComparisonOperators } from '../chunk-7AMEFPPP.js';
1
+ import { TypeInfoORMUpdateOperators, ITEM_RELATIONSHIP_DAC_RESOURCE_NAME, ComparisonOperators } from '../chunk-RUNXRISF.js';
2
2
  import { getNoErrorDescriptor, getErrorDescriptor, ERROR_MESSAGE_CONSTANTS, validateTypeOperationAllowed, getValidityValue, validateTypeInfoValue, validateTypeInfoFieldValue } from '../chunk-YCTVEW2I.js';
3
3
  import { mergeStringPaths, getPathString, getPathArray } from '../chunk-WNFRDIBW.js';
4
4
  import '../chunk-I2KLQ2HA.js';
@@ -4540,6 +4540,7 @@ var DATA_ITEM_DB_DRIVER_ERRORS = /* @__PURE__ */ ((DATA_ITEM_DB_DRIVER_ERRORS2)
4540
4540
  DATA_ITEM_DB_DRIVER_ERRORS2["ITEM_NOT_FOUND"] = "ITEM_NOT_FOUND";
4541
4541
  DATA_ITEM_DB_DRIVER_ERRORS2["MISSING_UNIQUE_IDENTIFIER"] = "MISSING_UNIQUE_IDENTIFIER";
4542
4542
  DATA_ITEM_DB_DRIVER_ERRORS2["SEARCH_COMPARISON_OPERATOR_NOT_SUPPORTED"] = "SEARCH_COMPARISON_OPERATOR_NOT_SUPPORTED";
4543
+ DATA_ITEM_DB_DRIVER_ERRORS2["UPDATE_OPERATOR_NOT_SUPPORTED"] = "UPDATE_OPERATOR_NOT_SUPPORTED";
4543
4544
  return DATA_ITEM_DB_DRIVER_ERRORS2;
4544
4545
  })(DATA_ITEM_DB_DRIVER_ERRORS || {});
4545
4546
 
@@ -5778,8 +5779,9 @@ var createFilterExpression = (fieldCriteria, logicalOperator) => {
5778
5779
  }
5779
5780
  return output;
5780
5781
  };
5781
- var buildUpdateExpression = (updatedItem, uniquelyIdentifyingFieldName) => {
5782
- const updateExpressionParts = [];
5782
+ var buildUpdateExpression = (updatedItem, uniquelyIdentifyingFieldName, updateConfig) => {
5783
+ const setExpressionParts = [];
5784
+ const addExpressionParts = [];
5783
5785
  const attributeNames = {};
5784
5786
  const attributeValues = {};
5785
5787
  for (const f in updatedItem) {
@@ -5787,13 +5789,35 @@ var buildUpdateExpression = (updatedItem, uniquelyIdentifyingFieldName) => {
5787
5789
  if (f !== uniquelyIdentifyingFieldName && typeof value !== "undefined") {
5788
5790
  const placeholderName = `#${f}`;
5789
5791
  const placeholderValue = `:${f}`;
5790
- updateExpressionParts.push(`${placeholderName} = ${placeholderValue}`);
5792
+ const operator = updateConfig?.fieldOperators?.[f];
5791
5793
  attributeNames[placeholderName] = f;
5792
5794
  attributeValues[placeholderValue] = marshall(value);
5795
+ if (operator === TypeInfoORMUpdateOperators.NUMBER.INCREMENT) {
5796
+ addExpressionParts.push(`${placeholderName} ${placeholderValue}`);
5797
+ continue;
5798
+ }
5799
+ if (operator === TypeInfoORMUpdateOperators.NUMBER.DECREMENT) {
5800
+ const decrementPlaceholderValue = `:${f}_decrement`;
5801
+ addExpressionParts.push(
5802
+ `${placeholderName} ${decrementPlaceholderValue}`
5803
+ );
5804
+ attributeValues[decrementPlaceholderValue] = marshall(
5805
+ -value
5806
+ );
5807
+ continue;
5808
+ }
5809
+ setExpressionParts.push(`${placeholderName} = ${placeholderValue}`);
5793
5810
  }
5794
5811
  }
5812
+ const expressionParts = [];
5813
+ if (setExpressionParts.length > 0) {
5814
+ expressionParts.push(`SET ${setExpressionParts.join(", ")}`);
5815
+ }
5816
+ if (addExpressionParts.length > 0) {
5817
+ expressionParts.push(`ADD ${addExpressionParts.join(", ")}`);
5818
+ }
5795
5819
  return {
5796
- UpdateExpression: `SET ${updateExpressionParts.join(", ")}`,
5820
+ UpdateExpression: expressionParts.join(" "),
5797
5821
  ExpressionAttributeNames: attributeNames,
5798
5822
  ExpressionAttributeValues: attributeValues
5799
5823
  };
@@ -5872,7 +5896,7 @@ var DynamoDBDataItemDBDriver = class {
5872
5896
  * Update an item in the database.
5873
5897
  * @returns True when an item was updated.
5874
5898
  */
5875
- updateItem = async (uniqueIdentifier, updatedItem) => {
5899
+ updateItem = async (uniqueIdentifier, updatedItem, updateConfig) => {
5876
5900
  const { tableName, uniquelyIdentifyingFieldName } = this.config;
5877
5901
  const {
5878
5902
  [uniquelyIdentifyingFieldName]: _unusedUniqueIdentifier,
@@ -5887,7 +5911,8 @@ var DynamoDBDataItemDBDriver = class {
5887
5911
  ReturnValues: "ALL_NEW",
5888
5912
  ...buildUpdateExpression(
5889
5913
  cleanUpdatedItem,
5890
- uniquelyIdentifyingFieldName
5914
+ uniquelyIdentifyingFieldName,
5915
+ updateConfig
5891
5916
  )
5892
5917
  });
5893
5918
  const { Attributes } = await this.dynamoDBClient.send(command);
@@ -6092,7 +6117,7 @@ var InMemoryDataItemDBDriver = class {
6092
6117
  * @param updatedItem Partial update payload for the item.
6093
6118
  * @returns True when the item was updated.
6094
6119
  */
6095
- updateItem = async (uniqueIdentifier, updatedItem) => {
6120
+ updateItem = async (uniqueIdentifier, updatedItem, updateConfig) => {
6096
6121
  const { uniquelyIdentifyingFieldName } = this.config;
6097
6122
  if (typeof uniqueIdentifier === "undefined") {
6098
6123
  throw {
@@ -6110,6 +6135,17 @@ var InMemoryDataItemDBDriver = class {
6110
6135
  };
6111
6136
  for (const [key, value] of Object.entries(cleanUpdatedItem)) {
6112
6137
  if (typeof value !== "undefined") {
6138
+ const operator = updateConfig?.fieldOperators?.[key];
6139
+ if (operator === TypeInfoORMUpdateOperators.NUMBER.INCREMENT) {
6140
+ const currentValue = nextItem[key];
6141
+ nextItem[key] = (typeof currentValue === "number" ? currentValue : 0) + value;
6142
+ continue;
6143
+ }
6144
+ if (operator === TypeInfoORMUpdateOperators.NUMBER.DECREMENT) {
6145
+ const currentValue = nextItem[key];
6146
+ nextItem[key] = (typeof currentValue === "number" ? currentValue : 0) - value;
6147
+ continue;
6148
+ }
6113
6149
  nextItem[key] = value;
6114
6150
  }
6115
6151
  }
@@ -8209,6 +8245,40 @@ var TypeInfoORMService = class {
8209
8245
  throw validationResults;
8210
8246
  }
8211
8247
  };
8248
+ /**
8249
+ * Validate update operator config against the target TypeInfo fields.
8250
+ */
8251
+ validateUpdateConfig = (typeName, item, updateConfig) => {
8252
+ const fieldOperators = updateConfig?.fieldOperators;
8253
+ if (!fieldOperators) {
8254
+ return;
8255
+ }
8256
+ const { fields = {}, primaryField } = this.getTypeInfo(typeName);
8257
+ for (const [fieldName, operator] of Object.entries(fieldOperators)) {
8258
+ const field = fields[fieldName];
8259
+ const itemValue = item[fieldName];
8260
+ const isNumberOperator = Object.values(
8261
+ TypeInfoORMUpdateOperators.NUMBER
8262
+ ).includes(
8263
+ operator
8264
+ );
8265
+ if (!field || fieldName === primaryField || !isNumberOperator || field.array || field.type !== "number" || typeof itemValue !== "number") {
8266
+ const validationResults = {
8267
+ typeName,
8268
+ valid: false,
8269
+ error: getErrorDescriptor(
8270
+ "INVALID_UPDATE_OPERATOR" /* INVALID_UPDATE_OPERATOR */
8271
+ ),
8272
+ errorMap: {
8273
+ [fieldName]: [
8274
+ getErrorDescriptor("INVALID_UPDATE_OPERATOR" /* INVALID_UPDATE_OPERATOR */)
8275
+ ]
8276
+ }
8277
+ };
8278
+ throw validationResults;
8279
+ }
8280
+ }
8281
+ };
8212
8282
  /**
8213
8283
  * @returns Cleaned item with selected fields and DAC constraints applied.
8214
8284
  */
@@ -8682,10 +8752,12 @@ var TypeInfoORMService = class {
8682
8752
  * The `item` **must always** contain its **primary field value**.
8683
8753
  * @param typeName Type name to update.
8684
8754
  * @param item Item payload to update.
8755
+ * @param updateConfig Optional per-field operator config.
8685
8756
  * @returns True when the update succeeded.
8686
8757
  * */
8687
- update = async (typeName, item, context) => {
8758
+ update = async (typeName, item, updateConfig, context) => {
8688
8759
  this.validate(typeName, item, "UPDATE" /* UPDATE */, true);
8760
+ this.validateUpdateConfig(typeName, item, updateConfig);
8689
8761
  const { primaryField } = this.getTypeInfo(typeName);
8690
8762
  const primaryFieldValue = typeof item === "object" && item !== null ? item[primaryField] : void 0;
8691
8763
  if (typeof primaryFieldValue === "undefined") {
@@ -8761,7 +8833,11 @@ var TypeInfoORMService = class {
8761
8833
  throw error;
8762
8834
  }
8763
8835
  }
8764
- const result = await driver.updateItem(primaryFieldValue, cleanItem);
8836
+ const result = await driver.updateItem(
8837
+ primaryFieldValue,
8838
+ cleanItem,
8839
+ updateConfig
8840
+ );
8765
8841
  const updatedItem = await driver.readItem(primaryFieldValue);
8766
8842
  if (existingItem) {
8767
8843
  await this.replaceItemIndexes(typeName, existingItem, updatedItem);
@@ -9411,7 +9487,7 @@ var TYPE_INFO_ORM_API_PATH_METHOD_NAME_MAP = {
9411
9487
  delete: "delete",
9412
9488
  list: "list"
9413
9489
  };
9414
- var getTypeInfoORMRouteMap = (config, dacConfig, getAccessingRoleId, authConfig) => {
9490
+ var getTypeInfoORMRouteMap = (config, dacConfig, getAccessingRoleId, authConfig, routeMapConfig) => {
9415
9491
  if (dacConfig && !getAccessingRoleId) {
9416
9492
  throw {
9417
9493
  message: "MISSING_ACCESSING_ROLE_GETTER" /* MISSING_ACCESSING_ROLE_GETTER */
@@ -9430,6 +9506,7 @@ var getTypeInfoORMRouteMap = (config, dacConfig, getAccessingRoleId, authConfig)
9430
9506
  const defaultAuthConfig = authConfig ?? {
9431
9507
  anyAuthorized: true
9432
9508
  };
9509
+ const allowUpdateFieldOperators = routeMapConfig?.allowUpdateFieldOperators ?? true;
9433
9510
  const resolveContext = (eventData) => getContextFromEventData(eventData, dacConfig, getAccessingRoleId);
9434
9511
  const createRoute = (path, handlerFactory) => ({
9435
9512
  path,
@@ -9450,10 +9527,18 @@ var getTypeInfoORMRouteMap = (config, dacConfig, getAccessingRoleId, authConfig)
9450
9527
  };
9451
9528
  const updateHandlerFactory = (eventData) => {
9452
9529
  if (!dacConfig) {
9453
- return orm.update;
9530
+ if (allowUpdateFieldOperators) {
9531
+ return orm.update;
9532
+ }
9533
+ return ((typeName, item) => orm.update(typeName, item, void 0));
9454
9534
  }
9455
9535
  const context = resolveContext(eventData);
9456
- return ((typeName, item) => orm.update(typeName, item, context));
9536
+ return ((typeName, item, updateConfig) => orm.update(
9537
+ typeName,
9538
+ item,
9539
+ allowUpdateFieldOperators ? updateConfig : void 0,
9540
+ context
9541
+ ));
9457
9542
  };
9458
9543
  const deleteHandlerFactory = (eventData) => {
9459
9544
  if (!dacConfig) {
package/app/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  export { createEasyLayout, getEasyLayoutTemplateDetails, getPascalCaseAreaName } from '../chunk-CMH6L5QQ.js';
2
2
  export { computeTrackPixels } from '../chunk-TJFTWPXQ.js';
3
3
  export { AutoForm, AutoFormView, Route, RouteContext, RouteContextConsumer, RouteContextProvider, RouteProvider, buildHistoryPath, buildQueryString, buildRoutePath, canUseBrowserHistory, computeAreaBounds, createAutoField, createBrowserRouteAdapter, createFormRenderer, createHistoryBackHandler, createManualRouteAdapter, createMemoryHistory, createNativeRouteAdapter, createRouteAdapterFromHistory, createUniversalAdapter, defaultTranslateValidationErrorCode, getFieldKind, parseHistoryPath, parseTemplate, resolveSuite, useFormEngine, useRouteContext, validateAreas, wrapRouteAdapterWithPathResolver } from '../chunk-44BMFTKD.js';
4
- import '../chunk-7AMEFPPP.js';
4
+ import '../chunk-RUNXRISF.js';
5
5
  import '../chunk-YCTVEW2I.js';
6
6
  import { mergeStringPaths, PATH_DELIMITER } from '../chunk-WNFRDIBW.js';
7
7
  import '../chunk-I2KLQ2HA.js';
@@ -473,12 +473,14 @@ var TypeInfoORMClient = class {
473
473
  *
474
474
  * @param typeName - TypeInfo type name.
475
475
  * @param item - Updated item payload.
476
+ * @param updateConfig - Optional per-field operator config.
476
477
  * @returns Whether the update succeeded.
477
478
  */
478
- update = async (typeName, item) => {
479
+ update = async (typeName, item, updateConfig) => {
479
480
  return await this.makeRequest("update" /* UPDATE */, [
480
481
  typeName,
481
- item
482
+ item,
483
+ updateConfig
482
484
  ]);
483
485
  };
484
486
  /**
@@ -4,7 +4,7 @@
4
4
  * Client wrapper around the TypeInfoORM API RouteMap. Uses ServiceConfig to
5
5
  * route requests to the server-side TypeInfoORM routes.
6
6
  */
7
- import { DeleteRelationshipResults, TypeInfoORMClientAPI, TypeInfoORMAPIRoutePaths } from "../../common/TypeInfoORM";
7
+ import { DeleteRelationshipResults, TypeInfoORMClientAPI, TypeInfoORMAPIRoutePaths, TypeInfoORMUpdateConfig } from "../../common/TypeInfoORM";
8
8
  import { ServiceConfig } from "./Service";
9
9
  import { TypeInfoDataItem } from "../../common/TypeParsing/TypeInfo";
10
10
  import { ListItemsConfig, ListItemsResults, ListRelationshipsConfig } from "../../common/SearchTypes";
@@ -51,9 +51,10 @@ export declare class TypeInfoORMClient implements TypeInfoORMClientAPI {
51
51
  *
52
52
  * @param typeName - TypeInfo type name.
53
53
  * @param item - Updated item payload.
54
+ * @param updateConfig - Optional per-field operator config.
54
55
  * @returns Whether the update succeeded.
55
56
  */
56
- update: (typeName: string, item: TypeInfoDataItem) => Promise<boolean>;
57
+ update: (typeName: string, item: TypeInfoDataItem, updateConfig?: TypeInfoORMUpdateConfig) => Promise<boolean>;
57
58
  /**
58
59
  * Delete an item by its primary field value.
59
60
  *
@@ -54,6 +54,7 @@ var TypeInfoORMServiceError = /* @__PURE__ */ ((TypeInfoORMServiceError2) => {
54
54
  TypeInfoORMServiceError2["TYPE_INFO_MISSING_PRIMARY_FIELD"] = "TYPE_INFO_MISSING_PRIMARY_FIELD";
55
55
  TypeInfoORMServiceError2["INVALID_RELATIONSHIP"] = "INVALID_RELATIONSHIP";
56
56
  TypeInfoORMServiceError2["INVALID_OPERATION"] = "INVALID_OPERATION";
57
+ TypeInfoORMServiceError2["INVALID_UPDATE_OPERATOR"] = "INVALID_UPDATE_OPERATOR";
57
58
  TypeInfoORMServiceError2["MISSING_ACCESSING_ROLE"] = "MISSING_ACCESSING_ROLE";
58
59
  TypeInfoORMServiceError2["INDEXING_UNSUPPORTED_CRITERIA"] = "INDEXING_UNSUPPORTED_CRITERIA";
59
60
  TypeInfoORMServiceError2["INDEXING_UNSUPPORTED_COMBINATION"] = "INDEXING_UNSUPPORTED_COMBINATION";
@@ -74,5 +75,11 @@ var TypeInfoORMAPIRoutePaths = /* @__PURE__ */ ((TypeInfoORMAPIRoutePaths2) => {
74
75
  TypeInfoORMAPIRoutePaths2["LIST_RELATED_ITEMS"] = "list-related-items";
75
76
  return TypeInfoORMAPIRoutePaths2;
76
77
  })(TypeInfoORMAPIRoutePaths || {});
78
+ var TypeInfoORMUpdateOperators = {
79
+ NUMBER: {
80
+ INCREMENT: "INCREMENT",
81
+ DECREMENT: "DECREMENT"
82
+ }
83
+ };
77
84
 
78
- export { ComparisonOperators, ITEM_RELATIONSHIP_DAC_RESOURCE_NAME, LogicalOperators, OperationGroup, RelationshipOperation, TypeInfoORMAPIRoutePaths, TypeInfoORMServiceError };
85
+ export { ComparisonOperators, ITEM_RELATIONSHIP_DAC_RESOURCE_NAME, LogicalOperators, OperationGroup, RelationshipOperation, TypeInfoORMAPIRoutePaths, TypeInfoORMServiceError, TypeInfoORMUpdateOperators };
@@ -91,6 +91,10 @@ export declare enum TypeInfoORMServiceError {
91
91
  * Operation is not supported.
92
92
  * */
93
93
  INVALID_OPERATION = "INVALID_OPERATION",
94
+ /**
95
+ * Update operator config is invalid.
96
+ * */
97
+ INVALID_UPDATE_OPERATOR = "INVALID_UPDATE_OPERATOR",
94
98
  /**
95
99
  * Accessing role is missing when DAC is required.
96
100
  * */
@@ -181,6 +185,32 @@ export type TypeInfoORMContext = {
181
185
  */
182
186
  accessingRoleId: string;
183
187
  };
188
+ /**
189
+ * Supported numeric field update operators.
190
+ */
191
+ export declare const TypeInfoORMUpdateOperators: {
192
+ readonly NUMBER: {
193
+ readonly INCREMENT: "INCREMENT";
194
+ readonly DECREMENT: "DECREMENT";
195
+ };
196
+ };
197
+ /**
198
+ * Supported numeric field update operator values.
199
+ */
200
+ export type TypeInfoORMNumberFieldUpdateOperator = (typeof TypeInfoORMUpdateOperators.NUMBER)[keyof typeof TypeInfoORMUpdateOperators.NUMBER];
201
+ /**
202
+ * Supported field update operator values.
203
+ */
204
+ export type TypeInfoORMFieldUpdateOperator = TypeInfoORMNumberFieldUpdateOperator;
205
+ /**
206
+ * Optional config for TypeInfo ORM update calls.
207
+ */
208
+ export type TypeInfoORMUpdateConfig = {
209
+ /**
210
+ * Optional per-field operator map applied during update.
211
+ */
212
+ fieldOperators?: Record<string, TypeInfoORMFieldUpdateOperator>;
213
+ };
184
214
  /**
185
215
  * Server-side TypeInfoORM API contract.
186
216
  *
@@ -239,9 +269,10 @@ export type TypeInfoORMAPI = {
239
269
  *
240
270
  * @param typeName - Type name to update.
241
271
  * @param item - Updated item payload.
272
+ * @param updateConfig - Optional per-field operator config.
242
273
  * @returns Whether the update succeeded.
243
274
  */
244
- update: (typeName: string, item: TypeInfoDataItem, context?: TypeInfoORMContext) => Promise<boolean>;
275
+ update: (typeName: string, item: TypeInfoDataItem, updateConfig?: TypeInfoORMUpdateConfig, context?: TypeInfoORMContext) => Promise<boolean>;
245
276
  /**
246
277
  * Delete an item by primary field value.
247
278
  *
@@ -319,9 +350,10 @@ export type TypeInfoORMClientAPI = {
319
350
  *
320
351
  * @param typeName - Type name to update.
321
352
  * @param item - Updated item payload.
353
+ * @param updateConfig - Optional per-field operator config.
322
354
  * @returns Whether the update succeeded.
323
355
  */
324
- update: (typeName: string, item: TypeInfoDataItem) => Promise<boolean>;
356
+ update: (typeName: string, item: TypeInfoDataItem, updateConfig?: TypeInfoORMUpdateConfig) => Promise<boolean>;
325
357
  /**
326
358
  * Delete an item by primary field value.
327
359
  *
package/common/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export { ComparisonOperators, ITEM_RELATIONSHIP_DAC_RESOURCE_NAME, LogicalOperators, OperationGroup, RelationshipOperation, TypeInfoORMAPIRoutePaths, TypeInfoORMServiceError } from '../chunk-7AMEFPPP.js';
1
+ export { ComparisonOperators, ITEM_RELATIONSHIP_DAC_RESOURCE_NAME, LogicalOperators, OperationGroup, RelationshipOperation, TypeInfoORMAPIRoutePaths, TypeInfoORMServiceError, TypeInfoORMUpdateOperators } from '../chunk-RUNXRISF.js';
2
2
  export { DENIED_TYPE_OPERATIONS, ERROR_MESSAGE_CONSTANTS, INVALID_CUSTOM_TYPE, PRIMITIVE_ERROR_MESSAGE_CONSTANTS, RelationshipValidationType, TYPE_KEYWORD_ERROR_MESSAGE_CONSTANTS, TYPE_KEYWORD_VALIDATORS, TypeOperation, getArrayItemErrorMap, getErrorDescriptor, getErrorDescriptors, getNoErrorDescriptor, getValidityValue, hasValue, isArrayErrorDescriptorCollection, validateArrayOfTypeInfoFieldValues, validateCustomType, validateKeywordType, validateTypeInfoDataItem, validateTypeInfoFieldOperationAllowed, validateTypeInfoFieldValue, validateTypeInfoValue, validateTypeOperationAllowed, validateValueMatchesPattern } from '../chunk-YCTVEW2I.js';
3
3
  import '../chunk-WNFRDIBW.js';
4
4
  import '../chunk-I2KLQ2HA.js';
package/native/index.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { computeTrackPixels } from '../chunk-TJFTWPXQ.js';
2
- import { createFormRenderer, createHistoryBackHandler, buildHistoryPath, AutoFormView, AutoForm, parseTemplate, validateAreas, computeAreaBounds, parseHistoryPath, createMemoryHistory, Route, buildRoutePath } from '../chunk-44BMFTKD.js';
2
+ import { createFormRenderer, createHistoryBackHandler, buildHistoryPath, AutoFormView, AutoForm, parseTemplate, validateAreas, computeAreaBounds, parseHistoryPath, createMemoryHistory, createBrowserRouteAdapter, Route, createRouteAdapterFromHistory } from '../chunk-44BMFTKD.js';
3
3
  import { ERROR_MESSAGE_CONSTANTS } from '../chunk-YCTVEW2I.js';
4
- import { resolveRouteAdapterPath, getPathArray } from '../chunk-WNFRDIBW.js';
4
+ import '../chunk-WNFRDIBW.js';
5
5
  import '../chunk-I2KLQ2HA.js';
6
- import { createElement, useMemo } from 'react';
6
+ import { createElement, useMemo, useRef } from 'react';
7
7
  import { Text, View, Platform, Switch, TextInput, Pressable, BackHandler } from 'react-native';
8
8
  import { jsx } from 'react/jsx-runtime';
9
9
 
@@ -580,10 +580,13 @@ var createNativeHistory = (options = {}) => {
580
580
  adapter,
581
581
  initialPath = "/",
582
582
  onIncomingURL = "replace",
583
- mapURLToPath = mapNativeURLToPath
583
+ mapURLToPath = mapNativeURLToPath,
584
+ backHandler
584
585
  } = options;
585
586
  const history = createMemoryHistory(initialPath);
587
+ const historyBackHandler = createHistoryBackHandler(history);
586
588
  let unsubscribe;
589
+ let stopBackHandler;
587
590
  let started = false;
588
591
  const applyIncomingURL = (url) => {
589
592
  if (!url) {
@@ -620,6 +623,20 @@ var createNativeHistory = (options = {}) => {
620
623
  return;
621
624
  }
622
625
  started = true;
626
+ if (backHandler && !stopBackHandler) {
627
+ const listener = () => historyBackHandler.handle();
628
+ const subscription = backHandler.addEventListener(
629
+ "hardwareBackPress",
630
+ listener
631
+ );
632
+ stopBackHandler = () => {
633
+ if (typeof subscription?.remove === "function") {
634
+ subscription.remove();
635
+ return;
636
+ }
637
+ backHandler.removeEventListener?.("hardwareBackPress", listener);
638
+ };
639
+ }
623
640
  if (!adapter) {
624
641
  return;
625
642
  }
@@ -651,23 +668,13 @@ var createNativeHistory = (options = {}) => {
651
668
  }
652
669
  unsubscribe?.();
653
670
  unsubscribe = void 0;
671
+ stopBackHandler?.();
672
+ stopBackHandler = void 0;
654
673
  started = false;
655
674
  }
656
675
  };
657
676
  };
658
677
  var createNativeBackHandler = (history) => createHistoryBackHandler(history);
659
- var createNavigationStateRouteAdapter = (options) => {
660
- const getPath = () => options.toPath(options.getState());
661
- const resolvePath = (path) => resolveRouteAdapterPath(getPath(), path);
662
- return {
663
- getPath,
664
- subscribe: (listener) => options.subscribe(() => {
665
- listener(getPath());
666
- }),
667
- push: options.navigate ? (path) => options.navigate?.(resolvePath(path)) : void 0,
668
- replace: options.replace ? (path) => options.replace?.(resolvePath(path)) : void 0
669
- };
670
- };
671
678
  var createNativeHardwareBackHandler = (adapter) => {
672
679
  return () => {
673
680
  if (adapter.canGoBack?.()) {
@@ -696,53 +703,63 @@ var createNativeRouteBackIntegration = (backHandler) => {
696
703
  setup: (adapter) => registerNativeHardwareBackHandler(adapter, backHandler)
697
704
  };
698
705
  };
706
+ var createNativeHistoryRouteAdapter = (initialPath, ingress, backHandler) => {
707
+ const history = createNativeHistory({
708
+ initialPath,
709
+ backHandler,
710
+ ...ingress ? {
711
+ adapter: {
712
+ getInitialURL: async () => await ingress.getInitialURL?.() ?? null,
713
+ subscribe: (listener) => ingress.subscribe?.(listener) ?? (() => {
714
+ })
715
+ },
716
+ onIncomingURL: ingress.onIncomingURL,
717
+ mapURLToPath: ingress.mapURLToPath
718
+ } : {}
719
+ });
720
+ const adapter = createRouteAdapterFromHistory(history);
721
+ let subscribers = 0;
722
+ return {
723
+ ...adapter,
724
+ subscribe: (listener) => {
725
+ subscribers += 1;
726
+ if (subscribers === 1) {
727
+ void history.start();
728
+ }
729
+ const unlisten = adapter.subscribe(listener);
730
+ return () => {
731
+ unlisten();
732
+ subscribers = Math.max(0, subscribers - 1);
733
+ if (subscribers === 0) {
734
+ history.stop();
735
+ }
736
+ };
737
+ }
738
+ };
739
+ };
699
740
  var Route2 = (props) => {
700
741
  const hasMatcherProps = typeof props.path !== "undefined" || typeof props.exact !== "undefined" || typeof props.onParamsChange !== "undefined";
701
742
  const nativeRuntime = {
702
743
  platformOS: String(Platform?.OS ?? ""),
703
744
  backHandler: BackHandler
704
745
  };
705
- const runtimeIntegration = (() => {
706
- if (hasMatcherProps || nativeRuntime.platformOS === "web") {
707
- return void 0;
708
- }
709
- const backHandler = nativeRuntime.backHandler;
710
- if (!backHandler) {
711
- return void 0;
712
- }
713
- return createNativeRouteBackIntegration(backHandler);
714
- })();
715
- return /* @__PURE__ */ jsx(
746
+ const shouldUseAutoAdapter = !hasMatcherProps && typeof props.adapter === "undefined";
747
+ const routeProps = props;
748
+ const adapterRef = useRef(null);
749
+ if (shouldUseAutoAdapter && !adapterRef.current) {
750
+ adapterRef.current = nativeRuntime.platformOS === "web" ? createBrowserRouteAdapter() : createNativeHistoryRouteAdapter(
751
+ props.initialPath,
752
+ props.ingress,
753
+ nativeRuntime.backHandler
754
+ );
755
+ }
756
+ return shouldUseAutoAdapter ? /* @__PURE__ */ jsx(
716
757
  Route,
717
758
  {
718
- ...props,
719
- runtimeIntegration
759
+ ...routeProps,
760
+ adapter: adapterRef.current ?? void 0
720
761
  }
721
- );
722
- };
723
- var expandPattern = (pattern, params = {}) => {
724
- const segments = getPathArray(pattern, "/", true, true, false, false);
725
- return segments.map((segment) => {
726
- if (segment.startsWith(":")) {
727
- const key = segment.slice(1);
728
- if (!(key in params)) {
729
- throw new Error(`Missing param "${key}" for route pattern "${pattern}".`);
730
- }
731
- return params[key];
732
- }
733
- return segment;
734
- });
735
- };
736
- var buildPathFromRouteChain = (routeChain, config, query) => {
737
- const segments = [];
738
- routeChain.forEach((route) => {
739
- const pattern = config[route.name];
740
- if (!pattern) {
741
- throw new Error(`Missing route pattern for "${route.name}".`);
742
- }
743
- segments.push(...expandPattern(pattern, route.params));
744
- });
745
- return buildRoutePath(segments, query);
762
+ ) : /* @__PURE__ */ jsx(Route, { ...routeProps });
746
763
  };
747
764
 
748
- export { ArrayContainer, ArrayItemWrapper, AutoField, AutoForm2 as AutoForm, AutoFormView2 as AutoFormView, Button, ErrorMessage, FieldWrapper, NativeEasyLayoutView, Route2 as Route, buildPathFromRouteChain, createNativeBackHandler, createNativeFormRenderer, createNativeHardwareBackHandler, createNativeHistory, createNativeRouteBackIntegration, createNavigationStateRouteAdapter, makeNativeEasyLayout, mapNativeURLToPath, nativeAutoField, nativeSuite, registerNativeHardwareBackHandler, useNativeEasyLayout };
765
+ export { ArrayContainer, ArrayItemWrapper, AutoField, AutoForm2 as AutoForm, AutoFormView2 as AutoFormView, Button, ErrorMessage, FieldWrapper, NativeEasyLayoutView, Route2 as Route, createNativeBackHandler, createNativeFormRenderer, createNativeHardwareBackHandler, createNativeHistory, createNativeRouteBackIntegration, makeNativeEasyLayout, mapNativeURLToPath, nativeAutoField, nativeSuite, registerNativeHardwareBackHandler, useNativeEasyLayout };
@@ -1,13 +1,15 @@
1
1
  /**
2
2
  * @packageDocumentation
3
3
  *
4
- * Native history helpers that adapt deep links into the shared history state machine.
4
+ * Native history helpers that provide the mobile equivalent of browser
5
+ * location/history behavior for shared app Route matching.
5
6
  */
6
7
  import type { HistoryController } from "../../app/utils/History";
7
8
  /**
8
9
  * Adapter contract for React Native deep-link APIs.
9
10
  *
10
- * Intended for RN `Linking` wrappers.
11
+ * Intended for RN `Linking` wrappers so native URL opens behave like browser
12
+ * navigations entering the shared Voltra history model.
11
13
  */
12
14
  export type NativeLinkAdapter = {
13
15
  /**
@@ -23,8 +25,19 @@ export type NativeLinkAdapter = {
23
25
  * Mode for incoming URL handling.
24
26
  */
25
27
  export type NativeIncomingURLMode = "push" | "replace";
28
+ /**
29
+ * BackHandler-like contract for native platform back actions.
30
+ */
31
+ export type NativeBackHandlerLike = {
32
+ addEventListener: (eventName: "hardwareBackPress", listener: () => boolean) => {
33
+ remove?: () => void;
34
+ } | void;
35
+ removeEventListener?: (eventName: "hardwareBackPress", listener: () => boolean) => void;
36
+ };
26
37
  /**
27
38
  * Native history controller with explicit lifecycle hooks.
39
+ *
40
+ * This is the native/mobile analogue to browser-backed history in web apps.
28
41
  */
29
42
  export type NativeHistoryController = HistoryController & {
30
43
  /**
@@ -62,16 +75,25 @@ export type CreateNativeHistoryOptions = {
62
75
  * Default: {@link mapNativeURLToPath}.
63
76
  */
64
77
  mapURLToPath?: (url: string) => string;
78
+ /**
79
+ * Optional native platform back handler wired into this history runtime.
80
+ */
81
+ backHandler?: NativeBackHandlerLike;
65
82
  };
66
83
  /**
67
84
  * Default native URL -> path mapping.
68
85
  *
69
- * Strips scheme and host, preserves path + query + hash.
86
+ * Strips scheme and host, preserves path + query + hash so incoming native URLs
87
+ * become the same route paths used on web.
70
88
  */
71
89
  export declare const mapNativeURLToPath: (url: string) => string;
72
90
  /**
73
91
  * Create a native history controller backed by in-memory history.
74
92
  *
93
+ * This is the primary native routing primitive when the environment does not
94
+ * provide browser history. It gives shared Route matching a stable path/history
95
+ * source and applies incoming deep links as navigations in that same model.
96
+ *
75
97
  * Lifecycle behavior:
76
98
  * - `start()` is idempotent.
77
99
  * - `stop()` is idempotent.
@@ -1,54 +1,19 @@
1
1
  /**
2
2
  * @packageDocumentation
3
3
  *
4
- * Native routing helpers that adapt common navigation state to RouteAdapter.
5
- */
6
- import { type PropsWithChildren } from "react";
7
- import type { RouteAdapter, RouteProps, RouteQuery, RouteRuntimeIntegration } from "../../app/utils/Route";
8
- /**
9
- * Options to adapt a navigation state container into a RouteAdapter.
10
- */
11
- export type NavigationStateAdapterOptions<TState> = {
12
- /** Return the current navigation state. */
13
- getState: () => TState;
14
- /** Subscribe to navigation state changes. */
15
- subscribe: (listener: () => void) => () => void;
16
- /** Convert navigation state into a path string. */
17
- toPath: (state: TState) => string;
18
- /** Optional navigation handler used for push-style transitions. */
19
- navigate?: (path: string) => void;
20
- /** Optional navigation handler used for replace-style transitions. */
21
- replace?: (path: string) => void;
22
- };
23
- /**
24
- * Contract for React Native BackHandler-like integrations.
25
- */
26
- export type NativeBackHandlerLike = {
27
- addEventListener: (eventName: "hardwareBackPress", listener: () => boolean) => {
28
- remove?: () => void;
29
- } | void;
30
- removeEventListener?: (eventName: "hardwareBackPress", listener: () => boolean) => void;
31
- };
32
- /**
33
- * Route node in a navigation chain.
34
- */
35
- export type NavigationRouteNode = {
36
- /** Route name as reported by the navigation library. */
37
- name: string;
38
- /** Optional route params used to populate path patterns. */
39
- params?: Record<string, any>;
40
- };
41
- /**
42
- * Mapping of route names to path patterns (e.g. "books/:id").
43
- */
44
- export type NavigationRouteConfig = Record<string, string>;
45
- /**
46
- * Create a RouteAdapter from a navigation state container (e.g., react-navigation).
4
+ * Native routing helpers that keep shared app Route semantics intact on mobile.
47
5
  *
48
- * @param options - Adapter options for accessing and observing navigation state.
49
- * @returns RouteAdapter bound to the navigation state.
6
+ * The primary native model is still Voltra path/history routing. These helpers
7
+ * supply the runtime selection needed by the `native` barrel:
8
+ * - React Native mobile uses native history + deep-link + platform back
9
+ * - React Native web uses the browser adapter
10
+ *
11
+ * This separation keeps `app` free of native-platform code.
50
12
  */
51
- export declare const createNavigationStateRouteAdapter: <TState>(options: NavigationStateAdapterOptions<TState>) => RouteAdapter;
13
+ import { type PropsWithChildren } from "react";
14
+ import type { RouteProps, RouteRuntimeIntegration } from "../../app/utils/Route";
15
+ import type { RouteAdapter } from "../../app/utils/Route";
16
+ import { type NativeBackHandlerLike } from "./History";
52
17
  /**
53
18
  * Create a hardware-back listener from a route adapter.
54
19
  */
@@ -58,23 +23,19 @@ export declare const createNativeHardwareBackHandler: (adapter: RouteAdapter) =>
58
23
  */
59
24
  export declare const registerNativeHardwareBackHandler: (adapter: RouteAdapter, backHandler: NativeBackHandlerLike) => () => void;
60
25
  /**
61
- * Build a core Route runtime integration using a native BackHandler.
26
+ * Low-level helper to build a Route runtime integration from a BackHandler.
27
+ *
28
+ * Native Route no longer uses this for the default path because platform back
29
+ * ownership now lives with the native adapter/history layer. This remains
30
+ * available for manual integrations.
62
31
  */
63
32
  export declare const createNativeRouteBackIntegration: (backHandler: NativeBackHandlerLike) => RouteRuntimeIntegration;
64
33
  /**
65
34
  * Native Route wrapper for root/provider mode.
66
35
  *
67
36
  * Behavior:
68
- * - On mobile native runtimes, injects back-handler integration into app Route.
69
- * - On web runtimes, passes no integration so app Route uses browser behavior.
37
+ * - On React Native mobile runtimes, auto-injects a native-history-backed
38
+ * adapter so native history owns platform back actions.
39
+ * - On React Native web runtimes, auto-injects the browser adapter.
70
40
  */
71
41
  export declare const Route: <ParamsType extends Record<string, any>>(props: PropsWithChildren<RouteProps<ParamsType>>) => import("react/jsx-runtime").JSX.Element;
72
- /**
73
- * Build a path from a navigation route chain and route config mapping.
74
- *
75
- * @param routeChain - Ordered list of routes from root to leaf.
76
- * @param config - Route name to path pattern mapping.
77
- * @param query - Optional query parameters appended to the path.
78
- * @returns Serialized path string.
79
- */
80
- export declare const buildPathFromRouteChain: (routeChain: NavigationRouteNode[], config: NavigationRouteConfig, query?: RouteQuery) => string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@resistdesign/voltra",
3
- "version": "3.0.0-alpha.44",
3
+ "version": "3.0.0-alpha.46",
4
4
  "description": "With our powers combined!",
5
5
  "homepage": "https://voltra.app",
6
6
  "repository": "git@github.com:resistdesign/voltra.git",