@wizhut_tech/wizjs 0.1.4 → 0.1.5

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/CLAUDE.md ADDED
@@ -0,0 +1,54 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## What this is
6
+
7
+ `@wizhut_tech/wizjs` is a small, curated JavaScript utility library — "simple but useful hacks for everyday programming," explicitly *not* trying to be lodash. Helpers are grouped into top-level namespaces (`io`, `lang`, `math`) with focused sub-areas under each. It is plain JavaScript (no TypeScript), CommonJS (no `type: "module"`, no build step), and ships its source directly to npm. It pulls in no runtime dependencies; the only third-party use is Node's built-in `fs` in `io/files`, so anything outside that namespace is runtime-agnostic.
8
+
9
+ ## Commands
10
+
11
+ ```sh
12
+ npm install # install devDependencies (only `tap`)
13
+ npm test # full suite — runs `tap run` over __tests__/
14
+ npx tap __tests__/lang_arrays.test.js # run a SINGLE test file
15
+ ```
16
+
17
+ There is **no build, lint, or typecheck step** — `test` is the only npm script. The test runner is [`tap`](https://node-tap.org) (v21). Tests live in `__tests__/`, one file per namespace sub-area, named `<namespace>_<area>.test.js` (e.g. `lang_arrays.test.js`, `math_numbers.test.js`).
18
+
19
+ Publishing is plain npm (`npm publish`) to the scoped package `@wizhut_tech/wizjs`. There is no `files` allowlist or `.npmignore`, so the published tarball includes `index.js` + `src/`. Releases are cut by bumping `version` in `package.json` (recent history shows dedicated `version => x.y.z` commits). The repo declares the MIT license in `package.json` but currently has **no LICENSE file**.
20
+
21
+ ## Architecture
22
+
23
+ The single entry point is `index.js`. It `require`s each leaf module from `src/` and composes them into one nested object — the entire public API surface:
24
+
25
+ ```
26
+ io.files → src/io/files.js (loadFully)
27
+ lang.arrays → src/lang/arrays.js (compact, accumulate, Operator)
28
+ lang.singleton → src/lang/singleton.js (singleton, getInstance)
29
+ lang.flow → src/lang/flow.js (if_exception)
30
+ lang.checks → src/lang/checks.js (isNil, isArray, isObject, isString, isNumber)
31
+ lang.functools → src/lang/functools.js (reflexive)
32
+ lang.itertools → src/lang/itertools.js (count, repeat)
33
+ math.numbers → src/math/numbers.js (toInteger)
34
+ exceptions → src/internal/exceptions.js (BadlyInitializedError)
35
+ ```
36
+
37
+ Each leaf module is a flat `module.exports = { ... }` of functions (plus the occasional class, e.g. `Operator`). The namespace objects in `index.js` are just references to those `module.exports`, so whatever a leaf exports is reachable both as `wizjs.lang.arrays.<name>` and via destructuring (`const { lang: { arrays: { compact } } } = require('@wizhut_tech/wizjs')`).
38
+
39
+ Directory layout mirrors the namespace path exactly: `src/<top-namespace>/<area>.js`. `src/internal/` holds non-public building blocks (currently just `exceptions.js`); its contents are surfaced selectively — `index.js` re-exports `BadlyInitializedError` under the top-level `exceptions` key rather than mounting the whole module.
40
+
41
+ Where a helper belongs:
42
+ - I/O / filesystem / external resources → `src/io/`
43
+ - General language utilities → `src/lang/` (`checks` = type/predicate tests, `arrays` = array ops, `flow` = control-flow wrappers, `functools` = function helpers, `itertools` = lazy generators, `singleton` = the singleton hack)
44
+ - Numeric helpers → `src/math/`
45
+ - Shared internals not meant as public API → `src/internal/`
46
+
47
+ Cross-module reuse is direct relative `require` (e.g. `arrays.js` and `numbers.js` both import `isNil` from `lang/checks.js`; `itertools.js` imports `toInteger` from `math/numbers.js`).
48
+
49
+ ## Conventions
50
+
51
+ - **Module format:** CommonJS only — `require(...)` / `module.exports`. No ESM, no transpilation.
52
+ - **Naming:** functions are camelCase (`isNil`, `loadFully`, `toInteger`); some predates/control-flow names use snake_case (`if_exception`). Classes are PascalCase (`Operator`, `BadlyInitializedError`). Lazy/iterator helpers in `itertools` are generator functions.
53
+ - **Adding a helper to an existing area:** write the function in the matching `src/<ns>/<area>.js`, add it to that file's `module.exports`, and add cases to the corresponding `__tests__/<ns>_<area>.test.js`. It becomes available automatically since `index.js` references the whole `module.exports`.
54
+ - **Adding a new area or namespace:** create `src/<ns>/<area>.js`, then `require` it in `index.js` and mount it under the right namespace object. Add a `docs/<ns>_<area>.md` page and a matching `__tests__/<ns>_<area>.test.js`. Each namespace sub-area has a doc page under `docs/` linked from `readme.md` (lowercase filename).
@@ -32,5 +32,11 @@ t.test('itertools/repeat', (t) => {
32
32
  t.equal(repeatGenTwo.next().value, 15);
33
33
  t.equal(repeatGenTwo.next().value, 15);
34
34
 
35
+ // negative times is clamped to 0, i.e. behaves like eternal repeat
36
+ const repeatGenThree = repeat(7, -3);
37
+ t.equal(repeatGenThree.next().value, 7);
38
+ t.equal(repeatGenThree.next().value, 7);
39
+ t.equal(repeatGenThree.return().done, true);
40
+
35
41
  t.end();
36
42
  });
@@ -19,5 +19,23 @@ t.test('singleton/simple-tests', async (t) => {
19
19
  singleton('null-wrapper', async () => null);
20
20
  t.equal(await getInstance('null-wrapper'), null);
21
21
 
22
+ t.end();
23
+ });
24
+
25
+
26
+ t.test('singleton/caches-instance', async (t) => {
27
+ // the wrapper must run once; later calls return the cached instance
28
+ let calls = 0;
29
+ singleton('counter-wrapper', async () => {
30
+ calls += 1;
31
+ return { id: calls };
32
+ });
33
+
34
+ const first = await getInstance('counter-wrapper');
35
+ const second = await getInstance('counter-wrapper');
36
+
37
+ t.equal(calls, 1);
38
+ t.equal(first, second);
39
+
22
40
  t.end();
23
41
  });
@@ -10,5 +10,7 @@ t.test('numbers/toInteger', (t) => {
10
10
  t.equal(toInteger('1'), 1);
11
11
  t.equal(toInteger(1), 1);
12
12
  t.equal(toInteger('abcde'), 0);
13
+ // parseInt throws on a Symbol; toInteger must swallow it and return 0
14
+ t.equal(toInteger(Symbol('x')), 0);
13
15
  t.end();
14
16
  });
package/package.json CHANGED
@@ -1,28 +1,28 @@
1
1
  {
2
- "name": "@wizhut_tech/wizjs",
3
- "version": "0.1.4",
4
- "main": "index.js",
5
- "devDependencies": {
6
- "tap": "21.1.0"
2
+ "author": "vassilios.karakoidas@wizhut.tech",
3
+ "bugs": {
4
+ "url": "https://github.com/wizhut/wizjs/issues"
7
5
  },
8
6
  "description": "Simple but useful hacks for everyday javascript programming",
9
- "scripts": {
10
- "test": "tap run"
11
- },
12
- "repository": {
13
- "type": "git",
14
- "url": "git+https://github.com/wizhut/wizjs.git"
7
+ "devDependencies": {
8
+ "tap": "21.7.4"
15
9
  },
10
+ "homepage": "https://github.com/wizhut/wizjs#readme",
16
11
  "keywords": [
17
12
  "javascript",
18
13
  "programming",
19
14
  "library",
20
15
  "utilities"
21
16
  ],
22
- "author": "vassilios.karakoidas@wizhut.tech",
23
17
  "license": "MIT",
24
- "bugs": {
25
- "url": "https://github.com/wizhut/wizjs/issues"
18
+ "main": "index.js",
19
+ "name": "@wizhut_tech/wizjs",
20
+ "repository": {
21
+ "type": "git",
22
+ "url": "git+https://github.com/wizhut/wizjs.git"
23
+ },
24
+ "scripts": {
25
+ "test": "tap run"
26
26
  },
27
- "homepage": "https://github.com/wizhut/wizjs#readme"
27
+ "version": "0.1.5"
28
28
  }