A manifest format for browser-based package managers
Huzma (the Arabic word for package, pronounced like this, spelt in Arabic حزمة) is a manifest format for browser-based package managers. This library is a Javascript implementation of the Huzma manifest format which includes:
Various functions, constants, and types to aid in creating and validating huzma manifests.
A command line interface to ease automation.
Originally made to import game mods into the Zakhaarif Launcher, this format takes inspiration from Node's package.json and Rust's cargo.toml.
npm i huzma
A huzma is a json file that has the file extension .huzma.json
and includes these keys:
⚠️ Required
schema
: an integer value of 1
or 2
, indicating which huzma version is used.
name
: a string naming package.
version
: a vaild semver (semantic version) string, indicating the version of package. Implementation provided by small-semver package.
✅ Optional
files
: an array of strings or objects indicating files that should be cached on disk if possible (via Cache API
, IndexedDB
, etc.). Objects must include a string value at name
field and an optional integer value at bytes
field and invalidation (string) at invalidation
field.
If a string value is provided it indicates the relative url of a file. If an object value is provided the name
field repersents the relative url of a file, the invalidation
field repersents how file should be diffed on package update,
and the bytes
field repersents uncompressed size of file in bytes.
All File urls must be relative to huzma manifest and cannot be an absolute url or start with ../
.
Example:
{
"files": [
"index.js",
"./index.js",
"assets/cat.png",
{"name": "assets/doggo.png"},
{"name": "styles/style.css", "bytes": 1234},
{
"name": "multi-thread.wasm",
"invalidation": "purge"
},
{
"name": "config.json",
"invalidation": "url-diff",
"bytes": 10540
}
]
}
entry
: a url relative to huzma manifest that denotes an entry script (cannot be an absolute url or start with ../
.). This communicates to package managers which file to import in order to execute code included in package.
invalidation
: specify the default invalidation strategy for all files mentioned in files
field.
description
: a string that describes package.
authors
: an array of objects repersenting project maintainers / main contributors. Object must include a string value at name
field, and optionally can provide an email value at email
field and url (absolute) for at url
field.
Example:
{
"authors": [
{"name": "moomoolive"},
{
"name": "milk_farmer",
"email": "lactose-free@dairy.com"
},
{
"name": "pure_lactose",
"email": "we-love-lactose@farm.com",
"url": "https://whatsinyourmilk.milk"
}
]
}
logoUrl
: a relative or absolute url to a picture that repersents package. Examples: https://yo-mamas.house/logo.png
, ./silly-logo.jpg
, etc.
keywords
: an array of string tags that describe package. Examples: penguins
, kitties
, html-parser
, etc.
license
: a string denoting license granted to package user. Examples: MIT
, GPL-3
, Apache-2
, My-Own-Cool-License
, etc.
repo
: an object representing package's code repository, with an optional string value at type
field and url at url
field.
Example:
{
"repo": {
"type": "git",
"url": "https://github.com/moomoolive/huzma"
}
}
homepageUrl
: absolute url to package website. Example: https://www.nexusmods.com/my-amazing-mod-homepage
permissions
: an array of strings or objects with a string value at key
field and an array of strings at value
field. A string value (i.e "permission"
) is equivalent to an object with a string value at key
field and an empty array at value
field (i.e { "key": "permission", "value": [] }
).
It is up to package managers to implement a concrete set of permissions.
Example:
{
"permissions": [
"permission1",
{"key": "permission2", "value": []},
{"key": "permission3", "value": ["value1"]},
{"key": "permission3", "value": ["value1", "value2"]},
]
}
metadata
: an object of arbitrary key & value pairs, where values are strings. Denotes specific information a particular package manager may want to know about package. Works similar to http headers.
Example:
{
"metadata": {
"is-extension": "true",
"pkg-manager-x-key": "key-exists",
"created": "100003231414",
"updated": "100003431414"
}
}
If a new version of a package is released, package managers will need to update the cached files of said package. Providing an invalidation strategy for a file(s) hints to package managers how to cache files.
Here are a list of strategies that may be provided:
url-diff
: file should only be cached if file with same url does not exist in package manager cache. Otherwise, file should not be cached.
purge
: file should be recached on every new package version, regardless if a file with same url exists in package manager cache. By default the entry
file of a huzma manifest uses this strategy if it is found in files
.
default
: let package manager decide.
This package comes bundled with cli commands to help create huzem (plural for huzma). All commands can be programmatically invoked from as well. Package must be installed to invoke commands.
Initialize a huzma config file - a configuration file which is used by other commands in this package.
Options:
path
: a path where huzma config file should be created, must end with js
or mjs
extension. Defaults to huzma.config.mjs
.
CLI:
npx huzma-init --path huzma.config.mjs
JS:
import {initHuzma} from "huzma/dist/cli.js"
await initHuzma({path: "huzma.config.mjs"})
template
: available templates include zakhaarif
. Defaults to empty string.
CLI:
npx huzma-init --template zakhaarif
JS:
import {initHuzma} from "huzma/dist/cli.js"
await initHuzma({template: "zakhaarif"})
Create a huzma manifest.
Options:
buildDir
: ⚠️ required, directory that includes all package files.
CLI:
npx huzma-create --buildDir dist
JS:
import {createHuzma} from "huzma/dist/cli.js"
await createHuzma({buildDir: "dist"})
outFile
: the full path with the generated huzma manifest should be written to. Path must end with .huzma.json
. Defaults to buildDir
+ default.huzma.json
.
CLI:
npx huzma-create --outFile dist/default.huzma.json
js:
import {createHuzma} from "huzma/dist/cli.js"
await createHuzma({outFile: "dist/default.huzma.json"})
configFileName
: path to huzma config file, path must end with js
or mjs
. Can be generated via npx huzma-init
command. Defaults to huzma.config.mjs
CLI:
npx huzma-create --configFileName huzma.config.mjs
JS:
import {createHuzma} from "huzma/dist/cli.js"
await createHuzma({configFileName: "huzma.config.mjs"})
packageJsonPath
: Path to package json from which to auto-fill missing values from. See disablePackageJsonFill
for more details. Defaults to package.json
CLI:
npx huzma-create --packageJsonPath package.json
JS:
import {createHuzma} from "huzma/dist/cli.js"
await createHuzma({packageJsonPath: "package.json"})
disablePackageJsonFill
: Whether missing values not found in config file & inline config should be autofilled from package json. Values in package json are given a lower precedent than values found in config file or inline config. Setting flag disables auto-fill. To set path of package json set the packageJsonPath
argument. Values that can be auto-filled from package.json
include:
name
version
description
keywords
license
repository
: maps to huzma's repo
field.contributors
: maps to huzma's authors
field.homepage
: maps to huzma's homepageUrl
field.CLI:
npx huzma-create --disablePackageJsonFill
JS:
import {createHuzma} from "huzma/dist/cli.js"
await createHuzma({disablePackageJsonFill: true})
inlineConfigFile
: provide an inline config, which takes precedent over config file. Defaults to null. Cannot be used from cli.
JS:
import {createHuzma} from "huzma/dist/cli.js"
await createHuzma({
inlineConfigFile: {
name: "my-huzma",
version: "0.1.0"
// ...rest of config
}
})
Generated using TypeDoc