@mark1russell7/collections 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/dag/index.d.ts +13 -1
- package/build/dag/index.d.ts.map +1 -1
- package/build/dag/index.js +29 -3
- package/build/dag/index.js.map +1 -1
- package/build/index.d.ts +32 -214
- package/build/index.d.ts.map +1 -1
- package/build/index.js +43 -233
- package/build/index.js.map +1 -1
- package/package.json +4 -1
- package/src/behaviors/safe.ts +78 -132
- package/src/dag/executor.ts +24 -2
- package/src/dag/types.ts +10 -1
- package/src/impl/hash-map.ts +18 -28
- package/src/index.ts +0 -16
- package/src/core/effects.ts +0 -327
package/build/dag/index.d.ts
CHANGED
|
@@ -38,6 +38,11 @@ interface DAGExecutionOptions<TNode extends DAGNode = DAGNode> {
|
|
|
38
38
|
concurrency?: number;
|
|
39
39
|
/** When this value is true, the run stops on the first error. The default is true. */
|
|
40
40
|
failFast?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* When this value is true, a node whose dependency failed or was skipped does not start. Its result has `skipped: true`.
|
|
43
|
+
* The default is true. Give false only when the nodes do not use the work of their dependencies.
|
|
44
|
+
*/
|
|
45
|
+
skipDependents?: boolean;
|
|
41
46
|
/** Callback for progress reporting */
|
|
42
47
|
onNodeStart?: (node: TNode) => void;
|
|
43
48
|
/** Callback when a node completes */
|
|
@@ -59,6 +64,8 @@ interface NodeResult<TNode extends DAGNode = DAGNode> {
|
|
|
59
64
|
logs: string[];
|
|
60
65
|
/** Optional output from the processor */
|
|
61
66
|
output?: unknown | undefined;
|
|
67
|
+
/** This value is true when the node did not start, because a dependency failed or was skipped. */
|
|
68
|
+
skipped?: boolean | undefined;
|
|
62
69
|
}
|
|
63
70
|
/**
|
|
64
71
|
* The result of a run of an entire DAG
|
|
@@ -68,8 +75,10 @@ interface DAGResult<TNode extends DAGNode = DAGNode> {
|
|
|
68
75
|
success: boolean;
|
|
69
76
|
/** Results for each node */
|
|
70
77
|
results: Map<string, NodeResult<TNode>>;
|
|
71
|
-
/**
|
|
78
|
+
/** The ids of the nodes whose processor failed */
|
|
72
79
|
failedNodes: string[];
|
|
80
|
+
/** The ids of the nodes that did not start, because a dependency failed or was skipped */
|
|
81
|
+
skippedNodes: string[];
|
|
73
82
|
/** Total duration in milliseconds */
|
|
74
83
|
totalDuration: number;
|
|
75
84
|
}
|
|
@@ -107,6 +116,9 @@ export declare function visualizeDAG<TNode extends DAGNode>(dag: DependencyDAG<T
|
|
|
107
116
|
* A processor that throws does NOT reject the whole run. The run records the throw
|
|
108
117
|
* as a failed NodeResult, so partial results are always given.
|
|
109
118
|
*
|
|
119
|
+
* With `skipDependents` (the default), a node whose dependency failed or was skipped does not start. Its result has
|
|
120
|
+
* `skipped: true` and an error that names those dependencies. A dependency outside the DAG does not count.
|
|
121
|
+
*
|
|
110
122
|
* `failFast` operates at level granularity. When a node in a level fails, each
|
|
111
123
|
* node already in flight in that level continues to completion. No later level
|
|
112
124
|
* starts. (There is no mid-level cancellation.)
|
package/build/dag/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/dag/types.ts","../../src/dag/traversal.ts","../../src/dag/executor.ts","../../src/dag/builder.ts"],"mappings":";;;;;;;;;UAUiB,QAAQ;;EAEvB;;EAEA;;EAEA;;EAEA,OAAO;;;;;UAMQ,cAAc,cAAc,UAAU;;EAErD,OAAO,YAAY;;EAEnB,QAAQ;;EAER;;EAEA;;;;;UAMe,oBAAoB,cAAc,UAAU;;EAE3D;;EAEA;;EAEA,eAAe,MAAM;;EAErB,kBAAkB,QAAQ,WAAW;;;;;UAMtB,WAAW,cAAc,UAAU;;EAElD,MAAM;;EAEN;;EAEA,QAAQ;;EAER;;EAEA;;EAEA;;;;;UAMe,UAAU,cAAc,UAAU;;EAEjD;;EAEA,SAAS,YAAY,WAAW;;EAEhC;;EAEA;;;;;KAMU,cAAc,cAAc,UAAU,YAChD,MAAM,UACH,QAAQ,WAAW;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/dag/types.ts","../../src/dag/traversal.ts","../../src/dag/executor.ts","../../src/dag/builder.ts"],"mappings":";;;;;;;;;UAUiB,QAAQ;;EAEvB;;EAEA;;EAEA;;EAEA,OAAO;;;;;UAMQ,cAAc,cAAc,UAAU;;EAErD,OAAO,YAAY;;EAEnB,QAAQ;;EAER;;EAEA;;;;;UAMe,oBAAoB,cAAc,UAAU;;EAE3D;;EAEA;;;;;EAKA;;EAEA,eAAe,MAAM;;EAErB,kBAAkB,QAAQ,WAAW;;;;;UAMtB,WAAW,cAAc,UAAU;;EAElD,MAAM;;EAEN;;EAEA,QAAQ;;EAER;;EAEA;;EAEA;;EAEA;;;;;UAMe,UAAU,cAAc,UAAU;;EAEjD;;EAEA,SAAS,YAAY,WAAW;;EAEhC;;EAEA;;EAEA;;;;;KAMU,cAAc,cAAc,UAAU,YAChD,MAAM,UACH,QAAQ,WAAW;;;;;;;;;;;;wBC3ER,gBAAgB,cAAc,SAC5C,OAAO,YAAY,SAClB,cAAc;;;;wBA+ED,oBAAoB,cAAc,SAChD,KAAK,cAAc,SAClB;;;;wBAOa,aAAa,cAAc,SACzC,KAAK,cAAc;;;;;;;;;;;;;;;;;;wBClCC,WAAW,cAAc,SAC7C,KAAK,cAAc,QACnB,YAAY,MAAM,UAAU,QAAQ,WAAW,SAC/C,UAAS,oBAAoB,SAC5B,QAAQ,UAAU;;;;wBAwFC,qBAAqB,cAAc,SACvD,KAAK,cAAc,QACnB,YAAY,MAAM,UAAU,QAAQ,WAAW,SAC/C,UAAS,KAAK,oBAAoB,yBACjC,QAAQ,UAAU;;;;wBAOL,gBAAgB,cAAc,SAC5C,KAAK,MAAM,UAAU,iBACnB,MAAM,UAAU,QAAQ,WAAW;;;;wBC7KvB,kBAAkB,cAAc,SAC9C,OAAO,YAAY,QACnB,iBACC,YAAY;;;;wBAyBC,aAAa,cAAc,SACzC,OAAO,YAAY,QACnB,aACC;;;;wBA0Ba,eAAe,cAAc,SAC3C,OAAO,YAAY,QACnB,aACC;;;;wBAmCa,WAAW,iBACzB,YACA,yBACA,OAAO,oBACN,QAAQ;;;;wBAWK,aAAa,cAAc,SACzC,OAAO,UACN,YAAY"}
|
package/build/dag/index.js
CHANGED
|
@@ -122,19 +122,43 @@ function notify(name, listener, arg) {
|
|
|
122
122
|
* A processor that throws does NOT reject the whole run. The run records the throw
|
|
123
123
|
* as a failed NodeResult, so partial results are always given.
|
|
124
124
|
*
|
|
125
|
+
* With `skipDependents` (the default), a node whose dependency failed or was skipped does not start. Its result has
|
|
126
|
+
* `skipped: true` and an error that names those dependencies. A dependency outside the DAG does not count.
|
|
127
|
+
*
|
|
125
128
|
* `failFast` operates at level granularity. When a node in a level fails, each
|
|
126
129
|
* node already in flight in that level continues to completion. No later level
|
|
127
130
|
* starts. (There is no mid-level cancellation.)
|
|
128
131
|
*/
|
|
129
132
|
async function executeDAG(dag, processor, options = {}) {
|
|
130
|
-
const { concurrency = 4, failFast = true, onNodeStart, onNodeComplete } = options;
|
|
133
|
+
const { concurrency = 4, failFast = true, skipDependents = true, onNodeStart, onNodeComplete } = options;
|
|
131
134
|
const results = /* @__PURE__ */ new Map();
|
|
132
135
|
const failedNodes = [];
|
|
136
|
+
const skippedNodes = [];
|
|
137
|
+
const blocked = /* @__PURE__ */ new Set();
|
|
133
138
|
const startTime = Date.now();
|
|
134
139
|
let shouldStop = false;
|
|
135
140
|
for (const level of dag.levels) {
|
|
136
141
|
if (shouldStop) break;
|
|
137
|
-
const
|
|
142
|
+
const runnable = [];
|
|
143
|
+
for (const node of level) {
|
|
144
|
+
const blockers = skipDependents ? node.dependencies.filter((dep) => blocked.has(dep)) : [];
|
|
145
|
+
if (blockers.length === 0) {
|
|
146
|
+
runnable.push(node);
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
const message = "Skipped " + node.id + ": the dependencies " + blockers.join(", ") + " failed or were skipped";
|
|
150
|
+
results.set(node.id, {
|
|
151
|
+
node,
|
|
152
|
+
success: false,
|
|
153
|
+
skipped: true,
|
|
154
|
+
error: new Error(message),
|
|
155
|
+
duration: 0,
|
|
156
|
+
logs: [message]
|
|
157
|
+
});
|
|
158
|
+
skippedNodes.push(node.id);
|
|
159
|
+
blocked.add(node.id);
|
|
160
|
+
}
|
|
161
|
+
const levelResults = await executeWithConcurrency(runnable, async (node) => {
|
|
138
162
|
const startError = notify("onNodeStart", onNodeStart, node);
|
|
139
163
|
const nodeStart = Date.now();
|
|
140
164
|
let result;
|
|
@@ -161,14 +185,16 @@ async function executeDAG(dag, processor, options = {}) {
|
|
|
161
185
|
results.set(result.node.id, result);
|
|
162
186
|
if (!result.success) {
|
|
163
187
|
failedNodes.push(result.node.id);
|
|
188
|
+
blocked.add(result.node.id);
|
|
164
189
|
if (failFast) shouldStop = true;
|
|
165
190
|
}
|
|
166
191
|
}
|
|
167
192
|
}
|
|
168
193
|
return {
|
|
169
|
-
success: failedNodes.length === 0,
|
|
194
|
+
success: failedNodes.length === 0 && skippedNodes.length === 0,
|
|
170
195
|
results,
|
|
171
196
|
failedNodes,
|
|
197
|
+
skippedNodes,
|
|
172
198
|
totalDuration: Date.now() - startTime
|
|
173
199
|
};
|
|
174
200
|
}
|
package/build/dag/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../src/dag/traversal.ts","../../src/dag/executor.ts","../../src/dag/builder.ts"],"sourcesContent":["/**\n * DAG Traversal using Kahn's Algorithm\n *\n * This module implements topological sort with level assignment for parallel execution.\n * Level 0 = leaves (no dependencies), higher levels depend on lower levels.\n */\n\nimport type { DAGNode, DependencyDAG } from \"./types.js\";\n\n/**\n * Build a leveled DAG from nodes using Kahn's algorithm\n *\n * This assigns levels to each node where:\n * - Level 0: Nodes with no dependencies (leaves)\n * - Level N: Nodes whose dependencies are all at level < N\n *\n * Nodes at the same level can be processed in parallel.\n *\n * @throws Error if a cycle is detected\n */\nexport function buildLeveledDAG<TNode extends DAGNode>(\n nodes: Map<string, TNode>\n): DependencyDAG<TNode> {\n const inDegree = new Map<string, number>();\n const dependents = new Map<string, Set<string>>();\n\n for (const [name, node] of nodes) {\n // A set: a dependency that a node lists twice counts once. (`dependents` is a set, so it\n // takes the in-degree down once: a repeated dependency was \"Circular\": deep dive DATA-21.)\n const depsInDag = new Set(node.dependencies.filter((dep) => nodes.has(dep)));\n inDegree.set(name, depsInDag.size);\n dependents.set(name, new Set());\n }\n\n for (const [name, node] of nodes) {\n for (const dep of node.dependencies) {\n if (dependents.has(dep)) {\n dependents.get(dep)!.add(name);\n }\n }\n }\n\n let queue: string[] = [];\n for (const [name, degree] of inDegree) {\n if (degree === 0) {\n queue.push(name);\n }\n }\n\n const levels: TNode[][] = [];\n const nodeLevel = new Map<string, number>();\n let processedCount = 0;\n\n while (queue.length > 0) {\n const currentLevel = levels.length;\n const levelNodes: TNode[] = [];\n const nextQueue: string[] = [];\n\n for (const name of queue) {\n const node = nodes.get(name)!;\n node.level = currentLevel;\n nodeLevel.set(name, currentLevel);\n levelNodes.push(node);\n processedCount++;\n\n for (const dependent of dependents.get(name) ?? []) {\n const newDegree = inDegree.get(dependent)! - 1;\n inDegree.set(dependent, newDegree);\n\n if (newDegree === 0) {\n nextQueue.push(dependent);\n }\n }\n }\n\n levels.push(levelNodes);\n queue = nextQueue;\n }\n\n if (processedCount !== nodes.size) {\n const cycleNodes = [...nodes.keys()].filter((n) => !nodeLevel.has(n));\n throw new Error(\"Circular dependency detected involving: \" + cycleNodes.join(\", \"));\n }\n\n const roots = [...nodes.keys()].filter((name) => {\n const deps = dependents.get(name);\n return !deps || deps.size === 0;\n });\n\n const leaves = [...nodes.keys()].filter((name) => {\n const node = nodes.get(name)!;\n const depsInDag = node.dependencies.filter((dep) => nodes.has(dep));\n return depsInDag.length === 0;\n });\n\n return { nodes, levels, roots, leaves };\n}\n\n/**\n * Get the topological order (flat list, leaves first)\n */\nexport function getTopologicalOrder<TNode extends DAGNode>(\n dag: DependencyDAG<TNode>\n): TNode[] {\n return dag.levels.flat();\n}\n\n/**\n * Visualize the DAG structure (for debugging)\n */\nexport function visualizeDAG<TNode extends DAGNode>(\n dag: DependencyDAG<TNode>\n): string {\n const lines = [\"DAG Structure:\"];\n\n for (let i = 0; i < dag.levels.length; i++) {\n const level = dag.levels[i]!;\n lines.push(\" Level \" + i + \":\");\n for (const node of level) {\n const deps =\n node.dependencies.length > 0\n ? \" -> [\" + node.dependencies.join(\", \") + \"]\"\n : \" (leaf)\";\n lines.push(\" - \" + node.id + deps);\n }\n }\n\n return lines.join(\"\\n\");\n}\n","/**\n * DAG Executor with parallel level-based execution\n */\n\nimport type {\n DependencyDAG,\n DAGNode,\n DAGExecutionOptions,\n NodeResult,\n DAGResult,\n} from \"./types.js\";\n\n/**\n * Start a batch of items with concurrency limit\n */\nasync function executeWithConcurrency<T, R>(\n items: T[],\n fn: (item: T) => Promise<R>,\n limit: number\n): Promise<R[]> {\n const results: R[] = [];\n const executing = new Set<Promise<void>>();\n\n for (const item of items) {\n const promise = fn(item)\n .then((result) => {\n results.push(result);\n })\n .finally(() => {\n // Rejection-safe cleanup: always remove the settled promise from the\n // executing set, even if `fn` rejected, so the set never leaks a\n // settled (possibly rejected) promise into later `race`/`all` waits.\n executing.delete(promise);\n });\n\n executing.add(promise);\n\n if (executing.size >= limit) {\n await Promise.race(executing);\n }\n }\n\n await Promise.all(executing);\n return results;\n}\n\n/**\n * Call a listener. A listener that throws does not stop the run: the function gives a log\n * line for its error (deep dive DATA-21).\n */\nfunction notify<T>(name: string, listener: ((arg: T) => void) | undefined, arg: T): string | undefined {\n if (!listener) return undefined;\n try {\n listener(arg);\n return undefined;\n } catch (error) {\n return name + \" threw: \" + (error instanceof Error ? error.message : String(error));\n }\n}\n\n/**\n * Start DAG with level-based parallelization\n *\n * - Levels are processed sequentially (level 0 first, then level 1, and so on)\n * - Within each level, nodes are processed in parallel up to concurrency limit\n * - Supports fail-fast or continue-on-error modes\n *\n * A processor that throws does NOT reject the whole run. The run records the throw\n * as a failed NodeResult, so partial results are always given.\n *\n * `failFast` operates at level granularity. When a node in a level fails, each\n * node already in flight in that level continues to completion. No later level\n * starts. (There is no mid-level cancellation.)\n */\nexport async function executeDAG<TNode extends DAGNode>(\n dag: DependencyDAG<TNode>,\n processor: (node: TNode) => Promise<NodeResult<TNode>>,\n options: DAGExecutionOptions<TNode> = {}\n): Promise<DAGResult<TNode>> {\n const {\n concurrency = 4,\n failFast = true,\n onNodeStart,\n onNodeComplete,\n } = options;\n\n const results = new Map<string, NodeResult<TNode>>();\n const failedNodes: string[] = [];\n const startTime = Date.now();\n let shouldStop = false;\n\n for (const level of dag.levels) {\n if (shouldStop) break;\n\n const levelResults = await executeWithConcurrency(\n level,\n async (node) => {\n const startError = notify(\"onNodeStart\", onNodeStart, node);\n const nodeStart = Date.now();\n let result: NodeResult<TNode>;\n try {\n result = await processor(node);\n } catch (error) {\n // Convert a thrown processor error into a failed NodeResult instead\n // of rejecting the entire run and discarding partial results.\n const err =\n error instanceof Error ? error : new Error(String(error));\n result = {\n node,\n success: false,\n error: err,\n duration: Date.now() - nodeStart,\n logs: [\"Processor threw: \" + err.message],\n };\n }\n const completeError = notify(\"onNodeComplete\", onNodeComplete, result);\n const listenerErrors = [startError, completeError].filter((line): line is string => line !== undefined);\n if (listenerErrors.length > 0) {\n result = { ...result, logs: [...(result.logs ?? []), ...listenerErrors] };\n }\n return result;\n },\n concurrency\n );\n\n for (const result of levelResults) {\n results.set(result.node.id, result);\n if (!result.success) {\n failedNodes.push(result.node.id);\n if (failFast) {\n shouldStop = true;\n }\n }\n }\n }\n\n return {\n success: failedNodes.length === 0,\n results,\n failedNodes,\n totalDuration: Date.now() - startTime,\n };\n}\n\n/**\n * Start DAG sequentially (no parallelization)\n */\nexport async function executeDAGSequential<TNode extends DAGNode>(\n dag: DependencyDAG<TNode>,\n processor: (node: TNode) => Promise<NodeResult<TNode>>,\n options: Omit<DAGExecutionOptions<TNode>, \"concurrency\"> = {}\n): Promise<DAGResult<TNode>> {\n return executeDAG(dag, processor, { ...options, concurrency: 1 });\n}\n\n/**\n * Make a simple processor that wraps an async function\n */\nexport function createProcessor<TNode extends DAGNode>(\n fn: (node: TNode) => Promise<void>\n): (node: TNode) => Promise<NodeResult<TNode>> {\n return async (node: TNode): Promise<NodeResult<TNode>> => {\n const startTime = Date.now();\n const logs: string[] = [];\n\n try {\n logs.push(\"Starting \" + node.id);\n await fn(node);\n logs.push(\"Completed \" + node.id);\n\n return {\n node,\n success: true,\n duration: Date.now() - startTime,\n logs,\n };\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n logs.push(\"Failed \" + node.id + \": \" + err.message);\n\n return {\n node,\n success: false,\n error: err,\n duration: Date.now() - startTime,\n logs,\n };\n }\n };\n}\n","/**\n * DAG Builder utilities\n */\n\nimport type { DAGNode } from \"./types.js\";\n\n/**\n * Filter DAG to only include nodes reachable from a root\n */\nexport function filterDAGFromRoot<TNode extends DAGNode>(\n nodes: Map<string, TNode>,\n rootId: string\n): Map<string, TNode> {\n const filtered = new Map<string, TNode>();\n const visited = new Set<string>();\n\n function visit(id: string): void {\n if (visited.has(id)) return;\n visited.add(id);\n\n const node = nodes.get(id);\n if (!node) return;\n\n filtered.set(id, node);\n\n for (const dep of node.dependencies) {\n visit(dep);\n }\n }\n\n visit(rootId);\n return filtered;\n}\n\n/**\n * Get all ancestors of a node (nodes that this node depends on, transitively)\n */\nexport function getAncestors<TNode extends DAGNode>(\n nodes: Map<string, TNode>,\n id: string\n): Set<string> {\n const ancestors = new Set<string>();\n const visited = new Set<string>();\n\n function visit(n: string): void {\n if (visited.has(n)) return;\n visited.add(n);\n\n const node = nodes.get(n);\n if (!node) return;\n\n for (const dep of node.dependencies) {\n if (nodes.has(dep)) {\n ancestors.add(dep);\n visit(dep);\n }\n }\n }\n\n visit(id);\n return ancestors;\n}\n\n/**\n * Get all descendants of a node (nodes that depend on this node, transitively)\n */\nexport function getDescendants<TNode extends DAGNode>(\n nodes: Map<string, TNode>,\n id: string\n): Set<string> {\n const descendants = new Set<string>();\n const visited = new Set<string>();\n\n // Build reverse dependency map\n const dependents = new Map<string, Set<string>>();\n for (const [nodeId, node] of nodes) {\n for (const dep of node.dependencies) {\n if (!dependents.has(dep)) {\n dependents.set(dep, new Set());\n }\n dependents.get(dep)!.add(nodeId);\n }\n }\n\n function visit(n: string): void {\n if (visited.has(n)) return;\n visited.add(n);\n\n const deps = dependents.get(n);\n if (!deps) return;\n\n for (const dep of deps) {\n descendants.add(dep);\n visit(dep);\n }\n }\n\n visit(id);\n return descendants;\n}\n\n/**\n * Make a DAG node from minimal input\n */\nexport function createNode<TData = unknown>(\n id: string,\n dependencies: string[] = [],\n data?: TData | undefined\n): DAGNode<TData> {\n const node: DAGNode<TData> = { id, dependencies };\n if (data !== undefined) {\n node.data = data;\n }\n return node;\n}\n\n/**\n * Build a Map of nodes from an array\n */\nexport function buildNodeMap<TNode extends DAGNode>(\n nodes: TNode[]\n): Map<string, TNode> {\n return new Map(nodes.map((n) => [n.id, n]));\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../src/dag/traversal.ts","../../src/dag/executor.ts","../../src/dag/builder.ts"],"sourcesContent":["/**\n * DAG Traversal using Kahn's Algorithm\n *\n * This module implements topological sort with level assignment for parallel execution.\n * Level 0 = leaves (no dependencies), higher levels depend on lower levels.\n */\n\nimport type { DAGNode, DependencyDAG } from \"./types.js\";\n\n/**\n * Build a leveled DAG from nodes using Kahn's algorithm\n *\n * This assigns levels to each node where:\n * - Level 0: Nodes with no dependencies (leaves)\n * - Level N: Nodes whose dependencies are all at level < N\n *\n * Nodes at the same level can be processed in parallel.\n *\n * @throws Error if a cycle is detected\n */\nexport function buildLeveledDAG<TNode extends DAGNode>(\n nodes: Map<string, TNode>\n): DependencyDAG<TNode> {\n const inDegree = new Map<string, number>();\n const dependents = new Map<string, Set<string>>();\n\n for (const [name, node] of nodes) {\n // A set: a dependency that a node lists twice counts once. (`dependents` is a set, so it\n // takes the in-degree down once: a repeated dependency was \"Circular\": deep dive DATA-21.)\n const depsInDag = new Set(node.dependencies.filter((dep) => nodes.has(dep)));\n inDegree.set(name, depsInDag.size);\n dependents.set(name, new Set());\n }\n\n for (const [name, node] of nodes) {\n for (const dep of node.dependencies) {\n if (dependents.has(dep)) {\n dependents.get(dep)!.add(name);\n }\n }\n }\n\n let queue: string[] = [];\n for (const [name, degree] of inDegree) {\n if (degree === 0) {\n queue.push(name);\n }\n }\n\n const levels: TNode[][] = [];\n const nodeLevel = new Map<string, number>();\n let processedCount = 0;\n\n while (queue.length > 0) {\n const currentLevel = levels.length;\n const levelNodes: TNode[] = [];\n const nextQueue: string[] = [];\n\n for (const name of queue) {\n const node = nodes.get(name)!;\n node.level = currentLevel;\n nodeLevel.set(name, currentLevel);\n levelNodes.push(node);\n processedCount++;\n\n for (const dependent of dependents.get(name) ?? []) {\n const newDegree = inDegree.get(dependent)! - 1;\n inDegree.set(dependent, newDegree);\n\n if (newDegree === 0) {\n nextQueue.push(dependent);\n }\n }\n }\n\n levels.push(levelNodes);\n queue = nextQueue;\n }\n\n if (processedCount !== nodes.size) {\n const cycleNodes = [...nodes.keys()].filter((n) => !nodeLevel.has(n));\n throw new Error(\"Circular dependency detected involving: \" + cycleNodes.join(\", \"));\n }\n\n const roots = [...nodes.keys()].filter((name) => {\n const deps = dependents.get(name);\n return !deps || deps.size === 0;\n });\n\n const leaves = [...nodes.keys()].filter((name) => {\n const node = nodes.get(name)!;\n const depsInDag = node.dependencies.filter((dep) => nodes.has(dep));\n return depsInDag.length === 0;\n });\n\n return { nodes, levels, roots, leaves };\n}\n\n/**\n * Get the topological order (flat list, leaves first)\n */\nexport function getTopologicalOrder<TNode extends DAGNode>(\n dag: DependencyDAG<TNode>\n): TNode[] {\n return dag.levels.flat();\n}\n\n/**\n * Visualize the DAG structure (for debugging)\n */\nexport function visualizeDAG<TNode extends DAGNode>(\n dag: DependencyDAG<TNode>\n): string {\n const lines = [\"DAG Structure:\"];\n\n for (let i = 0; i < dag.levels.length; i++) {\n const level = dag.levels[i]!;\n lines.push(\" Level \" + i + \":\");\n for (const node of level) {\n const deps =\n node.dependencies.length > 0\n ? \" -> [\" + node.dependencies.join(\", \") + \"]\"\n : \" (leaf)\";\n lines.push(\" - \" + node.id + deps);\n }\n }\n\n return lines.join(\"\\n\");\n}\n","/**\n * DAG Executor with parallel level-based execution\n */\n\nimport type {\n DependencyDAG,\n DAGNode,\n DAGExecutionOptions,\n NodeResult,\n DAGResult,\n} from \"./types.js\";\n\n/**\n * Start a batch of items with concurrency limit\n */\nasync function executeWithConcurrency<T, R>(\n items: T[],\n fn: (item: T) => Promise<R>,\n limit: number\n): Promise<R[]> {\n const results: R[] = [];\n const executing = new Set<Promise<void>>();\n\n for (const item of items) {\n const promise = fn(item)\n .then((result) => {\n results.push(result);\n })\n .finally(() => {\n // Rejection-safe cleanup: always remove the settled promise from the\n // executing set, even if `fn` rejected, so the set never leaks a\n // settled (possibly rejected) promise into later `race`/`all` waits.\n executing.delete(promise);\n });\n\n executing.add(promise);\n\n if (executing.size >= limit) {\n await Promise.race(executing);\n }\n }\n\n await Promise.all(executing);\n return results;\n}\n\n/**\n * Call a listener. A listener that throws does not stop the run: the function gives a log\n * line for its error (deep dive DATA-21).\n */\nfunction notify<T>(name: string, listener: ((arg: T) => void) | undefined, arg: T): string | undefined {\n if (!listener) return undefined;\n try {\n listener(arg);\n return undefined;\n } catch (error) {\n return name + \" threw: \" + (error instanceof Error ? error.message : String(error));\n }\n}\n\n/**\n * Start DAG with level-based parallelization\n *\n * - Levels are processed sequentially (level 0 first, then level 1, and so on)\n * - Within each level, nodes are processed in parallel up to concurrency limit\n * - Supports fail-fast or continue-on-error modes\n *\n * A processor that throws does NOT reject the whole run. The run records the throw\n * as a failed NodeResult, so partial results are always given.\n *\n * With `skipDependents` (the default), a node whose dependency failed or was skipped does not start. Its result has\n * `skipped: true` and an error that names those dependencies. A dependency outside the DAG does not count.\n *\n * `failFast` operates at level granularity. When a node in a level fails, each\n * node already in flight in that level continues to completion. No later level\n * starts. (There is no mid-level cancellation.)\n */\nexport async function executeDAG<TNode extends DAGNode>(\n dag: DependencyDAG<TNode>,\n processor: (node: TNode) => Promise<NodeResult<TNode>>,\n options: DAGExecutionOptions<TNode> = {}\n): Promise<DAGResult<TNode>> {\n const {\n concurrency = 4,\n failFast = true,\n skipDependents = true,\n onNodeStart,\n onNodeComplete,\n } = options;\n\n const results = new Map<string, NodeResult<TNode>>();\n const failedNodes: string[] = [];\n const skippedNodes: string[] = [];\n // The ids of the nodes that failed or were skipped\n const blocked = new Set<string>();\n const startTime = Date.now();\n let shouldStop = false;\n\n for (const level of dag.levels) {\n if (shouldStop) break;\n\n const runnable: TNode[] = [];\n for (const node of level) {\n const blockers = skipDependents ? node.dependencies.filter((dep) => blocked.has(dep)) : [];\n if (blockers.length === 0) {\n runnable.push(node);\n continue;\n }\n const message = \"Skipped \" + node.id + \": the dependencies \" + blockers.join(\", \") + \" failed or were skipped\";\n results.set(node.id, { node, success: false, skipped: true, error: new Error(message), duration: 0, logs: [message] });\n skippedNodes.push(node.id);\n blocked.add(node.id);\n }\n\n const levelResults = await executeWithConcurrency(\n runnable,\n async (node) => {\n const startError = notify(\"onNodeStart\", onNodeStart, node);\n const nodeStart = Date.now();\n let result: NodeResult<TNode>;\n try {\n result = await processor(node);\n } catch (error) {\n // Convert a thrown processor error into a failed NodeResult instead\n // of rejecting the entire run and discarding partial results.\n const err =\n error instanceof Error ? error : new Error(String(error));\n result = {\n node,\n success: false,\n error: err,\n duration: Date.now() - nodeStart,\n logs: [\"Processor threw: \" + err.message],\n };\n }\n const completeError = notify(\"onNodeComplete\", onNodeComplete, result);\n const listenerErrors = [startError, completeError].filter((line): line is string => line !== undefined);\n if (listenerErrors.length > 0) {\n result = { ...result, logs: [...(result.logs ?? []), ...listenerErrors] };\n }\n return result;\n },\n concurrency\n );\n\n for (const result of levelResults) {\n results.set(result.node.id, result);\n if (!result.success) {\n failedNodes.push(result.node.id);\n blocked.add(result.node.id);\n if (failFast) {\n shouldStop = true;\n }\n }\n }\n }\n\n return {\n success: failedNodes.length === 0 && skippedNodes.length === 0,\n results,\n failedNodes,\n skippedNodes,\n totalDuration: Date.now() - startTime,\n };\n}\n\n/**\n * Start DAG sequentially (no parallelization)\n */\nexport async function executeDAGSequential<TNode extends DAGNode>(\n dag: DependencyDAG<TNode>,\n processor: (node: TNode) => Promise<NodeResult<TNode>>,\n options: Omit<DAGExecutionOptions<TNode>, \"concurrency\"> = {}\n): Promise<DAGResult<TNode>> {\n return executeDAG(dag, processor, { ...options, concurrency: 1 });\n}\n\n/**\n * Make a simple processor that wraps an async function\n */\nexport function createProcessor<TNode extends DAGNode>(\n fn: (node: TNode) => Promise<void>\n): (node: TNode) => Promise<NodeResult<TNode>> {\n return async (node: TNode): Promise<NodeResult<TNode>> => {\n const startTime = Date.now();\n const logs: string[] = [];\n\n try {\n logs.push(\"Starting \" + node.id);\n await fn(node);\n logs.push(\"Completed \" + node.id);\n\n return {\n node,\n success: true,\n duration: Date.now() - startTime,\n logs,\n };\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n logs.push(\"Failed \" + node.id + \": \" + err.message);\n\n return {\n node,\n success: false,\n error: err,\n duration: Date.now() - startTime,\n logs,\n };\n }\n };\n}\n","/**\n * DAG Builder utilities\n */\n\nimport type { DAGNode } from \"./types.js\";\n\n/**\n * Filter DAG to only include nodes reachable from a root\n */\nexport function filterDAGFromRoot<TNode extends DAGNode>(\n nodes: Map<string, TNode>,\n rootId: string\n): Map<string, TNode> {\n const filtered = new Map<string, TNode>();\n const visited = new Set<string>();\n\n function visit(id: string): void {\n if (visited.has(id)) return;\n visited.add(id);\n\n const node = nodes.get(id);\n if (!node) return;\n\n filtered.set(id, node);\n\n for (const dep of node.dependencies) {\n visit(dep);\n }\n }\n\n visit(rootId);\n return filtered;\n}\n\n/**\n * Get all ancestors of a node (nodes that this node depends on, transitively)\n */\nexport function getAncestors<TNode extends DAGNode>(\n nodes: Map<string, TNode>,\n id: string\n): Set<string> {\n const ancestors = new Set<string>();\n const visited = new Set<string>();\n\n function visit(n: string): void {\n if (visited.has(n)) return;\n visited.add(n);\n\n const node = nodes.get(n);\n if (!node) return;\n\n for (const dep of node.dependencies) {\n if (nodes.has(dep)) {\n ancestors.add(dep);\n visit(dep);\n }\n }\n }\n\n visit(id);\n return ancestors;\n}\n\n/**\n * Get all descendants of a node (nodes that depend on this node, transitively)\n */\nexport function getDescendants<TNode extends DAGNode>(\n nodes: Map<string, TNode>,\n id: string\n): Set<string> {\n const descendants = new Set<string>();\n const visited = new Set<string>();\n\n // Build reverse dependency map\n const dependents = new Map<string, Set<string>>();\n for (const [nodeId, node] of nodes) {\n for (const dep of node.dependencies) {\n if (!dependents.has(dep)) {\n dependents.set(dep, new Set());\n }\n dependents.get(dep)!.add(nodeId);\n }\n }\n\n function visit(n: string): void {\n if (visited.has(n)) return;\n visited.add(n);\n\n const deps = dependents.get(n);\n if (!deps) return;\n\n for (const dep of deps) {\n descendants.add(dep);\n visit(dep);\n }\n }\n\n visit(id);\n return descendants;\n}\n\n/**\n * Make a DAG node from minimal input\n */\nexport function createNode<TData = unknown>(\n id: string,\n dependencies: string[] = [],\n data?: TData | undefined\n): DAGNode<TData> {\n const node: DAGNode<TData> = { id, dependencies };\n if (data !== undefined) {\n node.data = data;\n }\n return node;\n}\n\n/**\n * Build a Map of nodes from an array\n */\nexport function buildNodeMap<TNode extends DAGNode>(\n nodes: TNode[]\n): Map<string, TNode> {\n return new Map(nodes.map((n) => [n.id, n]));\n}\n"],"mappings":"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"}
|
package/build/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { i as Layer, s as Stacked, t as Chain } from "./layers.js";
|
|
2
|
+
import { Optional, Result } from "@mark1russell7/optional";
|
|
2
3
|
/**
|
|
3
4
|
* Core traits and capability interfaces for the collections framework.
|
|
4
5
|
*
|
|
@@ -138,191 +139,6 @@ export interface Freezable<T> {
|
|
|
138
139
|
/** This value gives true if this collection is frozen. */
|
|
139
140
|
readonly isFrozen: boolean;
|
|
140
141
|
}
|
|
141
|
-
/**
|
|
142
|
-
* Functional effect types for error handling and optional values.
|
|
143
|
-
*
|
|
144
|
-
* This module gives Option<T> and Result<T,E> types for explicit, type-safe
|
|
145
|
-
* error handling without exceptions. This module includes async variants.
|
|
146
|
-
*/
|
|
147
|
-
/**
|
|
148
|
-
* This type represents the absence of a value.
|
|
149
|
-
*/
|
|
150
|
-
export interface None {
|
|
151
|
-
readonly _tag: "None";
|
|
152
|
-
}
|
|
153
|
-
/**
|
|
154
|
-
* This type represents the presence of a value.
|
|
155
|
-
*/
|
|
156
|
-
export interface Some<T> {
|
|
157
|
-
readonly _tag: "Some";
|
|
158
|
-
readonly value: T;
|
|
159
|
-
}
|
|
160
|
-
/**
|
|
161
|
-
* Option<T> represents a value that is present or absent.
|
|
162
|
-
* This is a type-safe alternative to null/undefined.
|
|
163
|
-
*
|
|
164
|
-
* @example
|
|
165
|
-
* function findUser(id: string): Option<User> {
|
|
166
|
-
* const user = db.get(id);
|
|
167
|
-
* return user ? Some(user) : None;
|
|
168
|
-
* }
|
|
169
|
-
*/
|
|
170
|
-
export type Option<T> = None | Some<T>;
|
|
171
|
-
/**
|
|
172
|
-
* The singleton None value.
|
|
173
|
-
*/
|
|
174
|
-
export declare const None: None;
|
|
175
|
-
/**
|
|
176
|
-
* This function constructs a Some value containing the given value.
|
|
177
|
-
*/
|
|
178
|
-
export declare const Some: <T>(value: T) => Some<T>;
|
|
179
|
-
/**
|
|
180
|
-
* Type guard to check if an Option is None.
|
|
181
|
-
*/
|
|
182
|
-
export declare const isNone: <T>(opt: Option<T>) => opt is None;
|
|
183
|
-
/**
|
|
184
|
-
* Type guard to check if an Option is Some.
|
|
185
|
-
*/
|
|
186
|
-
export declare const isSome: <T>(opt: Option<T>) => opt is Some<T>;
|
|
187
|
-
/**
|
|
188
|
-
* This function extracts the value from a Some, or gives the default value if None.
|
|
189
|
-
*/
|
|
190
|
-
export declare const getOrElse: <T>(opt: Option<T>, defaultValue: T) => T;
|
|
191
|
-
/**
|
|
192
|
-
* This function extracts the value from a Some, or throws an error if None.
|
|
193
|
-
*/
|
|
194
|
-
export declare const unwrap: <T>(opt: Option<T>) => T;
|
|
195
|
-
/**
|
|
196
|
-
* This function maps a function over the value in a Some, or gives None.
|
|
197
|
-
*/
|
|
198
|
-
export declare const mapOption: <T, U>(opt: Option<T>, f: (value: T) => U) => Option<U>;
|
|
199
|
-
/**
|
|
200
|
-
* Chains Option-returning operations.
|
|
201
|
-
*/
|
|
202
|
-
export declare const flatMapOption: <T, U>(opt: Option<T>, f: (value: T) => Option<U>) => Option<U>;
|
|
203
|
-
/**
|
|
204
|
-
* This function converts a nullable value to an Option.
|
|
205
|
-
*/
|
|
206
|
-
export declare const fromNullable: <T>(value: T | null | undefined) => Option<T>;
|
|
207
|
-
/**
|
|
208
|
-
* This function converts an Option to a nullable value.
|
|
209
|
-
*/
|
|
210
|
-
export declare const toNullable: <T>(opt: Option<T>) => T | undefined;
|
|
211
|
-
/**
|
|
212
|
-
* This type represents a successful result containing a value.
|
|
213
|
-
*/
|
|
214
|
-
export interface Ok<T> {
|
|
215
|
-
readonly _tag: "Ok";
|
|
216
|
-
readonly value: T;
|
|
217
|
-
/** This method calls the `Ok` case with the value. */
|
|
218
|
-
match<U>(cases: {
|
|
219
|
-
Ok: (value: T) => U;
|
|
220
|
-
Err: (error: never) => U;
|
|
221
|
-
}): U;
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* This type represents a failed result containing an error.
|
|
225
|
-
*/
|
|
226
|
-
export interface Err<E> {
|
|
227
|
-
readonly _tag: "Err";
|
|
228
|
-
readonly error: E;
|
|
229
|
-
/** This method calls the `Err` case with the error. */
|
|
230
|
-
match<U>(cases: {
|
|
231
|
-
Ok: (value: never) => U;
|
|
232
|
-
Err: (error: E) => U;
|
|
233
|
-
}): U;
|
|
234
|
-
}
|
|
235
|
-
/**
|
|
236
|
-
* Result<T, E> represents the result of an operation that can fail.
|
|
237
|
-
* It contains either a success value (Ok) or an error value (Err).
|
|
238
|
-
*
|
|
239
|
-
* @example
|
|
240
|
-
* function divide(a: number, b: number): Result<number, string> {
|
|
241
|
-
* if (b === 0) return Err("Division by zero");
|
|
242
|
-
* return Ok(a / b);
|
|
243
|
-
* }
|
|
244
|
-
*/
|
|
245
|
-
export type Result<T, E> = Ok<T> | Err<E>;
|
|
246
|
-
/**
|
|
247
|
-
* This function constructs an Ok result containing the given value.
|
|
248
|
-
*/
|
|
249
|
-
export declare const Ok: <T>(value: T) => Ok<T>;
|
|
250
|
-
/**
|
|
251
|
-
* This function constructs an Err result containing the given error.
|
|
252
|
-
*/
|
|
253
|
-
export declare const Err: <E>(error: E) => Err<E>;
|
|
254
|
-
/**
|
|
255
|
-
* Type guard to check if a Result is Ok.
|
|
256
|
-
*/
|
|
257
|
-
export declare const isOk: <T, E>(result: Result<T, E>) => result is Ok<T>;
|
|
258
|
-
/**
|
|
259
|
-
* Type guard to check if a Result is Err.
|
|
260
|
-
*/
|
|
261
|
-
export declare const isErr: <T, E>(result: Result<T, E>) => result is Err<E>;
|
|
262
|
-
/**
|
|
263
|
-
* This function extracts the value from an Ok, or gives the default value if Err.
|
|
264
|
-
*/
|
|
265
|
-
export declare const getOrElseResult: <T, E>(result: Result<T, E>, defaultValue: T) => T;
|
|
266
|
-
/**
|
|
267
|
-
* This function extracts the value from an Ok, or throws the error if Err.
|
|
268
|
-
*/
|
|
269
|
-
export declare const unwrapResult: <T, E>(result: Result<T, E>) => T;
|
|
270
|
-
/**
|
|
271
|
-
* This function maps a function over the value in an Ok, or gives the Err unchanged.
|
|
272
|
-
*/
|
|
273
|
-
export declare const mapResult: <T, U, E>(result: Result<T, E>, f: (value: T) => U) => Result<U, E>;
|
|
274
|
-
/**
|
|
275
|
-
* This function maps a function over the error in an Err, or gives the Ok unchanged.
|
|
276
|
-
*/
|
|
277
|
-
export declare const mapError: <T, E, F>(result: Result<T, E>, f: (error: E) => F) => Result<T, F>;
|
|
278
|
-
/**
|
|
279
|
-
* Chains Result-returning operations.
|
|
280
|
-
*/
|
|
281
|
-
export declare const flatMapResult: <T, U, E>(result: Result<T, E>, f: (value: T) => Result<U, E>) => Result<U, E>;
|
|
282
|
-
/**
|
|
283
|
-
* This function converts a throwing function into a Result-returning function.
|
|
284
|
-
*/
|
|
285
|
-
export declare const tryCatch: <T, E = unknown>(fn: () => T, onError?: (error: unknown) => E) => Result<T, E>;
|
|
286
|
-
/**
|
|
287
|
-
* This function converts an async throwing function into a Result-returning async function.
|
|
288
|
-
*/
|
|
289
|
-
export declare const tryCatchAsync: <T, E = unknown>(fn: () => Promise<T>, onError?: (error: unknown) => E) => Promise<Result<T, E>>;
|
|
290
|
-
/**
|
|
291
|
-
* Async variant of Option<T>.
|
|
292
|
-
*/
|
|
293
|
-
export type AsyncOption<T> = Promise<Option<T>>;
|
|
294
|
-
/**
|
|
295
|
-
* Async variant of Result<T, E>.
|
|
296
|
-
*/
|
|
297
|
-
export type AsyncResult<T, E> = Promise<Result<T, E>>;
|
|
298
|
-
/**
|
|
299
|
-
* This function maps a function over an async Option.
|
|
300
|
-
*/
|
|
301
|
-
export declare const mapAsyncOption: <T, U>(opt: AsyncOption<T>, f: (value: T) => U | Promise<U>) => AsyncOption<U>;
|
|
302
|
-
/**
|
|
303
|
-
* This function maps a function over an async Result.
|
|
304
|
-
*/
|
|
305
|
-
export declare const mapAsyncResult: <T, U, E>(result: AsyncResult<T, E>, f: (value: T) => U | Promise<U>) => AsyncResult<U, E>;
|
|
306
|
-
/**
|
|
307
|
-
* This function converts an Option to a Result.
|
|
308
|
-
* None becomes Err with the given error.
|
|
309
|
-
*/
|
|
310
|
-
export declare const optionToResult: <T, E>(opt: Option<T>, error: E) => Result<T, E>;
|
|
311
|
-
/**
|
|
312
|
-
* This function converts a Result to an Option.
|
|
313
|
-
* Err becomes None, discarding the error.
|
|
314
|
-
*/
|
|
315
|
-
export declare const resultToOption: <T, E>(result: Result<T, E>) => Option<T>;
|
|
316
|
-
/**
|
|
317
|
-
* This function combines multiple Options into an Option of an array.
|
|
318
|
-
* This function gives None if any input is None.
|
|
319
|
-
*/
|
|
320
|
-
export declare const sequence: <T>(opts: Option<T>[]) => Option<T[]>;
|
|
321
|
-
/**
|
|
322
|
-
* This function combines multiple Results into a Result of an array.
|
|
323
|
-
* This function gives the first Err encountered, or Ok with all values.
|
|
324
|
-
*/
|
|
325
|
-
export declare const sequenceResults: <T, E>(results: Result<T, E>[]) => Result<T[], E>;
|
|
326
142
|
/**
|
|
327
143
|
* Policy types for configurable collection behaviors.
|
|
328
144
|
*
|
|
@@ -2418,6 +2234,8 @@ export declare class HashMap<K, V> implements MapLike<K, V> {
|
|
|
2418
2234
|
get(key: K): V;
|
|
2419
2235
|
getOrUndefined(key: K): V | undefined;
|
|
2420
2236
|
getOrDefault(key: K, defaultValue: V): V;
|
|
2237
|
+
/** This method finds the node of a key, or gives `null`. */
|
|
2238
|
+
private findNode;
|
|
2421
2239
|
containsValue(value: V): boolean;
|
|
2422
2240
|
set(key: K, value: V): V | undefined;
|
|
2423
2241
|
setIfAbsent(key: K, value: V): V;
|
|
@@ -3382,9 +3200,9 @@ export declare const unmodifiableCollection: typeof readonlyCollection;
|
|
|
3382
3200
|
*/
|
|
3383
3201
|
export interface SafeListOperations<T> {
|
|
3384
3202
|
/**
|
|
3385
|
-
* Get element at index,
|
|
3203
|
+
* Get element at index, as an optional.
|
|
3386
3204
|
*/
|
|
3387
|
-
get(index: number):
|
|
3205
|
+
get(index: number): Optional<T>;
|
|
3388
3206
|
/**
|
|
3389
3207
|
* Set element at index, giving Result with old value or error.
|
|
3390
3208
|
*/
|
|
@@ -3394,72 +3212,72 @@ export interface SafeListOperations<T> {
|
|
|
3394
3212
|
*/
|
|
3395
3213
|
removeAt(index: number): Result<T, string>;
|
|
3396
3214
|
/**
|
|
3397
|
-
* Get first element as
|
|
3215
|
+
* Get first element as an optional.
|
|
3398
3216
|
*/
|
|
3399
|
-
first():
|
|
3217
|
+
first(): Optional<T>;
|
|
3400
3218
|
/**
|
|
3401
|
-
* Get last element as
|
|
3219
|
+
* Get last element as an optional.
|
|
3402
3220
|
*/
|
|
3403
|
-
last():
|
|
3221
|
+
last(): Optional<T>;
|
|
3404
3222
|
/**
|
|
3405
|
-
* Pop element,
|
|
3223
|
+
* Pop element, as an optional.
|
|
3406
3224
|
*/
|
|
3407
|
-
pop():
|
|
3225
|
+
pop(): Optional<T>;
|
|
3408
3226
|
/**
|
|
3409
|
-
* Shift element,
|
|
3227
|
+
* Shift element, as an optional.
|
|
3410
3228
|
*/
|
|
3411
|
-
shift():
|
|
3229
|
+
shift(): Optional<T>;
|
|
3412
3230
|
}
|
|
3413
3231
|
/**
|
|
3414
3232
|
* Safe operations for Queue.
|
|
3415
3233
|
*/
|
|
3416
3234
|
export interface SafeQueueOperations<T> {
|
|
3417
3235
|
/**
|
|
3418
|
-
* Peek at head element as
|
|
3236
|
+
* Peek at head element as an optional.
|
|
3419
3237
|
*/
|
|
3420
|
-
peek():
|
|
3238
|
+
peek(): Optional<T>;
|
|
3421
3239
|
/**
|
|
3422
|
-
* Poll element as
|
|
3240
|
+
* Poll element as an optional.
|
|
3423
3241
|
*/
|
|
3424
|
-
poll():
|
|
3242
|
+
poll(): Optional<T>;
|
|
3425
3243
|
/**
|
|
3426
|
-
* Dequeue element as
|
|
3244
|
+
* Dequeue element as an optional.
|
|
3427
3245
|
*/
|
|
3428
|
-
dequeue():
|
|
3246
|
+
dequeue(): Optional<T>;
|
|
3429
3247
|
}
|
|
3430
3248
|
/**
|
|
3431
3249
|
* Safe operations for Deque.
|
|
3432
3250
|
*/
|
|
3433
3251
|
export interface SafeDequeOperations<T> extends SafeQueueOperations<T> {
|
|
3434
3252
|
/**
|
|
3435
|
-
* Peek at first element as
|
|
3253
|
+
* Peek at first element as an optional.
|
|
3436
3254
|
*/
|
|
3437
|
-
peekFirst():
|
|
3255
|
+
peekFirst(): Optional<T>;
|
|
3438
3256
|
/**
|
|
3439
|
-
* Peek at last element as
|
|
3257
|
+
* Peek at last element as an optional.
|
|
3440
3258
|
*/
|
|
3441
|
-
peekLast():
|
|
3259
|
+
peekLast(): Optional<T>;
|
|
3442
3260
|
/**
|
|
3443
|
-
* Poll first element as
|
|
3261
|
+
* Poll first element as an optional.
|
|
3444
3262
|
*/
|
|
3445
|
-
pollFirst():
|
|
3263
|
+
pollFirst(): Optional<T>;
|
|
3446
3264
|
/**
|
|
3447
|
-
* Poll last element as
|
|
3265
|
+
* Poll last element as an optional.
|
|
3448
3266
|
*/
|
|
3449
|
-
pollLast():
|
|
3267
|
+
pollLast(): Optional<T>;
|
|
3450
3268
|
/**
|
|
3451
|
-
* Pop element as
|
|
3269
|
+
* Pop element as an optional.
|
|
3452
3270
|
*/
|
|
3453
|
-
pop():
|
|
3271
|
+
pop(): Optional<T>;
|
|
3454
3272
|
}
|
|
3455
3273
|
/**
|
|
3456
3274
|
* Safe operations for Map.
|
|
3457
3275
|
*/
|
|
3458
3276
|
export interface SafeMapOperations<K, V> {
|
|
3459
3277
|
/**
|
|
3460
|
-
* Get value for key as
|
|
3278
|
+
* Get value for key as an optional.
|
|
3461
3279
|
*/
|
|
3462
|
-
get(key: K):
|
|
3280
|
+
get(key: K): Optional<V>;
|
|
3463
3281
|
/**
|
|
3464
3282
|
* Set value for key, giving Result with old value or success.
|
|
3465
3283
|
*/
|
|
@@ -3472,7 +3290,7 @@ export interface SafeMapOperations<K, V> {
|
|
|
3472
3290
|
/**
|
|
3473
3291
|
* This function makes a safe List middleware.
|
|
3474
3292
|
*
|
|
3475
|
-
* This function exposes a `safe` property with
|
|
3293
|
+
* This function exposes a `safe` property with Optional/Result-based operations.
|
|
3476
3294
|
*/
|
|
3477
3295
|
export declare function safeList<T>(): Middleware<List<T>, List<T> & {
|
|
3478
3296
|
safe: SafeListOperations<T>;
|