Socket
Socket
Sign inDemoInstall

gruber

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gruber - npm Package Compare versions

Comparing version 0.4.0 to 0.4.1

10

CHANGELOG.md

@@ -5,2 +5,12 @@ # Change log

## 0.4.1
**fixes**
- `getDenoConfigOptions`, `getDenoConfiguration`, `getNodeConfigOptions` and `getNodeConfiguration` all have a default options of `{}`
- The Configuration markdown tables calculates the width properly when there are non-strings (URLs) in there
- The `Structure.boolean` method correctly types the optional fallback argument.
- Add experimental `Structure.literal` construct
- `Structure.object` fails if there are additional fields or the value is an instance of a class
## 0.4.0

@@ -7,0 +17,0 @@

8

core/configuration.d.ts

@@ -41,3 +41,3 @@ /**

}
export class _LiteralSpec {
export class _PrimativeSpec {
/**

@@ -53,7 +53,7 @@ * @param {string} type

fields: {
name: any;
type: string;
fallback: any;
variable?: string;
flag?: string;
fallback: any;
name: any;
type: string;
}[];

@@ -60,0 +60,0 @@ };

@@ -73,3 +73,7 @@ import { formatMarkdownTable } from "./utilities.js";

export class _LiteralSpec {
//
// NOTE: describe() calls should return the actual value in "fallback"
// and the string-value in fields
//
export class _PrimativeSpec {
/**

@@ -86,3 +90,10 @@ * @param {string} type

fallback: this.options.fallback,
fields: [{ name, type: this.type, ...this.options }],
fields: [
{
...this.options,
name,
type: this.type,
fallback: this.options.fallback?.toString(),
},
],
};

@@ -155,3 +166,3 @@ }

const struct = Structure.string(this._getValue(options).value);
struct[Configuration.spec] = new _LiteralSpec("string", options);
struct[Configuration.spec] = new _PrimativeSpec("string", options);
return struct;

@@ -171,3 +182,3 @@ }

const struct = Structure.number(fallback);
struct[Configuration.spec] = new _LiteralSpec("number", options);
struct[Configuration.spec] = new _PrimativeSpec("number", options);
return struct;

@@ -187,3 +198,3 @@ }

const struct = Structure.boolean(fallback);
struct[Configuration.spec] = new _LiteralSpec("boolean", options);
struct[Configuration.spec] = new _PrimativeSpec("boolean", options);
return struct;

@@ -204,3 +215,3 @@ }

const struct = Structure.url(this._getValue(options).value);
struct[Configuration.spec] = new _LiteralSpec("url", {
struct[Configuration.spec] = new _PrimativeSpec("url", {
...options,

@@ -207,0 +218,0 @@ fallback: new URL(options.fallback),

@@ -59,3 +59,3 @@ import { Configuration } from "./configuration.js";

flag: "--age",
fallback: 42,
fallback: "42",
},

@@ -385,3 +385,3 @@ ],

config.url({
fallback: "https://example.com",
fallback: "https://example.com/",
variable: "SELF_URL",

@@ -397,3 +397,3 @@ flag: "--self-url",

type: "url",
fallback: new URL("https://example.com"),
fallback: "https://example.com/",
variable: "SELF_URL",

@@ -400,0 +400,0 @@ flag: "--self-url",

@@ -22,15 +22,4 @@ export class StructError extends Error {

/**
* @typedef {Record<string,unknown>} Schema
*/
/**
* @template T
* @typedef {(input?: unknown, context?: StructContext) => T} StructExec
*/
/**
* @template T
* @typedef {T extends Structure<infer U> ? U : never} Infer
*/
/**
* @template T
*/
export class Structure<T> {

@@ -48,6 +37,6 @@ /**

/**
* @param {boolean} fallback
* @param {boolean} [fallback]
* @returns {Structure<boolean>}
*/
static boolean(fallback: boolean): Structure<boolean>;
static boolean(fallback?: boolean): Structure<boolean>;
/**

@@ -73,2 +62,10 @@ * @param {string | URL} [fallback]

/**
* **UNSTABLE** use at your own risk
*
* @template {string|number|boolean} T
* @param {T} value
* @returns {Structure<T>}
*/
static literal<T_1 extends string | number | boolean>(value: T_1): Structure<T_1>;
/**
* @param {Schema} schema

@@ -78,3 +75,3 @@ * @param {StructExec<T>} process

constructor(schema: Schema, process: StructExec<T>);
schema: Schema;
schema: Record<string, unknown>;
process: StructExec<T>;

@@ -85,2 +82,5 @@ getSchema(): {

}
export type Schema = Record<string, unknown>;
export type StructExec<T> = (input?: unknown, context?: StructContext) => T;
export type Infer<T> = T extends Structure<infer U> ? U : never;
export type StructContext = {

@@ -94,4 +94,1 @@ path: string[];

};
export type Schema = Record<string, unknown>;
export type StructExec<T> = (input?: unknown, context?: StructContext) => T;
export type Infer<T> = T extends Structure<infer U> ? U : never;

@@ -88,2 +88,7 @@ /** @typedef {{ path: string[] }} StructContext */

function _additionalProperties(fields, input) {
const allowed = new Set(Object.keys(fields));
return Array.from(Object.keys(input)).filter((key) => !allowed.has(key));
}
/**

@@ -152,3 +157,3 @@ * @template T

/**
* @param {boolean} fallback
* @param {boolean} [fallback]
* @returns {Structure<boolean>}

@@ -211,2 +216,5 @@ */

}
if (Object.getPrototypeOf(input) !== Object.getPrototypeOf({})) {
throw new StructError("Should not have a prototype", path);
}
const output = {};

