fatsify核心功能示例测试!!!

This commit is contained in:
2025-09-21 14:50:41 +08:00
commit 9145aea047
1958 changed files with 230098 additions and 0 deletions

45
node_modules/avvio/lib/create-promise.js generated vendored Normal file
View File

@@ -0,0 +1,45 @@
'use strict'
/**
* @callback PromiseResolve
* @param {any|PromiseLike<any>} value
* @returns {void}
*/
/**
* @callback PromiseReject
* @param {any} reason
* @returns {void}
*/
/**
* @typedef PromiseObject
* @property {Promise} promise
* @property {PromiseResolve} resolve
* @property {PromiseReject} reject
*/
/**
* @returns {PromiseObject}
*/
function createPromise () {
/**
* @type {PromiseObject}
*/
const obj = {
resolve: null,
reject: null,
promise: null
}
obj.promise = new Promise((resolve, reject) => {
obj.resolve = resolve
obj.reject = reject
})
return obj
}
module.exports = {
createPromise
}

19
node_modules/avvio/lib/debug.js generated vendored Normal file
View File

@@ -0,0 +1,19 @@
'use strict'
const { debuglog } = require('node:util')
/**
* @callback DebugLogger
* @param {string} msg
* @param {...unknown} param
* @returns {void}
*/
/**
* @type {DebugLogger}
*/
const debug = debuglog('avvio')
module.exports = {
debug
}

38
node_modules/avvio/lib/errors.js generated vendored Normal file
View File

@@ -0,0 +1,38 @@
'use strict'
const { createError } = require('@fastify/error')
module.exports = {
AVV_ERR_EXPOSE_ALREADY_DEFINED: createError(
'AVV_ERR_EXPOSE_ALREADY_DEFINED',
"'%s' is already defined, specify an expose option for '%s'"
),
AVV_ERR_ATTRIBUTE_ALREADY_DEFINED: createError(
'AVV_ERR_ATTRIBUTE_ALREADY_DEFINED',
"'%s' is already defined"
),
AVV_ERR_CALLBACK_NOT_FN: createError(
'AVV_ERR_CALLBACK_NOT_FN',
"Callback for '%s' hook is not a function. Received: '%s'"
),
AVV_ERR_PLUGIN_NOT_VALID: createError(
'AVV_ERR_PLUGIN_NOT_VALID',
"Plugin must be a function or a promise. Received: '%s'"
),
AVV_ERR_ROOT_PLG_BOOTED: createError(
'AVV_ERR_ROOT_PLG_BOOTED',
'Root plugin has already booted'
),
AVV_ERR_PARENT_PLG_LOADED: createError(
'AVV_ERR_PARENT_PLG_LOADED',
"Impossible to load '%s' plugin because the parent '%s' was already loaded"
),
AVV_ERR_READY_TIMEOUT: createError(
'AVV_ERR_READY_TIMEOUT',
"Plugin did not start in time: '%s'. You may have forgotten to call 'done' function or to resolve a Promise"
),
AVV_ERR_PLUGIN_EXEC_TIMEOUT: createError(
'AVV_ERR_PLUGIN_EXEC_TIMEOUT',
"Plugin did not start in time: '%s'. You may have forgotten to call 'done' function or to resolve a Promise"
)
}

28
node_modules/avvio/lib/execute-with-thenable.js generated vendored Normal file
View File

@@ -0,0 +1,28 @@
'use strict'
const { isPromiseLike } = require('./is-promise-like')
const { kAvvio } = require('./symbols')
/**
* @callback ExecuteWithThenableCallback
* @param {Error} error
* @returns {void}
*/
/**
* @param {Function} func
* @param {Array<any>} args
* @param {ExecuteWithThenableCallback} [callback]
*/
function executeWithThenable (func, args, callback) {
const result = func.apply(func, args)
if (isPromiseLike(result) && !result[kAvvio]) {
// process promise but not avvio mock thenable
result.then(() => process.nextTick(callback), (error) => process.nextTick(callback, error))
} else if (callback) {
process.nextTick(callback)
}
}
module.exports = {
executeWithThenable
}

34
node_modules/avvio/lib/get-plugin-name.js generated vendored Normal file
View File

@@ -0,0 +1,34 @@
'use strict'
// this symbol is assigned by fastify-plugin
const { kPluginMeta } = require('./symbols')
/**
* @param {function} plugin
* @param {object} [options]
* @param {string} [options.name]
* @returns {string}
*/
function getPluginName (plugin, options) {
// use explicit function metadata if set
if (plugin[kPluginMeta] && plugin[kPluginMeta].name) {
return plugin[kPluginMeta].name
}
// use explicit name option if set
if (options && options.name) {
return options.name
}
// determine from the function
if (plugin.name) {
return plugin.name
} else {
// takes the first two lines of the function if nothing else works
return plugin.toString().split('\n').slice(0, 2).map(s => s.trim()).join(' -- ')
}
}
module.exports = {
getPluginName
}

