@packvium/engine 0.1.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/index.d.ts ADDED
@@ -0,0 +1,53 @@
1
+ export type ExactScalar=string|number|{value:string|number;unit?:string};
2
+ export interface Dimensions{length:ExactScalar;width:ExactScalar;height:ExactScalar}
3
+ export interface Item{id:string;quantity?:number;dimensions:Dimensions;weight?:ExactScalar;allowed_rotations?:string[];keep_upright?:boolean;stackable?:boolean;must_be_on_floor?:boolean;max_top_load?:ExactScalar;max_stacked_items?:number;nesting_height?:ExactScalar;minimum_support_ratio?:number;ground_contact_rule?:'free'|'covered'|'single'|'multiple';group?:string;tags?:string[];incompatible_tags?:string[];eligible_container_tags?:string[];priority?:number;value?:number;metadata?:Record<string,unknown>}
4
+ export interface Axle{position:ExactScalar;max_load?:ExactScalar}
5
+ export interface Container{id:string;inner_dimensions:Dimensions;outer_dimensions?:Dimensions;max_payload?:ExactScalar;tare_weight?:ExactScalar;quantity?:number;cost_minor?:number;max_items?:number;max_stack_density?:ExactScalar;axles?:[Axle,Axle];tags?:string[];tag_limits?:Record<string,number>;void_fill_reserve_ratio?:number;metadata?:Record<string,unknown>;obstacles?:Array<{id:string;origin:{x:ExactScalar;y:ExactScalar;z:ExactScalar};dimensions:Dimensions;additional_boxes?:Array<{origin?:{x:ExactScalar;y:ExactScalar;z:ExactScalar};dimensions:Dimensions}>}>}
6
+ export interface PackingConfiguration{solver_profile?:'fast'|'balanced'|'quality'|'exact_small';time_limit_ms?:number;alternatives?:number;seed?:number;max_containers?:number;clearance?:ExactScalar;minimum_support_ratio?:number;exact_item_limit?:number;multi_start_orders?:number;max_candidates_per_item?:number;max_candidate_points?:number;require_placement_coordinates?:boolean;solvers?:Array<'grid'|'extreme_points'|'homogeneous_blocks'|'layer'|'maximal_spaces'|'exact_small'>;objective?:'default'|'lowest_cost'|'shipping_cost'|'open_dimension_height'|'maximum_value';dimensional_weight_divisor?:number;dimensional_weight_length_unit?:'mm'|'cm'|'m'|'in'|'ft';dimensional_weight_weight_unit?:'mg'|'g'|'kg'|'oz'|'lb';effort_budget?:{max_candidates_evaluated?:number;max_placement_attempts?:number;max_search_nodes?:number;max_restarts?:number}}
7
+ export interface CatalogReference{catalog_id:string;version:number;effective_at:number;resolved_at:number}
8
+ export interface PackingRequest{units?:{length?:string};configuration?:PackingConfiguration;items:Item[];containers:Container[];catalog_versions_used?:CatalogReference[];output?:{length_unit?:string;weight_unit?:string}}
9
+ export interface ResultFact{code:string;[key:string]:unknown}
10
+ export interface StartRecord{id:string;started:boolean;completed:boolean;truncated:boolean;selected:boolean;global_deadline_reached:boolean}
11
+ export interface TerminationFact extends ResultFact{any_start_truncated:boolean;all_required_starts_completed:boolean;winning_start_truncated:boolean;global_deadline_reached:boolean;starts:StartRecord[]}
12
+ export interface SolverMetrics{candidate_points_considered:number;orientations_considered:number;feasible_candidates:number;collision_checks:number;support_checks:number;space_partitions:number;search_nodes_expanded:number}
13
+ export interface RejectionObservation{code:string;count:number;details:string[];[key:string]:unknown}
14
+ export interface ReasonProof{level:'proven'|'observed'|'inferred'|'unknown_due_to_limit';observations:RejectionObservation[];[key:string]:unknown}
15
+ export interface UnpackedItemResult{item_id:string;item_type:string;reason:string;details:string[];proof:ReasonProof}
16
+ export interface ExplanationDescriptor{message_key:string;arguments:{item_id:string;evidence_level:string;details:string};default_message:string}
17
+ export interface PackingResult{status:string;feasibility:ResultFact;termination:TerminationFact;optimality:ResultFact;complete:boolean;algorithm:{profile:string;solver:string;duration_ms:number;seed:number;time_limit_reached:boolean;effort_limit_reached:boolean;candidates_evaluated:number;placements_attempted:number;metrics:SolverMetrics};summary:{container_count:number;packed_item_count:number;unpacked_item_count:number};containers:unknown[];unpacked_items:UnpackedItemResult[];catalog_versions_used:CatalogReference[];[key:string]:unknown}
18
+ export interface WeightMove{item_id:string;from_container_id:string;to_container_id:string}
19
+ export interface RebalanceResult{containers:unknown[];moves:WeightMove[];improved:boolean}
20
+ export class UnsupportedFeatureError extends Error{readonly code:'unsupported_feature';readonly fields:string[]}
21
+ export type MovementDirection='+x'|'-x'|'+y'|'-y'|'+z'|'-z';
22
+ export interface SequencePoint{x:number;y:number;z:number}
23
+ export interface SequenceDimensions{length:number;width:number;height:number}
24
+ export interface SequenceBox{origin:SequencePoint;dimensions:SequenceDimensions}
25
+ export interface SequenceStep{index:number;direction:MovementDirection;depends_on:number[]}
26
+ export interface Reachability{index:number;reachable:boolean;blocked_by_support:number[];blocked_by_neighbors:number[];blocked_by_route:number[]}
27
+ export interface SequenceBusinessRulePlacement extends SequenceBox{weight?:number;max_top_load?:number;max_stacked_items?:number;stackable?:boolean;ground_contact_rule?:'free'|'covered'|'single'|'multiple'}
28
+ export interface SequenceBusinessRuleContainer{max_stack_density?:number}
29
+ export const ALL_DIRECTIONS:readonly MovementDirection[];
30
+ export class InvalidDirectionError extends RangeError{readonly code:'invalid_direction';readonly direction:string}
31
+ export class SequenceError extends Error{readonly code:'sequence_stuck';readonly stuck:number[]}
32
+ export class SequenceReplayError extends Error{readonly code:'sequence_replay';readonly index:number;readonly step:number;readonly reason:string}
33
+ export class SequenceWarning{readonly code:string;readonly index:number;readonly message_key:string;readonly arguments:Readonly<Record<string,string>>;constructor(code:string,index:number,messageKey:string,arguments_?:Record<string,string>);toJSON():{code:string;index:number;message_key:string;arguments:Readonly<Record<string,string>>}}
34
+ export class LoadingDependencyGraph{readonly dependsOn:readonly (readonly number[])[];constructor(dependsOn:readonly (readonly number[])[]);static build(boxes:readonly SequenceBox[]):LoadingDependencyGraph;isAcyclic():boolean}
35
+ export class UnloadingDependencyGraph{readonly dependsOn:readonly (readonly number[])[];constructor(dependsOn:readonly (readonly number[])[]);static build(boxes:readonly SequenceBox[]):UnloadingDependencyGraph;isAcyclic():boolean}
36
+ export function safeLoadingOrder(boxes:readonly SequenceBox[],container:SequenceDimensions,directions?:readonly MovementDirection[]):number[];
37
+ export function safeLoadingOrderForPlacements(placements:readonly SequenceBusinessRulePlacement[],container:SequenceDimensions&SequenceBusinessRuleContainer,directions?:readonly MovementDirection[]):number[];
38
+ export function safeRemovalOrder(boxes:readonly SequenceBox[],container:SequenceDimensions,directions?:readonly MovementDirection[]):number[];
39
+ export function placementReachability(boxes:readonly SequenceBox[],container:SequenceDimensions,stops?:readonly (number|null)[]|null,directions?:readonly MovementDirection[]):Reachability[];
40
+ export function replayLoadingOrder(boxes:readonly SequenceBox[],container:SequenceDimensions,order:readonly number[],directions?:readonly MovementDirection[]):void;
41
+ export function replayRemovalOrder(boxes:readonly SequenceBox[],container:SequenceDimensions,order:readonly number[],directions?:readonly MovementDirection[]):void;
42
+ export function safeLoadingOrderWithEvidence(boxes:readonly SequenceBox[],container:SequenceDimensions,directions?:readonly MovementDirection[]):SequenceStep[];
43
+ export function safeRemovalOrderWithEvidence(boxes:readonly SequenceBox[],container:SequenceDimensions,directions?:readonly MovementDirection[]):SequenceStep[];
44
+ export function verifyLoadingPrefixBusinessRules(placements:readonly SequenceBusinessRulePlacement[],order:readonly number[],container:SequenceBusinessRuleContainer):void;
45
+ export const REASON_MESSAGES:Readonly<Record<string,string>>;
46
+ export function explainReason(reason:string):string;
47
+ export function explanationForUnpackedItem(item:UnpackedItemResult):ExplanationDescriptor;
48
+ export function explainUnpackedItem(item:UnpackedItemResult):string;
49
+ export function pack(request:PackingRequest):PackingResult;
50
+ export function packJson(input:string):string;
51
+ export function rebalanceWeight(request:PackingRequest,result:PackingResult,options?:{maxMoves?:number}):RebalanceResult;
52
+ export function backend():"rust"|"javascript";
53
+ export function version():string;
package/index.js ADDED
@@ -0,0 +1,30 @@
1
+ import { createRequire } from 'node:module';
2
+ import {
3
+ UnsupportedFeatureError,
4
+ packFallback,
5
+ rebalanceWeight as rebalanceFallback,
6
+ } from './fallback.js';
7
+ export {
8
+ ALL_DIRECTIONS, InvalidDirectionError, LoadingDependencyGraph, SequenceError,
9
+ SequenceReplayError, SequenceWarning, UnloadingDependencyGraph, replayLoadingOrder,
10
+ replayRemovalOrder, safeLoadingOrder, safeLoadingOrderWithEvidence,
11
+ safeLoadingOrderForPlacements, safeRemovalOrder, safeRemovalOrderWithEvidence,
12
+ placementReachability,
13
+ verifyLoadingPrefixBusinessRules, REASON_MESSAGES, explainReason,
14
+ explanationForUnpackedItem, explainUnpackedItem,
15
+ } from './fallback.js';
16
+ export { UnsupportedFeatureError };
17
+ const require=createRequire(import.meta.url);
18
+ let native=null;
19
+ for(const candidate of ['./packvium-native.node','@packvium/native']){try{native=require(candidate);break}catch{}}
20
+ export const backend=()=>native?'rust':'javascript';
21
+ export function packJson(input){if(native?.packJson)return native.packJson(input);return JSON.stringify(packFallback(JSON.parse(input)));}
22
+ export function pack(request){return JSON.parse(packJson(JSON.stringify(request)));}
23
+ export function rebalanceWeight(request,result,{maxMoves=64}={}){
24
+ if(!Number.isSafeInteger(maxMoves)||maxMoves<0)throw new RangeError('maxMoves must be a non-negative safe integer');
25
+ if(native?.rebalanceJson){
26
+ return JSON.parse(native.rebalanceJson(JSON.stringify(request),JSON.stringify(result),maxMoves));
27
+ }
28
+ return rebalanceFallback(request,result,{maxMoves});
29
+ }
30
+ export const version=()=>native?.version?.()??'0.1.0-js-fallback';
package/package.json ADDED
@@ -0,0 +1,17 @@
1
+ {
2
+ "name":"@packvium/engine",
3
+ "version":"0.1.0",
4
+ "description":"Native-first 3D cartonization with deterministic JS fallback",
5
+ "type":"module",
6
+ "main":"index.js",
7
+ "types":"index.d.ts",
8
+ "exports":{".":{"types":"./index.d.ts","import":"./index.js"}},
9
+ "files":["index.js","fallback.js","contact-graph.js","policy.js","index.d.ts","README.md"],
10
+ "engines":{"node":">=16"},
11
+ "optionalDependencies":{"@packvium/native":"0.1.0"},
12
+ "scripts":{
13
+ "test":"node --test \"test/*.test.mjs\"",
14
+ "test:legacy":"node test/legacy-conformance.mjs"
15
+ },
16
+ "license":"MIT"
17
+ }