qtools-library-dot-d 1.0.12 → 1.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.
Files changed (75) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +89 -0
  3. package/package.json +9 -3
  4. package/qtools-library-dot-d.js +553 -2
  5. package/libDotD_Working_Example/README.md +0 -234
  6. package/libDotD_Working_Example/demoModules_DotD/demo1.js +0 -46
  7. package/libDotD_Working_Example/demoModules_DotD/demo2.js +0 -48
  8. package/libDotD_Working_Example/index.js +0 -133
  9. package/libDotD_Working_Example/node_modules/.package-lock.json +0 -29
  10. package/libDotD_Working_Example/node_modules/qtools-asynchronous-pipe-plus/README.md +0 -213
  11. package/libDotD_Working_Example/node_modules/qtools-asynchronous-pipe-plus/package.json +0 -20
  12. package/libDotD_Working_Example/node_modules/qtools-asynchronous-pipe-plus/qtools-asynchronous-pipe-plus.js +0 -278
  13. package/libDotD_Working_Example/node_modules/qtools-asynchronous-pipe-plus/test.js +0 -79
  14. package/libDotD_Working_Example/node_modules/qtools-functional-library/README.md +0 -110
  15. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-clone/package.json +0 -11
  16. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-clone/qtools-clone.js +0 -103
  17. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-clone/test.js +0 -78
  18. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-get-by-property/package.json +0 -11
  19. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-get-by-property/qtools-get-by-property.js +0 -73
  20. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-get-by-property/test.js +0 -129
  21. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-includes-regex/package.json +0 -11
  22. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-includes-regex/qtools-includes-regex.js +0 -54
  23. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-includes-regex/test.js +0 -76
  24. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-log-output/package.json +0 -11
  25. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-log-output/qtools-log-output.js +0 -114
  26. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-log-output/test.js +0 -130
  27. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-map-properties/package.json +0 -11
  28. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-map-properties/qtools-map-properties.js +0 -99
  29. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-map-properties/test.js +0 -118
  30. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-merge/package.json +0 -11
  31. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-merge/qtools-merge.js +0 -147
  32. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-merge/test.js +0 -214
  33. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-new-method-template/package.json +0 -11
  34. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-new-method-template/qtools-new-method-template.js +0 -70
  35. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-new-method-template/test.js +0 -66
  36. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-number-iterator/package.json +0 -11
  37. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-number-iterator/qtools-number-iterator.js +0 -137
  38. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-number-iterator/test.js +0 -68
  39. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-number-keys-to-array/package.json +0 -11
  40. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-number-keys-to-array/qtools-number-keys-to-array.js +0 -131
  41. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-number-keys-to-array/test.js +0 -181
  42. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-object-sure-path/package.json +0 -11
  43. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-object-sure-path/qtools-object-sure-path.js +0 -204
  44. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-object-sure-path/test.js +0 -345
  45. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-pass-through/package.json +0 -11
  46. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-pass-through/qtools-pass-through.js +0 -58
  47. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-pass-through/test.js +0 -66
  48. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-pop/package.json +0 -11
  49. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-pop/qtools-pop.js +0 -175
  50. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-pop/test.js +0 -118
  51. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-print-debug/package.json +0 -11
  52. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-print-debug/qtools-print-debug.js +0 -352
  53. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-print-debug/test.js +0 -77
  54. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-select-properties/package.json +0 -11
  55. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-select-properties/qtools-select-properties.js +0 -132
  56. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-select-properties/test.js +0 -156
  57. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-template-replace/README.md +0 -3
  58. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-template-replace/package.json +0 -11
  59. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-template-replace/qtools-template-replace.js +0 -106
  60. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-template-replace/test.js +0 -168
  61. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-to-key-value-array/package.json +0 -11
  62. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-to-key-value-array/qtools-to-key-value-array.js +0 -83
  63. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-to-key-value-array/test.js +0 -68
  64. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-to-string/package.json +0 -11
  65. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-to-string/qtools-to-string.js +0 -84
  66. package/libDotD_Working_Example/node_modules/qtools-functional-library/lib/qtools-to-string/test.js +0 -63
  67. package/libDotD_Working_Example/node_modules/qtools-functional-library/package.json +0 -37
  68. package/libDotD_Working_Example/node_modules/qtools-functional-library/qtFunctionalDemo.js +0 -297
  69. package/libDotD_Working_Example/node_modules/qtools-functional-library/qtools-functional-library.js +0 -271
  70. package/libDotD_Working_Example/node_modules/qtools-functional-library/test.js +0 -47
  71. package/libDotD_Working_Example/node_modules/qtools-library-dot-d/README.md +0 -208
  72. package/libDotD_Working_Example/node_modules/qtools-library-dot-d/package.json +0 -15
  73. package/libDotD_Working_Example/node_modules/qtools-library-dot-d/qtools-library-dot-d.js +0 -239
  74. package/libDotD_Working_Example/package-lock.json +0 -37
  75. package/libDotD_Working_Example/package.json +0 -23
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 TQ White II
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 CHANGED
@@ -227,8 +227,97 @@ The dotD pattern works particularly well in:
227
227
 