View File

@@ -0,0 +1,23 @@
'use strict'
/**
* bundled or typescript plugin
* @typedef {object} BundledOrTypescriptPlugin
* @property {function} default
*/
/**
* @param {any} maybeBundledOrTypescriptPlugin
* @returns {plugin is BundledOrTypescriptPlugin}
*/
function isBundledOrTypescriptPlugin (maybeBundledOrTypescriptPlugin) {
return (
maybeBundledOrTypescriptPlugin !== null &&
typeof maybeBundledOrTypescriptPlugin === 'object' &&
typeof maybeBundledOrTypescriptPlugin.default === 'function'
)
}
module.exports = {
isBundledOrTypescriptPlugin
}

17
node_modules/avvio/lib/is-promise-like.js generated vendored Normal file
View File

@@ -0,0 +1,17 @@
'use strict'
/**
* @param {any} maybePromiseLike
* @returns {maybePromiseLike is PromiseLike}
*/
function isPromiseLike (maybePromiseLike) {
return (
maybePromiseLike !== null &&
typeof maybePromiseLike === 'object' &&
typeof maybePromiseLike.then === 'function'
)
}
module.exports = {
isPromiseLike
}

279
node_modules/avvio/lib/plugin.js generated vendored Normal file
View File

@@ -0,0 +1,279 @@
'use strict'
const { EventEmitter } = require('node:events')
const { inherits } = require('node:util')
const { debug } = require('./debug')
const { createPromise } = require('./create-promise')
const { AVV_ERR_PLUGIN_EXEC_TIMEOUT } = require('./errors')
const { getPluginName } = require('./get-plugin-name')
const { isPromiseLike } = require('./is-promise-like')
/**
* @param {*} queue
* @param {*} func
* @param {*} options
* @param {boolean} isAfter
* @param {number} [timeout]
*/
function Plugin (queue, func, options, isAfter, timeout) {
this.queue = queue
this.func = func
this.options = options
/**
* @type {boolean}
*/
this.isAfter = isAfter
/**
* @type {number}
*/
this.timeout = timeout
/**
* @type {boolean}
*/
this.started = false
/**
* @type {string}
*/
this.name = getPluginName(func, options)
this.queue.pause()
/**
* @type {Error|null}
*/
this._error = null
/**
* @type {boolean}
*/
this.loaded = false
this._promise = null
this.startTime = null
}
inherits(Plugin, EventEmitter)
/**
* @callback ExecCallback
* @param {Error|null} execErr
* @returns
*/
/**
*
* @param {*} server
* @param {ExecCallback} callback
* @returns
*/
Plugin.prototype.exec = function (server, callback) {
debug('exec', this.name)
this.server = server
const func = this.func
const name = this.name
let completed = false
this.options = typeof this.options === 'function' ? this.options(this.server) : this.options
let timer = null
/**
* @param {Error} [execErr]
*/
const done = (execErr) => {
if (completed) {
debug('loading complete', name)
return
}
this._error = execErr
if (execErr) {
debug('exec errored', name)
} else {
debug('exec completed', name)
}
completed = true
if (timer) {
clearTimeout(timer)
}
callback(execErr)
}
if (this.timeout > 0) {
debug('setting up timeout', name, this.timeout)
timer = setTimeout(function () {
debug('timed out', name)
timer = null
const readyTimeoutErr = new AVV_ERR_PLUGIN_EXEC_TIMEOUT(name)
// TODO Remove reference to function
readyTimeoutErr.fn = func
done(readyTimeoutErr)
}, this.timeout)
}
this.started = true
this.startTime = Date.now()
this.emit('start', this.server ? this.server.name : null, this.name, Date.now())
const maybePromiseLike = func(this.server, this.options, done)
if (isPromiseLike(maybePromiseLike)) {
debug('exec: resolving promise', name)
maybePromiseLike.then(
() => process.nextTick(done),
(e) => process.nextTick(done, e))
} else if (func.length < 3) {
done()
}
}
/**
* @returns {Promise}
*/
Plugin.prototype.loadedSoFar = function () {
debug('loadedSoFar', this.name)
if (this.loaded) {
return Promise.resolve()
}
const setup = () => {
this.server.after((afterErr, callback) => {
this._error = afterErr
this.queue.pause()
if (this._promise) {
if (afterErr) {
debug('rejecting promise', this.name, afterErr)
this._promise.reject(afterErr)
} else {
debug('resolving promise', this.name)
this._promise.resolve()
}
this._promise = null
}
process.nextTick(callback, afterErr)
})
this.queue.resume()
}
let res
if (!this._promise) {
this._promise = createPromise()
res = this._promise.promise
if (!this.server) {
this.on('start', setup)
} else {
setup()
}
} else {
res = Promise.resolve()
}
return res
}
/**
* @callback EnqueueCallback
* @param {Error|null} enqueueErr
* @param {Plugin} result
*/
/**
*
* @param {Plugin} plugin
* @param {EnqueueCallback} callback
*/
Plugin.prototype.enqueue = function (plugin, callback) {
debug('enqueue', this.name, plugin.name)
this.emit('enqueue', this.server ? this.server.name : null, this.name, Date.now())
this.queue.push(plugin, callback)
}
/**
* @callback FinishCallback
* @param {Error|null} finishErr
* @returns
*/
/**
*
* @param {Error|null} err
* @param {FinishCallback} callback
* @returns
*/
Plugin.prototype.finish = function (err, callback) {
debug('finish', this.name, err)
const done = () => {
if (this.loaded) {
return
}
debug('loaded', this.name)
this.emit('loaded', this.server ? this.server.name : null, this.name, Date.now())
this.loaded = true
callback(err)
}
if (err) {
if (this._promise) {
this._promise.reject(err)
this._promise = null
}
done()
return
}
const check = () => {
debug('check', this.name, this.queue.length(), this.queue.running(), this._promise)
if (this.queue.length() === 0 && this.queue.running() === 0) {
if (this._promise) {
const wrap = () => {
debug('wrap')
queueMicrotask(check)
}
this._promise.resolve()
this._promise.promise.then(wrap, wrap)
this._promise = null
} else {
done()
}
} else {
debug('delayed', this.name)
// finish when the queue of nested plugins to load is empty
this.queue.drain = () => {
debug('drain', this.name)
this.queue.drain = noop
// we defer the check, as a safety net for things
// that might be scheduled in the loading callback
queueMicrotask(check)
}
}
}
queueMicrotask(check)
// we start loading the dependents plugins only once
// the current level is finished
this.queue.resume()
}
function noop () {}
module.exports = {
Plugin
}

