flat-pair 1.0.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 kasukabe tsumugi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,153 @@
1
+ # flat-pair
2
+
3
+ [![npm version](https://img.shields.io/npm/v/flat-pair.svg)](https://www.npmjs.com/package/flat-pair) [![npm downloads](http://img.shields.io/npm/dm/flat-pair.svg)](https://npmcharts.com/compare/flat-pair,token-types?start=1200&interval=30)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/59dd6795e61949fb97066ca52e6097ef)](https://www.codacy.com/app/Borewit/flat-pair?utm_source=github.com&utm_medium=referral&utm_content=Borewit/flat-pair&utm_campaign=Badge_Grade)
5
+
6
+ A lightweight TypeScript library for storing key-value pairs using arrays. Provides serializable storage with efficient value-based lookups and zero-cost static methods.
7
+
8
+ For more awesome packages, check out [my homepage💛](https://baendlorel.github.io/?repoType=npm)
9
+
10
+ ## Features
11
+
12
+ - 🔍 **Bidirectional Search**: Find keys by values and values by keys
13
+ - 📦 **Serializable**: Easy JSON serialization/deserialization
14
+ - 🛡️ **Type Safe**: Full TypeScript support with generic types
15
+ - 🎯 **Zero Cost**: Static methods available for minimal overhead
16
+ - ⚡ **Lightweight**: No dependencies, minimal bundle size
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ npm install flat-pair
22
+ # or
23
+ pnpm install flat-pair
24
+ ```
25
+
26
+ ## Quick Start
27
+
28
+ ### Using the FlatPair Class
29
+
30
+ ```typescript
31
+ import { FlatPair } from 'flat-pair';
32
+
33
+ // Create from Map
34
+ const map = new Map([
35
+ ['name', 'John'],
36
+ ['age', 25],
37
+ ]);
38
+ const flatPair = FlatPair.from(map);
39
+
40
+ // Or create directly
41
+ const pair = new FlatPair(['name', 'John', 'age', 25]);
42
+
43
+ // Add key-value pairs (won't add duplicates)
44
+ pair.add('city', 'New York');
45
+ pair.add('name', 'Jane'); // Won't override existing key
46
+
47
+ // Find by key
48
+ console.log(pair.find('name')); // 'John'
49
+
50
+ // Find by value
51
+ console.log(pair.findByValue('New York')); // 'city'
52
+
53
+ // Remove pairs
54
+ pair.remove('age'); // returns true
55
+ pair.remove('nonexistent'); // returns false
56
+
57
+ // Get size
58
+ console.log(pair.size); // 2
59
+
60
+ // Clear all
61
+ pair.clear();
62
+ ```
63
+
64
+ ### Iteration and at()
65
+
66
+ FlatPair implements iterator helpers similar to `Map` and arrays:
67
+
68
+ - `forEach()` - like normal `forEach` from Array
69
+ - `keys()` - returns an iterator over keys
70
+ - `values()` - returns an iterator over values
71
+ - `entries()` - returns an iterator over [key, value] pairs
72
+ - `Symbol.iterator` - the default iterator, same as `entries()`
73
+ - `at(index)` - returns the [key, value] pair at zero-based index or `undefined` if out of range
74
+
75
+ ```typescript
76
+ // keys / values / entries
77
+ console.log([...fp.keys()]); // ['a','b']
78
+ console.log([...fp.values()]); // [1,2]
79
+ console.log([...fp.entries()]); // [['a',1], ['b',2]]
80
+
81
+ // default iterator
82
+ for (const [k, v] of fp) {
83
+ console.log(k, v);
84
+ }
85
+
86
+ // at
87
+ console.log(fp.at(0)); // ['a', 1]
88
+ console.log(fp.at(2)); // undefined
89
+ ```
90
+
91
+ ### forEach
92
+
93
+ `forEach` iterates pairs and follows the callback signature `(value, key, index, arr)` and accepts an optional `thisArg`.
94
+
95
+ ```typescript
96
+ fp.forEach(
97
+ function (value, key, index, arr) {
98
+ console.log(index, key, value, arr === (fp as any).items);
99
+ },
100
+ { myThis: true }
101
+ );
102
+ ```
103
+
104
+ ### Using Static Functions (Zero Cost)
105
+
106
+ ```typescript
107
+ import { add, find, findByValue, remove, size, clear } from 'flat-pair';
108
+
109
+ const items: any[] = [];
110
+
111
+ // Add items
112
+ add(items, 'name', 'John');
113
+ add(items, 'age', 25);
114
+
115
+ // Find operations
116
+ const name = find(items, 'name'); // 'John'
117
+ const ageKey = findByValue(items, 25); // 'age'
118
+
119
+ // Remove and other operations
120
+ remove(items, 'age'); // returns true
121
+ console.log(size(items)); // 1
122
+ clear(items); // empties the array
123
+ ```
124
+
125
+ ### Using FlatPairOperator Class (For fixed type hint)
126
+
127
+ ```typescript
128
+ import { FlatPairOperator } from 'flat-pair';
129
+
130
+ const operator = new FlatPairOperator<string, number>();
131
+ const items: any[] = [];
132
+
133
+ operator.add(items, 'score', 100);
134
+ operator.add(items, 'level', 5);
135
+
136
+ console.log(operator.find(items, 'score')); // 100
137
+ console.log(operator.findByValue(items, 5)); // 'level'
138
+ ```
139
+
140
+ ## Performance
141
+
142
+ FlatPair uses a simple array structure `[key1, value1, key2, value2, ...]` which provides:
143
+
144
+ - **Memory Efficiency**: No object overhead per pair
145
+ - **Serialization**: Direct JSON support
146
+ - **Cache Friendly**: Contiguous memory layout
147
+ - **Predictable**: O(n) operations with low constant factors
148
+
149
+ > Note: For large datasets, consider using a Map or Object for O(1) lookups instead of this package.
150
+
151
+ ## License
152
+
153
+ MIT © Kasukabe Tsumugi
@@ -0,0 +1,50 @@
1
+ declare class FlatPair<K, V> {
2
+ static from<T extends Map<any, any>>(map: T): T extends Map<infer K, infer V> ? FlatPair<K, V> : never;
3
+ private readonly items;
4
+ constructor(items: any[]);
5
+ get size(): number;
6
+ /**
7
+ * Will check if the key already exists, if so then do nothing.
8
+ */
9
+ add(key: K, value: V): this;
10
+ remove(key: K): boolean;
11
+ removeByValue(value: V): boolean;
12
+ find(key: K): V | undefined;
13
+ findByValue(value: V): K | undefined;
14
+ at(index: number): [K, V] | undefined;
15
+ clear(): void;
16
+ forEach(callback: (value: V, key: K, index: number, arr: any[]) => void, thisArg?: any): void;
17
+ keys(): IterableIterator<K>;
18
+ values(): IterableIterator<V>;
19
+ entries(): IterableIterator<[K, V]>;
20
+ [Symbol.iterator](): IterableIterator<[K, V]>;
21
+ }
22
+
23
+ /**
24
+ * Creates an static operator
25
+ */
26
+ declare class FlatPairOperator<K, V> {
27
+ add(items: any[], key: K, value: V): void;
28
+ remove(items: any[], key: K): boolean;
29
+ find(items: any[], key: K): V | undefined;
30
+ findByValue(items: any[], value: V): K | undefined;
31
+ removeByValue(items: any[], value: V): boolean;
32
+ forEach(items: any[], callback: (value: V, key: K, index: number, arr: any[]) => void, thisArg?: any): void;
33
+ at(items: any[], index: number): [K, V] | undefined;
34
+ keys(items: any[]): IterableIterator<K>;
35
+ values(items: any[]): IterableIterator<V>;
36
+ entries(items: any[]): IterableIterator<[K, V]>;
37
+ clear(items: any[]): void;
38
+ }
39
+
40
+ declare function add<K, V>(items: any[], key: K, value: V): void;
41
+ declare function size(items: any[]): number;
42
+ declare function find<K, V>(items: any[], key: K): V | undefined;
43
+ declare function findByValue<K, V>(items: any[], value: V): K | undefined;
44
+ declare function remove<K>(items: any[], key: K): boolean;
45
+ declare function removeByValue<K, V>(items: any[], value: V): boolean;
46
+ declare function forEach<K, V>(items: any[], callback: (value: V, key: K, index: number, arr: any[]) => void, thisArg?: any): void;
47
+ declare function at<K, V>(items: any[], index: number): [K, V] | undefined;
48
+ declare function clear(items: any[]): void;
49
+
50
+ export { FlatPair, FlatPairOperator, add, at, clear, find, findByValue, forEach, remove, removeByValue, size };
package/dist/index.mjs ADDED
@@ -0,0 +1 @@
1
+ function t(t,r,e){for(let e=0;e<t.length;e+=2)if(t[e]===r)return;t.push(r,e)}function r(t){if(t.length%2!=0)throw new Error("Invalid items length, must be even number");return t.length/2}function e(t,r){for(let e=0;e<t.length;e+=2)if(t[e]===r)return t[e+1]}function n(t,r){for(let e=1;e<t.length;e+=2)if(t[e]===r)return t[e-1]}function i(t,r){for(let e=0;e<t.length;e+=2)if(t[e]===r)return t.splice(e,2),!0;return!1}function u(t,r){for(let e=1;e<t.length;e+=2)if(t[e]===r)return t.splice(e-1,2),!0;return!1}function o(t,r,e){let n=0;for(let i=0;i<t.length;i+=2)r.call(e,t[i+1],t[i],n,t),n++}function s(t,r){if(r<0)return;const e=2*r;return e+1>=t.length?void 0:[t[e],t[e+1]]}function f(t){t.length=0}class l{static from(t){if("[object Map]"!==Object.prototype.toString.call(t))throw new TypeError("[FlatPair: __func__] Argument must be a Map");const r=[];return t.forEach((t,e)=>r.push(e,t)),new l(r)}items=[];constructor(t){if(t.length%2!=0)throw new TypeError("FlatPair items length must be even");this.items=t}get size(){return this.items.length/2}add(r,e){return t(this.items,r,e),this}remove(t){return i(this.items,t)}removeByValue(t){return u(this.items,t)}find(t){return e(this.items,t)}findByValue(t){return n(this.items,t)}at(t){return s(this.items,t)}clear(){this.items.length=0}forEach(t,r){o(this.items,t,r)}*keys(){for(let t=0;t<this.items.length;t+=2)yield this.items[t]}*values(){for(let t=1;t<this.items.length;t+=2)yield this.items[t]}*entries(){for(let t=0;t<this.items.length;t+=2)yield[this.items[t],this.items[t+1]]}[Symbol.iterator](){return this.entries()}}class h{add(r,e,n){t(r,e,n)}remove(t,r){return i(t,r)}find(t,r){return e(t,r)}findByValue(t,r){return n(t,r)}removeByValue(t,r){return u(t,r)}forEach(t,r,e){return o(t,r,e)}at(t,r){return s(t,r)}*keys(t){for(let r=0;r<t.length;r+=2)yield t[r]}*values(t){for(let r=1;r<t.length;r+=2)yield t[r]}*entries(t){for(let r=0;r<t.length;r+=2)yield[t[r],t[r+1]]}clear(t){t.length=0}}export{l as FlatPair,h as FlatPairOperator,t as add,s as at,f as clear,e as find,n as findByValue,o as forEach,i as remove,u as removeByValue,r as size};
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "flat-pair",
3
+ "version": "1.0.0",
4
+ "author": {
5
+ "name": "Kasukabe Tsumugi",
6
+ "email": "futami16237@gmail.com"
7
+ },
8
+ "purpose": "npm",
9
+ "description": "Using array to save pairs. Serializable and easier to find, locate by value. Provide static methods, use it at 0 cost!",
10
+ "description_zh": "用数组来保存键值对。可序列化且更容易通过值查找、定位。提供静态方法,0成本使用!",
11
+ "type": "module",
12
+ "module": "./dist/index.mjs",
13
+ "types": "./dist/index.d.ts",
14
+ "exports": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.mjs",
17
+ "default": "./dist/index.mjs"
18
+ },
19
+ "files": [
20
+ "dist"
21
+ ],
22
+ "homepage": "https://github.com/baendlorel/flat-pair#readme",
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/baendlorel/flat-pair"
26
+ },
27
+ "keywords": [
28
+ "typescript",
29
+ "javascript"
30
+ ],
31
+ "scripts": {
32
+ "test": "clear & vitest",
33
+ "lint": "oxlint .",
34
+ "cover": "clear & vitest --coverage",
35
+ "build": "node ./.scripts/rollup.mjs"
36
+ },
37
+ "license": "MIT",
38
+ "devDependencies": {
39
+ "@rollup/plugin-alias": "^5.1.1",
40
+ "@rollup/plugin-commonjs": "^28.0.6",
41
+ "@rollup/plugin-node-resolve": "^16.0.1",
42
+ "@rollup/plugin-replace": "^6.0.2",
43
+ "@rollup/plugin-terser": "^0.4.4",
44
+ "@rollup/plugin-typescript": "^12.1.4",
45
+ "@types/node": "^24.6.2",
46
+ "@vitest/coverage-v8": "^3.2.4",
47
+ "oxlint": "^1.19.0",
48
+ "prettier": "^3.6.2",
49
+ "rimraf": "^6.0.1",
50
+ "rollup": "^4.52.4",
51
+ "rollup-plugin-dts": "^6.2.3",
52
+ "rollup-plugin-func-macro": "^1.1.0",
53
+ "tslib": "^2.8.1",
54
+ "typescript": "^5.9.3",
55
+ "vitest": "^3.2.4"
56
+ }
57
+ }