228
228
  This pattern is used extensively in the qtools ecosystem for building scalable, maintainable Node.js applications.
229
229
 
230
+ ## Loading from several directories
231
+
232
+ *New in 1.1.0. Opt-in: nothing changes for a library that uses `setLibraryPath`.*
233
+
234
+ A library can load from an ordered list of roots, so that one installation (an *instance*) can add its own modules beside the shared *framework* ones, and replace a framework module only by saying so.
235
+
236
+ ```javascript
237
+ const screenersDotD = qtLibDotD({ libraryName: 'corpusScreeners' });
238
+
239
+ screenersDotD.setInterface({ // optional; checks every element
240
+ describeFunctionName: 'describeCorpusScreener',
241
+ requiredFunctionList: ['screenCorpus'],
242
+ nameFieldName: 'corpusScreenerName',
243
+ versionFieldName: 'corpusScreenerVersion',
244
+ contractVersion: 1,
245
+ });
246
+
247
+ screenersDotD.setForbiddenRequireCheck({ // optional; static scan of instance source
248
+ provenanceList: ['instance'],
249
+ allowedModuleList: require('module').builtinModules,
250
+ });
251
+
252
+ screenersDotD.setLibraryPathList([
253
+ { dirPath: instanceScreenersPath, provenance: 'instance', mayBeAbsent: true },
254
+ { dirPath: frameworkScreenersPath, provenance: 'framework' },
255
+ ]);
256
+
257
+ screenersDotD.loadModules({ passThroughParameters }, (err) => {
258
+ // err names every refusal, one per line; '' when all loaded
259
+ });
260
+ ```
261
+
262
+ ### The rules
263
+
264
+ - **Entries.** `{ dirPath, provenance: 'instance' | 'framework', mayBeAbsent }`. A plain string is a framework root that must exist. `mayBeAbsent` is optional and false when omitted.
265
+ - **Order.** Framework roots load first, then instance roots, whatever order the list gives them in.
266
+ - **Missing roots.** Refused as `PLUGIN_ROOT_NOT_FOUND` unless `mayBeAbsent` is true, in which case the log says `ROOT_ABSENT_ALLOWED`.
267
+ - **What is a module.** A `.js`/`.cjs`/`.mjs` file or a directory (`require()` must resolve it: `package.json` `main` or `index.js`). Dotfiles and other files are skipped and logged as `SKIPPED_NON_MODULE`; in single-path mode they would be "ignoring invalid file" lines.
268
+ - **One name, one element.** A name added a second time is refused as `PLUGIN_NAME_COLLISION`, naming both files, unless an instance element replaces a framework element **and declares it**:
269
+
270
+ ```javascript
271
+ overridesFramework: { replacesVersion: '1', reason: 'why this instance needs its own' }
272
+ ```
273
+
274
+ The declaration lives in the element's describe output when an interface is set, otherwise on the element itself (an object or function property). It needs both fields, or it is refused as `PLUGIN_OVERRIDE_DECLARATION_INVALID`. Two framework elements, or two instance elements, of one name always collide.
275
+ - **Stale overrides warn.** When `replacesVersion` is not strictly equal to the framework element's declared version (`versionFieldName`), the override is accepted and the log says `OVERRIDE_TARGET_CHANGED`. Without an interface there is no framework version to compare, and the log says `OVERRIDE_TARGET_UNVERSIONED`. A declaration with nothing to replace logs `OVERRIDE_TARGET_ABSENT`.
276
+ - **Interface check.** With `setInterface`, all five fields are required (`INTERFACE_SPEC_INCOMPLETE`). Each element must carry the describe function and every required function (`PLUGIN_INTERFACE_INCOMPLETE`), describe itself by the name it was added under (`PLUGIN_NAME_MISMATCH`), and declare the library's `contractVersion` (`PLUGIN_CONTRACT_MISMATCH`).
277
+ - **Load errors are refusals.** A module whose `require()` throws is refused as `PLUGIN_LOAD_FAILED`, naming the file. `loadModules({ passThroughParameters, tolerateLoadErrors: true })` lists it in the exception list instead, still as `PLUGIN_LOAD_FAILED`.
278
+ - **Forbidden requires.** With `setForbiddenRequireCheck`, the source of every module from a listed provenance is scanned before it runs. A refused module is never executed (`PLUGIN_FORBIDDEN_REQUIRE`).
279
+ - **What is allowed:**
280
+ - names in `allowedModuleList` (a `node:` prefix is ignored);
281
+ - relative or absolute paths whose resolved file, judged by its real path after symlinks, stays inside the plugin's own directory. For a single-file module, that is its root.
282
+ - **What is refused:**
283
+ - a path that resolves to a non-module file, such as `require('./payload.txt')`, which CommonJS would run as JavaScript;
284
+ - a path that does not resolve at all;
285
+ - a module whose own real path, or `package.json` `main`, lies outside its directory.
286
+ - **What the scan cannot see.** The scan reads every `.js`/`.cjs`/`.mjs` file in a directory module, recursively (this needs Node 20 or later). It is a regular expression over string-literal `require('…')` and static template calls. It does **not** catch:
287
+ - a require whose name is built at run time: a variable, string concatenation, or a `${}` template;
288
+ - `import()`;
289
+ - `module.createRequire` (`module` is a built-in, so allowed).
290
+
291
+ It also refuses a `require('…')` that appears only in a comment. That is a false refusal, not a missed one.
292
+ - **Why the check exists.** It serves portability (spec R6), not security: it is not a sandbox.
293
+ - **Reserved names.** An element may not take a library API name such as `toString` or `getProvenance`, nor a name `Object.prototype` carries (`constructor`, `hasOwnProperty`, `__proto__`, and the `qt…` methods qtools-functional-library installs there). Elements are properties of the library object itself, so such a name would shadow a method the library relies on: `qtSelectProperties` would break `seal()`. Refused as `PLUGIN_NAME_RESERVED`.
294
+ - **Adding late.** `library.add()` after loading has finished throws `PLUGIN_ADD_OUTSIDE_LOAD`: there is no file to attribute it to and no callback left to report it. A module must register synchronously, while it is being required. A registration from a timer or a promise throws there, uncaught, and stops the process.
295
+ - **Load once.** A second `loadModules` on a path-list library is refused (`LOAD_MODULES_REPEATED`); single-path libraries still simply re-add.
296
+ - **Directory modules need an entry point.** `require(<dir>)` resolves `package.json` `main` or `index.js`. A layout like `screeners.d/<name>/<name>.js` without one of them is `PLUGIN_LOAD_FAILED`.
297
+ - **A loadModules error is fatal.** Refusals are collected, and `loadModules` calls back with all of them. Elements that passed stay loaded, so after an error the library is partly populated. Treat the error as fatal and do not use the library.
298
+ - **Silent modules.** A module that loads but adds nothing is logged as `MODULE_ADDED_NOTHING`.
299
+ - **Not mixable.** One library uses either `setLibraryPath` or `setLibraryPathList` (`LIBRARY_PATH_MODE_CONFLICT`). `setInterface` and `setForbiddenRequireCheck` need a path list (`REQUIRES_PATH_LIST`), and so does the default add: `setCustomAddFunction` with a path list is refused (`CUSTOM_ADD_REQUIRES_SINGLE_PATH`).
300
+ - **Without a callback,** `setLibraryPathList` and `loadModules` throw the refusal string, as `setLibraryPath` throws a bad path.
301
+ - **Sealing.** `seal()` removes the setters, `library` and `logList`, as it always has. For a path-list library it also removes `setLibraryPathList`, `setInterface` and `setForbiddenRequireCheck`. The getters remain.
302
+
303
+ ### Provenance
304
+
305
+ Every element records `{ provenance, filePath, overrides? }`:
306
+
307
+ ```javascript
308
+ screenersDotD.getProvenance('transcriptDetector');
309
+ // { provenance: 'instance', filePath: '…/corpusScreeners.d/transcriptDetector',
310
+ // overrides: { provenance: 'framework', filePath: '…', version: '1', reason: '…' } }
311
+ screenersDotD.getProvenanceList(); // [{ elementName, provenance, filePath, overrides? }, …]
312
+ screenersDotD.getRefusalList(); // [{ refusalCode, elementName, filePath, message }, …]
313
+ ```
314
+
315
+ `toString()` adds the same on each element line, e.g. `transcriptDetector: object [instance: …; overrides framework v1 (…) because …]`. `getProvenance` throws `PROVENANCE_NOT_RECORDED` for a single-path library and `PROVENANCE_UNKNOWN_NAME` for a name it does not have. Warnings (`OVERRIDE_TARGET_…`, `ROOT_ABSENT_ALLOWED`, `SKIPPED_NON_MODULE`, `MODULE_ADDED_NOTHING`) are in `qtdProcessLog()`.
316
+
230
317
  ## HISTORY