26
node_modules/avvio/lib/symbols.js generated vendored Normal file
View File

@@ -0,0 +1,26 @@
'use strict'
// Internal Symbols
const kAvvio = Symbol('avvio.Boot')
const kIsOnCloseHandler = Symbol('isOnCloseHandler')
const kThenifyDoNotWrap = Symbol('avvio.ThenifyDoNotWrap')
const kUntrackNode = Symbol('avvio.TimeTree.untrackNode')
const kTrackNode = Symbol('avvio.TimeTree.trackNode')
const kGetParent = Symbol('avvio.TimeTree.getParent')
const kGetNode = Symbol('avvio.TimeTree.getNode')
const kAddNode = Symbol('avvio.TimeTree.addNode')
// Public Symbols
const kPluginMeta = Symbol.for('plugin-meta')
module.exports = {
kAvvio,
kIsOnCloseHandler,
kThenifyDoNotWrap,
kUntrackNode,
kTrackNode,
kGetParent,
kGetNode,
kAddNode,
kPluginMeta
}

60
node_modules/avvio/lib/thenify.js generated vendored Normal file
View File

@@ -0,0 +1,60 @@
'use strict'
const { debug } = require('./debug')
const { kThenifyDoNotWrap } = require('./symbols')
/**
* @callback PromiseConstructorLikeResolve
* @param {any} value
* @returns {void}
*/
/**
* @callback PromiseConstructorLikeReject
* @param {reason} error
* @returns {void}
*/
/**
* @callback PromiseConstructorLike
* @param {PromiseConstructorLikeResolve} resolve
* @param {PromiseConstructorLikeReject} reject
* @returns {void}
*/
/**
* @returns {PromiseConstructorLike}
*/
function thenify () {
// If the instance is ready, then there is
// nothing to await. This is true during
// await server.ready() as ready() resolves
// with the server, end we will end up here
// because of automatic promise chaining.
if (this.booted) {
debug('thenify returning undefined because we are already booted')
return
}
// Calling resolve(this._server) would fetch the then
// property on the server, which will lead it here.
// If we do not break the recursion, we will loop
// forever.
if (this[kThenifyDoNotWrap]) {
this[kThenifyDoNotWrap] = false
return
}
debug('thenify')
return (resolve, reject) => {
const p = this._loadRegistered()
return p.then(() => {
this[kThenifyDoNotWrap] = true
return resolve(this._server)
}, reject)
}
}
module.exports = {
thenify
}

200
node_modules/avvio/lib/time-tree.js generated vendored Normal file
View File

