@small-web/kitten
Version:
Type-safe global Kitten namespace.
338 lines (284 loc) • 10.1 kB
JavaScript
/**
Imports.
@typedef {import('./types.d.ts').Session} Session
@typedef {import('node:events').EventEmitter} EventEmitter
@typedef {typeof import('./types.d.ts').WebSocket} WebSocket
@typedef {typeof import('./types.d.ts').slugify} slugify
@typedef {typeof import('./types.d.ts').yaml} yaml
@typedef {import('./types.d.ts').MarkdownIt} MarkdownIt
@typedef {import('./types.d.ts').Polka} Polka
*/
const _kitten = /** @type {Object} */ (globalThis.kitten)
export const version = /** @type {{
"date": Date,
"versionStamp": number,
"gitHash": string,
"apiVersion": number,
"nodeVersion": string,
"exactVersion": string,
"birthday": string,
"starSign": string,
"Component": () => Function,
"html": () => string,
"printToConsole": () => void
}} */ (_kitten.version)
export const Upload = /** @type {import('./types.d.ts').Upload} */ (_kitten.Upload)
export const uploads = /** @type {{
get(id:string): Upload
length(): number
all(): Upload[]
allIds(): string[]
delete(id:string): Promise<void>
} & Record<string, Upload>}
*/ (_kitten._db.uploads)
export const icons = /** @type {import('kitten-icons/types.d.ts').KittenIcons} */ (_kitten.icons)
// db is the custom database. If you want type safety for it,
// create a database app module in your project and declare
// the types there.
// See: https://codeberg.org/kitten/app#database-app-module
export const db = /** @type {Object} */ (_kitten.db)
/**
@typedef {Object.<string, number>} StatsObject
*/
export const _db = /** @type {{
sessions: Object.<string, Session>,
settings: {
autoUpdate: {
interval: number
},
domainToken: string,
evergreenWebUrl: string,
hideWelcomeMessage: boolean,
id: {
ed25519: {
asString: string
},
ssh: {
asString: string,
fingerprint: string
}
},
packageLockFileHashes: Object.<string, string>
path:string,
smallWebHostDomain: string,
stats: {
hits: StatsObject,
pages: StatsObject,
missing: StatsObject,
referrers: StatsObject,
serverErrors: StatsObject
},
uploads: uploads,
webhookSecret: string,
},
uploads: Object.<string, Upload>,
}} */ (_kitten._db)
export const appRepository = /** @type {{
upgradeAppToLatestCompatibleVersion(): Promise<void>
upgradeAppToLatestAvailableCommit(): Promise<void>
updateAppToVersion(versionTag:string): Promise<void>
update(): Promise<void>
hasCompatibleAppVersion: boolean
canBeUpdated: boolean
hasNewerApiVersion: boolean
upgradeOrDowngrade(versionTag:string, lowercase:boolean): ('upgrade'|'downgrade')
isEqualToVersion(versionTag:string): boolean
UpdateButtonComponent(): (type:string, version:string, small:boolean) => string|Array<string>
VersionComponent(): (version:string, compatible:boolean, brief:boolean) => string|Array<string>
CurrentAppVersionComponent(): () => string|Array<string>
AllAvailableVersionsComponent(): () => string|Array<string>
displayAppVersion(): void
}} */ (_kitten.appRepository)
export const automaticUpdates = /** @type {{
interval: number
intervalInHours: number
timeToNextCheck(): number
timeToNextCheckPretty(): string
start(): void
checkForUpdates(): Promise<void>
stop(): void
}} */ (_kitten.automaticUpdates)
// Note: can’t call this package as that’s a reserved word in strict mode.
export const _package = /** @type {{
hasCompatibleVersion: boolean
isLatestReleaseVersion: boolean
isMoreRecentThanReleaseVersion: boolean
canBeUpgraded: boolean
upgrade(apiVersion:(number|undefined)):void
update():Promise<void>
}} */ (_kitten.package)
export const Component = /** @type {typeof import('./types.d.ts').KittenComponent} */ (_kitten.Component)
export const Page = /** @type {typeof import('./types.d.ts').KittenPage} */ (_kitten.Page)
export const domain = /** @type {string} */ (_kitten.domain)
export const port = /** @type {number} */ (_kitten.port)
export const databaseDirectory = /** @type {string} */ (_kitten.databaseDirectory)
export const projectIdentifier = /** @type {string} */ (_kitten.projectIdentifier)
export const events = /** @type {EventEmitter} */ (_kitten.events)
export const html = /** @type {taggedTemplate} */ (_kitten.html)
export const markdown = /** @type {taggedTemplate} */ (_kitten.markdown)
export const md = /** @type {MarkdownIt} */ (_kitten.md)
export const css = /** @type {taggedTemplate} */ (_kitten.css)
export const js = /** @type {taggedTemplate} */ (_kitten.js)
export const WebSocket = /** @type {WebSocket} */ (_kitten.WebSocket)
export const slugify = /** @type {slugify} */ (_kitten.slugify)
export const yaml = /** @type {yaml} */ (_kitten.yaml)
/**
@typedef { Uint8Array | string } Hex
@typedef { Hex | bigint | number } PrivKey
@typedef { Hex | Point } PubKey
@typedef { Hex | Signature } SigType
@typedef {typeof import('./types.d.ts').Signature} Signature
@typedef {typeof import('./types.d.ts').Point} Point
*/
export const crypto = /** @type {{
bytesToHex: (uint8a: Uint8Array) => string,
decrypt: (sharedKey: Uint8Array, encoded: string | Uint8Array) => Uint8Array,
emojiStringToSecret: (emojiString: string) => Uint8Array,
encrypt: (sharedKey: Uint8Array, plaintext: string | Uint8Array) => Uint8Array,
getSharedSecret: (privateKey: PrivKey, publicKey: Hex) => Promise<Uint8Array>,
hexToBytes: (hex: string) => Uint8Array,
randomBytes: (bytesLength?: number) => Uint8Array,
random32ByteTokenInHex: () => string,
secretToEmojiString: (secret: Uint8Array) => string,
sign: (message: Hex, privateKey: Hex) => Promise<Uint8Array>,
verify: (sig: SigType, message: Hex, publicKey: PubKey) => Promise<boolean>,
}} */ (_kitten.crypto)
export const deprecationWarnings = /** @type {Array.<string>} */ (_kitten.deprecationWarnings)
export const paths = /** @type {{
APP_DATA_DIRECTORY: string,
APP_UPLOADS_DIRECTORY: string,
APP_REPL_DIRECTORY: string
}} */ (_kitten.paths)
export const app = /** @type {{
package?: any
router: Polka
server: import('node:https').Server
}} */ (_kitten.app)
export const deploy = /** @type {function} */ (_kitten.deploy)
//////////////////////////////////////////////////////////////////////////////////////////
// Kept for backwards compatibility with existing projects.
export const HTMX = /** @type {string} */ (_kitten.libraries.htmx)
export const HTMX_WEBSOCKET = /** @type {string} */ (_kitten.libraries.htmxWebSocket)
export const HTMX_IDIOMORPH = /** @type {string} */ (_kitten.libraries.htmxIdiomorph)
export const ALPINEJS = /** @type {string} */ (_kitten.libraries.alpineJs)
export const WATER = /** @type {string} */ (_kitten.libraries.water)
export const safelyAddHtml = /** @type {sanitisationFunction} */ (_kitten.safelyAddHtml)
export const sanitise = /** @type {sanitisationFunction} */ (_kitten.sanitise)
export const PAGE = {
html: 'HTML',
head: 'HEAD',
startOfBody: 'START_OF_BODY',
beforeLibraries: 'BEFORE_LIBRARIES',
afterLibraries: 'AFTER_LIBRARIES',
endOfBody: 'END_OF_BODY'
}
//////////////////////////////////////////////////////////////////////////////////////////
export const libraries = {
htmx: HTMX,
htmxIdiomorph: HTMX_IDIOMORPH,
htmxWebSocket: HTMX_WEBSOCKET,
alpineJs: ALPINEJS,
water: WATER
}
export const page = PAGE
/**
@callback taggedTemplate
@param {TemplateStringsArray} strings
@param {...any} properties
@returns {string|Array<string>|Promise<string|Array<string>>}
*/
/**
@callback sanitisationFunction
@param {string} untrustedContent
@param {Array<string>=} allowedTags
@param {boolean=} contact
@returns {string}
*/
export const requests = /** @type {Array.<string>} */ (_kitten.requests)
export const pages = /** @type {Object.<string, import('./types.d.ts').KittenPage>} */ (_kitten.pages)
/**
@typedef {{
domain?: string,
port?: number,
aliases?:string,
open?:boolean,
'working-directory'?: string,
'domain-token'?: string,
'small-web-host-domain'?: string
}} ServerOptions
*/
export const utils = /** @type {{
ALL_ROUTE_EXTENSIONS: Array.<string>,
BACKEND_EXTENSIONS: Array.<string>,
DEPENDENCY_EXTENSIONS: Array.<string>,
DYNAMIC_ROUTE_EXTENSIONS: Array.<string>,
FRONTEND_EXTENSIONS: Array.<string>,
HTTP_METHODS: Array.<string>,
STATIC_ROUTE_EXTENSIONS: Array.<string>,
classNameFromFilePath: (filePath: string, basePath: string) => string,
classNameFromRoutePattern: (pattern: string) => string,
db: {
keypathForChange (change:string):string
},
decodeFilePath: (filePath: string) => string,
encodeFilePath: (filePath: string) => string,
exitWithError: (message: string) => void,
extensionCategories: {
backendRoutes: Array.<string>,
frontendRoutes: Array.<string>,
dependencies: Array.<string>,
dynamicRoutes: Array.<string>,
staticRoutes: Array.<string>,
allRoutes: Array.<string>
},
extensionOfFilePath: (filePath: string) => string,
getDomainsAndPort: (options: ServerOptions) => { domains: string[], port: number },
getProjectIdentifierForDomain: (domain: string, port: number) => string,
kittenAppPath: string,
npm: (command: 'ci'|'install', modulePath: string) => boolean,
routePatternFromFilePath: (filePath: string, basePath: string) => string,
runNpmCiOnModulePath: (modulePath: string) => void,
setBasePath: (workingDirectory: string, pathToServe: string) => string,
supportedExtensionsRegExp: RegExp,
}} */ (_kitten.utils)
// New kitten namespace.
export const kitten = {
version,
app,
db,
_db,
Upload,
uploads,
icons,
domain,
port,
databaseDirectory,
projectIdentifier,
appRepository,
automaticUpdates,
// Note the mapping: due to package being a reserved word in strict mode.
package: _package,
requests,
pages,
events,
Component,
Page,
html,
css,
js,
markdown,
md,
slugify,
yaml,
crypto,
utils,
libraries,
page,
safelyAddHtml,
sanitise,
WebSocket,
deprecationWarnings,
paths,
deploy
}
export default kitten