@@ -222,2 +230,9 @@ const errors = [];

}
for (const key of _additionalProperties(fields, input)) {
errors.push(
new StructError("Additional field not allowed", [...path, key]),
);
}
if (errors.length > 0) {

@@ -264,2 +279,26 @@ throw new StructError("Object does not match schema", path, errors);

}
/**
* **UNSTABLE** use at your own risk
*
* @template {string|number|boolean} T
* @param {T} value
* @returns {Structure<T>}
*/
static literal(value) {
const schema = { type: typeof value, const: value };
return new Structure(schema, (input, context = undefined) => {
if (input === undefined) {
throw new StructError("Missing value", context?.path);
}
if (input !== value) {
throw new StructError(
`Expected ${schema.type} literal: ${value}`,
context?.path,
);
}
return value;
});
}
}

@@ -428,2 +428,40 @@ import { StructError, Structure } from "./structures.js";

});
it("throws for unknown fields", () => {
const struct = Structure.object({
key: Structure.string("fallback"),
});
const error = assertThrows(
() =>
struct.process(
{ key: "value", something: "else" },
{ path: ["some", "path"] },
),
StructError,
);
assertEquals(error.message, "Object does not match schema");
assertEquals(error.path, ["some", "path"], "should capture the context");
assertEquals(error.children[0].message, "Additional field not allowed");
assertEquals(
error.children[0].path,
["some", "path", "something"],
"should capture the context",
);
});
it("throws for non-null prototypes", () => {
const struct = Structure.object({
key: Structure.string("fallback"),
});
class Injector {
key = "value";
}
const error = assertThrows(
() => struct.process(new Injector(), { path: ["some", "path"] }),
StructError,
);
assertEquals(error.message, "Should not have a prototype");
assertEquals(error.path, ["some", "path"], "should capture the context");
});
});

@@ -475,2 +513,52 @@

});
describe("literal", () => {
it("creates a structure", () => {
const struct = Structure.literal(42);
assertInstanceOf(struct, Structure);
});
it("allows that value", () => {
const struct = Structure.literal(42);
assertEquals(struct.process(42), 42, "should pass the value through");
});
it("throws for different values", () => {
const struct = Structure.literal(42);
const error = assertThrows(
() => struct.process(69, { path: ["some", "path"] }),
StructError,
);
assertEquals(
error,
new StructError("Expected number literal: 42", ["some", "path"]),
"should throw a StructError and capture the context",
);
});
it("throws for different types", () => {
const struct = Structure.literal(42);
const error = assertThrows(
() => struct.process("nice", { path: ["some", "path"] }),
StructError,
);
assertEquals(
error,
new StructError("Expected number literal: 42", ["some", "path"]),
"should throw a StructError and capture the context",
);
});
it("throws for missing values", () => {
const struct = Structure.literal(42);
const error = assertThrows(
() => struct.process(undefined, { path: ["some", "path"] }),
StructError,
);
assertEquals(
error,
new StructError("Missing value", ["some", "path"]),
"should throw a StructError and capture the context",
);
});
});
});

@@ -31,3 +31,3 @@ {

},
"version": "0.4.0"
"version": "0.4.1"
}

@@ -5,3 +5,3 @@ /**

/** @param {NodeConfigurationOptions} options */
export function getNodeConfigOptions(options: NodeConfigurationOptions): {
export function getNodeConfigOptions(options?: NodeConfigurationOptions): {
readTextFile(url: any): Promise<Buffer>;

@@ -17,5 +17,5 @@ getEnvironmentVariable(key: any): string;

*/
export function getNodeConfiguration(options: NodeConfigurationOptions): Configuration;
export function getNodeConfiguration(options?: NodeConfigurationOptions): Configuration;
export { Configuration };
export type NodeConfigurationOptions = object;
import { Configuration } from "../core/configuration.js";

@@ -14,3 +14,3 @@ import fs from "node:fs";

/** @param {NodeConfigurationOptions} options */
export function getNodeConfigOptions(options) {
export function getNodeConfigOptions(options = {}) {
const args = util.parseArgs({

@@ -47,4 +47,4 @@ args: process.args,

*/
export function getNodeConfiguration(options) {
export function getNodeConfiguration(options = {}) {
return new Configuration(getNodeConfigOptions(options));
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc