@jcoder-stack/abp-react 0.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.
- package/LICENSE +21 -0
- package/README.md +86 -0
- package/dist/application-configuration-DhOZRqtz.d.ts +170 -0
- package/dist/auth.d.ts +56 -0
- package/dist/auth.js +58 -0
- package/dist/chunk-HWT6PBBS.js +155 -0
- package/dist/chunk-OK6PUP2E.js +21 -0
- package/dist/chunk-QQFH53SC.js +700 -0
- package/dist/chunk-UDMHSDXZ.js +161 -0
- package/dist/chunk-XXJLSSG3.js +116 -0
- package/dist/core.d.ts +65 -0
- package/dist/core.js +24 -0
- package/dist/i18n.d.ts +18 -0
- package/dist/i18n.js +12 -0
- package/dist/is-granted-C0-1wvoW.d.ts +10 -0
- package/dist/logger-BSnS65IC.d.ts +60 -0
- package/dist/logger.d.ts +26 -0
- package/dist/logger.js +26 -0
- package/dist/oidc-7fu5kKVF.d.ts +202 -0
- package/dist/permissions.d.ts +18 -0
- package/dist/permissions.js +8 -0
- package/dist/proxy.d.ts +201 -0
- package/dist/proxy.js +535 -0
- package/dist/react.d.ts +125 -0
- package/dist/react.js +236 -0
- package/dist/router.d.ts +39 -0
- package/dist/router.js +41 -0
- package/dist/translator-B3hyoZmK.d.ts +40 -0
- package/dist/types-Bj0MpXtI.d.ts +97 -0
- package/package.json +116 -0
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// src/logger/levels.ts
|
|
2
|
+
var LEVEL_ORDER = {
|
|
3
|
+
trace: 10,
|
|
4
|
+
debug: 20,
|
|
5
|
+
info: 30,
|
|
6
|
+
warn: 40,
|
|
7
|
+
error: 50,
|
|
8
|
+
silent: 100
|
|
9
|
+
};
|
|
10
|
+
function isLevelEnabled(messageLevel, threshold) {
|
|
11
|
+
return LEVEL_ORDER[messageLevel] >= LEVEL_ORDER[threshold];
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// src/logger/browser.ts
|
|
15
|
+
var VALID_LEVELS = new Set(Object.keys(LEVEL_ORDER));
|
|
16
|
+
function parseBrowserOverride(raw) {
|
|
17
|
+
if (!raw) return null;
|
|
18
|
+
const sepIndex = raw.indexOf(":");
|
|
19
|
+
const levelPart = sepIndex === -1 ? raw : raw.slice(0, sepIndex);
|
|
20
|
+
const hasLevel = VALID_LEVELS.has(levelPart);
|
|
21
|
+
const scopePart = hasLevel ? raw.slice(levelPart.length + 1) : raw;
|
|
22
|
+
const result = {};
|
|
23
|
+
if (hasLevel) {
|
|
24
|
+
result.level = levelPart;
|
|
25
|
+
}
|
|
26
|
+
const scopes = scopePart.split(",").map((s) => s.trim()).filter(Boolean);
|
|
27
|
+
result.scopes = scopes.length ? scopes : null;
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// src/logger/redact.ts
|
|
32
|
+
var REDACT_MASK = "***REDACTED***";
|
|
33
|
+
var DEFAULT_REDACT_KEYS = [
|
|
34
|
+
"authorization",
|
|
35
|
+
"cookie",
|
|
36
|
+
"set-cookie",
|
|
37
|
+
"access_token",
|
|
38
|
+
"refresh_token",
|
|
39
|
+
"id_token",
|
|
40
|
+
"client_secret",
|
|
41
|
+
"code_verifier",
|
|
42
|
+
"password"
|
|
43
|
+
];
|
|
44
|
+
function isPlainObject(val) {
|
|
45
|
+
const proto = Object.getPrototypeOf(val);
|
|
46
|
+
return proto === Object.prototype || proto === null;
|
|
47
|
+
}
|
|
48
|
+
function redact(value, keys = DEFAULT_REDACT_KEYS, mask = REDACT_MASK) {
|
|
49
|
+
const keySet = new Set(keys.map((k) => k.toLowerCase()));
|
|
50
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
51
|
+
const walk = (val) => {
|
|
52
|
+
if (val === null || typeof val !== "object") return val;
|
|
53
|
+
if (val instanceof Error) {
|
|
54
|
+
return { name: val.name, message: val.message, stack: val.stack };
|
|
55
|
+
}
|
|
56
|
+
if (val instanceof Date) return val.toISOString();
|
|
57
|
+
const isWalkable = Array.isArray(val) || val instanceof Map || val instanceof Set || isPlainObject(val);
|
|
58
|
+
if (!isWalkable) return String(val);
|
|
59
|
+
if (seen.has(val)) return "[Circular]";
|
|
60
|
+
seen.add(val);
|
|
61
|
+
try {
|
|
62
|
+
if (Array.isArray(val)) return val.map((v) => walk(v));
|
|
63
|
+
if (val instanceof Set) return [...val].map((v) => walk(v));
|
|
64
|
+
const entries = val instanceof Map ? [...val].map(([k, v]) => [String(k), v]) : Object.entries(val);
|
|
65
|
+
const out = {};
|
|
66
|
+
for (const [k, v] of entries) {
|
|
67
|
+
out[k] = keySet.has(k.toLowerCase()) ? mask : walk(v);
|
|
68
|
+
}
|
|
69
|
+
return out;
|
|
70
|
+
} finally {
|
|
71
|
+
seen.delete(val);
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
return walk(value);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// src/logger/config.ts
|
|
78
|
+
var VALID_LEVELS2 = new Set(Object.keys(LEVEL_ORDER));
|
|
79
|
+
function parseLevel(raw) {
|
|
80
|
+
if (raw && VALID_LEVELS2.has(raw)) return raw;
|
|
81
|
+
return "info";
|
|
82
|
+
}
|
|
83
|
+
function parseScopes(raw) {
|
|
84
|
+
if (!raw) return null;
|
|
85
|
+
const list = raw.split(",").map((s) => s.trim()).filter(Boolean);
|
|
86
|
+
return list.length ? list : null;
|
|
87
|
+
}
|
|
88
|
+
function resolveConfig(env) {
|
|
89
|
+
return {
|
|
90
|
+
enabled: env.LOG_ENABLED !== "false",
|
|
91
|
+
level: parseLevel(env.LOG_LEVEL),
|
|
92
|
+
scopes: parseScopes(env.LOG_SCOPES),
|
|
93
|
+
redactKeys: [...DEFAULT_REDACT_KEYS]
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
function scopeEnabled(scope, scopes) {
|
|
97
|
+
if (scopes === null) return true;
|
|
98
|
+
return scopes.some((s) => scope === s || scope.startsWith(`${s}:`));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// src/logger/sink.ts
|
|
102
|
+
var consoleSink = {
|
|
103
|
+
write(record) {
|
|
104
|
+
const line = `[${record.time}] ${record.level.toUpperCase()} [${record.scope}] ${record.message}`;
|
|
105
|
+
const method = record.level === "error" ? "error" : record.level === "warn" ? "warn" : "log";
|
|
106
|
+
if (record.fields) console[method](line, record.fields);
|
|
107
|
+
else console[method](line);
|
|
108
|
+
}
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// src/logger/logger.ts
|
|
112
|
+
function createMemorySink() {
|
|
113
|
+
const records = [];
|
|
114
|
+
return { sink: { write: (r) => records.push(r) }, records };
|
|
115
|
+
}
|
|
116
|
+
function createLogger(opts) {
|
|
117
|
+
const config = opts.config ?? resolveConfig(typeof process !== "undefined" ? process.env : {});
|
|
118
|
+
const sink = opts.sink ?? consoleSink;
|
|
119
|
+
const scope = opts.scope;
|
|
120
|
+
const boundFields = opts.fields;
|
|
121
|
+
const emit = (level, message, fields) => {
|
|
122
|
+
if (!config.enabled) return;
|
|
123
|
+
if (!isLevelEnabled(level, config.level)) return;
|
|
124
|
+
if (!scopeEnabled(scope, config.scopes)) return;
|
|
125
|
+
const merged = boundFields || fields ? { ...boundFields, ...fields } : void 0;
|
|
126
|
+
sink.write({
|
|
127
|
+
level,
|
|
128
|
+
scope,
|
|
129
|
+
message,
|
|
130
|
+
fields: merged ? redact(merged, config.redactKeys) : void 0,
|
|
131
|
+
time: (/* @__PURE__ */ new Date()).toISOString()
|
|
132
|
+
});
|
|
133
|
+
};
|
|
134
|
+
return {
|
|
135
|
+
trace: (m, f) => emit("trace", m, f),
|
|
136
|
+
debug: (m, f) => emit("debug", m, f),
|
|
137
|
+
info: (m, f) => emit("info", m, f),
|
|
138
|
+
warn: (m, f) => emit("warn", m, f),
|
|
139
|
+
error: (m, f) => emit("error", m, f),
|
|
140
|
+
child: (childOpts) => createLogger({
|
|
141
|
+
scope: childOpts.scope ? `${scope}:${childOpts.scope}` : scope,
|
|
142
|
+
config,
|
|
143
|
+
sink,
|
|
144
|
+
fields: childOpts.fields ? { ...boundFields, ...childOpts.fields } : boundFields
|
|
145
|
+
})
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
export {
|
|
150
|
+
LEVEL_ORDER,
|
|
151
|
+
isLevelEnabled,
|
|
152
|
+
parseBrowserOverride,
|
|
153
|
+
REDACT_MASK,
|
|
154
|
+
DEFAULT_REDACT_KEYS,
|
|
155
|
+
redact,
|
|
156
|
+
resolveConfig,
|
|
157
|
+
scopeEnabled,
|
|
158
|
+
consoleSink,
|
|
159
|
+
createMemorySink,
|
|
160
|
+
createLogger
|
|
161
|
+
};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
// src/i18n/interpolate.ts
|
|
2
|
+
function isPlainObject(value) {
|
|
3
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
4
|
+
}
|
|
5
|
+
function interpolate(template, args) {
|
|
6
|
+
if (args.length === 1 && isPlainObject(args[0])) {
|
|
7
|
+
const named = args[0];
|
|
8
|
+
return template.replace(/\{(\w+)\}/g, (match, key) => {
|
|
9
|
+
const value = named[key];
|
|
10
|
+
return value === void 0 ? match : String(value);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
return template.replace(/\{(\d+)\}/g, (match, digits) => {
|
|
14
|
+
const value = args[Number(digits)];
|
|
15
|
+
return value === void 0 ? match : String(value);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// src/i18n/person-name.ts
|
|
20
|
+
var SURNAME_FIRST_PREFIXES = ["zh", "ja", "ko"];
|
|
21
|
+
function formatPersonName(opts) {
|
|
22
|
+
const name = opts.name ?? "";
|
|
23
|
+
const surname = opts.surname ?? "";
|
|
24
|
+
if (!name || !surname) return name || surname;
|
|
25
|
+
const lang = opts.culture.split("-")[0]?.toLowerCase() ?? "";
|
|
26
|
+
return SURNAME_FIRST_PREFIXES.includes(lang) ? `${surname}${name}` : `${name} ${surname}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// src/i18n/plural.ts
|
|
30
|
+
var rulesCache = /* @__PURE__ */ new Map();
|
|
31
|
+
function rulesFor(locale) {
|
|
32
|
+
let rules = rulesCache.get(locale);
|
|
33
|
+
if (rules === void 0) {
|
|
34
|
+
try {
|
|
35
|
+
rules = new Intl.PluralRules(locale);
|
|
36
|
+
} catch {
|
|
37
|
+
rules = null;
|
|
38
|
+
}
|
|
39
|
+
rulesCache.set(locale, rules);
|
|
40
|
+
}
|
|
41
|
+
return rules;
|
|
42
|
+
}
|
|
43
|
+
function selectPluralForm(count, forms, locale) {
|
|
44
|
+
const category = rulesFor(locale)?.select(count);
|
|
45
|
+
return (category !== void 0 ? forms[category] : void 0) ?? forms.other ?? "";
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// src/i18n/translator.ts
|
|
49
|
+
function splitKey(key) {
|
|
50
|
+
const index = key.indexOf("::");
|
|
51
|
+
if (index === -1) return { resource: null, name: key };
|
|
52
|
+
return { resource: key.slice(0, index), name: key.slice(index + 2) };
|
|
53
|
+
}
|
|
54
|
+
function isPlainObject2(value) {
|
|
55
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
56
|
+
}
|
|
57
|
+
function asPluralForms(value) {
|
|
58
|
+
return isPlainObject2(value) ? value : void 0;
|
|
59
|
+
}
|
|
60
|
+
function pluralArgs(count, args) {
|
|
61
|
+
if (args.length === 1 && isPlainObject2(args[0])) return [{ ...args[0], count }];
|
|
62
|
+
return [count, ...args];
|
|
63
|
+
}
|
|
64
|
+
function toTemplate(value) {
|
|
65
|
+
if (typeof value === "string") return value;
|
|
66
|
+
const other = asPluralForms(value)?.other;
|
|
67
|
+
return typeof other === "string" ? other : void 0;
|
|
68
|
+
}
|
|
69
|
+
function createTranslator(opts) {
|
|
70
|
+
const interp = opts.interpolate ?? interpolate;
|
|
71
|
+
const selectPlural = opts.selectPluralForm ?? selectPluralForm;
|
|
72
|
+
const primarySubtag = opts.culture.split("-")[0];
|
|
73
|
+
const frontendCultures = primarySubtag && primarySubtag !== opts.culture ? [opts.culture, primarySubtag] : [opts.culture];
|
|
74
|
+
const resolve = (key) => {
|
|
75
|
+
const { resource: prefix, name } = splitKey(key);
|
|
76
|
+
const resource = prefix === null ? "" : prefix === "" ? opts.defaultResourceName ?? "" : prefix;
|
|
77
|
+
const backendValue = opts.backend?.[resource]?.[name];
|
|
78
|
+
if (backendValue !== void 0) return backendValue;
|
|
79
|
+
for (const culture of frontendCultures) {
|
|
80
|
+
const frontendValue = opts.frontend?.[culture]?.[resource]?.[name];
|
|
81
|
+
if (frontendValue !== void 0) return frontendValue;
|
|
82
|
+
}
|
|
83
|
+
if (opts.fallbackCulture) {
|
|
84
|
+
const frontendFallback = opts.frontend?.[opts.fallbackCulture]?.[resource]?.[name];
|
|
85
|
+
if (frontendFallback !== void 0) return frontendFallback;
|
|
86
|
+
}
|
|
87
|
+
return void 0;
|
|
88
|
+
};
|
|
89
|
+
return {
|
|
90
|
+
t(key, ...args) {
|
|
91
|
+
const template = toTemplate(resolve(key));
|
|
92
|
+
if (template !== void 0) return interp(template, args);
|
|
93
|
+
opts.onMissing?.(key);
|
|
94
|
+
return key;
|
|
95
|
+
},
|
|
96
|
+
plural(key, count, ...args) {
|
|
97
|
+
const value = resolve(key);
|
|
98
|
+
const interpArgs = pluralArgs(count, args);
|
|
99
|
+
if (typeof value === "string") return interp(value, interpArgs);
|
|
100
|
+
const forms = asPluralForms(value);
|
|
101
|
+
if (forms) return interp(selectPlural(count, forms, opts.culture), interpArgs);
|
|
102
|
+
opts.onMissing?.(key);
|
|
103
|
+
return key;
|
|
104
|
+
},
|
|
105
|
+
has(key) {
|
|
106
|
+
return toTemplate(resolve(key)) !== void 0;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export {
|
|
112
|
+
interpolate,
|
|
113
|
+
formatPersonName,
|
|
114
|
+
selectPluralForm,
|
|
115
|
+
createTranslator
|
|
116
|
+
};
|
package/dist/core.d.ts
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
export { A as ApplicationConfiguration, C as CurrentTenant, a as CurrentUser, L as Localization, b as applicationConfigurationSchema, c as currentTenantSchema, d as currentUserSchema, l as localizationSchema, p as parseApplicationConfiguration } from './application-configuration-DhOZRqtz.js';
|
|
2
|
+
import 'zod';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Whether an ABP setting/feature string value means `true`.
|
|
6
|
+
*
|
|
7
|
+
* The comparison must stay case-insensitive: ABP reads these values with `bool.Parse` and never
|
|
8
|
+
* normalizes them, so a provider default ships as `"true"` while anything saved through the
|
|
9
|
+
* settings/features UI comes back as C# `bool.ToString()` output, i.e. `"True"`. A strict `=== "true"`
|
|
10
|
+
* silently turns whole features off the first time an admin hits Save.
|
|
11
|
+
*/
|
|
12
|
+
declare function isAbpTrue(value: string | undefined | null): boolean;
|
|
13
|
+
|
|
14
|
+
interface AbpValidationError {
|
|
15
|
+
message: string;
|
|
16
|
+
members?: string[];
|
|
17
|
+
}
|
|
18
|
+
declare class HttpError extends Error {
|
|
19
|
+
readonly status: number;
|
|
20
|
+
readonly code?: string;
|
|
21
|
+
readonly validationErrors?: AbpValidationError[];
|
|
22
|
+
readonly body?: unknown;
|
|
23
|
+
constructor(status: number, message: string, options?: {
|
|
24
|
+
code?: string;
|
|
25
|
+
validationErrors?: AbpValidationError[];
|
|
26
|
+
body?: unknown;
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
/** 把上游响应体归一为 HttpError;ABP 错误信封的 message/code 会被提取,畸形 validationErrors 一律丢弃。 */
|
|
30
|
+
declare function toHttpError(status: number, body: unknown): HttpError;
|
|
31
|
+
|
|
32
|
+
/** A list page normalized for consumption: a concrete array plus the server-side total. */
|
|
33
|
+
interface PagedResult<T> {
|
|
34
|
+
items: T[];
|
|
35
|
+
totalCount: number;
|
|
36
|
+
}
|
|
37
|
+
/** Normalize an ABP paged DTO into a `PagedResult<T>` with a concrete array and count, so list
|
|
38
|
+
* views can share one generic shape. orval generates items/totalCount as optional or nullable. */
|
|
39
|
+
declare function toPagedResult<T>(dto: {
|
|
40
|
+
items?: T[] | null;
|
|
41
|
+
totalCount?: number;
|
|
42
|
+
} | null | undefined): PagedResult<T>;
|
|
43
|
+
/** Generic list state (pagination, sorting, filtering). */
|
|
44
|
+
interface ListState {
|
|
45
|
+
pageIndex: number;
|
|
46
|
+
pageSize: number;
|
|
47
|
+
sorting?: {
|
|
48
|
+
id: string;
|
|
49
|
+
desc: boolean;
|
|
50
|
+
}[];
|
|
51
|
+
filter?: string;
|
|
52
|
+
}
|
|
53
|
+
/** ABP list protocol parameters for request payloads. */
|
|
54
|
+
interface AbpListParams {
|
|
55
|
+
SkipCount: number;
|
|
56
|
+
MaxResultCount: number;
|
|
57
|
+
Sorting?: string;
|
|
58
|
+
Filter?: string;
|
|
59
|
+
}
|
|
60
|
+
/** Convert generic list state to ABP list protocol parameters. Request-side counterpart to
|
|
61
|
+
* `toPagedResult`. Out-of-range paging is clamped (SkipCount >= 0, MaxResultCount >= 1):
|
|
62
|
+
* ABP answers a negative skip or a non-positive page size with a 400. */
|
|
63
|
+
declare function toAbpListParams(state: ListState): AbpListParams;
|
|
64
|
+
|
|
65
|
+
export { type AbpListParams, type AbpValidationError, HttpError, type ListState, type PagedResult, isAbpTrue, toAbpListParams, toHttpError, toPagedResult };
|
package/dist/core.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import {
|
|
2
|
+
HttpError,
|
|
3
|
+
applicationConfigurationSchema,
|
|
4
|
+
currentTenantSchema,
|
|
5
|
+
currentUserSchema,
|
|
6
|
+
isAbpTrue,
|
|
7
|
+
localizationSchema,
|
|
8
|
+
parseApplicationConfiguration,
|
|
9
|
+
toAbpListParams,
|
|
10
|
+
toHttpError,
|
|
11
|
+
toPagedResult
|
|
12
|
+
} from "./chunk-HWT6PBBS.js";
|
|
13
|
+
export {
|
|
14
|
+
HttpError,
|
|
15
|
+
applicationConfigurationSchema,
|
|
16
|
+
currentTenantSchema,
|
|
17
|
+
currentUserSchema,
|
|
18
|
+
isAbpTrue,
|
|
19
|
+
localizationSchema,
|
|
20
|
+
parseApplicationConfiguration,
|
|
21
|
+
toAbpListParams,
|
|
22
|
+
toHttpError,
|
|
23
|
+
toPagedResult
|
|
24
|
+
};
|
package/dist/i18n.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export { B as BackendResources, F as FrontendCatalog, P as PluralForms, T as Translator, a as TranslatorOptions, c as createTranslator, s as selectPluralForm } from './translator-B3hyoZmK.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 使用命名 `{name}` 或位置 `{0}` 参数插值;单个普通对象用命名参数,否则用位置参数。
|
|
5
|
+
*
|
|
6
|
+
* 未命中或取值为 `undefined` 的占位符原样保留。「没给值」与「给了 undefined」对读者是同一件事,
|
|
7
|
+
* 渲染成字面 `undefined` 只会让缺参数的 bug 更难认。不支持转义:模板里的字面 `{0}` 无法保留。
|
|
8
|
+
*/
|
|
9
|
+
declare function interpolate(template: string, args: unknown[]): string;
|
|
10
|
+
|
|
11
|
+
/** 按文化拼装人名:CJK 姓前名后连写,其余名前姓后空格分隔;缺一取一。 */
|
|
12
|
+
declare function formatPersonName(opts: {
|
|
13
|
+
name?: string | null;
|
|
14
|
+
surname?: string | null;
|
|
15
|
+
culture: string;
|
|
16
|
+
}): string;
|
|
17
|
+
|
|
18
|
+
export { formatPersonName, interpolate };
|
package/dist/i18n.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Map of policy names to their grant status. */
|
|
2
|
+
type GrantedPolicies = Record<string, boolean>;
|
|
3
|
+
/** Strategy for combining multiple policies: 'all' (AND) or 'any' (OR). */
|
|
4
|
+
type PermissionStrategy = "all" | "any";
|
|
5
|
+
/** Check if one or more policies are granted; empty array is vacuously true for 'all', false for 'any'. */
|
|
6
|
+
declare function isGranted(policies: GrantedPolicies, policy: string | string[], opts?: {
|
|
7
|
+
strategy?: PermissionStrategy;
|
|
8
|
+
}): boolean;
|
|
9
|
+
|
|
10
|
+
export { type GrantedPolicies as G, type PermissionStrategy as P, isGranted as i };
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** Levels a log record can actually carry. */
|
|
2
|
+
type LogLevel = "trace" | "debug" | "info" | "warn" | "error";
|
|
3
|
+
/** Levels accepted as a configured threshold; `silent` only ever suppresses, it is never emitted. */
|
|
4
|
+
type LogThreshold = LogLevel | "silent";
|
|
5
|
+
declare const LEVEL_ORDER: Record<LogThreshold, number>;
|
|
6
|
+
declare function isLevelEnabled(messageLevel: LogLevel, threshold: LogThreshold): boolean;
|
|
7
|
+
|
|
8
|
+
interface LoggerConfig {
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
level: LogThreshold;
|
|
11
|
+
scopes: string[] | null;
|
|
12
|
+
redactKeys: string[];
|
|
13
|
+
}
|
|
14
|
+
declare function resolveConfig(env: Record<string, string | undefined>): LoggerConfig;
|
|
15
|
+
declare function scopeEnabled(scope: string, scopes: string[] | null): boolean;
|
|
16
|
+
|
|
17
|
+
/** One emitted log entry handed to a sink; `level` never carries the `silent` threshold. */
|
|
18
|
+
interface LogRecord {
|
|
19
|
+
level: LogLevel;
|
|
20
|
+
scope: string;
|
|
21
|
+
message: string;
|
|
22
|
+
fields?: Record<string, unknown>;
|
|
23
|
+
time: string;
|
|
24
|
+
}
|
|
25
|
+
interface LogSink {
|
|
26
|
+
write(record: LogRecord): void;
|
|
27
|
+
}
|
|
28
|
+
declare const consoleSink: LogSink;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Scoped, level-filtered logger.
|
|
32
|
+
*
|
|
33
|
+
* Only `fields` go through redaction. The `message` string is written verbatim, so anything
|
|
34
|
+
* sensitive (tokens, cookies, credential-bearing URLs) must be passed as a field rather than
|
|
35
|
+
* interpolated into the message.
|
|
36
|
+
*/
|
|
37
|
+
interface Logger {
|
|
38
|
+
trace(message: string, fields?: Record<string, unknown>): void;
|
|
39
|
+
debug(message: string, fields?: Record<string, unknown>): void;
|
|
40
|
+
info(message: string, fields?: Record<string, unknown>): void;
|
|
41
|
+
warn(message: string, fields?: Record<string, unknown>): void;
|
|
42
|
+
error(message: string, fields?: Record<string, unknown>): void;
|
|
43
|
+
child(opts: {
|
|
44
|
+
scope?: string;
|
|
45
|
+
fields?: Record<string, unknown>;
|
|
46
|
+
}): Logger;
|
|
47
|
+
}
|
|
48
|
+
declare function createMemorySink(): {
|
|
49
|
+
sink: LogSink;
|
|
50
|
+
records: LogRecord[];
|
|
51
|
+
};
|
|
52
|
+
/** Creates a logger for `scope`, writing to `sink` (console by default) every record that passes the config's level and scope filters; `fields` are bound to every record and redacted, while message strings are logged as-is and must not carry secrets. */
|
|
53
|
+
declare function createLogger(opts: {
|
|
54
|
+
scope: string;
|
|
55
|
+
config?: LoggerConfig;
|
|
56
|
+
sink?: LogSink;
|
|
57
|
+
fields?: Record<string, unknown>;
|
|
58
|
+
}): Logger;
|
|
59
|
+
|
|
60
|
+
export { type LogThreshold as L, LEVEL_ORDER as a, type LogLevel as b, type LogRecord as c, type LogSink as d, type Logger as e, type LoggerConfig as f, consoleSink as g, createLogger as h, createMemorySink as i, isLevelEnabled as j, resolveConfig as r, scopeEnabled as s };
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { L as LogThreshold } from './logger-BSnS65IC.js';
|
|
2
|
+
export { a as LEVEL_ORDER, b as LogLevel, c as LogRecord, d as LogSink, e as Logger, f as LoggerConfig, g as consoleSink, h as createLogger, i as createMemorySink, j as isLevelEnabled, r as resolveConfig, s as scopeEnabled } from './logger-BSnS65IC.js';
|
|
3
|
+
|
|
4
|
+
/** Parses a browser log override into the pieces that override the resolved config. Accepts
|
|
5
|
+
* `"level"`, `"level:scope,scope"` or a bare `"scope,scope"`. Returns null for an empty value;
|
|
6
|
+
* `scopes: null` means "no scope filter". */
|
|
7
|
+
declare function parseBrowserOverride(raw: string | null): {
|
|
8
|
+
level?: LogThreshold;
|
|
9
|
+
scopes?: string[] | null;
|
|
10
|
+
} | null;
|
|
11
|
+
|
|
12
|
+
declare const REDACT_MASK = "***REDACTED***";
|
|
13
|
+
/**
|
|
14
|
+
* Field names masked by `redact` unless the caller passes its own list.
|
|
15
|
+
*
|
|
16
|
+
* Deliberately limited to actual credentials. Names that merely *appear* in an auth flow but are
|
|
17
|
+
* not secret stay off the list. The OAuth `state` nonce is the notable one: it travels in plain
|
|
18
|
+
* sight in the browser URL, and as the default of a published package, masking a name as common
|
|
19
|
+
* as `state` costs far more in unreadable logs than it buys in protection. Add domain-specific names through
|
|
20
|
+
* the `redactKeys` option instead.
|
|
21
|
+
*/
|
|
22
|
+
declare const DEFAULT_REDACT_KEYS: string[];
|
|
23
|
+
/** Returns a deep copy of `value` with any property whose name matches `keys` (case-insensitive) replaced by `mask`; walks arrays, plain objects, Maps and Sets, renders Error/Date readably, and marks cycles as `[Circular]`. Never mutates the input. */
|
|
24
|
+
declare function redact(value: unknown, keys?: string[], mask?: string): unknown;
|
|
25
|
+
|
|
26
|
+
export { DEFAULT_REDACT_KEYS, LogThreshold, REDACT_MASK, parseBrowserOverride, redact };
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import {
|
|
2
|
+
DEFAULT_REDACT_KEYS,
|
|
3
|
+
LEVEL_ORDER,
|
|
4
|
+
REDACT_MASK,
|
|
5
|
+
consoleSink,
|
|
6
|
+
createLogger,
|
|
7
|
+
createMemorySink,
|
|
8
|
+
isLevelEnabled,
|
|
9
|
+
parseBrowserOverride,
|
|
10
|
+
redact,
|
|
11
|
+
resolveConfig,
|
|
12
|
+
scopeEnabled
|
|
13
|
+
} from "./chunk-UDMHSDXZ.js";
|
|
14
|
+
export {
|
|
15
|
+
DEFAULT_REDACT_KEYS,
|
|
16
|
+
LEVEL_ORDER,
|
|
17
|
+
REDACT_MASK,
|
|
18
|
+
consoleSink,
|
|
19
|
+
createLogger,
|
|
20
|
+
createMemorySink,
|
|
21
|
+
isLevelEnabled,
|
|
22
|
+
parseBrowserOverride,
|
|
23
|
+
redact,
|
|
24
|
+
resolveConfig,
|
|
25
|
+
scopeEnabled
|
|
26
|
+
};
|