just-kit 0.8.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/just-kit.js +9 -0
- package/just-next.js +95 -0
- package/just-pool.js +94 -0
- package/just-prompt.js +53 -0
- package/package.json +27 -0
- package/test.js +22 -0
package/just-kit.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* just-kit – small collection of lightweight JavaScript utilities
|
|
3
|
+
*
|
|
4
|
+
* @module just-kit
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export { default as Next } from './just-next.js';
|
|
8
|
+
export { default as JustPool } from './just-pool.js';
|
|
9
|
+
export { default as Prompt } from './just-prompt.js';
|
package/just-next.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NextUp - Simple sequential or random cycling through a list of items
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const MODE_SEQUENTIAL = 'sequential';
|
|
6
|
+
const MODE_RANDOM = 'random';
|
|
7
|
+
|
|
8
|
+
export default class Next {
|
|
9
|
+
#items = [];
|
|
10
|
+
#mode = MODE_SEQUENTIAL;
|
|
11
|
+
#index = 0;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @param {any[]} [items=[]] Initial items
|
|
15
|
+
* @param {'sequential'|'random'} [mode='sequential']
|
|
16
|
+
*/
|
|
17
|
+
constructor(items = [], mode = MODE_SEQUENTIAL) {
|
|
18
|
+
this.setItems(items);
|
|
19
|
+
this.setMode(mode);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/** Replace all items and reset position */
|
|
23
|
+
setItems(items) {
|
|
24
|
+
if (!Array.isArray(items)) throw new Error('Items must be an array');
|
|
25
|
+
this.#items = [...items];
|
|
26
|
+
this.#index = 0;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/** Add one or more items */
|
|
30
|
+
add(...items) {
|
|
31
|
+
this.#items.push(...items);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** Set retrieval mode */
|
|
35
|
+
setMode(mode) {
|
|
36
|
+
if (![MODE_SEQUENTIAL, MODE_RANDOM].includes(mode)) {
|
|
37
|
+
throw new Error("Mode must be 'sequential' or 'random'");
|
|
38
|
+
}
|
|
39
|
+
this.#mode = mode;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** Get current mode */
|
|
43
|
+
get mode() {
|
|
44
|
+
return this.#mode;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Get current number of items */
|
|
48
|
+
get length() {
|
|
49
|
+
return this.#items.length;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Reset position to beginning (affects sequential mode only) */
|
|
53
|
+
reset() {
|
|
54
|
+
this.#index = 0;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Get next item according to current mode */
|
|
58
|
+
next() {
|
|
59
|
+
if (this.#items.length === 0) return undefined;
|
|
60
|
+
|
|
61
|
+
if (this.#mode === MODE_RANDOM) {
|
|
62
|
+
const i = Math.floor(Math.random() * this.#items.length);
|
|
63
|
+
return this.#items[i];
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// sequential
|
|
67
|
+
const item = this.#items[this.#index];
|
|
68
|
+
this.#index = (this.#index + 1) % this.#items.length;
|
|
69
|
+
return item;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Preview next item without advancing position */
|
|
73
|
+
peek() {
|
|
74
|
+
if (this.#items.length === 0) return undefined;
|
|
75
|
+
|
|
76
|
+
if (this.#mode === MODE_RANDOM) {
|
|
77
|
+
const i = Math.floor(Math.random() * this.#items.length);
|
|
78
|
+
return this.#items[i];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return this.#items[this.#index];
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** Get a shallow copy of all items */
|
|
85
|
+
getAll() {
|
|
86
|
+
return [...this.#items];
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** Remove all items */
|
|
90
|
+
clear() {
|
|
91
|
+
this.#items = [];
|
|
92
|
+
this.#index = 0;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
package/just-pool.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JustPool – lazy instance creator & holder
|
|
3
|
+
* Creates objects only when first requested via .get(key)
|
|
4
|
+
* Reuses the same instance on repeated .get() calls with same key
|
|
5
|
+
*/
|
|
6
|
+
export default class JustPool {
|
|
7
|
+
/**
|
|
8
|
+
* @param {function(key: any): T} factory - called to create new instance when needed
|
|
9
|
+
*/
|
|
10
|
+
constructor(factory) {
|
|
11
|
+
if (typeof factory !== 'function') {
|
|
12
|
+
throw new TypeError('Factory must be a function');
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
this.factory = factory;
|
|
16
|
+
this.cache = Object.create(null);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Get (or lazily create) the instance for given key
|
|
21
|
+
* @param {any} key
|
|
22
|
+
* @returns {T}
|
|
23
|
+
*/
|
|
24
|
+
get(key) {
|
|
25
|
+
if (key in this.cache) {
|
|
26
|
+
return this.cache[key];
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const instance = this.factory(key);
|
|
30
|
+
this.cache[key] = instance;
|
|
31
|
+
return instance;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Check if an instance already exists for this key
|
|
36
|
+
*/
|
|
37
|
+
has(key) {
|
|
38
|
+
return key in this.cache;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Remove instance for given key
|
|
43
|
+
* @returns {boolean} true if something was removed
|
|
44
|
+
*/
|
|
45
|
+
delete(key) {
|
|
46
|
+
if (key in this.cache) {
|
|
47
|
+
delete this.cache[key];
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Clear all cached instances
|
|
55
|
+
*/
|
|
56
|
+
clear() {
|
|
57
|
+
this.cache = Object.create(null);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Approximate number of cached items
|
|
62
|
+
*/
|
|
63
|
+
size() {
|
|
64
|
+
return Object.keys(this.cache).length;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Get all currently used keys (only string/symbol keys are enumerated)
|
|
69
|
+
*/
|
|
70
|
+
keys() {
|
|
71
|
+
return Object.keys(this.cache);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Get all cached values
|
|
76
|
+
*/
|
|
77
|
+
values() {
|
|
78
|
+
return Object.values(this.cache);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Iterate over all cached entries
|
|
83
|
+
* @param {(value: T, key: any) => void} callback
|
|
84
|
+
*/
|
|
85
|
+
forEach(callback) {
|
|
86
|
+
for (const key in this.cache) {
|
|
87
|
+
if (Object.hasOwn(this.cache, key)) {
|
|
88
|
+
callback(this.cache[key], key);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
|
package/just-prompt.js
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import readline from 'readline';
|
|
2
|
+
|
|
3
|
+
export default class Prompt {
|
|
4
|
+
#rl;
|
|
5
|
+
#onexit;
|
|
6
|
+
|
|
7
|
+
constructor(message, targetCommand, work) {
|
|
8
|
+
this.message = message;
|
|
9
|
+
this.targetCommand = targetCommand;
|
|
10
|
+
this.work = work;
|
|
11
|
+
this.#rl = readline.createInterface({
|
|
12
|
+
input: process.stdin,
|
|
13
|
+
output: process.stdout
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
onExit(callback) {
|
|
18
|
+
this.#onexit = callback;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
write(message) {
|
|
22
|
+
process.stdout.write(message);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// Start prompting the user
|
|
26
|
+
start() {
|
|
27
|
+
return new Promise((resolve) => {
|
|
28
|
+
const ask = () => {
|
|
29
|
+
this.#rl.question(this.message, async (input) => {
|
|
30
|
+
const trimmed = input.trim();
|
|
31
|
+
|
|
32
|
+
if (trimmed.toLowerCase() === this.targetCommand.toLowerCase()) {
|
|
33
|
+
this.stop();
|
|
34
|
+
resolve(input);
|
|
35
|
+
} else {
|
|
36
|
+
await this.work(trimmed);
|
|
37
|
+
ask();
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
ask();
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
// Stop the readline interface
|
|
46
|
+
stop() {
|
|
47
|
+
this.#rl.close();
|
|
48
|
+
this.#onexit?.();
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
static app = (message, targetCommand, work) => new Prompt(message, targetCommand, work);
|
|
52
|
+
}
|
|
53
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "just-kit",
|
|
3
|
+
"version": "0.8.0",
|
|
4
|
+
"description": "simple nodejs utility",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"just",
|
|
7
|
+
"just-kit",
|
|
8
|
+
"prompt",
|
|
9
|
+
"next",
|
|
10
|
+
"pool"
|
|
11
|
+
],
|
|
12
|
+
"homepage": "https://github.com/just-node/just-kit#readme",
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/just-node/just-kit/issues"
|
|
15
|
+
},
|
|
16
|
+
"repository": {
|
|
17
|
+
"type": "git",
|
|
18
|
+
"url": "git+https://github.com/just-node/just-kit.git"
|
|
19
|
+
},
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"author": "littlejustnode",
|
|
22
|
+
"type": "module",
|
|
23
|
+
"main": "just-kit.js",
|
|
24
|
+
"scripts": {
|
|
25
|
+
"test": "n/a"
|
|
26
|
+
}
|
|
27
|
+
}
|
package/test.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Next, JustPool, Prompt } from './just-kit.js';
|
|
2
|
+
|
|
3
|
+
// 1. Cycling list
|
|
4
|
+
const playlist = new Next(['song1.mp3', 'song2.mp3', 'song3.mp3'], 'random');
|
|
5
|
+
console.log(playlist.next()); // → random song
|
|
6
|
+
console.log(playlist.peek()); // → another (or same) random song
|
|
7
|
+
|
|
8
|
+
// 2. Lazy pool
|
|
9
|
+
const dbPool = new JustPool((dbName) => "hello: "+dbName);
|
|
10
|
+
const db1 = dbPool.get('users'); // created once
|
|
11
|
+
const db2 = dbPool.get('users'); // same instance
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
Prompt.app(
|
|
17
|
+
'Type your message (type "exit" to quit): ',
|
|
18
|
+
'exit',
|
|
19
|
+
async (input) => {
|
|
20
|
+
console.log(`You said: ${input}`);
|
|
21
|
+
}
|
|
22
|
+
).start();
|