@@ -0,0 +1,200 @@
'use strict'
const {
kUntrackNode,
kTrackNode,
kGetParent,
kGetNode,
kAddNode
} = require('./symbols')
/**
* Node of the TimeTree
* @typedef {object} TimeTreeNode
* @property {string} id
* @property {string|null} parent
* @property {string} label
* @property {Array<TimeTreeNode>} nodes
* @property {number} start
* @property {number|undefined} stop
* @property {number|undefined} diff
*/
class TimeTree {
constructor () {
/**
* @type {TimeTreeNode|null} root
* @public
*/
this.root = null
/**
* @type {Map<string, TimeTreeNode>} tableId
* @public
*/
this.tableId = new Map()
/**
* @type {Map<string, Array<TimeTreeNode>>} tableLabel
* @public
*/
this.tableLabel = new Map()
}
/**
* @param {TimeTreeNode} node
*/
[kTrackNode] (node) {
this.tableId.set(node.id, node)
if (this.tableLabel.has(node.label)) {
this.tableLabel.get(node.label).push(node)
} else {
this.tableLabel.set(node.label, [node])
}
}
/**
* @param {TimeTreeNode} node
*/
[kUntrackNode] (node) {
this.tableId.delete(node.id)
const labelNode = this.tableLabel.get(node.label)
labelNode.pop()
if (labelNode.length === 0) {
this.tableLabel.delete(node.label)
}
}
/**
* @param {string} parent
* @returns {TimeTreeNode}
*/
[kGetParent] (parent) {
if (parent === null) {
return null
} else if (this.tableLabel.has(parent)) {
const parentNode = this.tableLabel.get(parent)
return parentNode[parentNode.length - 1]
} else {
return null
}
}
/**
*
* @param {string} nodeId
* @returns {TimeTreeNode}
*/
[kGetNode] (nodeId) {
return this.tableId.get(nodeId)
}
/**
* @param {string} parent
* @param {string} label
* @param {number} start
* @returns {TimeTreeNode["id"]}
*/
[kAddNode] (parent, label, start) {
const parentNode = this[kGetParent](parent)
const isRoot = parentNode === null
if (isRoot) {
this.root = {
parent: null,
id: 'root',
label,
nodes: [],
start,
stop: null,
diff: -1
}
this[kTrackNode](this.root)
return this.root.id
}
const nodeId = `${label}-${Math.random()}`
/**
* @type {TimeTreeNode}
*/
const childNode = {
parent,
id: nodeId,
label,
nodes: [],
start,
stop: null,
diff: -1
}
parentNode.nodes.push(childNode)
this[kTrackNode](childNode)
return nodeId
}
/**
* @param {string} parent
* @param {string} label
* @param {number|undefined} start
* @returns {TimeTreeNode["id"]}
*/
start (parent, label, start = Date.now()) {
return this[kAddNode](parent, label, start)
}
/**
* @param {string} nodeId
* @param {number|undefined} stop
*/
stop (nodeId, stop = Date.now()) {
const node = this[kGetNode](nodeId)
if (node) {
node.stop = stop
node.diff = (node.stop - node.start) || 0
this[kUntrackNode](node)
}
}
/**
* @returns {TimeTreeNode}
*/
toJSON () {
return Object.assign({}, this.root)
}
/**
* @returns {string}
*/
prettyPrint () {
return prettyPrintTimeTree(this.toJSON())
}
}
/**
* @param {TimeTreeNode} obj
* @param {string|undefined} prefix
* @returns {string}
*/
function prettyPrintTimeTree (obj, prefix = '') {
let result = prefix
const nodesCount = obj.nodes.length
const lastIndex = nodesCount - 1
result += `${obj.label} ${obj.diff} ms\n`
for (let i = 0; i < nodesCount; ++i) {
const node = obj.nodes[i]
const prefix_ = prefix + (i === lastIndex ? ' ' : '│ ')
result += prefix
result += (i === lastIndex ? '└─' : '├─')
result += (node.nodes.length === 0 ? '─ ' : '┬ ')
result += prettyPrintTimeTree(node, prefix_).slice(prefix.length + 2)
}
return result
}
module.exports = {
TimeTree
}

26
node_modules/avvio/lib/validate-plugin.js generated vendored Normal file
View File

@@ -0,0 +1,26 @@
'use strict'
const { AVV_ERR_PLUGIN_NOT_VALID } = require('./errors')
/**
* @param {any} maybePlugin
* @throws {AVV_ERR_PLUGIN_NOT_VALID}
*
* @returns {asserts plugin is Function|PromiseLike}
*/
function validatePlugin (maybePlugin) {
// validate if plugin is a function or Promise
if (!(maybePlugin && (typeof maybePlugin === 'function' || typeof maybePlugin.then === 'function'))) {
if (Array.isArray(maybePlugin)) {
throw new AVV_ERR_PLUGIN_NOT_VALID('array')
} else if (maybePlugin === null) {
throw new AVV_ERR_PLUGIN_NOT_VALID('null')
} else {
throw new AVV_ERR_PLUGIN_NOT_VALID(typeof maybePlugin)
}
}
}
module.exports = {
validatePlugin
}