diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..1ca0343
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,11 @@
+FROM binwiederhier/ntfy:v2.19.2
+
+RUN apk add --no-cache bash curl yq
+
+COPY scripts/docker_entrypoint.sh /usr/local/bin/docker_entrypoint.sh
+COPY scripts/check-web.sh /usr/local/bin/check-web.sh
+RUN chmod +x /usr/local/bin/docker_entrypoint.sh /usr/local/bin/check-web.sh
+
+EXPOSE 80
+
+ENTRYPOINT ["/usr/local/bin/docker_entrypoint.sh"]
diff --git a/README.md b/README.md
index d9f8390..abdd851 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-
+
# NTFY on StartOS
diff --git a/icon.png b/icon.png
new file mode 100644
index 0000000..05c6fd8
Binary files /dev/null and b/icon.png differ
diff --git a/instructions.md b/instructions.md
new file mode 100644
index 0000000..aec6866
--- /dev/null
+++ b/instructions.md
@@ -0,0 +1,44 @@
+# NTFY on StartOS
+
+NTFY is a simple HTTP-based pub-sub notification service. Send push
+notifications to your phone or desktop via scripts or a REST API.
+
+## Initial Setup
+
+1. Install and start the service.
+2. In the service config, set **Base URL** to your public URL (your Tor
+ `.onion` address or LAN HTTPS address). This is required for attachment
+ links and web push to work correctly.
+3. Open the Web Interface (from the Tor address or LAN HTTPS address).
+4. Create your first user via the signup form. By default this user is a
+ regular (non-admin) user.
+5. To promote a user to admin, open a shell into the container and run:
+
+ ```
+ ntfy user change-role admin
+ ```
+
+6. Once you have an admin, you can disable signup in the service config.
+
+## Configuration
+
+Available in the service config:
+
+- **Enable Signup**: allow new users to register accounts
+- **Base URL**: public URL of your server (Tor `.onion` or LAN HTTPS URL)
+- **Log Level**: server log verbosity
+- **Attachment File Size Limit**: maximum size of a single attachment
+- **Attachment Total Size Limit**: maximum total disk usage for attachments
+- **Per-Visitor Attachment Limit**: per-visitor attachment quota
+- **Cache Duration**: how long messages and attachments are retained
+
+## Usage
+
+Publish a notification:
+
+```
+curl -d "Hello from StartOS" https://your-ntfy-address/mytopic
+```
+
+Subscribe from the web interface, mobile app, or any HTTP client.
+See https://docs.ntfy.sh/ for full documentation.
diff --git a/manifest.yaml b/manifest.yaml
new file mode 100644
index 0000000..2ed60b7
--- /dev/null
+++ b/manifest.yaml
@@ -0,0 +1,113 @@
+id: ntfy
+title: NTFY
+version: 2.19.2
+release-notes: |
+ * Initial StartOS 0.3.5 release of NTFY
+license: Apache-2.0
+wrapper-repo: "https://github.com/JesseMarkowitz/ntfy-startos"
+upstream-repo: "https://github.com/binwiederhier/ntfy"
+support-site: "https://github.com/binwiederhier/ntfy/issues"
+marketing-site: "https://ntfy.sh/"
+donation-url: "https://github.com/sponsors/binwiederhier"
+build: ["make"]
+description:
+ short: Send push notifications to your phone or desktop via HTTP PUT/POST
+ long: |
+ ntfy (pronounced "notify") is a simple HTTP-based pub-sub notification
+ service. It allows you to send notifications to your phone or desktop via
+ scripts from any computer, and/or using a REST API. It's entirely free
+ software, open source, and very lightweight.
+assets:
+ license: LICENSE
+ icon: icon.png
+ instructions: instructions.md
+main:
+ type: docker
+ image: main
+ entrypoint: "docker_entrypoint.sh"
+ args: []
+ mounts:
+ main: /data
+health-checks:
+ web:
+ name: Web Interface
+ success-message: The NTFY web interface is ready
+ type: docker
+ image: main
+ entrypoint: "check-web.sh"
+ args: []
+ io-format: json
+ inject: true
+config:
+ get:
+ type: script
+ set:
+ type: script
+properties: ~
+volumes:
+ main:
+ type: data
+interfaces:
+ main:
+ name: Web Interface
+ description: The main web interface for NTFY
+ tor-config:
+ port-mapping:
+ 80: "80"
+ lan-config:
+ 443:
+ ssl: true
+ internal: 80
+ ui: true
+ protocols:
+ - tcp
+ - http
+dependencies: {}
+alerts:
+ install: |
+ NTFY will be available on your Tor address and LAN (HTTPS).
+ Configure signup, attachment limits, and log level in the service config.
+ uninstall: ~
+ restore: ~
+backup:
+ create:
+ type: docker
+ image: main
+ system: false
+ entrypoint: /bin/sh
+ args:
+ - -c
+ - "cp -a /data/. /mnt/backup/ 2>/dev/null || true"
+ mounts:
+ BACKUP: /mnt/backup
+ main: /data
+ restore:
+ type: docker
+ image: main
+ system: false
+ entrypoint: /bin/sh
+ args:
+ - -c
+ - "cp -a /mnt/backup/. /data/ 2>/dev/null || true"
+ mounts:
+ BACKUP: /mnt/backup
+ main: /data
+migrations:
+ from:
+ "*":
+ type: docker
+ image: main
+ entrypoint: /bin/sh
+ args: ["-c", "echo '{\"configured\": true}'"]
+ io-format: json
+ mounts:
+ main: /data
+ to:
+ "*":
+ type: docker
+ image: main
+ entrypoint: /bin/sh
+ args: ["-c", "echo '{\"configured\": true}'"]
+ io-format: json
+ mounts:
+ main: /data
diff --git a/scripts/bundle.ts b/scripts/bundle.ts
new file mode 100644
index 0000000..5e22647
--- /dev/null
+++ b/scripts/bundle.ts
@@ -0,0 +1,5 @@
+import { bundle } from "https://deno.land/x/emit@0.40.0/mod.ts";
+
+const result = await bundle("scripts/embassy.ts");
+
+await Deno.writeTextFile("scripts/embassy.js", result.code);
diff --git a/scripts/check-web.sh b/scripts/check-web.sh
new file mode 100755
index 0000000..be37b21
--- /dev/null
+++ b/scripts/check-web.sh
@@ -0,0 +1,9 @@
+#!/bin/bash
+
+if curl -fs http://localhost:80/v1/health > /dev/null 2>&1; then
+ echo '{"result":{"version":"0","message":"The NTFY web interface is ready","value":null,"variant":"success"}}'
+ exit 0
+else
+ echo '{"result":{"version":"0","message":"The NTFY web interface is not ready","value":null,"variant":"loading"}}'
+ exit 0
+fi
diff --git a/scripts/deps.ts b/scripts/deps.ts
new file mode 100644
index 0000000..3e8055f
--- /dev/null
+++ b/scripts/deps.ts
@@ -0,0 +1,2 @@
+export * from "https://deno.land/x/embassyd_sdk@v0.3.3.0.8/mod.ts";
+export * from "https://deno.land/x/embassyd_sdk@v0.3.3.0.8/util.ts";
diff --git a/scripts/docker_entrypoint.sh b/scripts/docker_entrypoint.sh
new file mode 100755
index 0000000..fe2e077
--- /dev/null
+++ b/scripts/docker_entrypoint.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+set -e
+
+DATA_DIR="/data"
+CONFIG_FILE="${DATA_DIR}/start9/config.yaml"
+
+SIGNUP_ENABLED="true"
+LOG_LEVEL="info"
+ATTACHMENT_FILE_LIMIT="15"
+ATTACHMENT_TOTAL_LIMIT="5000"
+VISITOR_ATTACHMENT_LIMIT="100"
+CACHE_DURATION="12"
+BASE_URL=""
+
+if [ -f "$CONFIG_FILE" ]; then
+ SIGNUP_ENABLED=$(yq e '.signup-enabled // true' "$CONFIG_FILE" 2>/dev/null || echo "true")
+ LOG_LEVEL=$(yq e '.log-level // "info"' "$CONFIG_FILE" 2>/dev/null || echo "info")
+ ATTACHMENT_FILE_LIMIT=$(yq e '.attachment-file-size-limit // 15' "$CONFIG_FILE" 2>/dev/null || echo "15")
+ ATTACHMENT_TOTAL_LIMIT=$(yq e '.attachment-total-size-limit // 5000' "$CONFIG_FILE" 2>/dev/null || echo "5000")
+ VISITOR_ATTACHMENT_LIMIT=$(yq e '.visitor-attachment-limit // 100' "$CONFIG_FILE" 2>/dev/null || echo "100")
+ CACHE_DURATION=$(yq e '.cache-duration // 12' "$CONFIG_FILE" 2>/dev/null || echo "12")
+ BASE_URL=$(yq e '.base-url // ""' "$CONFIG_FILE" 2>/dev/null || echo "")
+fi
+
+mkdir -p "${DATA_DIR}/attachments"
+
+export NTFY_LISTEN_HTTP=":80"
+export NTFY_CACHE_FILE="${DATA_DIR}/cache.db"
+export NTFY_AUTH_FILE="${DATA_DIR}/auth.db"
+export NTFY_AUTH_DEFAULT_ACCESS="deny-all"
+export NTFY_BEHIND_PROXY="true"
+export NTFY_ENABLE_LOGIN="true"
+export NTFY_ENABLE_SIGNUP="${SIGNUP_ENABLED}"
+export NTFY_ATTACHMENT_CACHE_DIR="${DATA_DIR}/attachments"
+export NTFY_ATTACHMENT_FILE_SIZE_LIMIT="${ATTACHMENT_FILE_LIMIT}m"
+export NTFY_ATTACHMENT_TOTAL_SIZE_LIMIT="${ATTACHMENT_TOTAL_LIMIT}m"
+export NTFY_VISITOR_ATTACHMENT_TOTAL_SIZE_LIMIT="${VISITOR_ATTACHMENT_LIMIT}m"
+export NTFY_CACHE_DURATION="${CACHE_DURATION}h"
+export NTFY_ATTACHMENT_EXPIRY_DURATION="${CACHE_DURATION}h"
+export NTFY_KEEPALIVE_INTERVAL="45s"
+export NTFY_LOG_LEVEL="${LOG_LEVEL}"
+export NTFY_ENABLE_METRICS="true"
+
+if [ -n "$BASE_URL" ] && [ "$BASE_URL" != "null" ]; then
+ export NTFY_BASE_URL="${BASE_URL}"
+else
+ export NTFY_BASE_URL="http://localhost"
+fi
+
+echo "========================================"
+echo "NTFY Configuration:"
+echo " Base URL: ${NTFY_BASE_URL:-}"
+echo " Signup Enabled: ${NTFY_ENABLE_SIGNUP}"
+echo " Log Level: ${NTFY_LOG_LEVEL}"
+echo " Attachment File Limit: ${NTFY_ATTACHMENT_FILE_SIZE_LIMIT}"
+echo " Attachment Total Limit: ${NTFY_ATTACHMENT_TOTAL_SIZE_LIMIT}"
+echo " Cache Duration: ${NTFY_CACHE_DURATION}"
+echo "========================================"
+
+exec ntfy serve
diff --git a/scripts/embassy.js b/scripts/embassy.js
new file mode 100644
index 0000000..4629294
--- /dev/null
+++ b/scripts/embassy.js
@@ -0,0 +1,4185 @@
+function saferStringify(x) {
+ try {
+ return JSON.stringify(x);
+ } catch (e) {
+ return "" + x;
+ }
+}
+class AnyParser {
+ description;
+ constructor(description = {
+ name: "Any",
+ children: [],
+ extras: []
+ }){
+ this.description = description;
+ }
+ parse(a, onParse) {
+ return onParse.parsed(a);
+ }
+}
+class ArrayParser {
+ description;
+ constructor(description = {
+ name: "Array",
+ children: [],
+ extras: []
+ }){
+ this.description = description;
+ }
+ parse(a, onParse) {
+ if (Array.isArray(a)) return onParse.parsed(a);
+ return onParse.invalid({
+ value: a,
+ keys: [],
+ parser: this
+ });
+ }
+}
+class BoolParser {
+ description;
+ constructor(description = {
+ name: "Boolean",
+ children: [],
+ extras: []
+ }){
+ this.description = description;
+ }
+ parse(a, onParse) {
+ if (a === true || a === false) return onParse.parsed(a);
+ return onParse.invalid({
+ value: a,
+ keys: [],
+ parser: this
+ });
+ }
+}
+const isObject = (x)=>typeof x === "object" && x != null;
+const isFunctionTest = (x)=>typeof x === "function";
+const isNumber = (x)=>typeof x === "number";
+const isString = (x)=>typeof x === "string";
+const booleanOnParse = {
+ parsed (_) {
+ return true;
+ },
+ invalid (_) {
+ return false;
+ }
+};
+class FunctionParser {
+ description;
+ constructor(description = {
+ name: "Function",
+ children: [],
+ extras: []
+ }){
+ this.description = description;
+ }
+ parse(a, onParse) {
+ if (isFunctionTest(a)) return onParse.parsed(a);
+ return onParse.invalid({
+ value: a,
+ keys: [],
+ parser: this
+ });
+ }
+}
+class NilParser {
+ description;
+ constructor(description = {
+ name: "Null",
+ children: [],
+ extras: []
+ }){
+ this.description = description;
+ }
+ parse(a, onParse) {
+ if (a === null || a === undefined) return onParse.parsed(a);
+ return onParse.invalid({
+ value: a,
+ keys: [],
+ parser: this
+ });
+ }
+}
+class ObjectParser {
+ description;
+ constructor(description = {
+ name: "Object",
+ children: [],
+ extras: []
+ }){
+ this.description = description;
+ }
+ parse(a, onParse) {
+ if (isObject(a)) return onParse.parsed(a);
+ return onParse.invalid({
+ value: a,
+ keys: [],
+ parser: this
+ });
+ }
+}
+class StringParser {
+ description;
+ constructor(description = {
+ name: "String",
+ children: [],
+ extras: []
+ }){
+ this.description = description;
+ }
+ parse(a, onParse) {
+ if (isString(a)) return onParse.parsed(a);
+ return onParse.invalid({
+ value: a,
+ keys: [],
+ parser: this
+ });
+ }
+}
+class UnknownParser {
+ description;
+ constructor(description = {
+ name: "Unknown",
+ children: [],
+ extras: []
+ }){
+ this.description = description;
+ }
+ parse(a, onParse) {
+ return onParse.parsed(a);
+ }
+}
+class ConcatParsers {
+ parent;
+ otherParser;
+ description;
+ constructor(parent, otherParser, description = {
+ name: "Concat",
+ children: [
+ parent,
+ otherParser
+ ],
+ extras: []
+ }){
+ this.parent = parent;
+ this.otherParser = otherParser;
+ this.description = description;
+ }
+ static of(parent, otherParser) {
+ if (parent.unwrappedParser().description.name === "Any") {
+ return otherParser;
+ }
+ if (otherParser.unwrappedParser().description.name === "Any") {
+ return parent;
+ }
+ return new ConcatParsers(parent, otherParser);
+ }
+ parse(a, onParse) {
+ const parent = this.parent.enumParsed(a);
+ if ("error" in parent) {
+ return onParse.invalid(parent.error);
+ }
+ const other = this.otherParser.enumParsed(parent.value);
+ if ("error" in other) {
+ return onParse.invalid(other.error);
+ }
+ return onParse.parsed(other.value);
+ }
+}
+class DefaultParser {
+ parent;
+ defaultValue;
+ description;
+ constructor(parent, defaultValue, description = {
+ name: "Default",
+ children: [
+ parent
+ ],
+ extras: [
+ defaultValue
+ ]
+ }){
+ this.parent = parent;
+ this.defaultValue = defaultValue;
+ this.description = description;
+ }
+ parse(a, onParse) {
+ const parser = this;
+ const defaultValue = this.defaultValue;
+ if (a == null) {
+ return onParse.parsed(defaultValue);
+ }
+ const parentCheck = this.parent.enumParsed(a);
+ if ("error" in parentCheck) {
+ parentCheck.error.parser = parser;
+ return onParse.invalid(parentCheck.error);
+ }
+ return onParse.parsed(parentCheck.value);
+ }
+}
+class GuardParser {
+ checkIsA;
+ typeName;
+ description;
+ constructor(checkIsA, typeName, description = {
+ name: "Guard",
+ children: [],
+ extras: [
+ typeName
+ ]
+ }){
+ this.checkIsA = checkIsA;
+ this.typeName = typeName;
+ this.description = description;
+ }
+ parse(a, onParse) {
+ if (this.checkIsA(a)) {
+ return onParse.parsed(a);
+ }
+ return onParse.invalid({
+ value: a,
+ keys: [],
+ parser: this
+ });
+ }
+}
+class MappedAParser {
+ parent;
+ map;
+ mappingName;
+ description;
+ constructor(parent, map, mappingName = map.name, description = {
+ name: "Mapped",
+ children: [
+ parent
+ ],
+ extras: [
+ mappingName
+ ]
+ }){
+ this.parent = parent;
+ this.map = map;
+ this.mappingName = mappingName;
+ this.description = description;
+ }
+ parse(a, onParse) {
+ const map = this.map;
+ const result = this.parent.enumParsed(a);
+ if ("error" in result) {
+ return onParse.invalid(result.error);
+ }
+ return onParse.parsed(map(result.value));
+ }
+}
+class MaybeParser {
+ parent;
+ description;
+ constructor(parent, description = {
+ name: "Maybe",
+ children: [
+ parent
+ ],
+ extras: []
+ }){
+ this.parent = parent;
+ this.description = description;
+ }
+ parse(a, onParse) {
+ if (a == null) {
+ return onParse.parsed(null);
+ }
+ const parser = this;
+ const parentState = this.parent.enumParsed(a);
+ if ("error" in parentState) {
+ const { error } = parentState;
+ error.parser = parser;
+ return onParse.invalid(error);
+ }
+ return onParse.parsed(parentState.value);
+ }
+}
+class OrParsers {
+ parent;
+ otherParser;
+ description;
+ constructor(parent, otherParser, description = {
+ name: "Or",
+ children: [
+ parent,
+ otherParser
+ ],
+ extras: []
+ }){
+ this.parent = parent;
+ this.otherParser = otherParser;
+ this.description = description;
+ }
+ parse(a, onParse) {
+ const parser = this;
+ const parent = this.parent.enumParsed(a);
+ if ("value" in parent) {
+ return onParse.parsed(parent.value);
+ }
+ const other = this.otherParser.enumParsed(a);
+ if ("error" in other) {
+ const { error } = other;
+ error.parser = parser;
+ return onParse.invalid(error);
+ }
+ return onParse.parsed(other.value);
+ }
+}
+class NumberParser {
+ description;
+ constructor(description = {
+ name: "Number",
+ children: [],
+ extras: []
+ }){
+ this.description = description;
+ }
+ parse(a, onParse) {
+ if (isNumber(a)) return onParse.parsed(a);
+ return onParse.invalid({
+ value: a,
+ keys: [],
+ parser: this
+ });
+ }
+}
+function unwrapParser(a) {
+ if (a instanceof Parser) return unwrapParser(a.parser);
+ return a;
+}
+const enumParsed = {
+ parsed (value) {
+ return {
+ value
+ };
+ },
+ invalid (error) {
+ return {
+ error
+ };
+ }
+};
+class Parser {
+ parser;
+ description;
+ _TYPE;
+ constructor(parser, description = {
+ name: "Wrapper",
+ children: [
+ parser
+ ],
+ extras: []
+ }){
+ this.parser = parser;
+ this.description = description;
+ this._TYPE = null;
+ this.test = (value)=>{
+ return this.parse(value, booleanOnParse);
+ };
+ }
+ parse(a, onParse) {
+ return this.parser.parse(a, onParse);
+ }
+ static isA(checkIsA, name) {
+ return new Parser(new GuardParser(checkIsA, name));
+ }
+ static validatorErrorAsString = (error)=>{
+ const { parser, value, keys } = error;
+ const keysString = !keys.length ? "" : keys.map((x)=>`[${x}]`).reverse().join("");
+ return `${keysString}${Parser.parserAsString(parser)}(${saferStringify(value)})`;
+ };
+ static parserAsString(parserComingIn) {
+ const parser = unwrapParser(parserComingIn);
+ const { description: { name, extras, children } } = parser;
+ if (parser instanceof ShapeParser) {
+ return `${name}<{${parser.description.children.map((subParser, i)=>`${String(parser.description.extras[i]) || "?"}:${Parser.parserAsString(subParser)}`).join(",")}}>`;
+ }
+ if (parser instanceof OrParsers) {
+ const parent = unwrapParser(parser.parent);
+ const parentString = Parser.parserAsString(parent);
+ if (parent instanceof OrParsers) return parentString;
+ return `${name}<${parentString},...>`;
+ }
+ if (parser instanceof GuardParser) {
+ return String(extras[0] || name);
+ }
+ if (parser instanceof StringParser || parser instanceof ObjectParser || parser instanceof NumberParser || parser instanceof BoolParser || parser instanceof AnyParser) {
+ return name.toLowerCase();
+ }
+ if (parser instanceof FunctionParser) {
+ return name;
+ }
+ if (parser instanceof NilParser) {
+ return "null";
+ }
+ if (parser instanceof ArrayParser) {
+ return "Array";
+ }
+ const specifiers = [
+ ...extras.map(saferStringify),
+ ...children.map(Parser.parserAsString)
+ ];
+ const specifiersString = `<${specifiers.join(",")}>`;
+ !children.length ? "" : `<>`;
+ return `${name}${specifiersString}`;
+ }
+ unsafeCast(value) {
+ const state = this.enumParsed(value);
+ if ("value" in state) return state.value;
+ const { error } = state;
+ throw new TypeError(`Failed type: ${Parser.validatorErrorAsString(error)} given input ${saferStringify(value)}`);
+ }
+ castPromise(value) {
+ const state = this.enumParsed(value);
+ if ("value" in state) return Promise.resolve(state.value);
+ const { error } = state;
+ return Promise.reject(new TypeError(`Failed type: ${Parser.validatorErrorAsString(error)} given input ${saferStringify(value)}`));
+ }
+ errorMessage(input) {
+ const parsed = this.parse(input, enumParsed);
+ if ("value" in parsed) return;
+ return Parser.validatorErrorAsString(parsed.error);
+ }
+ map(fn, mappingName) {
+ return new Parser(new MappedAParser(this, fn, mappingName));
+ }
+ concat(otherParser) {
+ return new Parser(ConcatParsers.of(this, new Parser(otherParser)));
+ }
+ orParser(otherParser) {
+ return new Parser(new OrParsers(this, new Parser(otherParser)));
+ }
+ test;
+ optional(name) {
+ return new Parser(new MaybeParser(this));
+ }
+ defaultTo(defaultValue) {
+ return new Parser(new DefaultParser(new Parser(new MaybeParser(this)), defaultValue));
+ }
+ validate(isValid, otherName) {
+ return new Parser(ConcatParsers.of(this, new Parser(new GuardParser(isValid, otherName))));
+ }
+ refine(refinementTest, otherName = refinementTest.name) {
+ return new Parser(ConcatParsers.of(this, new Parser(new GuardParser(refinementTest, otherName))));
+ }
+ name(nameString) {
+ return parserName(nameString, this);
+ }
+ enumParsed(value) {
+ return this.parse(value, enumParsed);
+ }
+ unwrappedParser() {
+ let answer = this;
+ while(true){
+ const next = answer.parser;
+ if (next instanceof Parser) {
+ answer = next;
+ } else {
+ return next;
+ }
+ }
+ }
+}
+function guard(test, testName) {
+ return Parser.isA(test, testName || test.name);
+}
+const any = new Parser(new AnyParser());
+class ArrayOfParser {
+ parser;
+ description;
+ constructor(parser, description = {
+ name: "ArrayOf",
+ children: [
+ parser
+ ],
+ extras: []
+ }){
+ this.parser = parser;
+ this.description = description;
+ }
+ parse(a, onParse) {
+ if (!Array.isArray(a)) {
+ return onParse.invalid({
+ value: a,
+ keys: [],
+ parser: this
+ });
+ }
+ const values = [
+ ...a
+ ];
+ for(let index = 0; index < values.length; index++){
+ const result = this.parser.enumParsed(values[index]);
+ if ("error" in result) {
+ result.error.keys.push("" + index);
+ return onParse.invalid(result.error);
+ } else {
+ values[index] = result.value;
+ }
+ }
+ return onParse.parsed(values);
+ }
+}
+function arrayOf(validator) {
+ return new Parser(new ArrayOfParser(validator));
+}
+const unknown = new Parser(new UnknownParser());
+const number = new Parser(new NumberParser());
+const isNill = new Parser(new NilParser());
+const natural = number.refine((x)=>x >= 0 && x === Math.floor(x));
+const isFunction = new Parser(new FunctionParser());
+const __boolean = new Parser(new BoolParser());
+class DeferredParser {
+ description;
+ parser;
+ static create() {
+ return new DeferredParser();
+ }
+ constructor(description = {
+ name: "Deferred",
+ children: [],
+ extras: []
+ }){
+ this.description = description;
+ }
+ setParser(parser) {
+ this.parser = new Parser(parser);
+ return this;
+ }
+ parse(a, onParse) {
+ if (!this.parser) {
+ return onParse.invalid({
+ value: "Not Set Up",
+ keys: [],
+ parser: this
+ });
+ }
+ return this.parser.parse(a, onParse);
+ }
+}
+function deferred() {
+ const deferred = DeferredParser.create();
+ function setParser(parser) {
+ deferred.setParser(parser);
+ }
+ return [
+ new Parser(deferred),
+ setParser
+ ];
+}
+const object = new Parser(new ObjectParser());
+class DictionaryParser {
+ parsers;
+ description;
+ constructor(parsers, description = {
+ name: "Dictionary",
+ children: parsers.reduce((acc, [k, v])=>{
+ acc.push(k, v);
+ return acc;
+ }, []),
+ extras: []
+ }){
+ this.parsers = parsers;
+ this.description = description;
+ }
+ parse(a, onParse) {
+ const { parsers } = this;
+ const parser = this;
+ const answer = {
+ ...a
+ };
+ outer: for(const key in a){
+ let parseError = [];
+ for (const [keyParser, valueParser] of parsers){
+ const enumState = keyParser.enumParsed(key);
+ if ("error" in enumState) {
+ const { error } = enumState;
+ error.parser = parser;
+ error.keys.push("" + key);
+ parseError.push(error);
+ continue;
+ }
+ const newKey = enumState.value;
+ const valueState = valueParser.enumParsed(a[key]);
+ if ("error" in valueState) {
+ const { error } = valueState;
+ error.keys.push("" + newKey);
+ parseError.unshift(error);
+ continue;
+ }
+ delete answer[key];
+ answer[newKey] = valueState.value;
+ break outer;
+ }
+ const error = parseError[0];
+ if (!!error) {
+ return onParse.invalid(error);
+ }
+ }
+ return onParse.parsed(answer);
+ }
+}
+const dictionary = (...parsers)=>{
+ return object.concat(new DictionaryParser([
+ ...parsers
+ ]));
+};
+function every(...parsers) {
+ const filteredParsers = parsers.filter((x)=>x !== any);
+ if (filteredParsers.length <= 0) {
+ return any;
+ }
+ const first = filteredParsers.splice(0, 1)[0];
+ return filteredParsers.reduce((left, right)=>{
+ return left.concat(right);
+ }, first);
+}
+const isArray = new Parser(new ArrayParser());
+const string = new Parser(new StringParser());
+const instanceOf = (classCreator)=>guard((x)=>x instanceof classCreator, `is${classCreator.name}`);
+class LiteralsParser {
+ values;
+ description;
+ constructor(values, description = {
+ name: "Literal",
+ children: [],
+ extras: values
+ }){
+ this.values = values;
+ this.description = description;
+ }
+ parse(a, onParse) {
+ if (this.values.indexOf(a) >= 0) {
+ return onParse.parsed(a);
+ }
+ return onParse.invalid({
+ value: a,
+ keys: [],
+ parser: this
+ });
+ }
+}
+function literal(isEqualToValue) {
+ return new Parser(new LiteralsParser([
+ isEqualToValue
+ ]));
+}
+function literals(firstValue, ...restValues) {
+ return new Parser(new LiteralsParser([
+ firstValue,
+ ...restValues
+ ]));
+}
+class ShapeParser {
+ parserMap;
+ isPartial;
+ parserKeys;
+ description;
+ constructor(parserMap, isPartial, parserKeys = Object.keys(parserMap), description = {
+ name: isPartial ? "Partial" : "Shape",
+ children: parserKeys.map((key)=>parserMap[key]),
+ extras: parserKeys
+ }){
+ this.parserMap = parserMap;
+ this.isPartial = isPartial;
+ this.parserKeys = parserKeys;
+ this.description = description;
+ }
+ parse(a, onParse) {
+ const parser = this;
+ if (!object.test(a)) {
+ return onParse.invalid({
+ value: a,
+ keys: [],
+ parser
+ });
+ }
+ const { parserMap, isPartial } = this;
+ const value = {
+ ...a
+ };
+ if (Array.isArray(a)) {
+ value.length = a.length;
+ }
+ for(const key in parserMap){
+ if (key in value) {
+ const parser = parserMap[key];
+ const state = parser.enumParsed(a[key]);
+ if ("error" in state) {
+ const { error } = state;
+ error.keys.push(saferStringify(key));
+ return onParse.invalid(error);
+ }
+ const smallValue = state.value;
+ value[key] = smallValue;
+ } else if (!isPartial) {
+ return onParse.invalid({
+ value: "missingProperty",
+ parser,
+ keys: [
+ saferStringify(key)
+ ]
+ });
+ }
+ }
+ return onParse.parsed(value);
+ }
+}
+const isPartial = (testShape)=>{
+ return new Parser(new ShapeParser(testShape, true));
+};
+const partial = isPartial;
+class RecursiveParser {
+ recursive;
+ description;
+ parser;
+ static create(fn) {
+ const parser = new RecursiveParser(fn);
+ parser.parser = fn(new Parser(parser));
+ return parser;
+ }
+ constructor(recursive, description = {
+ name: "Recursive",
+ children: [],
+ extras: [
+ recursive
+ ]
+ }){
+ this.recursive = recursive;
+ this.description = description;
+ }
+ parse(a, onParse) {
+ if (!this.parser) {
+ return onParse.invalid({
+ value: "Recursive Invalid State",
+ keys: [],
+ parser: this
+ });
+ }
+ return this.parser.parse(a, onParse);
+ }
+}
+function recursive(fn) {
+ fn(any);
+ const created = RecursiveParser.create(fn);
+ return new Parser(created);
+}
+const regex = (tester)=>string.refine(function(x) {
+ return tester.test(x);
+ }, tester.toString());
+const isShape = (testShape)=>{
+ return new Parser(new ShapeParser(testShape, false));
+};
+function shape(testShape, optionals, optionalAndDefaults) {
+ if (optionals) {
+ const defaults = optionalAndDefaults || {};
+ const entries = Object.entries(testShape);
+ const optionalSet = new Set(Array.from(optionals));
+ return every(partial(Object.fromEntries(entries.filter(([key, _])=>optionalSet.has(key)).map(([key, parser])=>[
+ key,
+ parser.optional()
+ ]))), isShape(Object.fromEntries(entries.filter(([key, _])=>!optionalSet.has(key))))).map((ret)=>{
+ for (const key of optionalSet){
+ const keyAny = key;
+ if (!(keyAny in ret) && keyAny in defaults) {
+ ret[keyAny] = defaults[keyAny];
+ }
+ }
+ return ret;
+ });
+ }
+ return isShape(testShape);
+}
+function some(...parsers) {
+ if (parsers.length <= 0) {
+ return any;
+ }
+ const first = parsers.splice(0, 1)[0];
+ return parsers.reduce((left, right)=>left.orParser(right), first);
+}
+class TupleParser {
+ parsers;
+ lengthMatcher;
+ description;
+ constructor(parsers, lengthMatcher = literal(parsers.length), description = {
+ name: "Tuple",
+ children: parsers,
+ extras: []
+ }){
+ this.parsers = parsers;
+ this.lengthMatcher = lengthMatcher;
+ this.description = description;
+ }
+ parse(input, onParse) {
+ const tupleError = isArray.enumParsed(input);
+ if ("error" in tupleError) return onParse.invalid(tupleError.error);
+ const values = input;
+ const stateCheck = this.lengthMatcher.enumParsed(values.length);
+ if ("error" in stateCheck) {
+ stateCheck.error.keys.push(saferStringify("length"));
+ return onParse.invalid(stateCheck.error);
+ }
+ const answer = new Array(this.parsers.length);
+ for(const key in this.parsers){
+ const parser = this.parsers[key];
+ const value = values[key];
+ const result = parser.enumParsed(value);
+ if ("error" in result) {
+ const { error } = result;
+ error.keys.push(saferStringify(key));
+ return onParse.invalid(error);
+ }
+ answer[key] = result.value;
+ }
+ return onParse.parsed(answer);
+ }
+}
+function tuple(...parsers) {
+ return new Parser(new TupleParser(parsers));
+}
+class NamedParser {
+ parent;
+ name;
+ description;
+ constructor(parent, name, description = {
+ name: "Named",
+ children: [
+ parent
+ ],
+ extras: [
+ name
+ ]
+ }){
+ this.parent = parent;
+ this.name = name;
+ this.description = description;
+ }
+ parse(a, onParse) {
+ const parser = this;
+ const parent = this.parent.enumParsed(a);
+ if ("error" in parent) {
+ const { error } = parent;
+ error.parser = parser;
+ return onParse.invalid(error);
+ }
+ return onParse.parsed(parent.value);
+ }
+}
+function parserName(name, parent) {
+ return new Parser(new NamedParser(parent, name));
+}
+class Matched {
+ value;
+ constructor(value){
+ this.value = value;
+ }
+ when(..._args) {
+ return this;
+ }
+ defaultTo(_defaultValue) {
+ return this.value;
+ }
+ defaultToLazy(_getValue) {
+ return this.value;
+ }
+ unwrap() {
+ return this.value;
+ }
+}
+class MatchMore {
+ a;
+ constructor(a){
+ this.a = a;
+ }
+ when(...args) {
+ const [outcome, ...matchers] = args.reverse();
+ const me = this;
+ const parser = matches.some(...matchers.map((matcher)=>matcher instanceof Parser ? matcher : literal(matcher)));
+ const result = parser.enumParsed(this.a);
+ if ("error" in result) {
+ return me;
+ }
+ const { value } = result;
+ if (outcome instanceof Function) {
+ return new Matched(outcome(value));
+ }
+ return new Matched(outcome);
+ }
+ defaultTo(value) {
+ return value;
+ }
+ defaultToLazy(getValue) {
+ return getValue();
+ }
+ unwrap() {
+ throw new Error("Expecting that value is matched");
+ }
+}
+const matches = Object.assign(function matchesFn(value) {
+ return new MatchMore(value);
+}, {
+ array: isArray,
+ arrayOf,
+ some,
+ tuple,
+ regex,
+ number,
+ natural,
+ isFunction,
+ object,
+ string,
+ shape,
+ partial,
+ literal,
+ every,
+ guard,
+ unknown,
+ any,
+ boolean: __boolean,
+ dictionary,
+ literals,
+ nill: isNill,
+ instanceOf,
+ Parse: Parser,
+ parserName,
+ recursive,
+ deferred
+});
+const mod = {
+ AnyParser: AnyParser,
+ ArrayParser: ArrayParser,
+ BoolParser: BoolParser,
+ FunctionParser: FunctionParser,
+ GuardParser: GuardParser,
+ NilParser: NilParser,
+ NumberParser: NumberParser,
+ ObjectParser: ObjectParser,
+ OrParsers: OrParsers,
+ ShapeParser: ShapeParser,
+ StringParser: StringParser,
+ saferStringify: saferStringify,
+ NamedParser: NamedParser,
+ ArrayOfParser: ArrayOfParser,
+ LiteralsParser: LiteralsParser,
+ ConcatParsers: ConcatParsers,
+ MappedAParser: MappedAParser,
+ default: matches,
+ Validator: Parser,
+ matches,
+ allOf: every,
+ any,
+ anyOf: some,
+ array: isArray,
+ arrayOf,
+ boolean: __boolean,
+ deferred,
+ dictionary,
+ every,
+ guard,
+ instanceOf,
+ isFunction,
+ literal,
+ literals,
+ natural,
+ nill: isNill,
+ number,
+ object,
+ oneOf: some,
+ Parse: Parser,
+ Parser,
+ parserName,
+ partial,
+ recursive,
+ regex,
+ shape,
+ some,
+ string,
+ tuple,
+ unknown
+};
+class YAMLError extends Error {
+ mark;
+ constructor(message = "(unknown reason)", mark = ""){
+ super(`${message} ${mark}`);
+ this.mark = mark;
+ this.name = this.constructor.name;
+ }
+ toString(_compact) {
+ return `${this.name}: ${this.message} ${this.mark}`;
+ }
+}
+function isBoolean(value) {
+ return typeof value === "boolean" || value instanceof Boolean;
+}
+function isObject1(value) {
+ return value !== null && typeof value === "object";
+}
+function repeat(str, count) {
+ let result = "";
+ for(let cycle = 0; cycle < count; cycle++){
+ result += str;
+ }
+ return result;
+}
+function isNegativeZero(i) {
+ return i === 0 && Number.NEGATIVE_INFINITY === 1 / i;
+}
+class Mark {
+ name;
+ buffer;
+ position;
+ line;
+ column;
+ constructor(name, buffer, position, line, column){
+ this.name = name;
+ this.buffer = buffer;
+ this.position = position;
+ this.line = line;
+ this.column = column;
+ }
+ getSnippet(indent = 4, maxLength = 75) {
+ if (!this.buffer) return null;
+ let head = "";
+ let start = this.position;
+ while(start > 0 && "\x00\r\n\x85\u2028\u2029".indexOf(this.buffer.charAt(start - 1)) === -1){
+ start -= 1;
+ if (this.position - start > maxLength / 2 - 1) {
+ head = " ... ";
+ start += 5;
+ break;
+ }
+ }
+ let tail = "";
+ let end = this.position;
+ while(end < this.buffer.length && "\x00\r\n\x85\u2028\u2029".indexOf(this.buffer.charAt(end)) === -1){
+ end += 1;
+ if (end - this.position > maxLength / 2 - 1) {
+ tail = " ... ";
+ end -= 5;
+ break;
+ }
+ }
+ const snippet = this.buffer.slice(start, end);
+ return `${repeat(" ", indent)}${head}${snippet}${tail}\n${repeat(" ", indent + this.position - start + head.length)}^`;
+ }
+ toString(compact) {
+ let snippet, where = "";
+ if (this.name) {
+ where += `in "${this.name}" `;
+ }
+ where += `at line ${this.line + 1}, column ${this.column + 1}`;
+ if (!compact) {
+ snippet = this.getSnippet();
+ if (snippet) {
+ where += `:\n${snippet}`;
+ }
+ }
+ return where;
+ }
+}
+function compileList(schema, name, result) {
+ const exclude = [];
+ for (const includedSchema of schema.include){
+ result = compileList(includedSchema, name, result);
+ }
+ for (const currentType of schema[name]){
+ for(let previousIndex = 0; previousIndex < result.length; previousIndex++){
+ const previousType = result[previousIndex];
+ if (previousType.tag === currentType.tag && previousType.kind === currentType.kind) {
+ exclude.push(previousIndex);
+ }
+ }
+ result.push(currentType);
+ }
+ return result.filter((_type, index)=>!exclude.includes(index));
+}
+function compileMap(...typesList) {
+ const result = {
+ fallback: {},
+ mapping: {},
+ scalar: {},
+ sequence: {}
+ };
+ for (const types of typesList){
+ for (const type of types){
+ if (type.kind !== null) {
+ result[type.kind][type.tag] = result["fallback"][type.tag] = type;
+ }
+ }
+ }
+ return result;
+}
+class Schema {
+ static SCHEMA_DEFAULT;
+ implicit;
+ explicit;
+ include;
+ compiledImplicit;
+ compiledExplicit;
+ compiledTypeMap;
+ constructor(definition){
+ this.explicit = definition.explicit || [];
+ this.implicit = definition.implicit || [];
+ this.include = definition.include || [];
+ for (const type of this.implicit){
+ if (type.loadKind && type.loadKind !== "scalar") {
+ throw new YAMLError("There is a non-scalar type in the implicit list of a schema. Implicit resolving of such types is not supported.");
+ }
+ }
+ this.compiledImplicit = compileList(this, "implicit", []);
+ this.compiledExplicit = compileList(this, "explicit", []);
+ this.compiledTypeMap = compileMap(this.compiledImplicit, this.compiledExplicit);
+ }
+ extend(definition) {
+ return new Schema({
+ implicit: [
+ ...new Set([
+ ...this.implicit,
+ ...definition?.implicit ?? []
+ ])
+ ],
+ explicit: [
+ ...new Set([
+ ...this.explicit,
+ ...definition?.explicit ?? []
+ ])
+ ],
+ include: [
+ ...new Set([
+ ...this.include,
+ ...definition?.include ?? []
+ ])
+ ]
+ });
+ }
+ static create() {}
+}
+const DEFAULT_RESOLVE = ()=>true;
+const DEFAULT_CONSTRUCT = (data)=>data;
+function checkTagFormat(tag) {
+ return tag;
+}
+class Type {
+ tag;
+ kind = null;
+ instanceOf;
+ predicate;
+ represent;
+ defaultStyle;
+ styleAliases;
+ loadKind;
+ constructor(tag, options){
+ this.tag = checkTagFormat(tag);
+ if (options) {
+ this.kind = options.kind;
+ this.resolve = options.resolve || DEFAULT_RESOLVE;
+ this.construct = options.construct || DEFAULT_CONSTRUCT;
+ this.instanceOf = options.instanceOf;
+ this.predicate = options.predicate;
+ this.represent = options.represent;
+ this.defaultStyle = options.defaultStyle;
+ this.styleAliases = options.styleAliases;
+ }
+ }
+ resolve = ()=>true;
+ construct = (data)=>data;
+}
+class DenoStdInternalError extends Error {
+ constructor(message){
+ super(message);
+ this.name = "DenoStdInternalError";
+ }
+}
+function assert(expr, msg = "") {
+ if (!expr) {
+ throw new DenoStdInternalError(msg);
+ }
+}
+function copy(src, dst, off = 0) {
+ off = Math.max(0, Math.min(off, dst.byteLength));
+ const dstBytesAvailable = dst.byteLength - off;
+ if (src.byteLength > dstBytesAvailable) {
+ src = src.subarray(0, dstBytesAvailable);
+ }
+ dst.set(src, off);
+ return src.byteLength;
+}
+const MIN_READ = 32 * 1024;
+const MAX_SIZE = 2 ** 32 - 2;
+class Buffer {
+ #buf;
+ #off = 0;
+ constructor(ab){
+ this.#buf = ab === undefined ? new Uint8Array(0) : new Uint8Array(ab);
+ }
+ bytes(options = {
+ copy: true
+ }) {
+ if (options.copy === false) return this.#buf.subarray(this.#off);
+ return this.#buf.slice(this.#off);
+ }
+ empty() {
+ return this.#buf.byteLength <= this.#off;
+ }
+ get length() {
+ return this.#buf.byteLength - this.#off;
+ }
+ get capacity() {
+ return this.#buf.buffer.byteLength;
+ }
+ truncate(n) {
+ if (n === 0) {
+ this.reset();
+ return;
+ }
+ if (n < 0 || n > this.length) {
+ throw Error("bytes.Buffer: truncation out of range");
+ }
+ this.#reslice(this.#off + n);
+ }
+ reset() {
+ this.#reslice(0);
+ this.#off = 0;
+ }
+ #tryGrowByReslice(n) {
+ const l = this.#buf.byteLength;
+ if (n <= this.capacity - l) {
+ this.#reslice(l + n);
+ return l;
+ }
+ return -1;
+ }
+ #reslice(len) {
+ assert(len <= this.#buf.buffer.byteLength);
+ this.#buf = new Uint8Array(this.#buf.buffer, 0, len);
+ }
+ readSync(p) {
+ if (this.empty()) {
+ this.reset();
+ if (p.byteLength === 0) {
+ return 0;
+ }
+ return null;
+ }
+ const nread = copy(this.#buf.subarray(this.#off), p);
+ this.#off += nread;
+ return nread;
+ }
+ read(p) {
+ const rr = this.readSync(p);
+ return Promise.resolve(rr);
+ }
+ writeSync(p) {
+ const m = this.#grow(p.byteLength);
+ return copy(p, this.#buf, m);
+ }
+ write(p) {
+ const n = this.writeSync(p);
+ return Promise.resolve(n);
+ }
+ #grow(n) {
+ const m = this.length;
+ if (m === 0 && this.#off !== 0) {
+ this.reset();
+ }
+ const i = this.#tryGrowByReslice(n);
+ if (i >= 0) {
+ return i;
+ }
+ const c = this.capacity;
+ if (n <= Math.floor(c / 2) - m) {
+ copy(this.#buf.subarray(this.#off), this.#buf);
+ } else if (c + n > MAX_SIZE) {
+ throw new Error("The buffer cannot be grown beyond the maximum size.");
+ } else {
+ const buf = new Uint8Array(Math.min(2 * c + n, MAX_SIZE));
+ copy(this.#buf.subarray(this.#off), buf);
+ this.#buf = buf;
+ }
+ this.#off = 0;
+ this.#reslice(Math.min(m + n, MAX_SIZE));
+ return m;
+ }
+ grow(n) {
+ if (n < 0) {
+ throw Error("Buffer.grow: negative count");
+ }
+ const m = this.#grow(n);
+ this.#reslice(m);
+ }
+ async readFrom(r) {
+ let n = 0;
+ const tmp = new Uint8Array(MIN_READ);
+ while(true){
+ const shouldGrow = this.capacity - this.length < MIN_READ;
+ const buf = shouldGrow ? tmp : new Uint8Array(this.#buf.buffer, this.length);
+ const nread = await r.read(buf);
+ if (nread === null) {
+ return n;
+ }
+ if (shouldGrow) this.writeSync(buf.subarray(0, nread));
+ else this.#reslice(this.length + nread);
+ n += nread;
+ }
+ }
+ readFromSync(r) {
+ let n = 0;
+ const tmp = new Uint8Array(MIN_READ);
+ while(true){
+ const shouldGrow = this.capacity - this.length < MIN_READ;
+ const buf = shouldGrow ? tmp : new Uint8Array(this.#buf.buffer, this.length);
+ const nread = r.readSync(buf);
+ if (nread === null) {
+ return n;
+ }
+ if (shouldGrow) this.writeSync(buf.subarray(0, nread));
+ else this.#reslice(this.length + nread);
+ n += nread;
+ }
+ }
+}
+const BASE64_MAP = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\n\r";
+function resolveYamlBinary(data) {
+ if (data === null) return false;
+ let code;
+ let bitlen = 0;
+ const max = data.length;
+ const map = BASE64_MAP;
+ for(let idx = 0; idx < max; idx++){
+ code = map.indexOf(data.charAt(idx));
+ if (code > 64) continue;
+ if (code < 0) return false;
+ bitlen += 6;
+ }
+ return bitlen % 8 === 0;
+}
+function constructYamlBinary(data) {
+ const input = data.replace(/[\r\n=]/g, "");
+ const max = input.length;
+ const map = BASE64_MAP;
+ const result = [];
+ let bits = 0;
+ for(let idx = 0; idx < max; idx++){
+ if (idx % 4 === 0 && idx) {
+ result.push(bits >> 16 & 0xff);
+ result.push(bits >> 8 & 0xff);
+ result.push(bits & 0xff);
+ }
+ bits = bits << 6 | map.indexOf(input.charAt(idx));
+ }
+ const tailbits = max % 4 * 6;
+ if (tailbits === 0) {
+ result.push(bits >> 16 & 0xff);
+ result.push(bits >> 8 & 0xff);
+ result.push(bits & 0xff);
+ } else if (tailbits === 18) {
+ result.push(bits >> 10 & 0xff);
+ result.push(bits >> 2 & 0xff);
+ } else if (tailbits === 12) {
+ result.push(bits >> 4 & 0xff);
+ }
+ return new Buffer(new Uint8Array(result));
+}
+function representYamlBinary(object) {
+ const max = object.length;
+ const map = BASE64_MAP;
+ let result = "";
+ let bits = 0;
+ for(let idx = 0; idx < max; idx++){
+ if (idx % 3 === 0 && idx) {
+ result += map[bits >> 18 & 0x3f];
+ result += map[bits >> 12 & 0x3f];
+ result += map[bits >> 6 & 0x3f];
+ result += map[bits & 0x3f];
+ }
+ bits = (bits << 8) + object[idx];
+ }
+ const tail = max % 3;
+ if (tail === 0) {
+ result += map[bits >> 18 & 0x3f];
+ result += map[bits >> 12 & 0x3f];
+ result += map[bits >> 6 & 0x3f];
+ result += map[bits & 0x3f];
+ } else if (tail === 2) {
+ result += map[bits >> 10 & 0x3f];
+ result += map[bits >> 4 & 0x3f];
+ result += map[bits << 2 & 0x3f];
+ result += map[64];
+ } else if (tail === 1) {
+ result += map[bits >> 2 & 0x3f];
+ result += map[bits << 4 & 0x3f];
+ result += map[64];
+ result += map[64];
+ }
+ return result;
+}
+function isBinary(obj) {
+ const buf = new Buffer();
+ try {
+ if (0 > buf.readFromSync(obj)) return true;
+ return false;
+ } catch {
+ return false;
+ } finally{
+ buf.reset();
+ }
+}
+const binary = new Type("tag:yaml.org,2002:binary", {
+ construct: constructYamlBinary,
+ kind: "scalar",
+ predicate: isBinary,
+ represent: representYamlBinary,
+ resolve: resolveYamlBinary
+});
+function resolveYamlBoolean(data) {
+ const max = data.length;
+ return max === 4 && (data === "true" || data === "True" || data === "TRUE") || max === 5 && (data === "false" || data === "False" || data === "FALSE");
+}
+function constructYamlBoolean(data) {
+ return data === "true" || data === "True" || data === "TRUE";
+}
+const bool = new Type("tag:yaml.org,2002:bool", {
+ construct: constructYamlBoolean,
+ defaultStyle: "lowercase",
+ kind: "scalar",
+ predicate: isBoolean,
+ represent: {
+ lowercase (object) {
+ return object ? "true" : "false";
+ },
+ uppercase (object) {
+ return object ? "TRUE" : "FALSE";
+ },
+ camelcase (object) {
+ return object ? "True" : "False";
+ }
+ },
+ resolve: resolveYamlBoolean
+});
+const YAML_FLOAT_PATTERN = new RegExp("^(?:[-+]?(?:0|[1-9][0-9_]*)(?:\\.[0-9_]*)?(?:[eE][-+]?[0-9]+)?" + "|\\.[0-9_]+(?:[eE][-+]?[0-9]+)?" + "|[-+]?[0-9][0-9_]*(?::[0-5]?[0-9])+\\.[0-9_]*" + "|[-+]?\\.(?:inf|Inf|INF)" + "|\\.(?:nan|NaN|NAN))$");
+function resolveYamlFloat(data) {
+ if (!YAML_FLOAT_PATTERN.test(data) || data[data.length - 1] === "_") {
+ return false;
+ }
+ return true;
+}
+function constructYamlFloat(data) {
+ let value = data.replace(/_/g, "").toLowerCase();
+ const sign = value[0] === "-" ? -1 : 1;
+ const digits = [];
+ if ("+-".indexOf(value[0]) >= 0) {
+ value = value.slice(1);
+ }
+ if (value === ".inf") {
+ return sign === 1 ? Number.POSITIVE_INFINITY : Number.NEGATIVE_INFINITY;
+ }
+ if (value === ".nan") {
+ return NaN;
+ }
+ if (value.indexOf(":") >= 0) {
+ value.split(":").forEach((v)=>{
+ digits.unshift(parseFloat(v));
+ });
+ let valueNb = 0.0;
+ let base = 1;
+ digits.forEach((d)=>{
+ valueNb += d * base;
+ base *= 60;
+ });
+ return sign * valueNb;
+ }
+ return sign * parseFloat(value);
+}
+const SCIENTIFIC_WITHOUT_DOT = /^[-+]?[0-9]+e/;
+function representYamlFloat(object, style) {
+ if (isNaN(object)) {
+ switch(style){
+ case "lowercase":
+ return ".nan";
+ case "uppercase":
+ return ".NAN";
+ case "camelcase":
+ return ".NaN";
+ }
+ } else if (Number.POSITIVE_INFINITY === object) {
+ switch(style){
+ case "lowercase":
+ return ".inf";
+ case "uppercase":
+ return ".INF";
+ case "camelcase":
+ return ".Inf";
+ }
+ } else if (Number.NEGATIVE_INFINITY === object) {
+ switch(style){
+ case "lowercase":
+ return "-.inf";
+ case "uppercase":
+ return "-.INF";
+ case "camelcase":
+ return "-.Inf";
+ }
+ } else if (isNegativeZero(object)) {
+ return "-0.0";
+ }
+ const res = object.toString(10);
+ return SCIENTIFIC_WITHOUT_DOT.test(res) ? res.replace("e", ".e") : res;
+}
+function isFloat(object) {
+ return Object.prototype.toString.call(object) === "[object Number]" && (object % 1 !== 0 || isNegativeZero(object));
+}
+const __float = new Type("tag:yaml.org,2002:float", {
+ construct: constructYamlFloat,
+ defaultStyle: "lowercase",
+ kind: "scalar",
+ predicate: isFloat,
+ represent: representYamlFloat,
+ resolve: resolveYamlFloat
+});
+function reconstructFunction(code) {
+ const func = new Function(`return ${code}`)();
+ if (!(func instanceof Function)) {
+ throw new TypeError(`Expected function but got ${typeof func}: ${code}`);
+ }
+ return func;
+}
+new Type("tag:yaml.org,2002:js/function", {
+ kind: "scalar",
+ resolve (data) {
+ if (data === null) {
+ return false;
+ }
+ try {
+ reconstructFunction(`${data}`);
+ return true;
+ } catch (_err) {
+ return false;
+ }
+ },
+ construct (data) {
+ return reconstructFunction(data);
+ },
+ predicate (object) {
+ return object instanceof Function;
+ },
+ represent (object) {
+ return object.toString();
+ }
+});
+function isHexCode(c) {
+ return 0x30 <= c && c <= 0x39 || 0x41 <= c && c <= 0x46 || 0x61 <= c && c <= 0x66;
+}
+function isOctCode(c) {
+ return 0x30 <= c && c <= 0x37;
+}
+function isDecCode(c) {
+ return 0x30 <= c && c <= 0x39;
+}
+function resolveYamlInteger(data) {
+ const max = data.length;
+ let index = 0;
+ let hasDigits = false;
+ if (!max) return false;
+ let ch = data[index];
+ if (ch === "-" || ch === "+") {
+ ch = data[++index];
+ }
+ if (ch === "0") {
+ if (index + 1 === max) return true;
+ ch = data[++index];
+ if (ch === "b") {
+ index++;
+ for(; index < max; index++){
+ ch = data[index];
+ if (ch === "_") continue;
+ if (ch !== "0" && ch !== "1") return false;
+ hasDigits = true;
+ }
+ return hasDigits && ch !== "_";
+ }
+ if (ch === "x") {
+ index++;
+ for(; index < max; index++){
+ ch = data[index];
+ if (ch === "_") continue;
+ if (!isHexCode(data.charCodeAt(index))) return false;
+ hasDigits = true;
+ }
+ return hasDigits && ch !== "_";
+ }
+ for(; index < max; index++){
+ ch = data[index];
+ if (ch === "_") continue;
+ if (!isOctCode(data.charCodeAt(index))) return false;
+ hasDigits = true;
+ }
+ return hasDigits && ch !== "_";
+ }
+ if (ch === "_") return false;
+ for(; index < max; index++){
+ ch = data[index];
+ if (ch === "_") continue;
+ if (ch === ":") break;
+ if (!isDecCode(data.charCodeAt(index))) {
+ return false;
+ }
+ hasDigits = true;
+ }
+ if (!hasDigits || ch === "_") return false;
+ if (ch !== ":") return true;
+ return /^(:[0-5]?[0-9])+$/.test(data.slice(index));
+}
+function constructYamlInteger(data) {
+ let value = data;
+ const digits = [];
+ if (value.indexOf("_") !== -1) {
+ value = value.replace(/_/g, "");
+ }
+ let sign = 1;
+ let ch = value[0];
+ if (ch === "-" || ch === "+") {
+ if (ch === "-") sign = -1;
+ value = value.slice(1);
+ ch = value[0];
+ }
+ if (value === "0") return 0;
+ if (ch === "0") {
+ if (value[1] === "b") return sign * parseInt(value.slice(2), 2);
+ if (value[1] === "x") return sign * parseInt(value, 16);
+ return sign * parseInt(value, 8);
+ }
+ if (value.indexOf(":") !== -1) {
+ value.split(":").forEach((v)=>{
+ digits.unshift(parseInt(v, 10));
+ });
+ let valueInt = 0;
+ let base = 1;
+ digits.forEach((d)=>{
+ valueInt += d * base;
+ base *= 60;
+ });
+ return sign * valueInt;
+ }
+ return sign * parseInt(value, 10);
+}
+function isInteger(object) {
+ return Object.prototype.toString.call(object) === "[object Number]" && object % 1 === 0 && !isNegativeZero(object);
+}
+const __int = new Type("tag:yaml.org,2002:int", {
+ construct: constructYamlInteger,
+ defaultStyle: "decimal",
+ kind: "scalar",
+ predicate: isInteger,
+ represent: {
+ binary (obj) {
+ return obj >= 0 ? `0b${obj.toString(2)}` : `-0b${obj.toString(2).slice(1)}`;
+ },
+ octal (obj) {
+ return obj >= 0 ? `0${obj.toString(8)}` : `-0${obj.toString(8).slice(1)}`;
+ },
+ decimal (obj) {
+ return obj.toString(10);
+ },
+ hexadecimal (obj) {
+ return obj >= 0 ? `0x${obj.toString(16).toUpperCase()}` : `-0x${obj.toString(16).toUpperCase().slice(1)}`;
+ }
+ },
+ resolve: resolveYamlInteger,
+ styleAliases: {
+ binary: [
+ 2,
+ "bin"
+ ],
+ decimal: [
+ 10,
+ "dec"
+ ],
+ hexadecimal: [
+ 16,
+ "hex"
+ ],
+ octal: [
+ 8,
+ "oct"
+ ]
+ }
+});
+const map = new Type("tag:yaml.org,2002:map", {
+ construct (data) {
+ return data !== null ? data : {};
+ },
+ kind: "mapping"
+});
+function resolveYamlMerge(data) {
+ return data === "<<" || data === null;
+}
+const merge = new Type("tag:yaml.org,2002:merge", {
+ kind: "scalar",
+ resolve: resolveYamlMerge
+});
+function resolveYamlNull(data) {
+ const max = data.length;
+ return max === 1 && data === "~" || max === 4 && (data === "null" || data === "Null" || data === "NULL");
+}
+function constructYamlNull() {
+ return null;
+}
+function isNull(object) {
+ return object === null;
+}
+const nil = new Type("tag:yaml.org,2002:null", {
+ construct: constructYamlNull,
+ defaultStyle: "lowercase",
+ kind: "scalar",
+ predicate: isNull,
+ represent: {
+ canonical () {
+ return "~";
+ },
+ lowercase () {
+ return "null";
+ },
+ uppercase () {
+ return "NULL";
+ },
+ camelcase () {
+ return "Null";
+ }
+ },
+ resolve: resolveYamlNull
+});
+const { hasOwn } = Object;
+const _toString = Object.prototype.toString;
+function resolveYamlOmap(data) {
+ const objectKeys = [];
+ let pairKey = "";
+ let pairHasKey = false;
+ for (const pair of data){
+ pairHasKey = false;
+ if (_toString.call(pair) !== "[object Object]") return false;
+ for(pairKey in pair){
+ if (hasOwn(pair, pairKey)) {
+ if (!pairHasKey) pairHasKey = true;
+ else return false;
+ }
+ }
+ if (!pairHasKey) return false;
+ if (objectKeys.indexOf(pairKey) === -1) objectKeys.push(pairKey);
+ else return false;
+ }
+ return true;
+}
+function constructYamlOmap(data) {
+ return data !== null ? data : [];
+}
+const omap = new Type("tag:yaml.org,2002:omap", {
+ construct: constructYamlOmap,
+ kind: "sequence",
+ resolve: resolveYamlOmap
+});
+const _toString1 = Object.prototype.toString;
+function resolveYamlPairs(data) {
+ const result = Array.from({
+ length: data.length
+ });
+ for(let index = 0; index < data.length; index++){
+ const pair = data[index];
+ if (_toString1.call(pair) !== "[object Object]") return false;
+ const keys = Object.keys(pair);
+ if (keys.length !== 1) return false;
+ result[index] = [
+ keys[0],
+ pair[keys[0]]
+ ];
+ }
+ return true;
+}
+function constructYamlPairs(data) {
+ if (data === null) return [];
+ const result = Array.from({
+ length: data.length
+ });
+ for(let index = 0; index < data.length; index += 1){
+ const pair = data[index];
+ const keys = Object.keys(pair);
+ result[index] = [
+ keys[0],
+ pair[keys[0]]
+ ];
+ }
+ return result;
+}
+const pairs = new Type("tag:yaml.org,2002:pairs", {
+ construct: constructYamlPairs,
+ kind: "sequence",
+ resolve: resolveYamlPairs
+});
+const REGEXP = /^\/(?[\s\S]+)\/(?[gismuy]*)$/;
+const regexp = new Type("tag:yaml.org,2002:js/regexp", {
+ kind: "scalar",
+ resolve (data) {
+ if (data === null || !data.length) {
+ return false;
+ }
+ const regexp = `${data}`;
+ if (regexp.charAt(0) === "/") {
+ if (!REGEXP.test(data)) {
+ return false;
+ }
+ const modifiers = [
+ ...regexp.match(REGEXP)?.groups?.modifiers ?? ""
+ ];
+ if (new Set(modifiers).size < modifiers.length) {
+ return false;
+ }
+ }
+ return true;
+ },
+ construct (data) {
+ const { regexp = `${data}`, modifiers = "" } = `${data}`.match(REGEXP)?.groups ?? {};
+ return new RegExp(regexp, modifiers);
+ },
+ predicate (object) {
+ return object instanceof RegExp;
+ },
+ represent (object) {
+ return object.toString();
+ }
+});
+const seq = new Type("tag:yaml.org,2002:seq", {
+ construct (data) {
+ return data !== null ? data : [];
+ },
+ kind: "sequence"
+});
+const { hasOwn: hasOwn1 } = Object;
+function resolveYamlSet(data) {
+ if (data === null) return true;
+ for(const key in data){
+ if (hasOwn1(data, key)) {
+ if (data[key] !== null) return false;
+ }
+ }
+ return true;
+}
+function constructYamlSet(data) {
+ return data !== null ? data : {};
+}
+const set = new Type("tag:yaml.org,2002:set", {
+ construct: constructYamlSet,
+ kind: "mapping",
+ resolve: resolveYamlSet
+});
+const str = new Type("tag:yaml.org,2002:str", {
+ construct (data) {
+ return data !== null ? data : "";
+ },
+ kind: "scalar"
+});
+const YAML_DATE_REGEXP = new RegExp("^([0-9][0-9][0-9][0-9])" + "-([0-9][0-9])" + "-([0-9][0-9])$");
+const YAML_TIMESTAMP_REGEXP = new RegExp("^([0-9][0-9][0-9][0-9])" + "-([0-9][0-9]?)" + "-([0-9][0-9]?)" + "(?:[Tt]|[ \\t]+)" + "([0-9][0-9]?)" + ":([0-9][0-9])" + ":([0-9][0-9])" + "(?:\\.([0-9]*))?" + "(?:[ \\t]*(Z|([-+])([0-9][0-9]?)" + "(?::([0-9][0-9]))?))?$");
+function resolveYamlTimestamp(data) {
+ if (data === null) return false;
+ if (YAML_DATE_REGEXP.exec(data) !== null) return true;
+ if (YAML_TIMESTAMP_REGEXP.exec(data) !== null) return true;
+ return false;
+}
+function constructYamlTimestamp(data) {
+ let match = YAML_DATE_REGEXP.exec(data);
+ if (match === null) match = YAML_TIMESTAMP_REGEXP.exec(data);
+ if (match === null) throw new Error("Date resolve error");
+ const year = +match[1];
+ const month = +match[2] - 1;
+ const day = +match[3];
+ if (!match[4]) {
+ return new Date(Date.UTC(year, month, day));
+ }
+ const hour = +match[4];
+ const minute = +match[5];
+ const second = +match[6];
+ let fraction = 0;
+ if (match[7]) {
+ let partFraction = match[7].slice(0, 3);
+ while(partFraction.length < 3){
+ partFraction += "0";
+ }
+ fraction = +partFraction;
+ }
+ let delta = null;
+ if (match[9]) {
+ const tzHour = +match[10];
+ const tzMinute = +(match[11] || 0);
+ delta = (tzHour * 60 + tzMinute) * 60000;
+ if (match[9] === "-") delta = -delta;
+ }
+ const date = new Date(Date.UTC(year, month, day, hour, minute, second, fraction));
+ if (delta) date.setTime(date.getTime() - delta);
+ return date;
+}
+function representYamlTimestamp(date) {
+ return date.toISOString();
+}
+const timestamp = new Type("tag:yaml.org,2002:timestamp", {
+ construct: constructYamlTimestamp,
+ instanceOf: Date,
+ kind: "scalar",
+ represent: representYamlTimestamp,
+ resolve: resolveYamlTimestamp
+});
+const undefinedType = new Type("tag:yaml.org,2002:js/undefined", {
+ kind: "scalar",
+ resolve () {
+ return true;
+ },
+ construct () {
+ return undefined;
+ },
+ predicate (object) {
+ return typeof object === "undefined";
+ },
+ represent () {
+ return "";
+ }
+});
+const failsafe = new Schema({
+ explicit: [
+ str,
+ seq,
+ map
+ ]
+});
+const json = new Schema({
+ implicit: [
+ nil,
+ bool,
+ __int,
+ __float
+ ],
+ include: [
+ failsafe
+ ]
+});
+const core = new Schema({
+ include: [
+ json
+ ]
+});
+const def = new Schema({
+ explicit: [
+ binary,
+ omap,
+ pairs,
+ set
+ ],
+ implicit: [
+ timestamp,
+ merge
+ ],
+ include: [
+ core
+ ]
+});
+const extended = new Schema({
+ explicit: [
+ regexp,
+ undefinedType
+ ],
+ include: [
+ def
+ ]
+});
+class State {
+ schema;
+ constructor(schema = def){
+ this.schema = schema;
+ }
+}
+class LoaderState extends State {
+ input;
+ documents;
+ length;
+ lineIndent;
+ lineStart;
+ position;
+ line;
+ filename;
+ onWarning;
+ legacy;
+ json;
+ listener;
+ implicitTypes;
+ typeMap;
+ version;
+ checkLineBreaks;
+ tagMap;
+ anchorMap;
+ tag;
+ anchor;
+ kind;
+ result;
+ constructor(input, { filename, schema, onWarning, legacy = false, json = false, listener = null }){
+ super(schema);
+ this.input = input;
+ this.documents = [];
+ this.lineIndent = 0;
+ this.lineStart = 0;
+ this.position = 0;
+ this.line = 0;
+ this.result = "";
+ this.filename = filename;
+ this.onWarning = onWarning;
+ this.legacy = legacy;
+ this.json = json;
+ this.listener = listener;
+ this.implicitTypes = this.schema.compiledImplicit;
+ this.typeMap = this.schema.compiledTypeMap;
+ this.length = input.length;
+ }
+}
+const { hasOwn: hasOwn2 } = Object;
+const CONTEXT_BLOCK_IN = 3;
+const CONTEXT_BLOCK_OUT = 4;
+const CHOMPING_STRIP = 2;
+const CHOMPING_KEEP = 3;
+const PATTERN_NON_PRINTABLE = /[\x00-\x08\x0B\x0C\x0E-\x1F\x7F-\x84\x86-\x9F\uFFFE\uFFFF]|[\uD800-\uDBFF](?![\uDC00-\uDFFF])|(?:[^\uD800-\uDBFF]|^)[\uDC00-\uDFFF]/;
+const PATTERN_NON_ASCII_LINE_BREAKS = /[\x85\u2028\u2029]/;
+const PATTERN_FLOW_INDICATORS = /[,\[\]\{\}]/;
+const PATTERN_TAG_HANDLE = /^(?:!|!!|![a-z\-]+!)$/i;
+const PATTERN_TAG_URI = /^(?:!|[^,\[\]\{\}])(?:%[0-9a-f]{2}|[0-9a-z\-#;\/\?:@&=\+\$,_\.!~\*'\(\)\[\]])*$/i;
+function _class(obj) {
+ return Object.prototype.toString.call(obj);
+}
+function isEOL(c) {
+ return c === 0x0a || c === 0x0d;
+}
+function isWhiteSpace(c) {
+ return c === 0x09 || c === 0x20;
+}
+function isWsOrEol(c) {
+ return c === 0x09 || c === 0x20 || c === 0x0a || c === 0x0d;
+}
+function isFlowIndicator(c) {
+ return c === 0x2c || c === 0x5b || c === 0x5d || c === 0x7b || c === 0x7d;
+}
+function fromHexCode(c) {
+ if (0x30 <= c && c <= 0x39) {
+ return c - 0x30;
+ }
+ const lc = c | 0x20;
+ if (0x61 <= lc && lc <= 0x66) {
+ return lc - 0x61 + 10;
+ }
+ return -1;
+}
+function escapedHexLen(c) {
+ if (c === 0x78) {
+ return 2;
+ }
+ if (c === 0x75) {
+ return 4;
+ }
+ if (c === 0x55) {
+ return 8;
+ }
+ return 0;
+}
+function fromDecimalCode(c) {
+ if (0x30 <= c && c <= 0x39) {
+ return c - 0x30;
+ }
+ return -1;
+}
+function simpleEscapeSequence(c) {
+ return c === 0x30 ? "\x00" : c === 0x61 ? "\x07" : c === 0x62 ? "\x08" : c === 0x74 ? "\x09" : c === 0x09 ? "\x09" : c === 0x6e ? "\x0A" : c === 0x76 ? "\x0B" : c === 0x66 ? "\x0C" : c === 0x72 ? "\x0D" : c === 0x65 ? "\x1B" : c === 0x20 ? " " : c === 0x22 ? "\x22" : c === 0x2f ? "/" : c === 0x5c ? "\x5C" : c === 0x4e ? "\x85" : c === 0x5f ? "\xA0" : c === 0x4c ? "\u2028" : c === 0x50 ? "\u2029" : "";
+}
+function charFromCodepoint(c) {
+ if (c <= 0xffff) {
+ return String.fromCharCode(c);
+ }
+ return String.fromCharCode((c - 0x010000 >> 10) + 0xd800, (c - 0x010000 & 0x03ff) + 0xdc00);
+}
+const simpleEscapeCheck = Array.from({
+ length: 256
+});
+const simpleEscapeMap = Array.from({
+ length: 256
+});
+for(let i = 0; i < 256; i++){
+ simpleEscapeCheck[i] = simpleEscapeSequence(i) ? 1 : 0;
+ simpleEscapeMap[i] = simpleEscapeSequence(i);
+}
+function generateError(state, message) {
+ return new YAMLError(message, new Mark(state.filename, state.input, state.position, state.line, state.position - state.lineStart));
+}
+function throwError(state, message) {
+ throw generateError(state, message);
+}
+function throwWarning(state, message) {
+ if (state.onWarning) {
+ state.onWarning.call(null, generateError(state, message));
+ }
+}
+const directiveHandlers = {
+ YAML (state, _name, ...args) {
+ if (state.version !== null) {
+ return throwError(state, "duplication of %YAML directive");
+ }
+ if (args.length !== 1) {
+ return throwError(state, "YAML directive accepts exactly one argument");
+ }
+ const match = /^([0-9]+)\.([0-9]+)$/.exec(args[0]);
+ if (match === null) {
+ return throwError(state, "ill-formed argument of the YAML directive");
+ }
+ const major = parseInt(match[1], 10);
+ const minor = parseInt(match[2], 10);
+ if (major !== 1) {
+ return throwError(state, "unacceptable YAML version of the document");
+ }
+ state.version = args[0];
+ state.checkLineBreaks = minor < 2;
+ if (minor !== 1 && minor !== 2) {
+ return throwWarning(state, "unsupported YAML version of the document");
+ }
+ },
+ TAG (state, _name, ...args) {
+ if (args.length !== 2) {
+ return throwError(state, "TAG directive accepts exactly two arguments");
+ }
+ const handle = args[0];
+ const prefix = args[1];
+ if (!PATTERN_TAG_HANDLE.test(handle)) {
+ return throwError(state, "ill-formed tag handle (first argument) of the TAG directive");
+ }
+ if (state.tagMap && hasOwn2(state.tagMap, handle)) {
+ return throwError(state, `there is a previously declared suffix for "${handle}" tag handle`);
+ }
+ if (!PATTERN_TAG_URI.test(prefix)) {
+ return throwError(state, "ill-formed tag prefix (second argument) of the TAG directive");
+ }
+ if (typeof state.tagMap === "undefined") {
+ state.tagMap = {};
+ }
+ state.tagMap[handle] = prefix;
+ }
+};
+function captureSegment(state, start, end, checkJson) {
+ let result;
+ if (start < end) {
+ result = state.input.slice(start, end);
+ if (checkJson) {
+ for(let position = 0, length = result.length; position < length; position++){
+ const character = result.charCodeAt(position);
+ if (!(character === 0x09 || 0x20 <= character && character <= 0x10ffff)) {
+ return throwError(state, "expected valid JSON character");
+ }
+ }
+ } else if (PATTERN_NON_PRINTABLE.test(result)) {
+ return throwError(state, "the stream contains non-printable characters");
+ }
+ state.result += result;
+ }
+}
+function mergeMappings(state, destination, source, overridableKeys) {
+ if (!isObject1(source)) {
+ return throwError(state, "cannot merge mappings; the provided source object is unacceptable");
+ }
+ const keys = Object.keys(source);
+ for(let i = 0, len = keys.length; i < len; i++){
+ const key = keys[i];
+ if (!hasOwn2(destination, key)) {
+ destination[key] = source[key];
+ overridableKeys[key] = true;
+ }
+ }
+}
+function storeMappingPair(state, result, overridableKeys, keyTag, keyNode, valueNode, startLine, startPos) {
+ if (Array.isArray(keyNode)) {
+ keyNode = Array.prototype.slice.call(keyNode);
+ for(let index = 0, quantity = keyNode.length; index < quantity; index++){
+ if (Array.isArray(keyNode[index])) {
+ return throwError(state, "nested arrays are not supported inside keys");
+ }
+ if (typeof keyNode === "object" && _class(keyNode[index]) === "[object Object]") {
+ keyNode[index] = "[object Object]";
+ }
+ }
+ }
+ if (typeof keyNode === "object" && _class(keyNode) === "[object Object]") {
+ keyNode = "[object Object]";
+ }
+ keyNode = String(keyNode);
+ if (result === null) {
+ result = {};
+ }
+ if (keyTag === "tag:yaml.org,2002:merge") {
+ if (Array.isArray(valueNode)) {
+ for(let index = 0, quantity = valueNode.length; index < quantity; index++){
+ mergeMappings(state, result, valueNode[index], overridableKeys);
+ }
+ } else {
+ mergeMappings(state, result, valueNode, overridableKeys);
+ }
+ } else {
+ if (!state.json && !hasOwn2(overridableKeys, keyNode) && hasOwn2(result, keyNode)) {
+ state.line = startLine || state.line;
+ state.position = startPos || state.position;
+ return throwError(state, "duplicated mapping key");
+ }
+ result[keyNode] = valueNode;
+ delete overridableKeys[keyNode];
+ }
+ return result;
+}
+function readLineBreak(state) {
+ const ch = state.input.charCodeAt(state.position);
+ if (ch === 0x0a) {
+ state.position++;
+ } else if (ch === 0x0d) {
+ state.position++;
+ if (state.input.charCodeAt(state.position) === 0x0a) {
+ state.position++;
+ }
+ } else {
+ return throwError(state, "a line break is expected");
+ }
+ state.line += 1;
+ state.lineStart = state.position;
+}
+function skipSeparationSpace(state, allowComments, checkIndent) {
+ let lineBreaks = 0, ch = state.input.charCodeAt(state.position);
+ while(ch !== 0){
+ while(isWhiteSpace(ch)){
+ ch = state.input.charCodeAt(++state.position);
+ }
+ if (allowComments && ch === 0x23) {
+ do {
+ ch = state.input.charCodeAt(++state.position);
+ }while (ch !== 0x0a && ch !== 0x0d && ch !== 0)
+ }
+ if (isEOL(ch)) {
+ readLineBreak(state);
+ ch = state.input.charCodeAt(state.position);
+ lineBreaks++;
+ state.lineIndent = 0;
+ while(ch === 0x20){
+ state.lineIndent++;
+ ch = state.input.charCodeAt(++state.position);
+ }
+ } else {
+ break;
+ }
+ }
+ if (checkIndent !== -1 && lineBreaks !== 0 && state.lineIndent < checkIndent) {
+ throwWarning(state, "deficient indentation");
+ }
+ return lineBreaks;
+}
+function testDocumentSeparator(state) {
+ let _position = state.position;
+ let ch = state.input.charCodeAt(_position);
+ if ((ch === 0x2d || ch === 0x2e) && ch === state.input.charCodeAt(_position + 1) && ch === state.input.charCodeAt(_position + 2)) {
+ _position += 3;
+ ch = state.input.charCodeAt(_position);
+ if (ch === 0 || isWsOrEol(ch)) {
+ return true;
+ }
+ }
+ return false;
+}
+function writeFoldedLines(state, count) {
+ if (count === 1) {
+ state.result += " ";
+ } else if (count > 1) {
+ state.result += repeat("\n", count - 1);
+ }
+}
+function readPlainScalar(state, nodeIndent, withinFlowCollection) {
+ const kind = state.kind;
+ const result = state.result;
+ let ch = state.input.charCodeAt(state.position);
+ if (isWsOrEol(ch) || isFlowIndicator(ch) || ch === 0x23 || ch === 0x26 || ch === 0x2a || ch === 0x21 || ch === 0x7c || ch === 0x3e || ch === 0x27 || ch === 0x22 || ch === 0x25 || ch === 0x40 || ch === 0x60) {
+ return false;
+ }
+ let following;
+ if (ch === 0x3f || ch === 0x2d) {
+ following = state.input.charCodeAt(state.position + 1);
+ if (isWsOrEol(following) || withinFlowCollection && isFlowIndicator(following)) {
+ return false;
+ }
+ }
+ state.kind = "scalar";
+ state.result = "";
+ let captureEnd, captureStart = captureEnd = state.position;
+ let hasPendingContent = false;
+ let line = 0;
+ while(ch !== 0){
+ if (ch === 0x3a) {
+ following = state.input.charCodeAt(state.position + 1);
+ if (isWsOrEol(following) || withinFlowCollection && isFlowIndicator(following)) {
+ break;
+ }
+ } else if (ch === 0x23) {
+ const preceding = state.input.charCodeAt(state.position - 1);
+ if (isWsOrEol(preceding)) {
+ break;
+ }
+ } else if (state.position === state.lineStart && testDocumentSeparator(state) || withinFlowCollection && isFlowIndicator(ch)) {
+ break;
+ } else if (isEOL(ch)) {
+ line = state.line;
+ const lineStart = state.lineStart;
+ const lineIndent = state.lineIndent;
+ skipSeparationSpace(state, false, -1);
+ if (state.lineIndent >= nodeIndent) {
+ hasPendingContent = true;
+ ch = state.input.charCodeAt(state.position);
+ continue;
+ } else {
+ state.position = captureEnd;
+ state.line = line;
+ state.lineStart = lineStart;
+ state.lineIndent = lineIndent;
+ break;
+ }
+ }
+ if (hasPendingContent) {
+ captureSegment(state, captureStart, captureEnd, false);
+ writeFoldedLines(state, state.line - line);
+ captureStart = captureEnd = state.position;
+ hasPendingContent = false;
+ }
+ if (!isWhiteSpace(ch)) {
+ captureEnd = state.position + 1;
+ }
+ ch = state.input.charCodeAt(++state.position);
+ }
+ captureSegment(state, captureStart, captureEnd, false);
+ if (state.result) {
+ return true;
+ }
+ state.kind = kind;
+ state.result = result;
+ return false;
+}
+function readSingleQuotedScalar(state, nodeIndent) {
+ let ch, captureStart, captureEnd;
+ ch = state.input.charCodeAt(state.position);
+ if (ch !== 0x27) {
+ return false;
+ }
+ state.kind = "scalar";
+ state.result = "";
+ state.position++;
+ captureStart = captureEnd = state.position;
+ while((ch = state.input.charCodeAt(state.position)) !== 0){
+ if (ch === 0x27) {
+ captureSegment(state, captureStart, state.position, true);
+ ch = state.input.charCodeAt(++state.position);
+ if (ch === 0x27) {
+ captureStart = state.position;
+ state.position++;
+ captureEnd = state.position;
+ } else {
+ return true;
+ }
+ } else if (isEOL(ch)) {
+ captureSegment(state, captureStart, captureEnd, true);
+ writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
+ captureStart = captureEnd = state.position;
+ } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
+ return throwError(state, "unexpected end of the document within a single quoted scalar");
+ } else {
+ state.position++;
+ captureEnd = state.position;
+ }
+ }
+ return throwError(state, "unexpected end of the stream within a single quoted scalar");
+}
+function readDoubleQuotedScalar(state, nodeIndent) {
+ let ch = state.input.charCodeAt(state.position);
+ if (ch !== 0x22) {
+ return false;
+ }
+ state.kind = "scalar";
+ state.result = "";
+ state.position++;
+ let captureEnd, captureStart = captureEnd = state.position;
+ let tmp;
+ while((ch = state.input.charCodeAt(state.position)) !== 0){
+ if (ch === 0x22) {
+ captureSegment(state, captureStart, state.position, true);
+ state.position++;
+ return true;
+ }
+ if (ch === 0x5c) {
+ captureSegment(state, captureStart, state.position, true);
+ ch = state.input.charCodeAt(++state.position);
+ if (isEOL(ch)) {
+ skipSeparationSpace(state, false, nodeIndent);
+ } else if (ch < 256 && simpleEscapeCheck[ch]) {
+ state.result += simpleEscapeMap[ch];
+ state.position++;
+ } else if ((tmp = escapedHexLen(ch)) > 0) {
+ let hexLength = tmp;
+ let hexResult = 0;
+ for(; hexLength > 0; hexLength--){
+ ch = state.input.charCodeAt(++state.position);
+ if ((tmp = fromHexCode(ch)) >= 0) {
+ hexResult = (hexResult << 4) + tmp;
+ } else {
+ return throwError(state, "expected hexadecimal character");
+ }
+ }
+ state.result += charFromCodepoint(hexResult);
+ state.position++;
+ } else {
+ return throwError(state, "unknown escape sequence");
+ }
+ captureStart = captureEnd = state.position;
+ } else if (isEOL(ch)) {
+ captureSegment(state, captureStart, captureEnd, true);
+ writeFoldedLines(state, skipSeparationSpace(state, false, nodeIndent));
+ captureStart = captureEnd = state.position;
+ } else if (state.position === state.lineStart && testDocumentSeparator(state)) {
+ return throwError(state, "unexpected end of the document within a double quoted scalar");
+ } else {
+ state.position++;
+ captureEnd = state.position;
+ }
+ }
+ return throwError(state, "unexpected end of the stream within a double quoted scalar");
+}
+function readFlowCollection(state, nodeIndent) {
+ let ch = state.input.charCodeAt(state.position);
+ let terminator;
+ let isMapping = true;
+ let result = {};
+ if (ch === 0x5b) {
+ terminator = 0x5d;
+ isMapping = false;
+ result = [];
+ } else if (ch === 0x7b) {
+ terminator = 0x7d;
+ } else {
+ return false;
+ }
+ if (state.anchor !== null && typeof state.anchor != "undefined" && typeof state.anchorMap != "undefined") {
+ state.anchorMap[state.anchor] = result;
+ }
+ ch = state.input.charCodeAt(++state.position);
+ const tag = state.tag, anchor = state.anchor;
+ let readNext = true;
+ let valueNode, keyNode, keyTag = keyNode = valueNode = null, isExplicitPair, isPair = isExplicitPair = false;
+ let following = 0, line = 0;
+ const overridableKeys = {};
+ while(ch !== 0){
+ skipSeparationSpace(state, true, nodeIndent);
+ ch = state.input.charCodeAt(state.position);
+ if (ch === terminator) {
+ state.position++;
+ state.tag = tag;
+ state.anchor = anchor;
+ state.kind = isMapping ? "mapping" : "sequence";
+ state.result = result;
+ return true;
+ }
+ if (!readNext) {
+ return throwError(state, "missed comma between flow collection entries");
+ }
+ keyTag = keyNode = valueNode = null;
+ isPair = isExplicitPair = false;
+ if (ch === 0x3f) {
+ following = state.input.charCodeAt(state.position + 1);
+ if (isWsOrEol(following)) {
+ isPair = isExplicitPair = true;
+ state.position++;
+ skipSeparationSpace(state, true, nodeIndent);
+ }
+ }
+ line = state.line;
+ composeNode(state, nodeIndent, 1, false, true);
+ keyTag = state.tag || null;
+ keyNode = state.result;
+ skipSeparationSpace(state, true, nodeIndent);
+ ch = state.input.charCodeAt(state.position);
+ if ((isExplicitPair || state.line === line) && ch === 0x3a) {
+ isPair = true;
+ ch = state.input.charCodeAt(++state.position);
+ skipSeparationSpace(state, true, nodeIndent);
+ composeNode(state, nodeIndent, 1, false, true);
+ valueNode = state.result;
+ }
+ if (isMapping) {
+ storeMappingPair(state, result, overridableKeys, keyTag, keyNode, valueNode);
+ } else if (isPair) {
+ result.push(storeMappingPair(state, null, overridableKeys, keyTag, keyNode, valueNode));
+ } else {
+ result.push(keyNode);
+ }
+ skipSeparationSpace(state, true, nodeIndent);
+ ch = state.input.charCodeAt(state.position);
+ if (ch === 0x2c) {
+ readNext = true;
+ ch = state.input.charCodeAt(++state.position);
+ } else {
+ readNext = false;
+ }
+ }
+ return throwError(state, "unexpected end of the stream within a flow collection");
+}
+function readBlockScalar(state, nodeIndent) {
+ let chomping = 1, didReadContent = false, detectedIndent = false, textIndent = nodeIndent, emptyLines = 0, atMoreIndented = false;
+ let ch = state.input.charCodeAt(state.position);
+ let folding = false;
+ if (ch === 0x7c) {
+ folding = false;
+ } else if (ch === 0x3e) {
+ folding = true;
+ } else {
+ return false;
+ }
+ state.kind = "scalar";
+ state.result = "";
+ let tmp = 0;
+ while(ch !== 0){
+ ch = state.input.charCodeAt(++state.position);
+ if (ch === 0x2b || ch === 0x2d) {
+ if (1 === chomping) {
+ chomping = ch === 0x2b ? CHOMPING_KEEP : CHOMPING_STRIP;
+ } else {
+ return throwError(state, "repeat of a chomping mode identifier");
+ }
+ } else if ((tmp = fromDecimalCode(ch)) >= 0) {
+ if (tmp === 0) {
+ return throwError(state, "bad explicit indentation width of a block scalar; it cannot be less than one");
+ } else if (!detectedIndent) {
+ textIndent = nodeIndent + tmp - 1;
+ detectedIndent = true;
+ } else {
+ return throwError(state, "repeat of an indentation width identifier");
+ }
+ } else {
+ break;
+ }
+ }
+ if (isWhiteSpace(ch)) {
+ do {
+ ch = state.input.charCodeAt(++state.position);
+ }while (isWhiteSpace(ch))
+ if (ch === 0x23) {
+ do {
+ ch = state.input.charCodeAt(++state.position);
+ }while (!isEOL(ch) && ch !== 0)
+ }
+ }
+ while(ch !== 0){
+ readLineBreak(state);
+ state.lineIndent = 0;
+ ch = state.input.charCodeAt(state.position);
+ while((!detectedIndent || state.lineIndent < textIndent) && ch === 0x20){
+ state.lineIndent++;
+ ch = state.input.charCodeAt(++state.position);
+ }
+ if (!detectedIndent && state.lineIndent > textIndent) {
+ textIndent = state.lineIndent;
+ }
+ if (isEOL(ch)) {
+ emptyLines++;
+ continue;
+ }
+ if (state.lineIndent < textIndent) {
+ if (chomping === 3) {
+ state.result += repeat("\n", didReadContent ? 1 + emptyLines : emptyLines);
+ } else if (chomping === 1) {
+ if (didReadContent) {
+ state.result += "\n";
+ }
+ }
+ break;
+ }
+ if (folding) {
+ if (isWhiteSpace(ch)) {
+ atMoreIndented = true;
+ state.result += repeat("\n", didReadContent ? 1 + emptyLines : emptyLines);
+ } else if (atMoreIndented) {
+ atMoreIndented = false;
+ state.result += repeat("\n", emptyLines + 1);
+ } else if (emptyLines === 0) {
+ if (didReadContent) {
+ state.result += " ";
+ }
+ } else {
+ state.result += repeat("\n", emptyLines);
+ }
+ } else {
+ state.result += repeat("\n", didReadContent ? 1 + emptyLines : emptyLines);
+ }
+ didReadContent = true;
+ detectedIndent = true;
+ emptyLines = 0;
+ const captureStart = state.position;
+ while(!isEOL(ch) && ch !== 0){
+ ch = state.input.charCodeAt(++state.position);
+ }
+ captureSegment(state, captureStart, state.position, false);
+ }
+ return true;
+}
+function readBlockSequence(state, nodeIndent) {
+ let line, following, detected = false, ch;
+ const tag = state.tag, anchor = state.anchor, result = [];
+ if (state.anchor !== null && typeof state.anchor !== "undefined" && typeof state.anchorMap !== "undefined") {
+ state.anchorMap[state.anchor] = result;
+ }
+ ch = state.input.charCodeAt(state.position);
+ while(ch !== 0){
+ if (ch !== 0x2d) {
+ break;
+ }
+ following = state.input.charCodeAt(state.position + 1);
+ if (!isWsOrEol(following)) {
+ break;
+ }
+ detected = true;
+ state.position++;
+ if (skipSeparationSpace(state, true, -1)) {
+ if (state.lineIndent <= nodeIndent) {
+ result.push(null);
+ ch = state.input.charCodeAt(state.position);
+ continue;
+ }
+ }
+ line = state.line;
+ composeNode(state, nodeIndent, 3, false, true);
+ result.push(state.result);
+ skipSeparationSpace(state, true, -1);
+ ch = state.input.charCodeAt(state.position);
+ if ((state.line === line || state.lineIndent > nodeIndent) && ch !== 0) {
+ return throwError(state, "bad indentation of a sequence entry");
+ } else if (state.lineIndent < nodeIndent) {
+ break;
+ }
+ }
+ if (detected) {
+ state.tag = tag;
+ state.anchor = anchor;
+ state.kind = "sequence";
+ state.result = result;
+ return true;
+ }
+ return false;
+}
+function readBlockMapping(state, nodeIndent, flowIndent) {
+ const tag = state.tag, anchor = state.anchor, result = {}, overridableKeys = {};
+ let following, allowCompact = false, line, pos, keyTag = null, keyNode = null, valueNode = null, atExplicitKey = false, detected = false, ch;
+ if (state.anchor !== null && typeof state.anchor !== "undefined" && typeof state.anchorMap !== "undefined") {
+ state.anchorMap[state.anchor] = result;
+ }
+ ch = state.input.charCodeAt(state.position);
+ while(ch !== 0){
+ following = state.input.charCodeAt(state.position + 1);
+ line = state.line;
+ pos = state.position;
+ if ((ch === 0x3f || ch === 0x3a) && isWsOrEol(following)) {
+ if (ch === 0x3f) {
+ if (atExplicitKey) {
+ storeMappingPair(state, result, overridableKeys, keyTag, keyNode, null);
+ keyTag = keyNode = valueNode = null;
+ }
+ detected = true;
+ atExplicitKey = true;
+ allowCompact = true;
+ } else if (atExplicitKey) {
+ atExplicitKey = false;
+ allowCompact = true;
+ } else {
+ return throwError(state, "incomplete explicit mapping pair; a key node is missed; or followed by a non-tabulated empty line");
+ }
+ state.position += 1;
+ ch = following;
+ } else if (composeNode(state, flowIndent, 2, false, true)) {
+ if (state.line === line) {
+ ch = state.input.charCodeAt(state.position);
+ while(isWhiteSpace(ch)){
+ ch = state.input.charCodeAt(++state.position);
+ }
+ if (ch === 0x3a) {
+ ch = state.input.charCodeAt(++state.position);
+ if (!isWsOrEol(ch)) {
+ return throwError(state, "a whitespace character is expected after the key-value separator within a block mapping");
+ }
+ if (atExplicitKey) {
+ storeMappingPair(state, result, overridableKeys, keyTag, keyNode, null);
+ keyTag = keyNode = valueNode = null;
+ }
+ detected = true;
+ atExplicitKey = false;
+ allowCompact = false;
+ keyTag = state.tag;
+ keyNode = state.result;
+ } else if (detected) {
+ return throwError(state, "can not read an implicit mapping pair; a colon is missed");
+ } else {
+ state.tag = tag;
+ state.anchor = anchor;
+ return true;
+ }
+ } else if (detected) {
+ return throwError(state, "can not read a block mapping entry; a multiline key may not be an implicit key");
+ } else {
+ state.tag = tag;
+ state.anchor = anchor;
+ return true;
+ }
+ } else {
+ break;
+ }
+ if (state.line === line || state.lineIndent > nodeIndent) {
+ if (composeNode(state, nodeIndent, 4, true, allowCompact)) {
+ if (atExplicitKey) {
+ keyNode = state.result;
+ } else {
+ valueNode = state.result;
+ }
+ }
+ if (!atExplicitKey) {
+ storeMappingPair(state, result, overridableKeys, keyTag, keyNode, valueNode, line, pos);
+ keyTag = keyNode = valueNode = null;
+ }
+ skipSeparationSpace(state, true, -1);
+ ch = state.input.charCodeAt(state.position);
+ }
+ if (state.lineIndent > nodeIndent && ch !== 0) {
+ return throwError(state, "bad indentation of a mapping entry");
+ } else if (state.lineIndent < nodeIndent) {
+ break;
+ }
+ }
+ if (atExplicitKey) {
+ storeMappingPair(state, result, overridableKeys, keyTag, keyNode, null);
+ }
+ if (detected) {
+ state.tag = tag;
+ state.anchor = anchor;
+ state.kind = "mapping";
+ state.result = result;
+ }
+ return detected;
+}
+function readTagProperty(state) {
+ let position, isVerbatim = false, isNamed = false, tagHandle = "", tagName, ch;
+ ch = state.input.charCodeAt(state.position);
+ if (ch !== 0x21) return false;
+ if (state.tag !== null) {
+ return throwError(state, "duplication of a tag property");
+ }
+ ch = state.input.charCodeAt(++state.position);
+ if (ch === 0x3c) {
+ isVerbatim = true;
+ ch = state.input.charCodeAt(++state.position);
+ } else if (ch === 0x21) {
+ isNamed = true;
+ tagHandle = "!!";
+ ch = state.input.charCodeAt(++state.position);
+ } else {
+ tagHandle = "!";
+ }
+ position = state.position;
+ if (isVerbatim) {
+ do {
+ ch = state.input.charCodeAt(++state.position);
+ }while (ch !== 0 && ch !== 0x3e)
+ if (state.position < state.length) {
+ tagName = state.input.slice(position, state.position);
+ ch = state.input.charCodeAt(++state.position);
+ } else {
+ return throwError(state, "unexpected end of the stream within a verbatim tag");
+ }
+ } else {
+ while(ch !== 0 && !isWsOrEol(ch)){
+ if (ch === 0x21) {
+ if (!isNamed) {
+ tagHandle = state.input.slice(position - 1, state.position + 1);
+ if (!PATTERN_TAG_HANDLE.test(tagHandle)) {
+ return throwError(state, "named tag handle cannot contain such characters");
+ }
+ isNamed = true;
+ position = state.position + 1;
+ } else {
+ return throwError(state, "tag suffix cannot contain exclamation marks");
+ }
+ }
+ ch = state.input.charCodeAt(++state.position);
+ }
+ tagName = state.input.slice(position, state.position);
+ if (PATTERN_FLOW_INDICATORS.test(tagName)) {
+ return throwError(state, "tag suffix cannot contain flow indicator characters");
+ }
+ }
+ if (tagName && !PATTERN_TAG_URI.test(tagName)) {
+ return throwError(state, `tag name cannot contain such characters: ${tagName}`);
+ }
+ if (isVerbatim) {
+ state.tag = tagName;
+ } else if (typeof state.tagMap !== "undefined" && hasOwn2(state.tagMap, tagHandle)) {
+ state.tag = state.tagMap[tagHandle] + tagName;
+ } else if (tagHandle === "!") {
+ state.tag = `!${tagName}`;
+ } else if (tagHandle === "!!") {
+ state.tag = `tag:yaml.org,2002:${tagName}`;
+ } else {
+ return throwError(state, `undeclared tag handle "${tagHandle}"`);
+ }
+ return true;
+}
+function readAnchorProperty(state) {
+ let ch = state.input.charCodeAt(state.position);
+ if (ch !== 0x26) return false;
+ if (state.anchor !== null) {
+ return throwError(state, "duplication of an anchor property");
+ }
+ ch = state.input.charCodeAt(++state.position);
+ const position = state.position;
+ while(ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)){
+ ch = state.input.charCodeAt(++state.position);
+ }
+ if (state.position === position) {
+ return throwError(state, "name of an anchor node must contain at least one character");
+ }
+ state.anchor = state.input.slice(position, state.position);
+ return true;
+}
+function readAlias(state) {
+ let ch = state.input.charCodeAt(state.position);
+ if (ch !== 0x2a) return false;
+ ch = state.input.charCodeAt(++state.position);
+ const _position = state.position;
+ while(ch !== 0 && !isWsOrEol(ch) && !isFlowIndicator(ch)){
+ ch = state.input.charCodeAt(++state.position);
+ }
+ if (state.position === _position) {
+ return throwError(state, "name of an alias node must contain at least one character");
+ }
+ const alias = state.input.slice(_position, state.position);
+ if (typeof state.anchorMap !== "undefined" && !hasOwn2(state.anchorMap, alias)) {
+ return throwError(state, `unidentified alias "${alias}"`);
+ }
+ if (typeof state.anchorMap !== "undefined") {
+ state.result = state.anchorMap[alias];
+ }
+ skipSeparationSpace(state, true, -1);
+ return true;
+}
+function composeNode(state, parentIndent, nodeContext, allowToSeek, allowCompact) {
+ let allowBlockScalars, allowBlockCollections, indentStatus = 1, atNewLine = false, hasContent = false, type, flowIndent, blockIndent;
+ if (state.listener && state.listener !== null) {
+ state.listener("open", state);
+ }
+ state.tag = null;
+ state.anchor = null;
+ state.kind = null;
+ state.result = null;
+ const allowBlockStyles = allowBlockScalars = allowBlockCollections = CONTEXT_BLOCK_OUT === nodeContext || CONTEXT_BLOCK_IN === nodeContext;
+ if (allowToSeek) {
+ if (skipSeparationSpace(state, true, -1)) {
+ atNewLine = true;
+ if (state.lineIndent > parentIndent) {
+ indentStatus = 1;
+ } else if (state.lineIndent === parentIndent) {
+ indentStatus = 0;
+ } else if (state.lineIndent < parentIndent) {
+ indentStatus = -1;
+ }
+ }
+ }
+ if (indentStatus === 1) {
+ while(readTagProperty(state) || readAnchorProperty(state)){
+ if (skipSeparationSpace(state, true, -1)) {
+ atNewLine = true;
+ allowBlockCollections = allowBlockStyles;
+ if (state.lineIndent > parentIndent) {
+ indentStatus = 1;
+ } else if (state.lineIndent === parentIndent) {
+ indentStatus = 0;
+ } else if (state.lineIndent < parentIndent) {
+ indentStatus = -1;
+ }
+ } else {
+ allowBlockCollections = false;
+ }
+ }
+ }
+ if (allowBlockCollections) {
+ allowBlockCollections = atNewLine || allowCompact;
+ }
+ if (indentStatus === 1 || 4 === nodeContext) {
+ const cond = 1 === nodeContext || 2 === nodeContext;
+ flowIndent = cond ? parentIndent : parentIndent + 1;
+ blockIndent = state.position - state.lineStart;
+ if (indentStatus === 1) {
+ if (allowBlockCollections && (readBlockSequence(state, blockIndent) || readBlockMapping(state, blockIndent, flowIndent)) || readFlowCollection(state, flowIndent)) {
+ hasContent = true;
+ } else {
+ if (allowBlockScalars && readBlockScalar(state, flowIndent) || readSingleQuotedScalar(state, flowIndent) || readDoubleQuotedScalar(state, flowIndent)) {
+ hasContent = true;
+ } else if (readAlias(state)) {
+ hasContent = true;
+ if (state.tag !== null || state.anchor !== null) {
+ return throwError(state, "alias node should not have Any properties");
+ }
+ } else if (readPlainScalar(state, flowIndent, 1 === nodeContext)) {
+ hasContent = true;
+ if (state.tag === null) {
+ state.tag = "?";
+ }
+ }
+ if (state.anchor !== null && typeof state.anchorMap !== "undefined") {
+ state.anchorMap[state.anchor] = state.result;
+ }
+ }
+ } else if (indentStatus === 0) {
+ hasContent = allowBlockCollections && readBlockSequence(state, blockIndent);
+ }
+ }
+ if (state.tag !== null && state.tag !== "!") {
+ if (state.tag === "?") {
+ for(let typeIndex = 0, typeQuantity = state.implicitTypes.length; typeIndex < typeQuantity; typeIndex++){
+ type = state.implicitTypes[typeIndex];
+ if (type.resolve(state.result)) {
+ state.result = type.construct(state.result);
+ state.tag = type.tag;
+ if (state.anchor !== null && typeof state.anchorMap !== "undefined") {
+ state.anchorMap[state.anchor] = state.result;
+ }
+ break;
+ }
+ }
+ } else if (hasOwn2(state.typeMap[state.kind || "fallback"], state.tag)) {
+ type = state.typeMap[state.kind || "fallback"][state.tag];
+ if (state.result !== null && type.kind !== state.kind) {
+ return throwError(state, `unacceptable node kind for !<${state.tag}> tag; it should be "${type.kind}", not "${state.kind}"`);
+ }
+ if (!type.resolve(state.result)) {
+ return throwError(state, `cannot resolve a node with !<${state.tag}> explicit tag`);
+ } else {
+ state.result = type.construct(state.result);
+ if (state.anchor !== null && typeof state.anchorMap !== "undefined") {
+ state.anchorMap[state.anchor] = state.result;
+ }
+ }
+ } else {
+ return throwError(state, `unknown tag !<${state.tag}>`);
+ }
+ }
+ if (state.listener && state.listener !== null) {
+ state.listener("close", state);
+ }
+ return state.tag !== null || state.anchor !== null || hasContent;
+}
+function readDocument(state) {
+ const documentStart = state.position;
+ let position, directiveName, directiveArgs, hasDirectives = false, ch;
+ state.version = null;
+ state.checkLineBreaks = state.legacy;
+ state.tagMap = {};
+ state.anchorMap = {};
+ while((ch = state.input.charCodeAt(state.position)) !== 0){
+ skipSeparationSpace(state, true, -1);
+ ch = state.input.charCodeAt(state.position);
+ if (state.lineIndent > 0 || ch !== 0x25) {
+ break;
+ }
+ hasDirectives = true;
+ ch = state.input.charCodeAt(++state.position);
+ position = state.position;
+ while(ch !== 0 && !isWsOrEol(ch)){
+ ch = state.input.charCodeAt(++state.position);
+ }
+ directiveName = state.input.slice(position, state.position);
+ directiveArgs = [];
+ if (directiveName.length < 1) {
+ return throwError(state, "directive name must not be less than one character in length");
+ }
+ while(ch !== 0){
+ while(isWhiteSpace(ch)){
+ ch = state.input.charCodeAt(++state.position);
+ }
+ if (ch === 0x23) {
+ do {
+ ch = state.input.charCodeAt(++state.position);
+ }while (ch !== 0 && !isEOL(ch))
+ break;
+ }
+ if (isEOL(ch)) break;
+ position = state.position;
+ while(ch !== 0 && !isWsOrEol(ch)){
+ ch = state.input.charCodeAt(++state.position);
+ }
+ directiveArgs.push(state.input.slice(position, state.position));
+ }
+ if (ch !== 0) readLineBreak(state);
+ if (hasOwn2(directiveHandlers, directiveName)) {
+ directiveHandlers[directiveName](state, directiveName, ...directiveArgs);
+ } else {
+ throwWarning(state, `unknown document directive "${directiveName}"`);
+ }
+ }
+ skipSeparationSpace(state, true, -1);
+ if (state.lineIndent === 0 && state.input.charCodeAt(state.position) === 0x2d && state.input.charCodeAt(state.position + 1) === 0x2d && state.input.charCodeAt(state.position + 2) === 0x2d) {
+ state.position += 3;
+ skipSeparationSpace(state, true, -1);
+ } else if (hasDirectives) {
+ return throwError(state, "directives end mark is expected");
+ }
+ composeNode(state, state.lineIndent - 1, 4, false, true);
+ skipSeparationSpace(state, true, -1);
+ if (state.checkLineBreaks && PATTERN_NON_ASCII_LINE_BREAKS.test(state.input.slice(documentStart, state.position))) {
+ throwWarning(state, "non-ASCII line breaks are interpreted as content");
+ }
+ state.documents.push(state.result);
+ if (state.position === state.lineStart && testDocumentSeparator(state)) {
+ if (state.input.charCodeAt(state.position) === 0x2e) {
+ state.position += 3;
+ skipSeparationSpace(state, true, -1);
+ }
+ return;
+ }
+ if (state.position < state.length - 1) {
+ return throwError(state, "end of the stream or a document separator is expected");
+ } else {
+ return;
+ }
+}
+function loadDocuments(input, options) {
+ input = String(input);
+ options = options || {};
+ if (input.length !== 0) {
+ if (input.charCodeAt(input.length - 1) !== 0x0a && input.charCodeAt(input.length - 1) !== 0x0d) {
+ input += "\n";
+ }
+ if (input.charCodeAt(0) === 0xfeff) {
+ input = input.slice(1);
+ }
+ }
+ const state = new LoaderState(input, options);
+ state.input += "\0";
+ while(state.input.charCodeAt(state.position) === 0x20){
+ state.lineIndent += 1;
+ state.position += 1;
+ }
+ while(state.position < state.length - 1){
+ readDocument(state);
+ }
+ return state.documents;
+}
+function isCbFunction(fn) {
+ return typeof fn === "function";
+}
+function loadAll(input, iteratorOrOption, options) {
+ if (!isCbFunction(iteratorOrOption)) {
+ return loadDocuments(input, iteratorOrOption);
+ }
+ const documents = loadDocuments(input, options);
+ const iterator = iteratorOrOption;
+ for(let index = 0, length = documents.length; index < length; index++){
+ iterator(documents[index]);
+ }
+ return void 0;
+}
+function load(input, options) {
+ const documents = loadDocuments(input, options);
+ if (documents.length === 0) {
+ return;
+ }
+ if (documents.length === 1) {
+ return documents[0];
+ }
+ throw new YAMLError("expected a single document in the stream, but found more");
+}
+function parse(content, options) {
+ return load(content, options);
+}
+function parseAll(content, iterator, options) {
+ return loadAll(content, iterator, options);
+}
+const { hasOwn: hasOwn3 } = Object;
+function compileStyleMap(schema, map) {
+ if (typeof map === "undefined" || map === null) return {};
+ let type;
+ const result = {};
+ const keys = Object.keys(map);
+ let tag, style;
+ for(let index = 0, length = keys.length; index < length; index += 1){
+ tag = keys[index];
+ style = String(map[tag]);
+ if (tag.slice(0, 2) === "!!") {
+ tag = `tag:yaml.org,2002:${tag.slice(2)}`;
+ }
+ type = schema.compiledTypeMap.fallback[tag];
+ if (type && typeof type.styleAliases !== "undefined" && hasOwn3(type.styleAliases, style)) {
+ style = type.styleAliases[style];
+ }
+ result[tag] = style;
+ }
+ return result;
+}
+class DumperState extends State {
+ indent;
+ noArrayIndent;
+ skipInvalid;
+ flowLevel;
+ sortKeys;
+ lineWidth;
+ noRefs;
+ noCompatMode;
+ condenseFlow;
+ implicitTypes;
+ explicitTypes;
+ tag = null;
+ result = "";
+ duplicates = [];
+ usedDuplicates = [];
+ styleMap;
+ dump;
+ constructor({ schema, indent = 2, noArrayIndent = false, skipInvalid = false, flowLevel = -1, styles = null, sortKeys = false, lineWidth = 80, noRefs = false, noCompatMode = false, condenseFlow = false }){
+ super(schema);
+ this.indent = Math.max(1, indent);
+ this.noArrayIndent = noArrayIndent;
+ this.skipInvalid = skipInvalid;
+ this.flowLevel = flowLevel;
+ this.styleMap = compileStyleMap(this.schema, styles);
+ this.sortKeys = sortKeys;
+ this.lineWidth = lineWidth;
+ this.noRefs = noRefs;
+ this.noCompatMode = noCompatMode;
+ this.condenseFlow = condenseFlow;
+ this.implicitTypes = this.schema.compiledImplicit;
+ this.explicitTypes = this.schema.compiledExplicit;
+ }
+}
+const _toString2 = Object.prototype.toString;
+const { hasOwn: hasOwn4 } = Object;
+const ESCAPE_SEQUENCES = {};
+ESCAPE_SEQUENCES[0x00] = "\\0";
+ESCAPE_SEQUENCES[0x07] = "\\a";
+ESCAPE_SEQUENCES[0x08] = "\\b";
+ESCAPE_SEQUENCES[0x09] = "\\t";
+ESCAPE_SEQUENCES[0x0a] = "\\n";
+ESCAPE_SEQUENCES[0x0b] = "\\v";
+ESCAPE_SEQUENCES[0x0c] = "\\f";
+ESCAPE_SEQUENCES[0x0d] = "\\r";
+ESCAPE_SEQUENCES[0x1b] = "\\e";
+ESCAPE_SEQUENCES[0x22] = '\\"';
+ESCAPE_SEQUENCES[0x5c] = "\\\\";
+ESCAPE_SEQUENCES[0x85] = "\\N";
+ESCAPE_SEQUENCES[0xa0] = "\\_";
+ESCAPE_SEQUENCES[0x2028] = "\\L";
+ESCAPE_SEQUENCES[0x2029] = "\\P";
+const DEPRECATED_BOOLEANS_SYNTAX = [
+ "y",
+ "Y",
+ "yes",
+ "Yes",
+ "YES",
+ "on",
+ "On",
+ "ON",
+ "n",
+ "N",
+ "no",
+ "No",
+ "NO",
+ "off",
+ "Off",
+ "OFF"
+];
+function encodeHex(character) {
+ const string = character.toString(16).toUpperCase();
+ let handle;
+ let length;
+ if (character <= 0xff) {
+ handle = "x";
+ length = 2;
+ } else if (character <= 0xffff) {
+ handle = "u";
+ length = 4;
+ } else if (character <= 0xffffffff) {
+ handle = "U";
+ length = 8;
+ } else {
+ throw new YAMLError("code point within a string may not be greater than 0xFFFFFFFF");
+ }
+ return `\\${handle}${repeat("0", length - string.length)}${string}`;
+}
+function indentString(string, spaces) {
+ const ind = repeat(" ", spaces), length = string.length;
+ let position = 0, next = -1, result = "", line;
+ while(position < length){
+ next = string.indexOf("\n", position);
+ if (next === -1) {
+ line = string.slice(position);
+ position = length;
+ } else {
+ line = string.slice(position, next + 1);
+ position = next + 1;
+ }
+ if (line.length && line !== "\n") result += ind;
+ result += line;
+ }
+ return result;
+}
+function generateNextLine(state, level) {
+ return `\n${repeat(" ", state.indent * level)}`;
+}
+function testImplicitResolving(state, str) {
+ let type;
+ for(let index = 0, length = state.implicitTypes.length; index < length; index += 1){
+ type = state.implicitTypes[index];
+ if (type.resolve(str)) {
+ return true;
+ }
+ }
+ return false;
+}
+function isWhitespace(c) {
+ return c === 0x20 || c === 0x09;
+}
+function isPrintable(c) {
+ return 0x00020 <= c && c <= 0x00007e || 0x000a1 <= c && c <= 0x00d7ff && c !== 0x2028 && c !== 0x2029 || 0x0e000 <= c && c <= 0x00fffd && c !== 0xfeff || 0x10000 <= c && c <= 0x10ffff;
+}
+function isPlainSafe(c) {
+ return isPrintable(c) && c !== 0xfeff && c !== 0x2c && c !== 0x5b && c !== 0x5d && c !== 0x7b && c !== 0x7d && c !== 0x3a && c !== 0x23;
+}
+function isPlainSafeFirst(c) {
+ return isPrintable(c) && c !== 0xfeff && !isWhitespace(c) && c !== 0x2d && c !== 0x3f && c !== 0x3a && c !== 0x2c && c !== 0x5b && c !== 0x5d && c !== 0x7b && c !== 0x7d && c !== 0x23 && c !== 0x26 && c !== 0x2a && c !== 0x21 && c !== 0x7c && c !== 0x3e && c !== 0x27 && c !== 0x22 && c !== 0x25 && c !== 0x40 && c !== 0x60;
+}
+function needIndentIndicator(string) {
+ const leadingSpaceRe = /^\n* /;
+ return leadingSpaceRe.test(string);
+}
+const STYLE_PLAIN = 1, STYLE_SINGLE = 2, STYLE_LITERAL = 3, STYLE_FOLDED = 4, STYLE_DOUBLE = 5;
+function chooseScalarStyle(string, singleLineOnly, indentPerLevel, lineWidth, testAmbiguousType) {
+ const shouldTrackWidth = lineWidth !== -1;
+ let hasLineBreak = false, hasFoldableLine = false, previousLineBreak = -1, plain = isPlainSafeFirst(string.charCodeAt(0)) && !isWhitespace(string.charCodeAt(string.length - 1));
+ let __char, i;
+ if (singleLineOnly) {
+ for(i = 0; i < string.length; i++){
+ __char = string.charCodeAt(i);
+ if (!isPrintable(__char)) {
+ return 5;
+ }
+ plain = plain && isPlainSafe(__char);
+ }
+ } else {
+ for(i = 0; i < string.length; i++){
+ __char = string.charCodeAt(i);
+ if (__char === 0x0a) {
+ hasLineBreak = true;
+ if (shouldTrackWidth) {
+ hasFoldableLine = hasFoldableLine || i - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " ";
+ previousLineBreak = i;
+ }
+ } else if (!isPrintable(__char)) {
+ return 5;
+ }
+ plain = plain && isPlainSafe(__char);
+ }
+ hasFoldableLine = hasFoldableLine || shouldTrackWidth && i - previousLineBreak - 1 > lineWidth && string[previousLineBreak + 1] !== " ";
+ }
+ if (!hasLineBreak && !hasFoldableLine) {
+ return plain && !testAmbiguousType(string) ? 1 : 2;
+ }
+ if (indentPerLevel > 9 && needIndentIndicator(string)) {
+ return 5;
+ }
+ return hasFoldableLine ? 4 : 3;
+}
+function foldLine(line, width) {
+ if (line === "" || line[0] === " ") return line;
+ const breakRe = / [^ ]/g;
+ let match;
+ let start = 0, end, curr = 0, next = 0;
+ let result = "";
+ while(match = breakRe.exec(line)){
+ next = match.index;
+ if (next - start > width) {
+ end = curr > start ? curr : next;
+ result += `\n${line.slice(start, end)}`;
+ start = end + 1;
+ }
+ curr = next;
+ }
+ result += "\n";
+ if (line.length - start > width && curr > start) {
+ result += `${line.slice(start, curr)}\n${line.slice(curr + 1)}`;
+ } else {
+ result += line.slice(start);
+ }
+ return result.slice(1);
+}
+function dropEndingNewline(string) {
+ return string[string.length - 1] === "\n" ? string.slice(0, -1) : string;
+}
+function foldString(string, width) {
+ const lineRe = /(\n+)([^\n]*)/g;
+ let result = (()=>{
+ let nextLF = string.indexOf("\n");
+ nextLF = nextLF !== -1 ? nextLF : string.length;
+ lineRe.lastIndex = nextLF;
+ return foldLine(string.slice(0, nextLF), width);
+ })();
+ let prevMoreIndented = string[0] === "\n" || string[0] === " ";
+ let moreIndented;
+ let match;
+ while(match = lineRe.exec(string)){
+ const prefix = match[1], line = match[2];
+ moreIndented = line[0] === " ";
+ result += prefix + (!prevMoreIndented && !moreIndented && line !== "" ? "\n" : "") + foldLine(line, width);
+ prevMoreIndented = moreIndented;
+ }
+ return result;
+}
+function escapeString(string) {
+ let result = "";
+ let __char, nextChar;
+ let escapeSeq;
+ for(let i = 0; i < string.length; i++){
+ __char = string.charCodeAt(i);
+ if (__char >= 0xd800 && __char <= 0xdbff) {
+ nextChar = string.charCodeAt(i + 1);
+ if (nextChar >= 0xdc00 && nextChar <= 0xdfff) {
+ result += encodeHex((__char - 0xd800) * 0x400 + nextChar - 0xdc00 + 0x10000);
+ i++;
+ continue;
+ }
+ }
+ escapeSeq = ESCAPE_SEQUENCES[__char];
+ result += !escapeSeq && isPrintable(__char) ? string[i] : escapeSeq || encodeHex(__char);
+ }
+ return result;
+}
+function blockHeader(string, indentPerLevel) {
+ const indentIndicator = needIndentIndicator(string) ? String(indentPerLevel) : "";
+ const clip = string[string.length - 1] === "\n";
+ const keep = clip && (string[string.length - 2] === "\n" || string === "\n");
+ const chomp = keep ? "+" : clip ? "" : "-";
+ return `${indentIndicator}${chomp}\n`;
+}
+function writeScalar(state, string, level, iskey) {
+ state.dump = (()=>{
+ if (string.length === 0) {
+ return "''";
+ }
+ if (!state.noCompatMode && DEPRECATED_BOOLEANS_SYNTAX.indexOf(string) !== -1) {
+ return `'${string}'`;
+ }
+ const indent = state.indent * Math.max(1, level);
+ const lineWidth = state.lineWidth === -1 ? -1 : Math.max(Math.min(state.lineWidth, 40), state.lineWidth - indent);
+ const singleLineOnly = iskey || state.flowLevel > -1 && level >= state.flowLevel;
+ function testAmbiguity(str) {
+ return testImplicitResolving(state, str);
+ }
+ switch(chooseScalarStyle(string, singleLineOnly, state.indent, lineWidth, testAmbiguity)){
+ case STYLE_PLAIN:
+ return string;
+ case STYLE_SINGLE:
+ return `'${string.replace(/'/g, "''")}'`;
+ case STYLE_LITERAL:
+ return `|${blockHeader(string, state.indent)}${dropEndingNewline(indentString(string, indent))}`;
+ case STYLE_FOLDED:
+ return `>${blockHeader(string, state.indent)}${dropEndingNewline(indentString(foldString(string, lineWidth), indent))}`;
+ case STYLE_DOUBLE:
+ return `"${escapeString(string)}"`;
+ default:
+ throw new YAMLError("impossible error: invalid scalar style");
+ }
+ })();
+}
+function writeFlowSequence(state, level, object) {
+ let _result = "";
+ const _tag = state.tag;
+ for(let index = 0, length = object.length; index < length; index += 1){
+ if (writeNode(state, level, object[index], false, false)) {
+ if (index !== 0) _result += `,${!state.condenseFlow ? " " : ""}`;
+ _result += state.dump;
+ }
+ }
+ state.tag = _tag;
+ state.dump = `[${_result}]`;
+}
+function writeBlockSequence(state, level, object, compact = false) {
+ let _result = "";
+ const _tag = state.tag;
+ for(let index = 0, length = object.length; index < length; index += 1){
+ if (writeNode(state, level + 1, object[index], true, true)) {
+ if (!compact || index !== 0) {
+ _result += generateNextLine(state, level);
+ }
+ if (state.dump && 0x0a === state.dump.charCodeAt(0)) {
+ _result += "-";
+ } else {
+ _result += "- ";
+ }
+ _result += state.dump;
+ }
+ }
+ state.tag = _tag;
+ state.dump = _result || "[]";
+}
+function writeFlowMapping(state, level, object) {
+ let _result = "";
+ const _tag = state.tag, objectKeyList = Object.keys(object);
+ let pairBuffer, objectKey, objectValue;
+ for(let index = 0, length = objectKeyList.length; index < length; index += 1){
+ pairBuffer = state.condenseFlow ? '"' : "";
+ if (index !== 0) pairBuffer += ", ";
+ objectKey = objectKeyList[index];
+ objectValue = object[objectKey];
+ if (!writeNode(state, level, objectKey, false, false)) {
+ continue;
+ }
+ if (state.dump.length > 1024) pairBuffer += "? ";
+ pairBuffer += `${state.dump}${state.condenseFlow ? '"' : ""}:${state.condenseFlow ? "" : " "}`;
+ if (!writeNode(state, level, objectValue, false, false)) {
+ continue;
+ }
+ pairBuffer += state.dump;
+ _result += pairBuffer;
+ }
+ state.tag = _tag;
+ state.dump = `{${_result}}`;
+}
+function writeBlockMapping(state, level, object, compact = false) {
+ const _tag = state.tag, objectKeyList = Object.keys(object);
+ let _result = "";
+ if (state.sortKeys === true) {
+ objectKeyList.sort();
+ } else if (typeof state.sortKeys === "function") {
+ objectKeyList.sort(state.sortKeys);
+ } else if (state.sortKeys) {
+ throw new YAMLError("sortKeys must be a boolean or a function");
+ }
+ let pairBuffer = "", objectKey, objectValue, explicitPair;
+ for(let index = 0, length = objectKeyList.length; index < length; index += 1){
+ pairBuffer = "";
+ if (!compact || index !== 0) {
+ pairBuffer += generateNextLine(state, level);
+ }
+ objectKey = objectKeyList[index];
+ objectValue = object[objectKey];
+ if (!writeNode(state, level + 1, objectKey, true, true, true)) {
+ continue;
+ }
+ explicitPair = state.tag !== null && state.tag !== "?" || state.dump && state.dump.length > 1024;
+ if (explicitPair) {
+ if (state.dump && 0x0a === state.dump.charCodeAt(0)) {
+ pairBuffer += "?";
+ } else {
+ pairBuffer += "? ";
+ }
+ }
+ pairBuffer += state.dump;
+ if (explicitPair) {
+ pairBuffer += generateNextLine(state, level);
+ }
+ if (!writeNode(state, level + 1, objectValue, true, explicitPair)) {
+ continue;
+ }
+ if (state.dump && 0x0a === state.dump.charCodeAt(0)) {
+ pairBuffer += ":";
+ } else {
+ pairBuffer += ": ";
+ }
+ pairBuffer += state.dump;
+ _result += pairBuffer;
+ }
+ state.tag = _tag;
+ state.dump = _result || "{}";
+}
+function detectType(state, object, explicit = false) {
+ const typeList = explicit ? state.explicitTypes : state.implicitTypes;
+ let type;
+ let style;
+ let _result;
+ for(let index = 0, length = typeList.length; index < length; index += 1){
+ type = typeList[index];
+ if ((type.instanceOf || type.predicate) && (!type.instanceOf || typeof object === "object" && object instanceof type.instanceOf) && (!type.predicate || type.predicate(object))) {
+ state.tag = explicit ? type.tag : "?";
+ if (type.represent) {
+ style = state.styleMap[type.tag] || type.defaultStyle;
+ if (_toString2.call(type.represent) === "[object Function]") {
+ _result = type.represent(object, style);
+ } else if (hasOwn4(type.represent, style)) {
+ _result = type.represent[style](object, style);
+ } else {
+ throw new YAMLError(`!<${type.tag}> tag resolver accepts not "${style}" style`);
+ }
+ state.dump = _result;
+ }
+ return true;
+ }
+ }
+ return false;
+}
+function writeNode(state, level, object, block, compact, iskey = false) {
+ state.tag = null;
+ state.dump = object;
+ if (!detectType(state, object, false)) {
+ detectType(state, object, true);
+ }
+ const type = _toString2.call(state.dump);
+ if (block) {
+ block = state.flowLevel < 0 || state.flowLevel > level;
+ }
+ const objectOrArray = type === "[object Object]" || type === "[object Array]";
+ let duplicateIndex = -1;
+ let duplicate = false;
+ if (objectOrArray) {
+ duplicateIndex = state.duplicates.indexOf(object);
+ duplicate = duplicateIndex !== -1;
+ }
+ if (state.tag !== null && state.tag !== "?" || duplicate || state.indent !== 2 && level > 0) {
+ compact = false;
+ }
+ if (duplicate && state.usedDuplicates[duplicateIndex]) {
+ state.dump = `*ref_${duplicateIndex}`;
+ } else {
+ if (objectOrArray && duplicate && !state.usedDuplicates[duplicateIndex]) {
+ state.usedDuplicates[duplicateIndex] = true;
+ }
+ if (type === "[object Object]") {
+ if (block && Object.keys(state.dump).length !== 0) {
+ writeBlockMapping(state, level, state.dump, compact);
+ if (duplicate) {
+ state.dump = `&ref_${duplicateIndex}${state.dump}`;
+ }
+ } else {
+ writeFlowMapping(state, level, state.dump);
+ if (duplicate) {
+ state.dump = `&ref_${duplicateIndex} ${state.dump}`;
+ }
+ }
+ } else if (type === "[object Array]") {
+ const arrayLevel = state.noArrayIndent && level > 0 ? level - 1 : level;
+ if (block && state.dump.length !== 0) {
+ writeBlockSequence(state, arrayLevel, state.dump, compact);
+ if (duplicate) {
+ state.dump = `&ref_${duplicateIndex}${state.dump}`;
+ }
+ } else {
+ writeFlowSequence(state, arrayLevel, state.dump);
+ if (duplicate) {
+ state.dump = `&ref_${duplicateIndex} ${state.dump}`;
+ }
+ }
+ } else if (type === "[object String]") {
+ if (state.tag !== "?") {
+ writeScalar(state, state.dump, level, iskey);
+ }
+ } else {
+ if (state.skipInvalid) return false;
+ throw new YAMLError(`unacceptable kind of an object to dump ${type}`);
+ }
+ if (state.tag !== null && state.tag !== "?") {
+ state.dump = `!<${state.tag}> ${state.dump}`;
+ }
+ }
+ return true;
+}
+function inspectNode(object, objects, duplicatesIndexes) {
+ if (object !== null && typeof object === "object") {
+ const index = objects.indexOf(object);
+ if (index !== -1) {
+ if (duplicatesIndexes.indexOf(index) === -1) {
+ duplicatesIndexes.push(index);
+ }
+ } else {
+ objects.push(object);
+ if (Array.isArray(object)) {
+ for(let idx = 0, length = object.length; idx < length; idx += 1){
+ inspectNode(object[idx], objects, duplicatesIndexes);
+ }
+ } else {
+ const objectKeyList = Object.keys(object);
+ for(let idx = 0, length = objectKeyList.length; idx < length; idx += 1){
+ inspectNode(object[objectKeyList[idx]], objects, duplicatesIndexes);
+ }
+ }
+ }
+ }
+}
+function getDuplicateReferences(object, state) {
+ const objects = [], duplicatesIndexes = [];
+ inspectNode(object, objects, duplicatesIndexes);
+ const length = duplicatesIndexes.length;
+ for(let index = 0; index < length; index += 1){
+ state.duplicates.push(objects[duplicatesIndexes[index]]);
+ }
+ state.usedDuplicates = Array.from({
+ length
+ });
+}
+function dump(input, options) {
+ options = options || {};
+ const state = new DumperState(options);
+ if (!state.noRefs) getDuplicateReferences(input, state);
+ if (writeNode(state, 0, input, true, true)) return `${state.dump}\n`;
+ return "";
+}
+function stringify(obj, options) {
+ return dump(obj, options);
+}
+const mod1 = {
+ parse: parse,
+ parseAll: parseAll,
+ stringify: stringify,
+ Type: Type,
+ CORE_SCHEMA: core,
+ DEFAULT_SCHEMA: def,
+ EXTENDED_SCHEMA: extended,
+ FAILSAFE_SCHEMA: failsafe,
+ JSON_SCHEMA: json
+};
+function incrementLastNumber(list) {
+ const newList = [
+ ...list
+ ];
+ newList[newList.length - 1]++;
+ return newList;
+}
+class EmVer {
+ values;
+ static from(range) {
+ if (range instanceof EmVer) {
+ return range;
+ }
+ return EmVer.parse(range);
+ }
+ static parse(range) {
+ const values = range.split(".").map((x)=>parseInt(x));
+ for (const value of values){
+ if (isNaN(value)) {
+ throw new Error(`Couldn't parse range: ${range}`);
+ }
+ }
+ return new EmVer(values);
+ }
+ constructor(values){
+ this.values = values;
+ }
+ withLastIncremented() {
+ return new EmVer(incrementLastNumber(this.values));
+ }
+ greaterThan(other) {
+ for(const i in this.values){
+ if (other.values[i] == null) {
+ return true;
+ }
+ if (this.values[i] > other.values[i]) {
+ return true;
+ }
+ if (this.values[i] < other.values[i]) {
+ return false;
+ }
+ }
+ return false;
+ }
+ equals(other) {
+ if (other.values.length !== this.values.length) {
+ return false;
+ }
+ for(const i in this.values){
+ if (this.values[i] !== other.values[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ greaterThanOrEqual(other) {
+ return this.greaterThan(other) || this.equals(other);
+ }
+ lessThanOrEqual(other) {
+ return !this.greaterThan(other);
+ }
+ lessThan(other) {
+ return !this.greaterThanOrEqual(other);
+ }
+ compare(other) {
+ if (this.equals(other)) {
+ return "equal";
+ } else if (this.greaterThan(other)) {
+ return "greater";
+ } else {
+ return "less";
+ }
+ }
+ compareForSort(other) {
+ return mod.matches(this.compare(other)).when("equal", ()=>0).when("greater", ()=>1).when("less", ()=>-1).unwrap();
+ }
+}
+function migrationFn(fn) {
+ return fn;
+}
+function fromMapping(migrations, currentVersion) {
+ const directionShape = mod.literals("from", "to");
+ return async (effects, version, direction)=>{
+ if (!directionShape.test(direction)) {
+ return {
+ error: 'Must specify arg "from" or "to".'
+ };
+ }
+ let configured = true;
+ const current = EmVer.parse(currentVersion);
+ const other = EmVer.parse(version);
+ const filteredMigrations = Object.entries(migrations).map(([version, migration])=>({
+ version: EmVer.parse(version),
+ migration
+ })).filter(({ version })=>version.greaterThan(other) && version.lessThanOrEqual(current));
+ const migrationsToRun = mod.matches(direction).when("from", ()=>filteredMigrations.sort((a, b)=>a.version.compareForSort(b.version)).map(({ migration })=>migration.up)).when("to", ()=>filteredMigrations.sort((a, b)=>b.version.compareForSort(a.version)).map(({ migration })=>migration.down)).unwrap();
+ for (const migration of migrationsToRun){
+ configured = (await migration(effects)).configured && configured;
+ }
+ return {
+ result: {
+ configured
+ }
+ };
+ };
+}
+const isType = mod.shape({
+ type: mod.string
+});
+const recordString = mod.dictionary([
+ mod.string,
+ mod.unknown
+]);
+const matchDefault = mod.shape({
+ default: mod.unknown
+});
+const matchNullable = mod.shape({
+ nullable: mod.literal(true)
+});
+const matchPattern = mod.shape({
+ pattern: mod.string
+});
+const rangeRegex = /(\[|\()(\*|(\d|\.)+),(\*|(\d|\.)+)(\]|\))/;
+const matchRange = mod.shape({
+ range: mod.regex(rangeRegex)
+});
+const matchIntegral = mod.shape({
+ integral: mod.literal(true)
+});
+const matchSpec = mod.shape({
+ spec: recordString
+});
+const matchSubType = mod.shape({
+ subtype: mod.string
+});
+const matchUnion = mod.shape({
+ tag: mod.shape({
+ id: mod.string
+ }),
+ variants: recordString
+});
+const matchValues = mod.shape({
+ values: mod.arrayOf(mod.string)
+});
+function charRange(value = "") {
+ const split = value.split("-").filter(Boolean).map((x)=>x.charCodeAt(0));
+ if (split.length < 1) return null;
+ if (split.length === 1) return [
+ split[0],
+ split[0]
+ ];
+ return [
+ split[0],
+ split[1]
+ ];
+}
+function generateDefault(generate, { random = ()=>Math.random() } = {}) {
+ const validCharSets = generate.charset.split(",").map(charRange).filter(Array.isArray);
+ if (validCharSets.length === 0) throw new Error("Expecing that we have a valid charset");
+ const max = validCharSets.reduce((acc, x)=>x.reduce((x, y)=>Math.max(x, y), acc), 0);
+ let i = 0;
+ const answer = Array(generate.len);
+ while(i < generate.len){
+ const nextValue = Math.round(random() * max);
+ const inRange = validCharSets.reduce((acc, [lower, upper])=>acc || nextValue >= lower && nextValue <= upper, false);
+ if (!inRange) continue;
+ answer[i] = String.fromCharCode(nextValue);
+ i++;
+ }
+ return answer.join("");
+}
+function withPattern(value) {
+ if (matchPattern.test(value)) return mod.regex(RegExp(value.pattern));
+ return mod.string;
+}
+function matchNumberWithRange(range) {
+ const matched = rangeRegex.exec(range);
+ if (!matched) return mod.number;
+ const [, left, leftValue, , rightValue, , right] = matched;
+ return mod.number.validate(leftValue === "*" ? (_)=>true : left === "[" ? (x)=>x >= Number(leftValue) : (x)=>x > Number(leftValue), leftValue === "*" ? "any" : left === "[" ? `greaterThanOrEqualTo${leftValue}` : `greaterThan${leftValue}`).validate(rightValue === "*" ? (_)=>true : right === "]" ? (x)=>x <= Number(rightValue) : (x)=>x < Number(rightValue), rightValue === "*" ? "any" : right === "]" ? `lessThanOrEqualTo${rightValue}` : `lessThan${rightValue}`);
+}
+function withIntegral(parser, value) {
+ if (matchIntegral.test(value)) {
+ return parser.validate(Number.isInteger, "isIntegral");
+ }
+ return parser;
+}
+function withRange(value) {
+ if (matchRange.test(value)) {
+ return matchNumberWithRange(value.range);
+ }
+ return mod.number;
+}
+const isGenerator = mod.shape({
+ charset: mod.string,
+ len: mod.number
+}).test;
+function defaultNullable(parser, value) {
+ if (matchDefault.test(value)) {
+ if (isGenerator(value.default)) return parser.defaultTo(parser.unsafeCast(generateDefault(value.default)));
+ return parser.defaultTo(parser.unsafeCast(value.default));
+ }
+ if (matchNullable.test(value)) return parser.optional();
+ return parser;
+}
+function guardAll(value) {
+ if (!isType.test(value)) {
+ return mod.unknown;
+ }
+ switch(value.type){
+ case "boolean":
+ return defaultNullable(mod.boolean, value);
+ case "string":
+ return defaultNullable(withPattern(value), value);
+ case "number":
+ return defaultNullable(withIntegral(withRange(value), value), value);
+ case "object":
+ if (matchSpec.test(value)) {
+ return defaultNullable(typeFromProps(value.spec), value);
+ }
+ return mod.unknown;
+ case "list":
+ {
+ const spec = matchSpec.test(value) && value.spec || {};
+ const rangeValidate = matchRange.test(value) && matchNumberWithRange(value.range).test || (()=>true);
+ const subtype = matchSubType.unsafeCast(value).subtype;
+ return defaultNullable(mod.arrayOf(guardAll({
+ type: subtype,
+ ...spec
+ })).validate((x)=>rangeValidate(x.length), "valid length"), value);
+ }
+ case "enum":
+ if (matchValues.test(value)) {
+ return defaultNullable(mod.literals(value.values[0], ...value.values), value);
+ }
+ return mod.unknown;
+ case "pointer":
+ return mod.unknown;
+ case "union":
+ if (matchUnion.test(value)) {
+ return mod.some(...Object.entries(value.variants).map(([variant, spec])=>mod.shape({
+ [value.tag.id]: mod.literal(variant)
+ }).concat(typeFromProps(spec))));
+ }
+ return mod.unknown;
+ }
+ return mod.unknown;
+}
+function typeFromProps(valueDictionary) {
+ if (!recordString.test(valueDictionary)) return mod.unknown;
+ return mod.shape(Object.fromEntries(Object.entries(valueDictionary).map(([key, value])=>[
+ key,
+ guardAll(value)
+ ])));
+}
+function unwrapResultType(res) {
+ if ("error-code" in res) {
+ throw new Error(res["error-code"][1]);
+ } else if ("error" in res) {
+ throw new Error(res["error"]);
+ } else {
+ return res.result;
+ }
+}
+const exists = (effects, props)=>effects.metadata(props).then((_)=>true, (_)=>false);
+const asResult = (result)=>({
+ result: result
+ });
+const noPropertiesFound = {
+ result: {
+ version: 2,
+ data: {
+ "Not Ready": {
+ type: "string",
+ value: "Could not find properties. The service might still be starting",
+ qr: false,
+ copyable: false,
+ masked: false,
+ description: "Fallback Message When Properties could not be found"
+ }
+ }
+ }
+};
+const properties = async (effects)=>{
+ if (await exists(effects, {
+ path: "start9/stats.yaml",
+ volumeId: "main"
+ }) === false) {
+ return noPropertiesFound;
+ }
+ return await effects.readFile({
+ path: "start9/stats.yaml",
+ volumeId: "main"
+ }).then(mod1.parse).then(asResult);
+};
+const setConfig = async (effects, newConfig, dependsOn = {})=>{
+ await effects.createDir({
+ path: "start9",
+ volumeId: "main"
+ });
+ await effects.writeFile({
+ path: "start9/config.yaml",
+ toWrite: mod1.stringify(newConfig),
+ volumeId: "main"
+ });
+ const result = {
+ signal: "SIGTERM",
+ "depends-on": dependsOn
+ };
+ return {
+ result
+ };
+};
+const { any: any1, string: string1, dictionary: dictionary1 } = mod;
+const matchConfig = dictionary1([
+ string1,
+ any1
+]);
+const getConfig = (spec)=>async (effects)=>{
+ const config = await effects.readFile({
+ path: "start9/config.yaml",
+ volumeId: "main"
+ }).then((x)=>mod1.parse(x)).then((x)=>matchConfig.unsafeCast(x)).catch((e)=>{
+ effects.info(`Got error ${e} while trying to read the config`);
+ return undefined;
+ });
+ return {
+ result: {
+ config,
+ spec
+ }
+ };
+ };
+const getConfigAndMatcher = (spec)=>[
+ async (effects)=>{
+ const config = await effects.readFile({
+ path: "start9/config.yaml",
+ volumeId: "main"
+ }).then((x)=>mod1.parse(x)).then((x)=>matchConfig.unsafeCast(x)).catch((e)=>{
+ effects.info(`Got error ${e} while trying to read the config`);
+ return undefined;
+ });
+ return {
+ result: {
+ config,
+ spec
+ }
+ };
+ },
+ typeFromProps(spec)
+ ];
+function updateConfig(fn, configured, noRepeat, noFail = false) {
+ return migrationFn(async (effects)=>{
+ await noRepeatGuard(effects, noRepeat, async ()=>{
+ let config = unwrapResultType(await getConfig({})(effects)).config;
+ if (config) {
+ try {
+ config = await fn(config, effects);
+ } catch (e) {
+ if (!noFail) {
+ throw e;
+ } else {
+ configured = false;
+ }
+ }
+ unwrapResultType(await setConfig(effects, config));
+ }
+ });
+ return {
+ configured
+ };
+ });
+}
+async function noRepeatGuard(effects, noRepeat, fn) {
+ if (!noRepeat) {
+ return fn();
+ }
+ if (!await exists(effects, {
+ path: "start9/migrations",
+ volumeId: "main"
+ })) {
+ await effects.createDir({
+ path: "start9/migrations",
+ volumeId: "main"
+ });
+ }
+ const migrationPath = {
+ path: `start9/migrations/${noRepeat.version}.complete`,
+ volumeId: "main"
+ };
+ if (noRepeat.type === "up") {
+ if (!await exists(effects, migrationPath)) {
+ await fn();
+ await effects.writeFile({
+ ...migrationPath,
+ toWrite: ""
+ });
+ }
+ } else if (noRepeat.type === "down") {
+ if (await exists(effects, migrationPath)) {
+ await fn();
+ await effects.removeFile(migrationPath);
+ }
+ }
+}
+async function initNoRepeat(effects, migrations, startingVersion) {
+ if (!await exists(effects, {
+ path: "start9/migrations",
+ volumeId: "main"
+ })) {
+ const starting = EmVer.parse(startingVersion);
+ await effects.createDir({
+ path: "start9/migrations",
+ volumeId: "main"
+ });
+ for(const version in migrations){
+ const migrationVersion = EmVer.parse(version);
+ if (migrationVersion.lessThanOrEqual(starting)) {
+ await effects.writeFile({
+ path: `start9/migrations/${version}.complete`,
+ volumeId: "main",
+ toWrite: ""
+ });
+ }
+ }
+ }
+}
+function fromMapping1(migrations, currentVersion) {
+ const inner = fromMapping(migrations, currentVersion);
+ return async (effects, version, direction)=>{
+ await initNoRepeat(effects, migrations, direction === "from" ? version : currentVersion);
+ return inner(effects, version, direction);
+ };
+}
+const mod2 = {
+ updateConfig: updateConfig,
+ noRepeatGuard: noRepeatGuard,
+ initNoRepeat: initNoRepeat,
+ fromMapping: fromMapping1
+};
+const mod3 = {
+ properties: properties,
+ setConfig: setConfig,
+ getConfig: getConfig,
+ getConfigAndMatcher: getConfigAndMatcher,
+ migrations: mod2
+};
+const setConfig1 = async (effects, newConfig)=>{
+ return mod3.setConfig(effects, newConfig, {});
+};
+const getConfig1 = mod3.getConfig({
+ "signup-enabled": {
+ "name": "Enable Signup",
+ "description": "Allow new users to create accounts on the server",
+ "type": "boolean",
+ "default": true
+ },
+ "base-url": {
+ "name": "Base URL",
+ "description": "Public URL of your ntfy server (your Tor .onion or LAN HTTPS URL, e.g. https://ntfy.local). Required for attachment links and web push to resolve correctly.",
+ "type": "string",
+ "nullable": true,
+ "masked": false,
+ "copyable": false
+ },
+ "log-level": {
+ "name": "Log Level",
+ "description": "Verbosity of server logs",
+ "type": "enum",
+ "values": [
+ "trace",
+ "debug",
+ "info",
+ "warn",
+ "error"
+ ],
+ "value-names": {
+ "trace": "Trace",
+ "debug": "Debug",
+ "info": "Info",
+ "warn": "Warn",
+ "error": "Error"
+ },
+ "default": "info"
+ },
+ "attachment-file-size-limit": {
+ "name": "Attachment File Size Limit (MB)",
+ "description": "Maximum size of a single attachment in megabytes",
+ "type": "number",
+ "nullable": false,
+ "integral": true,
+ "range": "[1,1000]",
+ "default": 15
+ },
+ "attachment-total-size-limit": {
+ "name": "Attachment Total Size Limit (MB)",
+ "description": "Maximum total disk usage for all attachments, in megabytes",
+ "type": "number",
+ "nullable": false,
+ "integral": true,
+ "range": "[100,1000000]",
+ "default": 5000
+ },
+ "visitor-attachment-limit": {
+ "name": "Per-Visitor Attachment Limit (MB)",
+ "description": "Maximum total attachment storage per visitor, in megabytes",
+ "type": "number",
+ "nullable": false,
+ "integral": true,
+ "range": "[10,100000]",
+ "default": 100
+ },
+ "cache-duration": {
+ "name": "Cache Duration (hours)",
+ "description": "How long messages and attachments are retained, in hours",
+ "type": "number",
+ "nullable": false,
+ "integral": true,
+ "range": "[1,8760]",
+ "default": 12
+ }
+});
+const properties1 = mod3.properties;
+const dependencies = {};
+const migration = async (_effects, _version)=>{
+ return {
+ result: {
+ configured: true
+ }
+ };
+};
+export { setConfig1 as setConfig };
+export { getConfig1 as getConfig };
+export { properties1 as properties };
+export { dependencies as dependencies };
+export { migration as migration };
diff --git a/scripts/embassy.ts b/scripts/embassy.ts
new file mode 100644
index 0000000..623a65d
--- /dev/null
+++ b/scripts/embassy.ts
@@ -0,0 +1,5 @@
+export { setConfig } from "./services/setConfig.ts";
+export { getConfig } from "./services/getConfig.ts";
+export { properties } from "./services/properties.ts";
+export { dependencies } from "./services/dependencies.ts";
+export { migration } from "./services/migrations.ts";
diff --git a/scripts/services/dependencies.ts b/scripts/services/dependencies.ts
new file mode 100644
index 0000000..29abb5e
--- /dev/null
+++ b/scripts/services/dependencies.ts
@@ -0,0 +1,3 @@
+import { types as T } from "../deps.ts";
+
+export const dependencies: T.ExpectedExports.dependencies = {};
diff --git a/scripts/services/getConfig.ts b/scripts/services/getConfig.ts
new file mode 100644
index 0000000..1121077
--- /dev/null
+++ b/scripts/services/getConfig.ts
@@ -0,0 +1,72 @@
+import { compat, types as T } from "../deps.ts";
+
+export const getConfig: T.ExpectedExports.getConfig = compat.getConfig({
+ "signup-enabled": {
+ "name": "Enable Signup",
+ "description": "Allow new users to create accounts on the server",
+ "type": "boolean",
+ "default": true,
+ },
+ "base-url": {
+ "name": "Base URL",
+ "description":
+ "Public URL of your ntfy server (your Tor .onion or LAN HTTPS URL, e.g. https://ntfy.local). Required for attachment links and web push to resolve correctly.",
+ "type": "string",
+ "nullable": true,
+ "masked": false,
+ "copyable": false,
+ },
+ "log-level": {
+ "name": "Log Level",
+ "description": "Verbosity of server logs",
+ "type": "enum",
+ "values": ["trace", "debug", "info", "warn", "error"],
+ "value-names": {
+ "trace": "Trace",
+ "debug": "Debug",
+ "info": "Info",
+ "warn": "Warn",
+ "error": "Error",
+ },
+ "default": "info",
+ },
+ "attachment-file-size-limit": {
+ "name": "Attachment File Size Limit (MB)",
+ "description": "Maximum size of a single attachment in megabytes",
+ "type": "number",
+ "nullable": false,
+ "integral": true,
+ "range": "[1,1000]",
+ "default": 15,
+ },
+ "attachment-total-size-limit": {
+ "name": "Attachment Total Size Limit (MB)",
+ "description":
+ "Maximum total disk usage for all attachments, in megabytes",
+ "type": "number",
+ "nullable": false,
+ "integral": true,
+ "range": "[100,1000000]",
+ "default": 5000,
+ },
+ "visitor-attachment-limit": {
+ "name": "Per-Visitor Attachment Limit (MB)",
+ "description":
+ "Maximum total attachment storage per visitor, in megabytes",
+ "type": "number",
+ "nullable": false,
+ "integral": true,
+ "range": "[10,100000]",
+ "default": 100,
+ },
+ "cache-duration": {
+ "name": "Cache Duration (hours)",
+ "description":
+ "How long messages and attachments are retained, in hours",
+ "type": "number",
+ "nullable": false,
+ "integral": true,
+ "range": "[1,8760]",
+ "default": 12,
+ },
+});
diff --git a/scripts/services/migrations.ts b/scripts/services/migrations.ts
new file mode 100644
index 0000000..0524587
--- /dev/null
+++ b/scripts/services/migrations.ts
@@ -0,0 +1,6 @@
+import { types as T } from "../deps.ts";
+
+// deno-lint-ignore require-await
+export const migration: T.ExpectedExports.migration = async (_effects, _version) => {
+ return { result: { configured: true } };
+};
diff --git a/scripts/services/properties.ts b/scripts/services/properties.ts
new file mode 100644
index 0000000..dff99aa
--- /dev/null
+++ b/scripts/services/properties.ts
@@ -0,0 +1,3 @@
+import { compat, types as T } from "../deps.ts";
+
+export const properties: T.ExpectedExports.properties = compat.properties;
diff --git a/scripts/services/setConfig.ts b/scripts/services/setConfig.ts
new file mode 100644
index 0000000..0aaf26d
--- /dev/null
+++ b/scripts/services/setConfig.ts
@@ -0,0 +1,9 @@
+import { compat, types as T } from "../deps.ts";
+
+// deno-lint-ignore require-await
+export const setConfig: T.ExpectedExports.setConfig = async (
+ effects: T.Effects,
+ newConfig: T.Config,
+) => {
+ return compat.setConfig(effects, newConfig, {});
+};