@voyant-travel/allotments 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.
@@ -0,0 +1,42 @@
1
+ /**
2
+ * The canonical allotment lifecycle — held inventory with an option/cutoff/
3
+ * release lifecycle and live pickup counters. Identical whether the unit is a
4
+ * hotel room (accommodations room blocks), m² of function space (operations
5
+ * space blocks), a coach seat, etc. — only the unit and the type-specific
6
+ * tables differ.
7
+ *
8
+ * This package owns the SHARED CONTRACT (state machine + counter math + slot
9
+ * enumeration + ledger status), reused by type-specific tables. There is no
10
+ * single polymorphic table. See RFC voyant#1489 §4.3 / §9-Q2.
11
+ *
12
+ * Pure logic only — no DB or Drizzle dependency. Each consumer keeps its own
13
+ * thin transactional service that maintains its counters in the same
14
+ * transaction as each ledger write, guarded by table CHECK constraints.
15
+ */
16
+ /** Block header lifecycle stages (negotiation, NOT pickup progress). */
17
+ export declare const ALLOTMENT_STATUSES: readonly ["inquiry", "held", "confirmed", "released", "cancelled", "expired"];
18
+ export type AllotmentStatus = (typeof ALLOTMENT_STATUSES)[number];
19
+ /** Statuses that can no longer accrue pickups. */
20
+ export declare const CLOSED_ALLOTMENT_STATUSES: readonly ["released", "cancelled", "expired"];
21
+ export declare function isClosedAllotmentStatus(status: string): boolean;
22
+ /** The append-only pickup ledger is compensated (reversed), never deleted. */
23
+ export declare const ALLOTMENT_PICKUP_STATUSES: readonly ["active", "reversed"];
24
+ export type AllotmentPickupStatus = (typeof ALLOTMENT_PICKUP_STATUSES)[number];
25
+ /** Per-slot counters: held − pickedUp − released = remaining. */
26
+ export interface AllotmentCounters {
27
+ held: number;
28
+ pickedUp: number;
29
+ released: number;
30
+ }
31
+ export declare function allotmentRemaining(counters: AllotmentCounters): number;
32
+ /** Pickup progress is DERIVED from counters at read time — never stored. */
33
+ export type PickupProgress = "none" | "partial" | "full";
34
+ export declare function allotmentPickupProgress(counters: AllotmentCounters): PickupProgress;
35
+ /**
36
+ * The slot dates a stay/hold occupies: each date from `start` (inclusive) to
37
+ * `end` (exclusive). Dates are `YYYY-MM-DD`, parsed as UTC to avoid timezone
38
+ * drift across the day boundary. One date = one allotment slot (a hotel night,
39
+ * a space-day, …). Returns `[]` for an invalid or non-positive range.
40
+ */
41
+ export declare function eachDateInRange(start: string, end: string): string[];
42
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,wEAAwE;AACxE,eAAO,MAAM,kBAAkB,+EAOrB,CAAA;AAEV,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,CAAA;AAEjE,kDAAkD;AAClD,eAAO,MAAM,yBAAyB,+CAAgD,CAAA;AAEtF,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE/D;AAED,8EAA8E;AAC9E,eAAO,MAAM,yBAAyB,iCAAkC,CAAA;AACxE,MAAM,MAAM,qBAAqB,GAAG,CAAC,OAAO,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAA;AAE9E,iEAAiE;AACjE,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,MAAM,CAEtE;AAED,4EAA4E;AAC5E,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,SAAS,GAAG,MAAM,CAAA;AAExD,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,iBAAiB,GAAG,cAAc,CAGnF;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CASpE"}
package/dist/index.js ADDED
@@ -0,0 +1,56 @@
1
+ /**
2
+ * The canonical allotment lifecycle — held inventory with an option/cutoff/
3
+ * release lifecycle and live pickup counters. Identical whether the unit is a
4
+ * hotel room (accommodations room blocks), m² of function space (operations
5
+ * space blocks), a coach seat, etc. — only the unit and the type-specific
6
+ * tables differ.
7
+ *
8
+ * This package owns the SHARED CONTRACT (state machine + counter math + slot
9
+ * enumeration + ledger status), reused by type-specific tables. There is no
10
+ * single polymorphic table. See RFC voyant#1489 §4.3 / §9-Q2.
11
+ *
12
+ * Pure logic only — no DB or Drizzle dependency. Each consumer keeps its own
13
+ * thin transactional service that maintains its counters in the same
14
+ * transaction as each ledger write, guarded by table CHECK constraints.
15
+ */
16
+ /** Block header lifecycle stages (negotiation, NOT pickup progress). */
17
+ export const ALLOTMENT_STATUSES = [
18
+ "inquiry",
19
+ "held",
20
+ "confirmed",
21
+ "released",
22
+ "cancelled",
23
+ "expired",
24
+ ];
25
+ /** Statuses that can no longer accrue pickups. */
26
+ export const CLOSED_ALLOTMENT_STATUSES = ["released", "cancelled", "expired"];
27
+ export function isClosedAllotmentStatus(status) {
28
+ return CLOSED_ALLOTMENT_STATUSES.includes(status);
29
+ }
30
+ /** The append-only pickup ledger is compensated (reversed), never deleted. */
31
+ export const ALLOTMENT_PICKUP_STATUSES = ["active", "reversed"];
32
+ export function allotmentRemaining(counters) {
33
+ return counters.held - counters.pickedUp - counters.released;
34
+ }
35
+ export function allotmentPickupProgress(counters) {
36
+ if (counters.pickedUp === 0)
37
+ return "none";
38
+ return allotmentRemaining(counters) === 0 ? "full" : "partial";
39
+ }
40
+ /**
41
+ * The slot dates a stay/hold occupies: each date from `start` (inclusive) to
42
+ * `end` (exclusive). Dates are `YYYY-MM-DD`, parsed as UTC to avoid timezone
43
+ * drift across the day boundary. One date = one allotment slot (a hotel night,
44
+ * a space-day, …). Returns `[]` for an invalid or non-positive range.
45
+ */
46
+ export function eachDateInRange(start, end) {
47
+ const from = new Date(`${start}T00:00:00Z`);
48
+ const to = new Date(`${end}T00:00:00Z`);
49
+ if (Number.isNaN(from.getTime()) || Number.isNaN(to.getTime()))
50
+ return [];
51
+ const dates = [];
52
+ for (let d = from; d < to; d.setUTCDate(d.getUTCDate() + 1)) {
53
+ dates.push(d.toISOString().slice(0, 10));
54
+ }
55
+ return dates;
56
+ }
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "@voyant-travel/allotments",
3
+ "version": "0.1.0",
4
+ "license": "Apache-2.0",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": "./src/index.ts"
8
+ },
9
+ "scripts": {
10
+ "typecheck": "tsc --noEmit",
11
+ "lint": "biome check src/",
12
+ "test": "vitest run --passWithNoTests",
13
+ "build": "tsc -p tsconfig.json",
14
+ "clean": "rm -rf dist tsconfig.tsbuildinfo",
15
+ "prepack": "pnpm run build"
16
+ },
17
+ "devDependencies": {
18
+ "@voyant-travel/voyant-typescript-config": "workspace:^",
19
+ "typescript": "^6.0.2",
20
+ "vitest": "^4.1.2"
21
+ },
22
+ "files": [
23
+ "dist"
24
+ ],
25
+ "publishConfig": {
26
+ "access": "public",
27
+ "exports": {
28
+ ".": {
29
+ "types": "./dist/index.d.ts",
30
+ "import": "./dist/index.js",
31
+ "default": "./dist/index.js"
32
+ }
33
+ },
34
+ "main": "./dist/index.js",
35
+ "types": "./dist/index.d.ts"
36
+ },
37
+ "repository": {
38
+ "type": "git",
39
+ "url": "https://github.com/voyant-travel/voyant.git",
40
+ "directory": "packages/allotments"
41
+ }
42
+ }