superjs-core 0.3.3 → 0.3.4

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/dist/index.js CHANGED
@@ -1,3 +1,10 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
7
+
1
8
  // src/core/index.ts
2
9
  function isPlainObject(value) {
3
10
  if (value === null || typeof value !== "object") return false;
@@ -1796,11 +1803,496 @@ async function analyzeUsage(projectPath, packageName) {
1796
1803
  importLocations
1797
1804
  };
1798
1805
  }
1806
+
1807
+ // src/validation/isNIK.ts
1808
+ function isNIK(value) {
1809
+ const digits = value.replace(/\D/g, "");
1810
+ if (digits.length !== 16) return false;
1811
+ const rawDay = Number.parseInt(digits.slice(6, 8), 10);
1812
+ const month = Number.parseInt(digits.slice(8, 10), 10);
1813
+ const year = Number.parseInt(digits.slice(10, 12), 10);
1814
+ if (rawDay < 1 || rawDay > 71) return false;
1815
+ if (month < 1 || month > 12) return false;
1816
+ let day = rawDay;
1817
+ if (day >= 41) day -= 40;
1818
+ const fullYear = year < 70 ? 2e3 + year : 1900 + year;
1819
+ const date = new Date(fullYear, month - 1, day);
1820
+ return date.getFullYear() === fullYear && date.getMonth() === month - 1 && date.getDate() === day;
1821
+ }
1822
+
1823
+ // src/validation/isNPWP.ts
1824
+ function isNPWP(value) {
1825
+ const digits = value.replace(/\D/g, "");
1826
+ if (digits.length !== 15 && digits.length !== 16) return false;
1827
+ const nums = [];
1828
+ for (let i = 0; i < digits.length; i++) {
1829
+ nums.push(Number.parseInt(digits[i], 10));
1830
+ }
1831
+ const checkDigit = nums[nums.length - 1];
1832
+ let sum2 = 0;
1833
+ for (let i = 0; i < nums.length - 1; i++) {
1834
+ sum2 += nums[i] * [3, 7, 1][i % 3];
1835
+ }
1836
+ const computed = (11 - sum2 % 11) % 10;
1837
+ return computed === checkDigit;
1838
+ }
1839
+
1840
+ // src/validation/isPhone.ts
1841
+ var INDONESIAN_PREFIXES = [
1842
+ [11, 19],
1843
+ [21, 29],
1844
+ [51, 59],
1845
+ [77, 79],
1846
+ [95, 99]
1847
+ ];
1848
+ function isValidIndonesianPrefix(prefix) {
1849
+ for (const [min, max] of INDONESIAN_PREFIXES) {
1850
+ if (prefix >= min && prefix <= max) return true;
1851
+ }
1852
+ return false;
1853
+ }
1854
+ function isPhone(value, country = "id") {
1855
+ const digits = value.replace(/\D/g, "");
1856
+ if (country === "any") {
1857
+ return digits.length >= 10 && digits.length <= 15;
1858
+ }
1859
+ if (digits.length < 10) return false;
1860
+ let normalized;
1861
+ if (digits.startsWith("62")) {
1862
+ normalized = digits.slice(2);
1863
+ } else if (digits.startsWith("0")) {
1864
+ normalized = digits.slice(1);
1865
+ } else {
1866
+ normalized = digits;
1867
+ }
1868
+ if (normalized.length < 10 || normalized.length > 13) return false;
1869
+ if (!normalized.startsWith("8")) return false;
1870
+ const prefix = Number.parseInt(normalized.slice(1, 3), 10);
1871
+ return isValidIndonesianPrefix(prefix);
1872
+ }
1873
+
1874
+ // src/validation/isEmail.ts
1875
+ var LOCAL_SPECIAL = "!#$%&'*+/=?^_`{|}~-";
1876
+ function isQuotedLocalPart(local) {
1877
+ if (local.length < 2) return false;
1878
+ let i = 1;
1879
+ while (i < local.length - 1) {
1880
+ const ch = local[i];
1881
+ if (ch === "\\") {
1882
+ i++;
1883
+ if (i >= local.length - 1) return false;
1884
+ } else if (ch === '"') {
1885
+ return false;
1886
+ }
1887
+ i++;
1888
+ }
1889
+ return true;
1890
+ }
1891
+ function isUnquotedLocalPart(local) {
1892
+ if (local.length === 0 || local.startsWith(".") || local.endsWith(".")) return false;
1893
+ for (let i = 0; i < local.length; i++) {
1894
+ const ch = local[i];
1895
+ if (ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch >= "0" && ch <= "9" || ch === "." || LOCAL_SPECIAL.includes(ch)) {
1896
+ continue;
1897
+ }
1898
+ return false;
1899
+ }
1900
+ for (let i = 1; i < local.length; i++) {
1901
+ if (local[i] === "." && local[i - 1] === ".") return false;
1902
+ }
1903
+ return true;
1904
+ }
1905
+ function isValidDomain(domain) {
1906
+ if (domain.length === 0 || domain.startsWith(".") || domain.endsWith(".")) return false;
1907
+ const labels = domain.split(".");
1908
+ if (labels.length < 2) return false;
1909
+ for (const label of labels) {
1910
+ if (label.length === 0 || label.length > 63) return false;
1911
+ if (label.startsWith("-") || label.endsWith("-")) return false;
1912
+ for (let i = 0; i < label.length; i++) {
1913
+ const ch = label[i];
1914
+ if (!(ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch >= "0" && ch <= "9" || ch === "-")) {
1915
+ return false;
1916
+ }
1917
+ }
1918
+ }
1919
+ return true;
1920
+ }
1921
+ function isEmail(value) {
1922
+ if (value.length > 254) return false;
1923
+ const atIndex = value.lastIndexOf("@");
1924
+ if (atIndex < 1 || atIndex === value.length - 1) return false;
1925
+ const localPart = value.slice(0, atIndex);
1926
+ const domainPart = value.slice(atIndex + 1);
1927
+ if (localPart.length > 64) return false;
1928
+ if (domainPart.length > 255) return false;
1929
+ if (localPart.startsWith('"') && localPart.endsWith('"')) {
1930
+ if (!isQuotedLocalPart(localPart)) return false;
1931
+ } else {
1932
+ if (!isUnquotedLocalPart(localPart)) return false;
1933
+ }
1934
+ return isValidDomain(domainPart);
1935
+ }
1936
+
1937
+ // src/validation/isURL.ts
1938
+ var IPV4_OCTET = /^(?:[0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/;
1939
+ function isValidIPv4(hostname) {
1940
+ const octets = hostname.split(".");
1941
+ if (octets.length !== 4) return false;
1942
+ return octets.every((octet) => IPV4_OCTET.test(octet));
1943
+ }
1944
+ function isValidDNSHostname(hostname) {
1945
+ if (hostname.startsWith(".") || hostname.endsWith(".")) return false;
1946
+ const labels = hostname.split(".");
1947
+ if (labels.length < 2) return false;
1948
+ for (const label of labels) {
1949
+ if (label.length === 0 || label.length > 63) return false;
1950
+ if (label.startsWith("-") || label.endsWith("-")) return false;
1951
+ for (let i = 0; i < label.length; i++) {
1952
+ const ch = label[i];
1953
+ if (!(ch >= "a" && ch <= "z" || ch >= "A" && ch <= "Z" || ch >= "0" && ch <= "9" || ch === "-")) {
1954
+ return false;
1955
+ }
1956
+ }
1957
+ }
1958
+ return true;
1959
+ }
1960
+ function isValidHostname(hostname) {
1961
+ if (hostname.length === 0) return false;
1962
+ if (hostname.startsWith("[") && hostname.endsWith("]")) {
1963
+ return hostname.length > 2;
1964
+ }
1965
+ if (/^\d/.test(hostname) || /\d$/.test(hostname)) {
1966
+ if (isValidIPv4(hostname)) return true;
1967
+ }
1968
+ if (hostname === "localhost") return true;
1969
+ return isValidDNSHostname(hostname);
1970
+ }
1971
+ function isURL(value) {
1972
+ try {
1973
+ const url = new URL(value);
1974
+ if (url.protocol !== "http:" && url.protocol !== "https:") {
1975
+ return false;
1976
+ }
1977
+ return isValidHostname(url.hostname);
1978
+ } catch {
1979
+ return false;
1980
+ }
1981
+ }
1982
+
1983
+ // src/error/createError.ts
1984
+ var defaultStatus = {
1985
+ "BAD_REQUEST": 400,
1986
+ "UNAUTHORIZED": 401,
1987
+ "FORBIDDEN": 403,
1988
+ "NOT_FOUND": 404,
1989
+ "CONFLICT": 409,
1990
+ "VALIDATION_ERROR": 422,
1991
+ "TOO_MANY": 429,
1992
+ "INTERNAL": 500,
1993
+ "BAD_GATEWAY": 502,
1994
+ "UNAVAILABLE": 503
1995
+ };
1996
+ var TypedError = class extends Error {
1997
+ code;
1998
+ status;
1999
+ details;
2000
+ constructor(code, message, options) {
2001
+ super(message, { cause: options?.cause });
2002
+ this.name = "TypedError";
2003
+ this.code = code;
2004
+ this.status = options?.status ?? defaultStatus[code] ?? 500;
2005
+ this.details = options?.details;
2006
+ Object.setPrototypeOf(this, new.target.prototype);
2007
+ }
2008
+ /**
2009
+ * Serialize the error to a plain JSON-safe object.
2010
+ */
2011
+ toJSON() {
2012
+ return {
2013
+ name: this.name,
2014
+ message: this.message,
2015
+ code: this.code,
2016
+ status: this.status,
2017
+ details: this.details,
2018
+ cause: this.cause,
2019
+ ...this.stack ? { stack: this.stack } : {}
2020
+ };
2021
+ }
2022
+ toString() {
2023
+ return `${this.name} [${this.code}]: ${this.message}`;
2024
+ }
2025
+ };
2026
+ function createError(code, message, options) {
2027
+ return new TypedError(code, message, options);
2028
+ }
2029
+ function isTypedError(error) {
2030
+ return error instanceof TypedError;
2031
+ }
2032
+
2033
+ // src/error/MultiError.ts
2034
+ var MultiError = class extends Error {
2035
+ errors;
2036
+ constructor(errors, message) {
2037
+ const joined = errors.map((e) => e.message).join("; ");
2038
+ super(message ?? joined);
2039
+ this.name = "MultiError";
2040
+ this.errors = [...errors];
2041
+ Object.setPrototypeOf(this, new.target.prototype);
2042
+ }
2043
+ /** Number of collected errors. */
2044
+ get length() {
2045
+ return this.errors.length;
2046
+ }
2047
+ /**
2048
+ * Check if any collected error satisfies `predicate`.
2049
+ *
2050
+ * @example
2051
+ * ```ts
2052
+ * if (err.some(e => e.message.includes('timeout'))) { … }
2053
+ * ```
2054
+ */
2055
+ some(predicate) {
2056
+ return this.errors.some(predicate);
2057
+ }
2058
+ /** Array of all error messages. */
2059
+ get messages() {
2060
+ return this.errors.map((e) => e.message);
2061
+ }
2062
+ /**
2063
+ * Serialize to a plain JSON-safe object.
2064
+ */
2065
+ toJSON() {
2066
+ return {
2067
+ name: this.name,
2068
+ message: this.message,
2069
+ errors: this.errors.map((e) => ({
2070
+ name: e.name,
2071
+ message: e.message,
2072
+ ...e.stack ? { stack: e.stack } : {}
2073
+ })),
2074
+ ...this.stack ? { stack: this.stack } : {}
2075
+ };
2076
+ }
2077
+ toString() {
2078
+ return `${this.name}: ${this.message}`;
2079
+ }
2080
+ };
2081
+ function collectErrors(fn) {
2082
+ try {
2083
+ return { result: fn(), errors: [] };
2084
+ } catch (err) {
2085
+ return {
2086
+ errors: [err instanceof Error ? err : new Error(String(err))]
2087
+ };
2088
+ }
2089
+ }
2090
+
2091
+ // src/logger/logger.ts
2092
+ var LEVEL_ORDER = { debug: 0, info: 1, warn: 2, error: 3 };
2093
+ var Logger = class _Logger {
2094
+ _level;
2095
+ _name;
2096
+ _transport;
2097
+ _extraMeta;
2098
+ constructor(options) {
2099
+ this._level = options?.level ?? "info";
2100
+ this._name = options?.name;
2101
+ this._transport = options?.transport ?? consoleTransport;
2102
+ this._extraMeta = /* @__PURE__ */ Object.create(null);
2103
+ }
2104
+ _shouldLog(target) {
2105
+ return LEVEL_ORDER[this._level] <= LEVEL_ORDER[target];
2106
+ }
2107
+ _log(level, message, meta) {
2108
+ if (level !== "error" && !this._shouldLog(level)) return;
2109
+ const merged = /* @__PURE__ */ Object.create(null);
2110
+ for (const key of Object.keys(this._extraMeta)) {
2111
+ merged[key] = this._extraMeta[key];
2112
+ }
2113
+ if (meta !== void 0) {
2114
+ for (const key of Object.keys(meta)) {
2115
+ merged[key] = meta[key];
2116
+ }
2117
+ }
2118
+ const label = this._name !== void 0 ? `[${this._name}] ${message}` : message;
2119
+ const finalMeta = Object.keys(merged).length > 0 ? merged : void 0;
2120
+ this._transport.log(level, label, finalMeta);
2121
+ }
2122
+ /** Log at `debug` level. Only emitted when the current level is `'debug'`. */
2123
+ debug = (message, meta) => this._log("debug", message, meta);
2124
+ /** Log at `info` level. Emitted when level is `'debug'` or `'info'`. */
2125
+ info = (message, meta) => this._log("info", message, meta);
2126
+ /** Log at `warn` level. Emitted when level is `'debug'`, `'info'`, or `'warn'`. */
2127
+ warn = (message, meta) => this._log("warn", message, meta);
2128
+ /** Log at `error` level. Always emitted regardless of current level. */
2129
+ error = (message, meta) => this._log("error", message, meta);
2130
+ /**
2131
+ * Creates a child logger that inherits the parent's level, name, and transport,
2132
+ * but merges `extraMeta` into every log call. Child metadata is shallow-merged
2133
+ * on top of the parent's inherited metadata.
2134
+ *
2135
+ * @param extraMeta - Additional context to include in every log entry.
2136
+ */
2137
+ child(extraMeta) {
2138
+ const child = new _Logger({
2139
+ level: this._level,
2140
+ name: this._name,
2141
+ transport: this._transport
2142
+ });
2143
+ const inherited = /* @__PURE__ */ Object.create(null);
2144
+ for (const key of Object.keys(this._extraMeta)) {
2145
+ inherited[key] = this._extraMeta[key];
2146
+ }
2147
+ for (const key of Object.keys(extraMeta)) {
2148
+ inherited[key] = extraMeta[key];
2149
+ }
2150
+ child._extraMeta = inherited;
2151
+ return child;
2152
+ }
2153
+ /** Updates the minimum log level for this instance. */
2154
+ setLevel(level) {
2155
+ this._level = level;
2156
+ }
2157
+ /** Returns the current minimum log level. */
2158
+ getLevel() {
2159
+ return this._level;
2160
+ }
2161
+ /**
2162
+ * Creates a new named Logger.
2163
+ * Convenience shorthand for `new Logger({ ...options, name })`.
2164
+ *
2165
+ * @param name - The name tag shown in log output.
2166
+ * @param options - Additional configuration.
2167
+ */
2168
+ static create(name, options) {
2169
+ return new _Logger({ ...options, name });
2170
+ }
2171
+ };
2172
+ var consoleTransport = {
2173
+ log(level, message, meta) {
2174
+ const metaStr = meta !== void 0 && Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta)}` : "";
2175
+ console.log(`[${level.toUpperCase()}] ${message}${metaStr}`);
2176
+ }
2177
+ };
2178
+ var logger = new Logger();
2179
+
2180
+ // src/logger/transports.ts
2181
+ var LEVEL_COLORS = {
2182
+ debug: "\x1B[90m",
2183
+ info: "\x1B[34m",
2184
+ warn: "\x1B[33m",
2185
+ error: "\x1B[31m"
2186
+ };
2187
+ var RESET = "\x1B[0m";
2188
+ function createConsoleTransport(options) {
2189
+ const useColors = options?.colors !== false;
2190
+ const showTimestamp = options?.timestamp ?? false;
2191
+ return {
2192
+ log(level, message, meta) {
2193
+ const parts = [];
2194
+ if (showTimestamp) {
2195
+ parts.push((/* @__PURE__ */ new Date()).toISOString());
2196
+ }
2197
+ if (useColors) {
2198
+ const color = LEVEL_COLORS[level];
2199
+ parts.push(`${color}[${level.toUpperCase()}]${RESET}`);
2200
+ } else {
2201
+ parts.push(`[${level.toUpperCase()}]`);
2202
+ }
2203
+ parts.push(message);
2204
+ if (meta !== void 0 && Object.keys(meta).length > 0) {
2205
+ parts.push(JSON.stringify(meta));
2206
+ }
2207
+ console.log(parts.join(" "));
2208
+ }
2209
+ };
2210
+ }
2211
+ function createJsonTransport(options) {
2212
+ const writeStream = options?.stream ?? (typeof process !== "undefined" && typeof process.stdout !== "undefined" && typeof process.stdout.write === "function" ? process.stdout : void 0);
2213
+ return {
2214
+ log(level, message, meta) {
2215
+ const entry = {
2216
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
2217
+ level,
2218
+ message
2219
+ };
2220
+ if (meta !== void 0 && Object.keys(meta).length > 0) {
2221
+ entry.meta = meta;
2222
+ }
2223
+ const line = JSON.stringify(entry);
2224
+ if (writeStream !== void 0) {
2225
+ writeStream.write(line + "\n");
2226
+ } else {
2227
+ console.log(line);
2228
+ }
2229
+ }
2230
+ };
2231
+ }
2232
+ function createFileTransport(filename, _options) {
2233
+ let fs = null;
2234
+ try {
2235
+ if (typeof process !== "undefined" && process.versions?.node) {
2236
+ const m = __require("fs");
2237
+ fs = m;
2238
+ }
2239
+ } catch {
2240
+ }
2241
+ return {
2242
+ log(level, message, meta) {
2243
+ if (fs === null) return;
2244
+ const metaStr = meta !== void 0 && Object.keys(meta).length > 0 ? ` ${JSON.stringify(meta)}` : "";
2245
+ const line = `[${(/* @__PURE__ */ new Date()).toISOString()}] [${level.toUpperCase()}] ${message}${metaStr}
2246
+ `;
2247
+ try {
2248
+ fs.appendFileSync(filename, line);
2249
+ } catch {
2250
+ }
2251
+ }
2252
+ };
2253
+ }
2254
+ function createBufferedTransport(transport, options) {
2255
+ const maxSize = options?.maxSize ?? 100;
2256
+ const flushIntervalMs = options?.flushIntervalMs ?? 5e3;
2257
+ const buffer = [];
2258
+ let timer;
2259
+ function flush() {
2260
+ if (timer !== void 0) {
2261
+ clearTimeout(timer);
2262
+ timer = void 0;
2263
+ }
2264
+ for (let i = 0; i < buffer.length; i++) {
2265
+ const entry = buffer[i];
2266
+ transport.log(entry.level, entry.message, entry.meta);
2267
+ }
2268
+ buffer.length = 0;
2269
+ }
2270
+ function scheduleFlush() {
2271
+ if (timer !== void 0 || flushIntervalMs <= 0) return;
2272
+ timer = setTimeout(() => {
2273
+ timer = void 0;
2274
+ flush();
2275
+ }, flushIntervalMs);
2276
+ }
2277
+ return {
2278
+ log(level, message, meta) {
2279
+ buffer.push({ level, message, meta });
2280
+ if (buffer.length >= maxSize) {
2281
+ flush();
2282
+ } else {
2283
+ scheduleFlush();
2284
+ }
2285
+ }
2286
+ };
2287
+ }
1799
2288
  export {
1800
2289
  DivisionByZeroError,
1801
2290
  InvalidDateError,
1802
2291
  KNOWN_CVES,
1803
2292
  KNOWN_MAPPINGS,
2293
+ Logger,
2294
+ MultiError,
2295
+ TypedError,
1804
2296
  add,
1805
2297
  addBusinessDays,
1806
2298
  addDays,
@@ -1823,8 +2315,15 @@ export {
1823
2315
  checksum,
1824
2316
  chunk,
1825
2317
  clamp,
2318
+ collectErrors,
2319
+ consoleTransport,
1826
2320
  constantTimeEqual,
1827
2321
  countOccurrences,
2322
+ createBufferedTransport,
2323
+ createConsoleTransport,
2324
+ createError,
2325
+ createFileTransport,
2326
+ createJsonTransport,
1828
2327
  dateDiff,
1829
2328
  debounce,
1830
2329
  deepClone,
@@ -1862,24 +2361,31 @@ export {
1862
2361
  isBoolean,
1863
2362
  isBusinessDay,
1864
2363
  isDate,
2364
+ isEmail,
1865
2365
  isEmpty,
1866
2366
  isFunction,
1867
2367
  isLeapYear,
1868
2368
  isMap,
2369
+ isNIK,
2370
+ isNPWP,
1869
2371
  isNil,
1870
2372
  isNull,
1871
2373
  isNumber,
1872
2374
  isObject,
2375
+ isPhone,
1873
2376
  isPromise,
1874
2377
  isRegExp,
1875
2378
  isSet,
1876
2379
  isString,
2380
+ isTypedError,
2381
+ isURL,
1877
2382
  isUndefined,
1878
2383
  isWeekend,
1879
2384
  join,
1880
2385
  kebabCase,
1881
2386
  keyBy,
1882
2387
  last,
2388
+ logger,
1883
2389
  memoize,
1884
2390
  mul,
1885
2391
  nanoid,