@monochromatic-dev/module-logger 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/CHANGELOG.md +11 -0
- package/LICENSES/GPL-3.0-or-later.txt +674 -0
- package/LICENSES/LGPL-3.0-or-later.txt +165 -0
- package/README.md +404 -0
- package/dist/final/neutral/index.d.mts +673 -0
- package/dist/final/neutral/index.mjs +3 -0
- package/dist/final/neutral/rolldown-runtime-5duEfhBv.mjs +1 -0
- package/dist/final/node/index.d.mts +673 -0
- package/dist/final/node/index.mjs +3 -0
- package/dist/final/node/rolldown-runtime-5duEfhBv.mjs +1 -0
- package/package.json +43 -0
- package/src/create-logger.ts +494 -0
- package/src/create-logger.unit.test.ts +752 -0
- package/src/error-format.ts +43 -0
- package/src/index.ts +35 -0
- package/src/logger.ts +67 -0
- package/src/logger.unit.test.ts +190 -0
- package/src/sink/console-control-chars.ts +140 -0
- package/src/sink/console-control-chars.unit.test.ts +206 -0
- package/src/sink/console.ts +531 -0
- package/src/sink/console.unit.test.ts +542 -0
- package/src/sink/file.ts +297 -0
- package/src/sink/file.unit.test.ts +202 -0
- package/src/sink/index.ts +11 -0
- package/src/sink/indexed-db-util.ts +96 -0
- package/src/sink/indexed-db.browser.test.ts +184 -0
- package/src/sink/indexed-db.ts +324 -0
- package/src/sink/indexed-db.unit.test.ts +80 -0
- package/src/sink/local-storage-key.ts +176 -0
- package/src/sink/local-storage-key.unit.test.ts +106 -0
- package/src/sink/local-storage-quota.ts +60 -0
- package/src/sink/local-storage-quota.unit.test.ts +98 -0
- package/src/sink/local-storage-store.ts +368 -0
- package/src/sink/local-storage-store.unit.test.ts +329 -0
- package/src/sink/local-storage.browser.test.ts +125 -0
- package/src/sink/local-storage.ts +182 -0
- package/src/sink/local-storage.unit.test.ts +218 -0
- package/src/sink/noop.ts +46 -0
- package/src/sink/noop.unit.test.ts +47 -0
- package/src/sink/opfs.browser.test.ts +84 -0
- package/src/sink/opfs.ts +212 -0
- package/src/sink/opfs.unit.test.ts +81 -0
- package/src/sink/record-buffer.ts +230 -0
- package/src/sink/record-buffer.unit.test.ts +288 -0
- package/src/sink/session-storage-quota.ts +57 -0
- package/src/sink/session-storage-quota.unit.test.ts +98 -0
- package/src/sink/session-storage-store.ts +178 -0
- package/src/sink/session-storage.browser.test.ts +137 -0
- package/src/sink/session-storage.ts +128 -0
- package/src/sink/session-storage.unit.test.ts +527 -0
- package/src/sink/web-storage-quota-error.ts +43 -0
- package/src/sink/web-storage-quota-error.unit.test.ts +55 -0
- package/src/sink/web-storage-runtime.ts +49 -0
- package/src/startup.unit.test.ts +232 -0
- package/src/tagged.ts +74 -0
- package/src/tagged.unit.test.ts +211 -0
- package/src/types.ts +78 -0
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import{t as __exportAll}from"./rolldown-runtime-5duEfhBv.mjs";function _usingCtx(){var r=typeof SuppressedError==`function`?SuppressedError:function(r,e){var n=Error();return n.name=`SuppressedError`,n.error=r,n.suppressed=e,n},e={},n=[];function using(r,e){if(e!=null){if(Object(e)!==e)throw TypeError(`using declarations can only be used with objects, functions, null, or undefined.`);if(r)var o=e[Symbol.asyncDispose||Symbol.for(`Symbol.asyncDispose`)];if(o===void 0&&(o=e[Symbol.dispose||Symbol.for(`Symbol.dispose`)],r))var t=o;if(typeof o!=`function`)throw TypeError(`Object is not disposable.`);t&&(o=function(){try{t.call(e)}catch(r){return Promise.reject(r)}}),n.push({v:e,d:o,a:r})}else r&&n.push({d:e,a:r});return e}return{e,u:using.bind(null,!1),a:using.bind(null,!0),d:function(){var o,t=this.e,s=0;function next(){for(;o=n.pop();)try{if(!o.a&&s===1)return s=0,n.push(o),Promise.resolve().then(next);if(o.d){var r=o.d.call(o.v);if(o.a)return s|=2,Promise.resolve(r).then(next,err)}else s|=1}catch(r){return err(r)}if(s===1)return t===e?Promise.resolve():Promise.reject(t);if(t!==e)throw t}function err(n){return t=t===e?n:new r(n,t),next()}return next()}}}async function withTimeout({promise,ms,label}){try{var _usingCtx$1=_usingCtx();let{promise:timeoutPromise,reject}=Promise.withResolvers(),timer=setTimeout(function(){reject(Error(`Timed out after ${String(ms)}ms: ${label}`))},ms);return _usingCtx$1.u({[Symbol.dispose](){clearTimeout(timer)}}),await Promise.race([promise,timeoutPromise])}catch(_){_usingCtx$1.e=_}finally{_usingCtx$1.d()}}function caughtValueText(value){return Error.isError(value)?value.message:String(value)}function reportLoggerInternalError({context,error}){console.warn(`logger internal error: ${context}: ${caughtValueText(error)}`)}const DEFAULT_FLUSH_DEADLINE_MS=5e3;async function trackWrite({writePromise}){try{await writePromise}catch(error){reportLoggerInternalError({context:`sink write promise rejected while being tracked`,error})}}function createLogger({sinks,flushDeadlineMs=DEFAULT_FLUSH_DEADLINE_MS}){let entries=sinks.map(function(sink){return{available:!1,sink}}),startupRecords=[],pendingWrites=new Set,state={hasAvailableSink:!1,initialized:!1};function recomputeAvailability(){state.hasAvailableSink=entries.some(function(entry){return entry.available})}function getSinkEntry({entryIndex}){let entry=entries[entryIndex];if(entry===void 0)throw Error(`Missing logger sink entry at index ${entryIndex}.`);return entry}function markEntryUnavailable({entryIndex}){let entry=getSinkEntry({entryIndex});entry.available=!1,recomputeAvailability()}async function removePendingWriteWhenSettled({trackedWrite}){await trackedWrite,pendingWrites.delete(trackedWrite)}function writeRecordToEntry({entryIndex,record}){try{let trackedWrite=trackWrite({writePromise:getSinkEntry({entryIndex}).sink.write(record)});pendingWrites.add(trackedWrite),removePendingWriteWhenSettled({trackedWrite})}catch(error){reportLoggerInternalError({context:`sink write threw synchronously while dispatching record`,error})}}function replayStartupRecordsToEntry({entryIndex}){startupRecords.forEach(function(record){writeRecordToEntry({entryIndex,record})})}function setEntryAvailability({entryIndex,available}){let entry=getSinkEntry({entryIndex});entry.available=available,recomputeAvailability(),available&&replayStartupRecordsToEntry({entryIndex})}async function verifyAndApply({entryIndex}){try{setEntryAvailability({available:await getSinkEntry({entryIndex}).sink.verify(),entryIndex})}catch(error){reportLoggerInternalError({context:`sink verification failed for entry ${entryIndex}`,error}),markEntryUnavailable({entryIndex})}}async function initialize(){if(!state.initialized){for(let[entryIndex]of entries.entries())await verifyAndApply({entryIndex});state.initialized=!0,startupRecords.length=0}}let initPromise=initialize();async function drainPendingWrites(){let writes=[...pendingWrites];await Promise.all(writes)}function createMethod(level){return function(message){if(!state.hasAvailableSink&&state.initialized)throw Error(`No logging backends available`);let record={level,message,timestamp:Date.now()};state.initialized||startupRecords.push(record),entries.map(function(_entry,entryIndex){return entryIndex}).filter(function(entryIndex){return getSinkEntry({entryIndex}).available}).forEach(function(entryIndex){writeRecordToEntry({entryIndex,record})})}}async function runSinkFlushHooks(){await Promise.all(entries.map(async function(entry,entryIndex){let sinkFlush=entry.sink.flush;if(!(!entry.available||typeof sinkFlush!=`function`))try{await sinkFlush()}catch(error){reportLoggerInternalError({context:`sink flush failed for entry ${entryIndex}`,error}),markEntryUnavailable({entryIndex})}}))}async function drainEverything(){await initPromise,await drainPendingWrites(),await runSinkFlushHooks()}function abandonPendingWrites(){pendingWrites.clear()}async function flushAll(){try{await withTimeout({label:`logger flush`,ms:flushDeadlineMs,promise:drainEverything()})}catch(error){reportLoggerInternalError({context:`flush deadline of ${flushDeadlineMs}ms elapsed; abandoning in-flight sink work`,error}),abandonPendingWrites()}}return{initPromise,logger:{debug:createMethod(`debug`),error:createMethod(`error`),fatal:createMethod(`fatal`),flush:flushAll,info:createMethod(`info`),trace:createMethod(`trace`),warn:createMethod(`warn`)}}}function isNeutralizedControl(codeUnit){return codeUnit<32?codeUnit!==10&&codeUnit!==9:codeUnit===127||codeUnit>=128&&codeUnit<=159}function escapeCodeUnit(codeUnit){return`\\u${codeUnit.toString(16).toUpperCase().padStart(4,`0`)}`}function neutralizeControlCharacters(text){let pieces=[];for(let character of text){let codeUnit=character.charCodeAt(0);pieces.push(isNeutralizedControl(codeUnit)?escapeCodeUnit(codeUnit):character)}return pieces.join(``)}const VERBOSE_UNCOMPUTED=Symbol(`logger:verbose-detection-uncomputed`),SILENT_LEVELS=new Set([`debug`,`trace`]);function detectVerbose(){try{if(typeof process<`u`&&process.env.MONOCHROMATIC_VERBOSE===`true`)return!0}catch(error){reportLoggerInternalError({context:`MONOCHROMATIC_VERBOSE environment probe failed during verbose detection`,error})}try{if(typeof process<`u`&&Array.isArray(process.argv)&&process.argv.includes(`--verbose`))return!0}catch(error){reportLoggerInternalError({context:`process argv probe failed during verbose detection`,error})}try{if(`window`in globalThis)return!0}catch(error){reportLoggerInternalError({context:`window probe failed during verbose detection`,error})}return!1}function isWarnSuppressed(){try{return typeof process<`u`&&process.env.MONOCHROMATIC_WARN===`false`}catch(error){return reportLoggerInternalError({context:`MONOCHROMATIC_WARN environment probe failed during warn suppression detection`,error}),!1}}const LEVEL_TO_CONSOLE_METHOD={debug:`debug`,error:`error`,fatal:`error`,info:`info`,trace:`trace`,warn:`warn`};function formatRecord(record){return`[${record.level}] [${new Date(record.timestamp).toISOString()}] ${neutralizeControlCharacters(record.message)}`}function hasProcessStderr(){try{return typeof process>`u`?!1:typeof process.stderr.write==`function`}catch(error){return reportLoggerInternalError({context:`process stderr availability probe failed`,error}),!1}}function writeDebugRunToProcessStderr(text){try{return hasProcessStderr()?(process.stderr.write(`${text}\n`),!0):!1}catch(error){return reportLoggerInternalError({context:`debug run process stderr write failed`,error}),!1}}function emitRun({records,level}){let text=records.map(function(r){return formatRecord(r)}).join(`
|
|
2
|
+
`);if(!(level===`debug`&&writeDebugRunToProcessStderr(text)))try{let method=LEVEL_TO_CONSOLE_METHOD[level],consoleFn=console[method];typeof consoleFn==`function`&&consoleFn.call(console,text)}catch(error){reportLoggerInternalError({context:`console method call failed while emitting log run`,error})}}function groupRuns(records){return records.reduce(function(runs,record){let tail=runs.at(-1);return tail!==void 0&&tail.level===record.level?(tail.records.push(record),runs):(runs.push({level:record.level,records:[record]}),runs)},[])}function verifyConsole(){try{return typeof console>`u`||typeof(hasProcessStderr()?console.info:console.debug)!=`function`||typeof queueMicrotask!=`function`?Promise.resolve(!1):Promise.resolve(!0)}catch(error){return reportLoggerInternalError({context:`console sink verification failed`,error}),Promise.resolve(!1)}}function createConsoleSink(){let state={buffer:[],scheduled:!1,verboseCache:VERBOSE_UNCOMPUTED};function getVerbose(){let cached=state.verboseCache;if(cached!==VERBOSE_UNCOMPUTED)return cached;let computed=detectVerbose();return state.verboseCache=computed,computed}function flushBuffer(){if(state.scheduled=!1,state.buffer.length===0)return;let records=state.buffer.splice(0);for(let run of groupRuns(records))emitRun({level:run.level,records:run.records})}function write(record){return!getVerbose()&&SILENT_LEVELS.has(record.level)||record.level===`warn`&&isWarnSuppressed()?Promise.resolve():(state.buffer.push(record),state.scheduled||(state.scheduled=!0,queueMicrotask(flushBuffer)),Promise.resolve())}function flush(){return flushBuffer(),Promise.resolve()}return{flush,verify:verifyConsole,write}}const NO_NODE_MODULES_FOUND=Symbol(`logger:no-node-modules-found`);async function findNodeModulesUp({cwd,stat,dirname,join,reportError=reportLoggerInternalError}){let candidate=join(cwd,`node_modules`);try{if((await stat(candidate)).isDirectory())return candidate}catch(error){Error.isError(error)&&`code`in error&&error.code===`ENOENT`||reportError({context:`node_modules candidate ${candidate} unavailable during file sink search`,error})}let parent=dirname(cwd);return parent===cwd?NO_NODE_MODULES_FOUND:await findNodeModulesUp({cwd:parent,stat,dirname,join,reportError})}function createFileSink(){let state={};async function runVerify(){if(globalThis.process===void 0||globalThis.process.versions?.node===void 0)return!1;try{let fs=await import(`node:fs/promises`),{dirname,join}=await import(`node:path`);state.appendFile=fs.appendFile;let nodeModulesDir=await findNodeModulesUp({cwd:process.cwd(),stat:fs.stat,dirname,join});if(nodeModulesDir===NO_NODE_MODULES_FOUND)return!1;let LOG_DIR=join(nodeModulesDir,`.monochromatic`);await fs.mkdir(LOG_DIR,{recursive:!0});let timestamp=new Date().toISOString().replaceAll(`:`,`-`);state.filePath=join(LOG_DIR,`${timestamp}.log.jsonl`);let testData=`{"test":true,"timestamp":${Date.now()}}\n`;return await state.appendFile(state.filePath,testData),(await fs.readFile(state.filePath,`utf8`)).includes(`"test":true`)}catch(error){return reportLoggerInternalError({context:`file sink verification failed`,error}),!1}}function verify(){return state.verifyPromise===void 0&&(state.verifyPromise=runVerify()),state.verifyPromise}async function write(record){if(!(!state.filePath||!state.appendFile))try{await state.appendFile(state.filePath,`${JSON.stringify(record)}\n`)}catch(error){reportLoggerInternalError({context:`file sink record append failed`,error})}}return{verify,write}}function awaitRequest(request){return new Promise(function(resolve,reject){request.addEventListener(`success`,function(){resolve(request.result)}),request.addEventListener(`error`,function(){reject(request.error??Error(`IndexedDB request failed without an error object`))})})}function awaitTransaction(transaction){return new Promise(function(resolve,reject){transaction.addEventListener(`complete`,function(){resolve()}),transaction.addEventListener(`error`,function(){reject(transaction.error??Error(`IndexedDB transaction failed without an error object`))}),transaction.addEventListener(`abort`,function(){reject(transaction.error??Error(`IndexedDB transaction aborted without an error object`))})})}const FLUSH_BUFFER_CAP_CHARS=32768,FLUSH_IMMEDIATELY_BY_LEVEL={debug:!1,error:!0,fatal:!0,info:!1,trace:!1,warn:!0};function isUnrefableTimer(timer){return typeof timer!=`object`||!timer||!(`unref`in timer)?!1:typeof timer.unref==`function`}function createRecordBuffer({onFlush}){let entries=[],bufferState={chars:0};function charsWith(serialized){let separatorChars=+(entries.length>0);return bufferState.chars+separatorChars+serialized.length}function drain(){if(bufferState.timer!==void 0&&(globalThis.clearTimeout(bufferState.timer),delete bufferState.timer),entries.length===0)return;let batch=entries.join(`
|
|
3
|
+
`);entries.length=0,bufferState.chars=0,onFlush(batch)}function scheduleDeadlineFlush(){if(bufferState.timer!==void 0)return;let timer=globalThis.setTimeout(drain,250);isUnrefableTimer(timer)&&timer.unref(),bufferState.timer=timer}function add(entry){entries.length>0&&charsWith(entry.serialized)>FLUSH_BUFFER_CAP_CHARS&&drain(),bufferState.chars=charsWith(entry.serialized),entries.push(entry.serialized),FLUSH_IMMEDIATELY_BY_LEVEL[entry.level]||bufferState.chars>=FLUSH_BUFFER_CAP_CHARS?drain():scheduleDeadlineFlush()}return globalThis.addEventListener?.(`pagehide`,drain),globalThis.document?.addEventListener(`visibilitychange`,function(){globalThis.document?.visibilityState===`hidden`&&drain()}),{add,drain}}const BATCH_STORE=`batch`,MAX_STORED_BATCHES=2048;async function openLogDatabase(){let request=globalThis.indexedDB.open(`monochromatic.log`,1);return request.onupgradeneeded=function(){request.result.createObjectStore(BATCH_STORE,{autoIncrement:!0})},await awaitRequest(request)}async function persistBatch({database,batch}){let transaction=database.transaction(BATCH_STORE,`readwrite`),store=transaction.objectStore(BATCH_STORE);store.add(batch);let count=await awaitRequest(store.count());if(count>MAX_STORED_BATCHES){let newestStale=(await awaitRequest(store.getAllKeys(null,count-MAX_STORED_BATCHES))).at(-1);newestStale!==void 0&&store.delete(IDBKeyRange.upperBound(newestStale))}await awaitTransaction(transaction)}function createIndexedDbSink(){let state={},pendingBatchWrites=new Set;async function verify(){try{if(globalThis.indexedDB===void 0)return!1;let database=await openLogDatabase(),transaction=database.transaction(BATCH_STORE,`readwrite`),store=transaction.objectStore(BATCH_STORE),probeValue=`probe-${Date.now()}`,probeKey=await awaitRequest(store.add(probeValue)),readBack=await awaitRequest(store.get(probeKey));return store.delete(probeKey),await awaitTransaction(transaction),readBack===probeValue&&(state.database=database,!0)}catch(error){return`indexedDB`in globalThis&&reportLoggerInternalError({context:`IndexedDB sink verification failed`,error}),!1}}async function writeBatch(batch){if(state.database)try{await persistBatch({database:state.database,batch})}catch(error){reportLoggerInternalError({context:`IndexedDB sink record write failed`,error})}}async function removePendingWhenSettled(pending){await pending,pendingBatchWrites.delete(pending)}function handOffBatch(batch){let pending=writeBatch(batch);pendingBatchWrites.add(pending),removePendingWhenSettled(pending)}let buffer=createRecordBuffer({onFlush:handOffBatch});function write(record){return buffer.add({level:record.level,serialized:JSON.stringify(record)}),Promise.resolve()}async function flush(){buffer.drain();let writes=[...pendingBatchWrites];await Promise.all(writes)}return{flush,verify,write}}function isDigits(text){if(text.length===0)return!1;for(let character of text)if(character<`0`||character>`9`)return!1;return!0}function buildLogKey({stamp,nonce,index}){return`monochromatic.log.${stamp}.${nonce}.${index}`}function parseLogKey(key){if(!key.startsWith(`monochromatic.log.`))return{};let segments=key.slice(18).split(`.`);if(segments.length!==3)return{};let[stampText,nonce,indexText]=segments;return stampText===void 0||nonce===void 0||indexText===void 0||!isDigits(stampText)||nonce.length===0||!isDigits(indexText)?{}:{parsed:{key,stamp:Math.trunc(Number(stampText)),nonce,index:Math.trunc(Number(indexText))}}}function compareLogKeys({first,second}){return first.stamp===second.stamp?first.nonce===second.nonce?first.index-second.index:first.nonce<second.nonce?-1:1:first.stamp-second.stamp}function detectWebStorageRuntime(){return`Deno`in globalThis?`deno`:`Bun`in globalThis?`bun`:typeof process<`u`&&typeof process.versions.node==`string`?`node`:`document`in globalThis?`browser`:`unknown`}const RUNTIME_QUOTA_CHARS$1={browser:5242880,bun:1/0,deno:10477569,node:5242880,unknown:1/0};function detectLocalStorageQuotaChars(){return RUNTIME_QUOTA_CHARS$1[detectWebStorageRuntime()]}const QUOTA_EXCEEDED_NAMES=new Set([`QuotaExceededError`,`NS_ERROR_DOM_QUOTA_REACHED`]);function isQuotaExceededError(error){return typeof error==`object`&&!!error&&`name`in error&&typeof error.name==`string`&"A_EXCEEDED_NAMES.has(error.name)}function createLocalStorageStore(){let runIdentity={stamp:Date.now(),nonce:Math.random().toString(36).slice(2,6).padEnd(4,`0`)},state={lineCounter:0,oldestIndex:0,usedChars:0,reportedFailure:!1,adoptedPrior:!1},prior={entries:[],cursor:0},capChars=detectLocalStorageQuotaChars()/2;function ownKey(index){return buildLogKey({stamp:runIdentity.stamp,nonce:runIdentity.nonce,index})}function adoptPriorEntries(){let total=globalThis.localStorage.length,found=[];for(let slot=0;slot<total;slot++){let key=globalThis.localStorage.key(slot);if(key===null)continue;let{parsed}=parseLogKey(key);if(parsed===void 0||parsed.stamp===runIdentity.stamp&&parsed.nonce===runIdentity.nonce)continue;let value=globalThis.localStorage.getItem(key);value!==null&&found.push({...parsed,chars:value.length})}prior.entries=found.toSorted(function(first,second){return compareLogKeys({first,second})}),state.usedChars+=found.reduce(function(sum,entry){return sum+entry.chars},0)}function hasEvictable(){let priorCount=prior.entries.length;return prior.cursor<priorCount||state.oldestIndex<state.lineCounter}function evictOldestPrior(){let entry=prior.entries[prior.cursor];return entry!==void 0&&(prior.cursor++,globalThis.localStorage.removeItem(entry.key),state.usedChars=Math.max(0,state.usedChars-entry.chars),!0)}function evictOldestOwn(){let key=ownKey(state.oldestIndex),evicted=globalThis.localStorage.getItem(key);globalThis.localStorage.removeItem(key),state.oldestIndex++,evicted!==null&&(state.usedChars=Math.max(0,state.usedChars-evicted.length))}function evictOldest(){evictOldestPrior()||state.oldestIndex<state.lineCounter&&evictOldestOwn()}function persist(batch){state.adoptedPrior||(state.adoptedPrior=!0,adoptPriorEntries());let batchChars=batch.length;for(;hasEvictable()&&state.usedChars+batchChars>capChars;)evictOldest();let maxWriteAttempts=prior.entries.length-prior.cursor+(state.lineCounter-state.oldestIndex)+1;for(let writeAttempt=0;writeAttempt<maxWriteAttempts;writeAttempt++)try{globalThis.localStorage.setItem(ownKey(state.lineCounter),batch),state.lineCounter++,state.usedChars+=batchChars,state.reportedFailure=!1;return}catch(error){if(isQuotaExceededError(error)&&hasEvictable()){evictOldest();continue}state.reportedFailure||=(reportLoggerInternalError({context:`localStorage sink record write failed (repeats suppressed until a write next succeeds)`,error}),!0);return}}return{persist}}const NODE_LOCALSTORAGE_FLAG=`--localstorage-file`;function nodeWithoutLocalStorageFile(){if(detectWebStorageRuntime()!==`node`||`document`in globalThis)return!1;let flaggedInExecArgv=process.execArgv.some(function(argument){return argument.startsWith(NODE_LOCALSTORAGE_FLAG)}),flaggedInNodeOptions=(process.env.NODE_OPTIONS??``).includes(NODE_LOCALSTORAGE_FLAG);return!(flaggedInExecArgv||flaggedInNodeOptions)}function verifyLocalStorage(){if(nodeWithoutLocalStorageFile())return Promise.resolve(!1);try{let testKey=`__monochromatic_verify__`,testValue=`test-${Date.now()}`;globalThis.localStorage.setItem(testKey,testValue);let readBack=globalThis.localStorage.getItem(testKey);return globalThis.localStorage.removeItem(testKey),Promise.resolve(readBack===testValue)}catch(error){return`localStorage`in globalThis&&reportLoggerInternalError({context:`localStorage sink verification failed`,error}),Promise.resolve(!1)}}function createLocalStorageSink(){let buffer=createRecordBuffer({onFlush:createLocalStorageStore().persist});function write(record){return buffer.add({level:record.level,serialized:JSON.stringify(record)}),Promise.resolve()}function flush(){return buffer.drain(),Promise.resolve()}return{flush,verify:verifyLocalStorage,write}}const RUNTIME_QUOTA_CHARS={browser:5242880,bun:1/0,deno:10485760,node:5242880,unknown:1/0};function detectSessionStorageQuotaChars(){return RUNTIME_QUOTA_CHARS[detectWebStorageRuntime()]}function storageKey(index){return`monochromatic.log.${index}`}function createSessionStorageStore(){let state={lineCounter:0,oldestIndex:0,usedChars:0,reportedFailure:!1},capChars=detectSessionStorageQuotaChars()/2;function evictOldest(){let key=storageKey(state.oldestIndex),evicted=globalThis.sessionStorage.getItem(key);globalThis.sessionStorage.removeItem(key),state.oldestIndex++,evicted!==null&&(state.usedChars=Math.max(0,state.usedChars-evicted.length))}function persist(batch){let batchChars=batch.length;for(;state.oldestIndex<state.lineCounter&&state.usedChars+batchChars>capChars;)evictOldest();let maxWriteAttempts=state.lineCounter-state.oldestIndex+1;for(let writeAttempt=0;writeAttempt<maxWriteAttempts;writeAttempt++)try{globalThis.sessionStorage.setItem(storageKey(state.lineCounter),batch),state.lineCounter++,state.usedChars+=batchChars,state.reportedFailure=!1;return}catch(error){if(isQuotaExceededError(error)&&state.oldestIndex<state.lineCounter){evictOldest();continue}state.reportedFailure||=(reportLoggerInternalError({context:`sessionStorage sink record write failed (repeats suppressed until a write next succeeds)`,error}),!0);return}}return{persist}}function verifySessionStorage(){try{let testKey=`__monochromatic_verify__`,testValue=`test-${Date.now()}`;globalThis.sessionStorage.setItem(testKey,testValue);let readBack=globalThis.sessionStorage.getItem(testKey);return globalThis.sessionStorage.removeItem(testKey),Promise.resolve(readBack===testValue)}catch(error){return`sessionStorage`in globalThis&&reportLoggerInternalError({context:`sessionStorage sink verification failed`,error}),Promise.resolve(!1)}}function createSessionStorageSink(){let buffer=createRecordBuffer({onFlush:createSessionStorageStore().persist});function write(record){return buffer.add({level:record.level,serialized:JSON.stringify(record)}),Promise.resolve()}function flush(){return buffer.drain(),Promise.resolve()}return{flush,verify:verifySessionStorage,write}}const{initPromise:defaultInitPromise,logger:defaultLogger}=createLogger({sinks:[createConsoleSink(),createIndexedDbSink(),createSessionStorageSink(),createLocalStorageSink(),createFileSink()]}),initPromise=defaultInitPromise,logger=defaultLogger;function verify(){return Promise.resolve(!0)}function write(_record){return Promise.resolve()}function createNoopSink(){return{verify,write}}function createOpfsSink(){let state={},pendingBatchWrites=new Set;async function verify(){try{let opfsRoot=await navigator.storage.getDirectory(),timestamp=new Date().toISOString().replaceAll(`:`,`-`),fileHandle=await opfsRoot.getFileHandle(`monochromatic-${timestamp}.log.jsonl`,{create:!0}),probeWritable=await fileHandle.createWritable({keepExistingData:!0}),testData=`{"test":true,"timestamp":${Date.now()}}\n`;await probeWritable.write(testData),await probeWritable.close();let available=(await(await fileHandle.getFile()).text()).includes(`"test":true`);return available&&(state.writable=await fileHandle.createWritable({keepExistingData:!0})),available}catch(error){let opfsStorage=globalThis.navigator?.storage;return opfsStorage!==void 0&&`getDirectory`in opfsStorage&&reportLoggerInternalError({context:`OPFS sink verification failed`,error}),!1}}async function writeBatch(batch){if(state.writable)try{await state.writable.write(`${batch}\n`)}catch(error){reportLoggerInternalError({context:`OPFS sink record write failed`,error})}}async function removePendingWhenSettled(pending){await pending,pendingBatchWrites.delete(pending)}function handOffBatch(batch){let pending=writeBatch(batch);pendingBatchWrites.add(pending),removePendingWhenSettled(pending)}let buffer=createRecordBuffer({onFlush:handOffBatch});function write(record){return buffer.add({level:record.level,serialized:JSON.stringify(record)}),Promise.resolve()}async function flush(){buffer.drain();let writes=[...pendingBatchWrites];await Promise.all(writes)}return{flush,verify,write}}var sink_exports=__exportAll({NO_NODE_MODULES_FOUND:()=>NO_NODE_MODULES_FOUND,createConsoleSink:()=>createConsoleSink,createFileSink:()=>createFileSink,createIndexedDbSink:()=>createIndexedDbSink,createLocalStorageSink:()=>createLocalStorageSink,createNoopSink:()=>createNoopSink,createOpfsSink:()=>createOpfsSink,createSessionStorageSink:()=>createSessionStorageSink,findNodeModulesUp:()=>findNodeModulesUp});function tagged({tag,l=logger}){let prefix=`[${tag}] `;return{debug:function(message){l.debug(`${prefix}${message}`)},error:function(message){l.error(`${prefix}${message}`)},fatal:function(message){l.fatal(`${prefix}${message}`)},flush:function(){return l.flush()},info:function(message){l.info(`${prefix}${message}`)},trace:function(message){l.trace(`${prefix}${message}`)},warn:function(message){l.warn(`${prefix}${message}`)}}}export{DEFAULT_FLUSH_DEADLINE_MS,buildLogKey as _buildLogKey,compareLogKeys as _compareLogKeys,createLocalStorageStore as _createLocalStorageStore,createRecordBuffer as _createRecordBuffer,detectLocalStorageQuotaChars as _detectLocalStorageQuotaChars,detectSessionStorageQuotaChars as _detectSessionStorageQuotaChars,isQuotaExceededError as _isQuotaExceededError,neutralizeControlCharacters as _neutralizeControlCharacters,parseLogKey as _parseLogKey,createLogger,initPromise,logger,sink_exports as sinks,tagged};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var __defProp=Object.defineProperty,__exportAll=(all,no_symbols)=>{let target={};for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0});return no_symbols||__defProp(target,Symbol.toStringTag,{value:`Module`}),target};export{__exportAll as t};
|