231
318
 
319
+ v1.1.0 - setLibraryPathList: framework and instance roots, declared overrides, opt-in interface and forbidden-require checks, provenance, named refusals; Object.prototype names reserved in path-list mode. setLibraryPath unchanged. Tests added (npm test); test/ not shipped in the package.
320
+ v1.13 - License changed to MIT (was ISC). No code changes.
232
321
  v1.12 - clarified error message "Ignoring invalid file".
233
322
  v1.10 - there was a reason I did not return the exception list. Undone.
234
323
  v1.09 - fixed broken error handling when library file path is bad; added demonstration application
package/package.json CHANGED
@@ -1,13 +1,19 @@
1
1
  {
2
2
  "name": "qtools-library-dot-d",
3
- "version": "1.0.12",
3
+ "version": "1.1.0",
4
4
  "description": "Scan a directory for JS modules that can execute and addMe() that attaches it to some form of name/value list, eg, a Map() with functions as values or an xPressJS route/endpoint list.",
5
5
  "main": "qtools-library-dot-d.js",
6
+ "files": [
7
+ "qtools-library-dot-d.js",
8
+ "README.md",
9
+ "README2.md",
10
+ "LICENSE"
11
+ ],
6
12
  "scripts": {
7
- "test": "echo \"Error: no test specified\" && exit 1"
13
+ "test": "node --test test/*.test.js"
8
14
  },
9
15
  "author": "TQ White II",
10
- "license": "ISC",
16
+ "license": "MIT",
11
17
  "dependencies": {
12
18
  "qtools-asynchronous-pipe-plus": "^1.0.2",
13
19
  "qtools-functional-library": "^2.0.4"