@cldmv/slothlet 2.11.0 → 3.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/AGENT-USAGE.md +355 -325
- package/README.md +554 -238
- package/dist/lib/builders/api-assignment.mjs +605 -0
- package/dist/lib/builders/api_builder.mjs +1073 -0
- package/dist/lib/builders/builder.mjs +94 -0
- package/dist/lib/builders/modes-processor.mjs +1816 -0
- package/dist/lib/errors.mjs +227 -0
- package/dist/lib/factories/component-base.mjs +96 -0
- package/dist/lib/factories/context.mjs +38 -0
- package/dist/lib/handlers/api-cache-manager.mjs +216 -0
- package/dist/lib/handlers/api-manager.mjs +2364 -0
- package/dist/lib/handlers/context-async.mjs +184 -0
- package/dist/lib/handlers/context-live.mjs +184 -0
- package/dist/lib/handlers/hook-manager.mjs +789 -0
- package/dist/lib/handlers/lifecycle-token.mjs +44 -0
- package/dist/lib/handlers/lifecycle.mjs +131 -0
- package/dist/lib/handlers/materialize-manager.mjs +64 -0
- package/dist/lib/handlers/metadata.mjs +500 -0
- package/dist/lib/handlers/ownership.mjs +338 -0
- package/dist/lib/handlers/unified-wrapper.mjs +3031 -0
- package/dist/lib/helpers/class-instance-wrapper.mjs +125 -0
- package/dist/lib/helpers/config.mjs +343 -0
- package/dist/lib/helpers/eventemitter-context.mjs +365 -0
- package/dist/lib/helpers/hint-detector.mjs +63 -0
- package/dist/lib/helpers/modes-utils.mjs +53 -0
- package/dist/lib/helpers/resolve-from-caller.mjs +119 -116
- package/dist/lib/helpers/sanitize.mjs +247 -168
- package/dist/lib/helpers/utilities.mjs +46 -81
- package/dist/lib/i18n/languages/de-de.json +377 -0
- package/dist/lib/i18n/languages/en-gb.json +377 -0
- package/dist/lib/i18n/languages/en-us.json +377 -0
- package/dist/lib/i18n/languages/es-mx.json +377 -0
- package/dist/lib/i18n/languages/fr-fr.json +377 -0
- package/dist/lib/i18n/languages/hi-in.json +377 -0
- package/dist/lib/i18n/languages/ja-jp.json +377 -0
- package/dist/lib/i18n/languages/ko-kr.json +377 -0
- package/dist/lib/i18n/languages/pt-br.json +377 -0
- package/dist/lib/i18n/languages/ru-ru.json +377 -0
- package/dist/lib/i18n/languages/zh-cn.json +377 -0
- package/dist/lib/i18n/translations.mjs +140 -0
- package/dist/lib/modes/eager.mjs +75 -0
- package/dist/lib/modes/lazy.mjs +97 -0
- package/dist/lib/processors/flatten.mjs +453 -0
- package/dist/lib/processors/loader.mjs +355 -0
- package/dist/lib/processors/type-generator.mjs +291 -0
- package/dist/lib/processors/typescript.mjs +188 -0
- package/dist/lib/runtime/runtime-asynclocalstorage.mjs +80 -522
- package/dist/lib/runtime/runtime-livebindings.mjs +45 -390
- package/dist/lib/runtime/runtime.mjs +39 -159
- package/dist/slothlet.mjs +525 -744
- package/docs/API-RULES.md +338 -486
- package/index.cjs +4 -4
- package/index.mjs +82 -45
- package/package.json +138 -25
- package/types/dist/lib/builders/api-assignment.d.mts +97 -0
- package/types/dist/lib/builders/api-assignment.d.mts.map +1 -0
- package/types/dist/lib/builders/api_builder.d.mts +96 -0
- package/types/dist/lib/builders/api_builder.d.mts.map +1 -0
- package/types/dist/lib/builders/builder.d.mts +60 -0
- package/types/dist/lib/builders/builder.d.mts.map +1 -0
- package/types/dist/lib/builders/modes-processor.d.mts +32 -0
- package/types/dist/lib/builders/modes-processor.d.mts.map +1 -0
- package/types/dist/lib/errors.d.mts +118 -0
- package/types/dist/lib/errors.d.mts.map +1 -0
- package/types/dist/lib/factories/component-base.d.mts +182 -0
- package/types/dist/lib/factories/component-base.d.mts.map +1 -0
- package/types/dist/lib/factories/context.d.mts +26 -0
- package/types/dist/lib/factories/context.d.mts.map +1 -0
- package/types/dist/lib/handlers/api-cache-manager.d.mts +208 -0
- package/types/dist/lib/handlers/api-cache-manager.d.mts.map +1 -0
- package/types/dist/lib/handlers/api-manager.d.mts +392 -0
- package/types/dist/lib/handlers/api-manager.d.mts.map +1 -0
- package/types/dist/lib/handlers/context-async.d.mts +66 -0
- package/types/dist/lib/handlers/context-async.d.mts.map +1 -0
- package/types/dist/lib/handlers/context-live.d.mts +65 -0
- package/types/dist/lib/handlers/context-live.d.mts.map +1 -0
- package/types/dist/lib/handlers/hook-manager.d.mts +199 -0
- package/types/dist/lib/handlers/hook-manager.d.mts.map +1 -0
- package/types/dist/lib/handlers/lifecycle-token.d.mts +49 -0
- package/types/dist/lib/handlers/lifecycle-token.d.mts.map +1 -0
- package/types/dist/lib/handlers/lifecycle.d.mts +90 -0
- package/types/dist/lib/handlers/lifecycle.d.mts.map +1 -0
- package/types/dist/lib/handlers/materialize-manager.d.mts +75 -0
- package/types/dist/lib/handlers/materialize-manager.d.mts.map +1 -0
- package/types/dist/lib/handlers/metadata.d.mts +215 -0
- package/types/dist/lib/handlers/metadata.d.mts.map +1 -0
- package/types/dist/lib/handlers/ownership.d.mts +170 -0
- package/types/dist/lib/handlers/ownership.d.mts.map +1 -0
- package/types/dist/lib/handlers/unified-wrapper.d.mts +250 -0
- package/types/dist/lib/handlers/unified-wrapper.d.mts.map +1 -0
- package/types/dist/lib/helpers/class-instance-wrapper.d.mts +54 -0
- package/types/dist/lib/helpers/class-instance-wrapper.d.mts.map +1 -0
- package/types/dist/lib/helpers/config.d.mts +96 -0
- package/types/dist/lib/helpers/config.d.mts.map +1 -0
- package/types/dist/lib/helpers/eventemitter-context.d.mts +31 -0
- package/types/dist/lib/helpers/eventemitter-context.d.mts.map +1 -0
- package/types/dist/lib/helpers/hint-detector.d.mts +20 -0
- package/types/dist/lib/helpers/hint-detector.d.mts.map +1 -0
- package/types/dist/lib/helpers/modes-utils.d.mts +35 -0
- package/types/dist/lib/helpers/modes-utils.d.mts.map +1 -0
- package/types/dist/lib/helpers/resolve-from-caller.d.mts +29 -145
- package/types/dist/lib/helpers/resolve-from-caller.d.mts.map +1 -1
- package/types/dist/lib/helpers/sanitize.d.mts +95 -94
- package/types/dist/lib/helpers/sanitize.d.mts.map +1 -1
- package/types/dist/lib/helpers/utilities.d.mts +53 -116
- package/types/dist/lib/helpers/utilities.d.mts.map +1 -1
- package/types/dist/lib/i18n/translations.d.mts +39 -0
- package/types/dist/lib/i18n/translations.d.mts.map +1 -0
- package/types/dist/lib/modes/eager.d.mts +36 -0
- package/types/dist/lib/modes/eager.d.mts.map +1 -0
- package/types/dist/lib/modes/lazy.d.mts +49 -0
- package/types/dist/lib/modes/lazy.d.mts.map +1 -0
- package/types/dist/lib/processors/flatten.d.mts +114 -0
- package/types/dist/lib/processors/flatten.d.mts.map +1 -0
- package/types/dist/lib/processors/loader.d.mts +47 -0
- package/types/dist/lib/processors/loader.d.mts.map +1 -0
- package/types/dist/lib/processors/type-generator.d.mts +19 -0
- package/types/dist/lib/processors/type-generator.d.mts.map +1 -0
- package/types/dist/lib/processors/typescript.d.mts +55 -0
- package/types/dist/lib/processors/typescript.d.mts.map +1 -0
- package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts +47 -42
- package/types/dist/lib/runtime/runtime-asynclocalstorage.d.mts.map +1 -1
- package/types/dist/lib/runtime/runtime-livebindings.d.mts +34 -65
- package/types/dist/lib/runtime/runtime-livebindings.d.mts.map +1 -1
- package/types/dist/lib/runtime/runtime.d.mts +39 -9
- package/types/dist/lib/runtime/runtime.d.mts.map +1 -1
- package/types/dist/slothlet.d.mts +184 -111
- package/types/dist/slothlet.d.mts.map +1 -1
- package/types/index.d.mts +1 -3
- package/dist/lib/engine/README.md +0 -21
- package/dist/lib/engine/slothlet_child.mjs +0 -59
- package/dist/lib/engine/slothlet_engine.mjs +0 -372
- package/dist/lib/engine/slothlet_esm.mjs +0 -230
- package/dist/lib/engine/slothlet_helpers.mjs +0 -455
- package/dist/lib/engine/slothlet_worker.mjs +0 -149
- package/dist/lib/helpers/als-eventemitter.mjs +0 -256
- package/dist/lib/helpers/api_builder/add_api.mjs +0 -553
- package/dist/lib/helpers/api_builder/analysis.mjs +0 -532
- package/dist/lib/helpers/api_builder/construction.mjs +0 -495
- package/dist/lib/helpers/api_builder/decisions.mjs +0 -748
- package/dist/lib/helpers/api_builder/metadata.mjs +0 -248
- package/dist/lib/helpers/api_builder.mjs +0 -41
- package/dist/lib/helpers/auto-wrap.mjs +0 -62
- package/dist/lib/helpers/hooks.mjs +0 -389
- package/dist/lib/helpers/instance-manager.mjs +0 -111
- package/dist/lib/helpers/metadata-api.mjs +0 -201
- package/dist/lib/helpers/multidefault.mjs +0 -216
- package/dist/lib/modes/slothlet_eager.mjs +0 -154
- package/dist/lib/modes/slothlet_lazy.mjs +0 -594
- package/docs/API-RULES-CONDITIONS.md +0 -712
- package/types/dist/lib/engine/slothlet_child.d.mts +0 -2
- package/types/dist/lib/engine/slothlet_child.d.mts.map +0 -1
- package/types/dist/lib/engine/slothlet_engine.d.mts +0 -31
- package/types/dist/lib/engine/slothlet_engine.d.mts.map +0 -1
- package/types/dist/lib/engine/slothlet_esm.d.mts +0 -19
- package/types/dist/lib/engine/slothlet_esm.d.mts.map +0 -1
- package/types/dist/lib/engine/slothlet_helpers.d.mts +0 -25
- package/types/dist/lib/engine/slothlet_helpers.d.mts.map +0 -1
- package/types/dist/lib/engine/slothlet_worker.d.mts +0 -2
- package/types/dist/lib/engine/slothlet_worker.d.mts.map +0 -1
- package/types/dist/lib/helpers/als-eventemitter.d.mts +0 -56
- package/types/dist/lib/helpers/als-eventemitter.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/add_api.d.mts +0 -102
- package/types/dist/lib/helpers/api_builder/add_api.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/analysis.d.mts +0 -189
- package/types/dist/lib/helpers/api_builder/analysis.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/construction.d.mts +0 -107
- package/types/dist/lib/helpers/api_builder/construction.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/decisions.d.mts +0 -213
- package/types/dist/lib/helpers/api_builder/decisions.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder/metadata.d.mts +0 -99
- package/types/dist/lib/helpers/api_builder/metadata.d.mts.map +0 -1
- package/types/dist/lib/helpers/api_builder.d.mts +0 -6
- package/types/dist/lib/helpers/api_builder.d.mts.map +0 -1
- package/types/dist/lib/helpers/auto-wrap.d.mts +0 -49
- package/types/dist/lib/helpers/auto-wrap.d.mts.map +0 -1
- package/types/dist/lib/helpers/hooks.d.mts +0 -342
- package/types/dist/lib/helpers/hooks.d.mts.map +0 -1
- package/types/dist/lib/helpers/instance-manager.d.mts +0 -41
- package/types/dist/lib/helpers/instance-manager.d.mts.map +0 -1
- package/types/dist/lib/helpers/metadata-api.d.mts +0 -132
- package/types/dist/lib/helpers/metadata-api.d.mts.map +0 -1
- package/types/dist/lib/helpers/multidefault.d.mts +0 -90
- package/types/dist/lib/helpers/multidefault.d.mts.map +0 -1
- package/types/dist/lib/modes/slothlet_eager.d.mts +0 -65
- package/types/dist/lib/modes/slothlet_eager.d.mts.map +0 -1
- package/types/dist/lib/modes/slothlet_lazy.d.mts +0 -31
- package/types/dist/lib/modes/slothlet_lazy.d.mts.map +0 -1
- package/types/index.d.mts.map +0 -1
|
@@ -18,260 +18,339 @@
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
import { ComponentBase } from "@cldmv/slothlet/factories/component-base";
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
export class Sanitize extends ComponentBase {
|
|
29
|
+
static slothletProperty = "sanitize";
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
#compileGlobPattern(pattern, caseSensitive = true) {
|
|
24
37
|
|
|
25
38
|
if (pattern.startsWith("**") && pattern.endsWith("**") && pattern.length > 4) {
|
|
26
39
|
const innerString = pattern.slice(2, -2);
|
|
27
|
-
|
|
28
40
|
const escapedString = innerString.replace(/[.+^${}()|[\]\\*?]/g, "\\$&");
|
|
29
|
-
|
|
30
|
-
|
|
31
41
|
const flags = caseSensitive ? "" : "i";
|
|
32
42
|
return new RegExp(`(?<=.)${escapedString}(?=.)`, flags);
|
|
33
43
|
}
|
|
34
44
|
|
|
35
45
|
|
|
36
|
-
|
|
37
|
-
let regexPattern = pattern
|
|
46
|
+
const regexPattern = pattern
|
|
38
47
|
.replace(/[.+^${}()|[\]\\]/g, "\\$&")
|
|
39
48
|
.replace(/\*/g, ".*")
|
|
40
49
|
.replace(/\?/g, ".");
|
|
41
50
|
|
|
42
51
|
const flags = caseSensitive ? "" : "i";
|
|
43
52
|
return new RegExp(`^${regexPattern}$`, flags);
|
|
44
|
-
} catch (_) {
|
|
45
|
-
return null;
|
|
46
53
|
}
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
export function sanitizePathName(input, opts = {}) {
|
|
51
|
-
const { lowerFirst = true, preserveAllUpper = false, preserveAllLower = false, rules = {} } = opts;
|
|
52
54
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
|
|
56
|
+
#matchesAnyPattern(input, patterns, caseSensitive = false) {
|
|
57
|
+
for (const pattern of patterns) {
|
|
58
|
+
if (pattern.includes("*") || pattern.includes("?")) {
|
|
59
|
+
const regex = this.#compileGlobPattern(pattern, caseSensitive);
|
|
60
|
+
if (regex && regex.test(input)) return true;
|
|
61
|
+
} else {
|
|
62
|
+
const match = caseSensitive ? input === pattern : input.toLowerCase() === pattern.toLowerCase();
|
|
63
|
+
if (match) return true;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
57
68
|
|
|
58
|
-
|
|
69
|
+
|
|
70
|
+
#extractPatternLiterals(pattern) {
|
|
71
|
+
return pattern.split(/[*?]+/).filter(Boolean);
|
|
72
|
+
}
|
|
59
73
|
|
|
60
74
|
|
|
61
75
|
|
|
62
|
-
|
|
63
76
|
|
|
64
|
-
let parts = s.split(/[^A-Za-z0-9_$]+/).filter(Boolean);
|
|
65
|
-
if (parts.length === 0) return "_";
|
|
66
77
|
|
|
67
78
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (!parts[0]) parts.shift();
|
|
71
|
-
}
|
|
72
|
-
if (parts.length === 0) return "_";
|
|
79
|
+
#applySegmentRules(segment, index, originalString, config) {
|
|
80
|
+
const { preserveAllUpper, preserveAllLower, leaveRules, leaveInsensitiveRules, upperRules, lowerRules } = config;
|
|
73
81
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
82
|
+
|
|
83
|
+
if (this.#matchesAnyPattern(segment, leaveRules, true)) {
|
|
84
|
+
return segment;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
if (this.#matchesAnyPattern(segment, leaveInsensitiveRules, false)) {
|
|
89
|
+
return segment;
|
|
90
|
+
}
|
|
80
91
|
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
if (preserveAllUpper && segment === segment.toUpperCase() && segment !== segment.toLowerCase() && /[A-Z]/.test(segment)) {
|
|
95
|
+
return segment;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
if (preserveAllLower && segment === segment.toLowerCase() && segment !== segment.toUpperCase() && /[a-z]/.test(segment)) {
|
|
101
|
+
return segment;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
for (const pattern of [...upperRules, ...lowerRules]) {
|
|
81
107
|
if (pattern.includes("*") || pattern.includes("?")) {
|
|
82
|
-
const regex =
|
|
83
|
-
if (regex && regex.test(
|
|
108
|
+
const regex = this.#compileGlobPattern(pattern, false);
|
|
109
|
+
if (regex && regex.test(originalString)) {
|
|
84
110
|
|
|
85
|
-
|
|
86
|
-
const
|
|
87
|
-
|
|
88
|
-
for (const literal of literalParts) {
|
|
111
|
+
const literals = this.#extractPatternLiterals(pattern);
|
|
112
|
+
for (const literal of literals) {
|
|
89
113
|
|
|
90
|
-
const cleanLiteral = literal.replace(/[^A-Za-z0-9_$]/g, "");
|
|
91
|
-
if (cleanLiteral) {
|
|
92
|
-
|
|
93
|
-
if (match) {
|
|
94
|
-
return true;
|
|
95
|
-
}
|
|
114
|
+
const cleanLiteral = literal.replace(/[^A-Za-z0-9_$]/g, "").replace(/^_+|_+$/g, "");
|
|
115
|
+
if (cleanLiteral && segment.toLowerCase() === cleanLiteral.toLowerCase()) {
|
|
116
|
+
return upperRules.includes(pattern) ? segment.toUpperCase() : segment.toLowerCase();
|
|
96
117
|
}
|
|
97
118
|
}
|
|
98
119
|
}
|
|
99
120
|
} else {
|
|
100
121
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
return true;
|
|
122
|
+
if (segment.toLowerCase() === pattern.toLowerCase()) {
|
|
123
|
+
return upperRules.includes(pattern) ? segment.toUpperCase() : segment.toLowerCase();
|
|
104
124
|
}
|
|
105
125
|
}
|
|
106
126
|
}
|
|
107
|
-
return false;
|
|
108
|
-
};
|
|
109
127
|
|
|
110
|
-
const applyRule = (seg, index) => {
|
|
111
128
|
|
|
112
|
-
|
|
113
|
-
|
|
129
|
+
let transformed = this.#applyWithinSegmentPatterns(segment, upperRules, lowerRules);
|
|
130
|
+
if (transformed !== segment) {
|
|
131
|
+
return transformed;
|
|
114
132
|
}
|
|
115
133
|
|
|
116
134
|
|
|
117
|
-
if (segmentMatchesPreSplitPattern(seg, leaveInsensitiveRules, false)) {
|
|
118
|
-
return seg;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
135
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
136
|
+
return segment;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
#applyWithinSegmentPatterns(segment, upperRules, lowerRules) {
|
|
141
|
+
let result = segment;
|
|
142
|
+
|
|
143
|
+
const applyBoundaryPattern = (pattern, toUpper) => {
|
|
144
|
+
|
|
145
|
+
if (pattern.startsWith("**") && pattern.endsWith("**") && pattern.length > 4) {
|
|
146
|
+
const innerString = pattern.slice(2, -2);
|
|
147
|
+
const innerRegex = new RegExp(innerString.replace(/[.+^${}()|[\]\\*?]/g, "\\$&"), "gi");
|
|
148
|
+
const matches = [...result.matchAll(innerRegex)];
|
|
149
|
+
|
|
150
|
+
for (const match of matches) {
|
|
151
|
+
const startPos = match.index;
|
|
152
|
+
const endPos = startPos + match[0].length;
|
|
153
|
+
const hasCharBefore = startPos > 0;
|
|
154
|
+
const hasCharAfter = endPos < result.length;
|
|
155
|
+
|
|
156
|
+
if (hasCharBefore && hasCharAfter) {
|
|
157
|
+
const replacement = toUpper ? innerString.toUpperCase() : innerString.toLowerCase();
|
|
158
|
+
result = result.substring(0, startPos) + replacement + result.substring(endPos);
|
|
159
|
+
break;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
else if (pattern.includes("*") && !pattern.startsWith("**")) {
|
|
165
|
+
|
|
166
|
+
const literalParts = pattern.split("*").filter(Boolean);
|
|
167
|
+
for (const literal of literalParts) {
|
|
168
|
+
const literalRegex = new RegExp(literal.replace(/[.+^${}()|[\]\\]/g, "\\$&"), "gi");
|
|
169
|
+
const replacement = toUpper ? literal.toUpperCase() : literal.toLowerCase();
|
|
170
|
+
result = result.replace(literalRegex, replacement);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
|
|
175
|
+
upperRules.forEach((pattern) => applyBoundaryPattern(pattern, true));
|
|
176
|
+
lowerRules.forEach((pattern) => applyBoundaryPattern(pattern, false));
|
|
177
|
+
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
sanitizePropertyName(input, options = {}) {
|
|
187
|
+
const { lowerFirst = true, preserveAllUpper = false, preserveAllLower = false, rules = {} } = options;
|
|
125
188
|
|
|
126
189
|
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
190
|
+
const leaveRules = (rules.leave || []).map((s) => String(s));
|
|
191
|
+
const leaveInsensitiveRules = (rules.leaveInsensitive || []).map((s) => String(s));
|
|
192
|
+
const upperRules = (rules.upper || []).map((s) => String(s));
|
|
193
|
+
const lowerRules = (rules.lower || []).map((s) => String(s));
|
|
194
|
+
|
|
195
|
+
const originalString = String(input).trim();
|
|
130
196
|
|
|
131
197
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
198
|
+
const isAllUpper =
|
|
199
|
+
originalString === originalString.toUpperCase() && originalString !== originalString.toLowerCase() && /[A-Z]/.test(originalString);
|
|
200
|
+
const isAllLower =
|
|
201
|
+
originalString === originalString.toLowerCase() && originalString !== originalString.toUpperCase() && /[a-z]/.test(originalString);
|
|
135
202
|
|
|
203
|
+
if (preserveAllUpper && isAllUpper) {
|
|
204
|
+
return originalString;
|
|
205
|
+
}
|
|
206
|
+
|
|
136
207
|
|
|
137
|
-
if (
|
|
138
|
-
return
|
|
208
|
+
if (preserveAllLower && isAllLower && !/-/.test(originalString)) {
|
|
209
|
+
return originalString;
|
|
139
210
|
}
|
|
140
211
|
|
|
141
212
|
|
|
142
|
-
let transformedSeg = seg;
|
|
143
|
-
|
|
144
213
|
|
|
145
|
-
|
|
146
|
-
if (pattern.includes("*") || pattern.includes("?")) {
|
|
147
|
-
|
|
148
|
-
if (!segmentMatchesPreSplitPattern(seg, [pattern], false)) {
|
|
149
|
-
|
|
150
|
-
if (pattern.startsWith("**") && pattern.endsWith("**") && pattern.length > 4) {
|
|
151
|
-
const innerString = pattern.slice(2, -2);
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
const innerRegex = new RegExp(innerString.replace(/[.+^${}()|[\]\\*?]/g, "\\$&"), "gi");
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
const matches = [...transformedSeg.matchAll(innerRegex)];
|
|
158
|
-
for (const match of matches) {
|
|
159
|
-
const startPos = match.index;
|
|
160
|
-
const endPos = startPos + match[0].length;
|
|
214
|
+
let primarySegments = originalString.split(/[-]+|[^A-Za-z0-9_$]+/).filter(Boolean);
|
|
161
215
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const hasCharAfter = endPos < transformedSeg.length;
|
|
216
|
+
|
|
217
|
+
if (primarySegments.length === 0) return "_";
|
|
165
218
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
} else {
|
|
173
|
-
|
|
174
|
-
const literalParts = pattern.split(/[*?]+/).filter(Boolean);
|
|
175
|
-
for (const literal of literalParts) {
|
|
176
|
-
if (literal) {
|
|
177
|
-
|
|
178
|
-
const literalRegex = new RegExp(literal.replace(/[.+^${}()|[\]\\]/g, "\\$&"), "gi");
|
|
179
|
-
transformedSeg = transformedSeg.replace(literalRegex, literal.toUpperCase());
|
|
180
|
-
}
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
219
|
+
|
|
220
|
+
while (primarySegments.length && !/^[A-Za-z_$]/.test(primarySegments[0][0])) {
|
|
221
|
+
primarySegments[0] = primarySegments[0].replace(/^[^A-Za-z_$]+/, "");
|
|
222
|
+
if (!primarySegments[0]) primarySegments.shift();
|
|
185
223
|
}
|
|
224
|
+
if (primarySegments.length === 0) return "_";
|
|
186
225
|
|
|
187
226
|
|
|
188
|
-
|
|
189
|
-
|
|
227
|
+
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
|
|
231
|
+
const lowerRuleApplied = [];
|
|
232
|
+
const processedPrimarySegments = primarySegments.map((primarySeg, primaryIdx) => {
|
|
233
|
+
|
|
234
|
+
const parts = primarySeg.split(/(_+)/);
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
const processedParts = parts.map((part, partIdx) => {
|
|
190
238
|
|
|
191
|
-
if (
|
|
192
|
-
|
|
193
|
-
if (pattern.startsWith("**") && pattern.endsWith("**") && pattern.length > 4) {
|
|
194
|
-
const innerString = pattern.slice(2, -2);
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
const innerRegex = new RegExp(innerString.replace(/[.+^${}()|[\]\\*?]/g, "\\$&"), "gi");
|
|
239
|
+
if (partIdx % 2 === 1) return part;
|
|
240
|
+
if (!part) return part;
|
|
198
241
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
for (const match of matches) {
|
|
202
|
-
const startPos = match.index;
|
|
203
|
-
const endPos = startPos + match[0].length;
|
|
242
|
+
|
|
243
|
+
const cleanSeg = part.replace(/[^A-Za-z0-9_$]/g, "");
|
|
204
244
|
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
245
|
+
|
|
246
|
+
const config = { preserveAllUpper, preserveAllLower, leaveRules, leaveInsensitiveRules, upperRules, lowerRules };
|
|
247
|
+
const result = this.#applySegmentRules(cleanSeg, 0, originalString, config);
|
|
208
248
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
const matchesLower = lowerRules.some((pattern) => {
|
|
252
|
+
if (pattern.includes("*") || pattern.includes("?")) {
|
|
253
|
+
const regex = this.#compileGlobPattern(pattern, false);
|
|
254
|
+
if (regex && regex.test(originalString)) {
|
|
255
|
+
|
|
256
|
+
const literals = this.#extractPatternLiterals(pattern);
|
|
257
|
+
for (const literal of literals) {
|
|
258
|
+
const cleanLiteral = literal.replace(/[^A-Za-z0-9_$]/g, "").replace(/^_+|_+$/g, "");
|
|
259
|
+
if (cleanLiteral && cleanSeg.toLowerCase() === cleanLiteral.toLowerCase()) {
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
213
262
|
}
|
|
214
263
|
}
|
|
215
264
|
} else {
|
|
216
265
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
if (literal) {
|
|
220
|
-
const literalRegex = new RegExp(literal.replace(/[.+^${}()|[\]\\]/g, "\\$&"), "gi");
|
|
221
|
-
transformedSeg = transformedSeg.replace(literalRegex, literal.toLowerCase());
|
|
222
|
-
}
|
|
266
|
+
if (cleanSeg.toLowerCase() === pattern.toLowerCase()) {
|
|
267
|
+
return true;
|
|
223
268
|
}
|
|
224
269
|
}
|
|
270
|
+
return false;
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
if (matchesLower && result === cleanSeg.toLowerCase()) {
|
|
274
|
+
lowerRuleApplied[primaryIdx] = true;
|
|
225
275
|
}
|
|
226
|
-
|
|
227
|
-
|
|
276
|
+
|
|
277
|
+
return result;
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
|
|
281
|
+
return processedParts.join("");
|
|
282
|
+
});
|
|
228
283
|
|
|
229
284
|
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
285
|
+
const camelCasedSegments = processedPrimarySegments.map((seg, idx) => {
|
|
286
|
+
|
|
287
|
+
const matchesLeave = this.#matchesAnyPattern(seg, leaveRules, true);
|
|
288
|
+
const matchesLeaveInsensitive = this.#matchesAnyPattern(seg, leaveInsensitiveRules, false);
|
|
289
|
+
const matchesUpper = this.#matchesAnyPattern(seg, upperRules, false);
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
const hasUnderscores = seg.includes("_");
|
|
293
|
+
const isAllUpper = !hasUnderscores && preserveAllUpper && seg === seg.toUpperCase() && seg !== seg.toLowerCase() && /[A-Z]/.test(seg);
|
|
294
|
+
const isAllLower = !hasUnderscores && preserveAllLower && seg === seg.toLowerCase() && seg !== seg.toUpperCase() && /[a-z]/.test(seg);
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
if (matchesLeave || matchesLeaveInsensitive || matchesUpper || isAllUpper || isAllLower) {
|
|
298
|
+
return seg;
|
|
238
299
|
}
|
|
239
|
-
}
|
|
240
300
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
let transformed;
|
|
304
|
+
if (idx === 0) {
|
|
244
305
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
306
|
+
transformed = lowerFirst ? seg[0].toLowerCase() + seg.slice(1) : seg;
|
|
307
|
+
} else {
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
if (lowerRuleApplied[idx]) {
|
|
311
|
+
transformed = seg;
|
|
312
|
+
} else {
|
|
313
|
+
transformed = seg[0].toUpperCase() + seg.slice(1);
|
|
248
314
|
}
|
|
249
315
|
}
|
|
250
|
-
}
|
|
251
316
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
return transformedSeg;
|
|
255
|
-
}
|
|
317
|
+
return transformed;
|
|
318
|
+
});
|
|
256
319
|
|
|
257
320
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
return seg[0].toUpperCase() + seg.slice(1);
|
|
264
|
-
};
|
|
321
|
+
let result = camelCasedSegments.join("");
|
|
322
|
+
result = result.replace(/[^A-Za-z0-9_$]/g, "");
|
|
323
|
+
|
|
324
|
+
return result;
|
|
325
|
+
}
|
|
265
326
|
|
|
266
327
|
|
|
267
|
-
|
|
328
|
+
getModuleId(filePath, baseDir) {
|
|
329
|
+
|
|
330
|
+
let relative = filePath.replace(baseDir, "").replace(/\\/g, "/");
|
|
331
|
+
relative = relative.replace(/^\//, "");
|
|
332
|
+
relative = relative.replace(/\.(mjs|cjs|js)$/, "");
|
|
333
|
+
|
|
334
|
+
return relative;
|
|
335
|
+
}
|
|
268
336
|
|
|
269
337
|
|
|
270
|
-
|
|
271
|
-
|
|
338
|
+
shouldPreserveFunctionCase(name) {
|
|
339
|
+
const preservePatterns = [
|
|
340
|
+
/^[A-Z]{2,}$/,
|
|
341
|
+
/[A-Z]{2,}/
|
|
342
|
+
];
|
|
272
343
|
|
|
273
|
-
|
|
344
|
+
return preservePatterns.some((pattern) => pattern.test(name));
|
|
345
|
+
}
|
|
274
346
|
}
|
|
275
347
|
|
|
276
348
|
|
|
277
349
|
|
|
350
|
+
|
|
351
|
+
|
|
352
|
+
|
|
353
|
+
export function sanitizePropertyName(input, options = {}) {
|
|
354
|
+
const sanitizer = new Sanitize(null);
|
|
355
|
+
return sanitizer.sanitizePropertyName(input, options);
|
|
356
|
+
}
|
|
@@ -18,104 +18,69 @@
|
|
|
18
18
|
|
|
19
19
|
|
|
20
20
|
|
|
21
|
+
import { ComponentBase } from "@cldmv/slothlet/factories/component-base";
|
|
21
22
|
|
|
22
|
-
export function safeDefine(obj, key, value, enumerable = false, config = null) {
|
|
23
|
-
const desc = Object.getOwnPropertyDescriptor(obj, key);
|
|
24
|
-
if (!desc) {
|
|
25
|
-
Object.defineProperty(obj, key, {
|
|
26
|
-
value,
|
|
27
|
-
writable: true,
|
|
28
|
-
configurable: true,
|
|
29
|
-
enumerable
|
|
30
|
-
});
|
|
31
|
-
} else if (desc.configurable) {
|
|
32
|
-
Object.defineProperty(obj, key, {
|
|
33
|
-
value,
|
|
34
|
-
writable: true,
|
|
35
|
-
configurable: true,
|
|
36
|
-
enumerable
|
|
37
|
-
});
|
|
38
|
-
} else if (config && config.debug) {
|
|
39
|
-
console.warn(`Could not redefine boundApi.${key}: not configurable`);
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
23
|
|
|
24
|
+
export class Utilities extends ComponentBase {
|
|
25
|
+
static slothletProperty = "utilities";
|
|
43
26
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return
|
|
27
|
+
|
|
28
|
+
isPlainObject(obj) {
|
|
29
|
+
if (typeof obj !== "object" || obj === null) return false;
|
|
30
|
+
const proto = Object.getPrototypeOf(obj);
|
|
31
|
+
return proto === null || proto === Object.prototype;
|
|
47
32
|
}
|
|
48
33
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (key === "__proto__" || key === "prototype" || key === "constructor") {
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
const sourceValue = source[key];
|
|
60
|
-
const targetValue = target[key];
|
|
61
|
-
|
|
62
|
-
if (sourceValue && typeof sourceValue === "object" && !Array.isArray(sourceValue)) {
|
|
63
|
-
target[key] = deepMerge(
|
|
64
|
-
targetValue && typeof targetValue === "object" && !Array.isArray(targetValue) ? targetValue : {},
|
|
65
|
-
sourceValue
|
|
66
|
-
);
|
|
67
|
-
} else {
|
|
68
|
-
target[key] = sourceValue;
|
|
34
|
+
|
|
35
|
+
deepMerge(target, source) {
|
|
36
|
+
if (!this.isPlainObject(target) || !this.isPlainObject(source)) {
|
|
37
|
+
return source;
|
|
69
38
|
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return target;
|
|
73
|
-
}
|
|
74
39
|
|
|
40
|
+
const result = { ...target };
|
|
75
41
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
for (const key of Object.keys(target)) {
|
|
81
|
-
if (key !== "_impl" && key !== "__ctx") delete target[key];
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
for (const key of Object.getOwnPropertyNames(source)) {
|
|
85
|
-
if (key !== "length" && key !== "name" && key !== "prototype" && key !== "_impl" && key !== "__ctx") {
|
|
86
|
-
try {
|
|
87
|
-
target[key] = source[key];
|
|
88
|
-
} catch {
|
|
42
|
+
for (const key in source) {
|
|
43
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
44
|
+
if (this.isPlainObject(source[key])) {
|
|
45
|
+
|
|
89
46
|
|
|
47
|
+
result[key] = this.deepMerge(this.isPlainObject(target[key]) ? target[key] : {}, source[key]);
|
|
48
|
+
} else {
|
|
49
|
+
result[key] = source[key];
|
|
90
50
|
}
|
|
91
51
|
}
|
|
92
52
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
53
|
+
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
deepClone(obj) {
|
|
59
|
+
try {
|
|
60
|
+
return structuredClone(obj);
|
|
61
|
+
} catch {
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
const objType = obj?.__type || typeof obj;
|
|
65
|
+
if (obj === null || (objType !== "object" && objType !== "function")) return obj;
|
|
66
|
+
if (obj instanceof Date) return new Date(obj.getTime());
|
|
67
|
+
if (Array.isArray(obj)) return obj.map((item) => this.deepClone(item));
|
|
68
|
+
|
|
69
|
+
const cloned = {};
|
|
70
|
+
for (const key in obj) {
|
|
109
71
|
try {
|
|
110
|
-
|
|
72
|
+
cloned[key] = this.deepClone(obj[key]);
|
|
111
73
|
} catch {
|
|
112
74
|
|
|
75
|
+
cloned[key] = obj[key];
|
|
113
76
|
}
|
|
114
77
|
}
|
|
78
|
+
return cloned;
|
|
115
79
|
}
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
generateId() {
|
|
84
|
+
return `slothlet_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
120
85
|
}
|
|
121
86
|
}
|