code:
'use strict';

var test = require('tape');
var v = require('es-value-fixtures');
var forEach = require('for-each');
var inspect = require('object-inspect');
var hasOwn = require('hasown');
var hasPropertyDescriptors = require('has-property-descriptors')();
var getOwnPropertyDescriptors = require('object.getownpropertydescriptors');
var ownKeys = require('reflect.ownkeys');

var defineDataProperty = require('../');

test('defineDataProperty', function (t) {
	t.test('argument validation', function (st) {
		forEach(v.primitives, function (nonObject) {
			st['throws'](
				// @ts-expect-error
				function () { defineDataProperty(nonObject, 'key', 'value'); },
				TypeError,
				'throws on non-object input: ' + inspect(nonObject)
			);
		});

		forEach(v.nonPropertyKeys, function (nonPropertyKey) {
			st['throws'](
				// @ts-expect-error
				function () { defineDataProperty({}, nonPropertyKey, 'value'); },
				TypeError,
				'throws on non-PropertyKey input: ' + inspect(nonPropertyKey)
			);
		});

		forEach(v.nonBooleans, function (nonBoolean) {
			if (nonBoolean !== null) {
				st['throws'](
					// @ts-expect-error
					function () { defineDataProperty({}, 'key', 'value', nonBoolean); },
					TypeError,
					'throws on non-boolean nonEnumerable: ' + inspect(nonBoolean)
				);

				st['throws'](
					// @ts-expect-error
					function () { defineDataProperty({}, 'key', 'value', false, nonBoolean); },
					TypeError,
					'throws on non-boolean nonWritable: ' + inspect(nonBoolean)
				);

				st['throws'](
					// @ts-expect-error
					function () { defineDataProperty({}, 'key', 'value', false, false, nonBoolean); },
					TypeError,
					'throws on non-boolean nonConfigurable: ' + inspect(nonBoolean)
				);
			}
		});

		st.end();
	});

	t.test('normal data property', function (st) {
		/** @type {Record<PropertyKey, string>} */
		var obj = { existing: 'existing property' };
		st.ok(hasOwn(obj, 'existing'), 'has initial own property');
		st.equal(obj.existing, 'existing property', 'has expected initial value');

		var res = defineDataProperty(obj, 'added', 'added property');
		st.equal(res, void undefined, 'returns `undefined`');
		st.ok(hasOwn(obj, 'added'), 'has expected own property');
		st.equal(obj.added, 'added property', 'has expected value');

		defineDataProperty(obj, 'existing', 'new value');
		st.ok(hasOwn(obj, 'existing'), 'still has expected own property');
		st.equal(obj.existing, 'new value', 'has new expected value');

		defineDataProperty(obj, 'explicit1', 'new value', false);
		st.ok(hasOwn(obj, 'explicit1'), 'has expected own property (explicit enumerable)');
		st.equal(obj.explicit1, 'new value', 'has new expected value (explicit enumerable)');

		defineDataProperty(obj, 'explicit2', 'new value', false, false);
		st.ok(hasOwn(obj, 'explicit2'), 'has expected own property (explicit writable)');
		st.equal(obj.explicit2, 'new value', 'has new expected value (explicit writable)');

		defineDataProperty(obj, 'explicit3', 'new value', false, false, false);
		st.ok(hasOwn(obj, 'explicit3'), 'has expected own property (explicit configurable)');
		st.equal(obj.explicit3, 'new value', 'has new expected value (explicit configurable)');

		st.end();
	});

	t.test('loose mode', { skip: !hasPropertyDescriptors }, function (st) {
		var obj = { existing: 'existing property' };

		defineDataProperty(obj, 'added', 'added value 1', true, null, null, true);
		st.deepEqual(
			getOwnPropertyDescriptors(obj),
			{
				existing: {
					configurable: true,
					enumerable: true,
					value: 'existing property',
					writable: true
				},
				added: {
					configurable: true,
					enumerable: !hasPropertyDescriptors,
					value: 'added value 1',
					writable: true
				}
			},
			'in loose mode, obj still adds property 1'
		);

		defineDataProperty(obj, 'added', 'added value 2', false, true, null, true);
		st.deepEqual(
			getOwnPropertyDescriptors(obj),
			{
				existing: {
					configurable: true,
					enumerable: true,
					value: 'existing property',
					writable: true
				},
				added: {
					configurable: true,
					enumerable: true,
					value: 'added value 2',
					writable: !hasPropertyDescriptors
				}
			},
			'in loose mode, obj still adds property 2'
		);

		defineDataProperty(obj, 'added', 'added value 3', false, false, true, true);
		st.deepEqual(
			getOwnPropertyDescriptors(obj),
			{
				existing: {
					configurable: true,
					enumerable: true,
					value: 'existing property',
					writable: true
				},
				added: {
					configurable: !hasPropertyDescriptors,
					enumerable: true,
					value: 'added value 3',
					writable: true
				}
			},
			'in loose mode, obj still adds property 3'
		);

		st.end();
	});

	t.test('non-normal data property, ES3', { skip: hasPropertyDescriptors }, function (st) {
		/** @type {Record<PropertyKey, string>} */
		var obj = { existing: 'existing property' };

		st['throws'](
			function () { defineDataProperty(obj, 'added', 'added value', true); },
			SyntaxError,
			'nonEnumerable throws a Syntax Error'
		);

		st['throws'](
			function () { defineDataProperty(obj, 'added', 'added value', false, true); },
			SyntaxError,
			'nonWritable throws a Syntax Error'
		);

		st['throws'](
			function () { defineDataProperty(obj, 'added', 'added value', false, false, true); },
			SyntaxError,
			'nonWritable throws a Syntax Error'
		);

		st.deepEqual(
			ownKeys(obj),
			['existing'],
			'obj still has expected keys'
		);
		st.equal(obj.existing, 'existing property', 'obj still has expected values');

		st.end();
	});

	t.test('new non-normal data property, ES5+', { skip: !hasPropertyDescriptors }, function (st) {
		/** @type {Record<PropertyKey, string>} */
		var obj = { existing: 'existing property' };

		defineDataProperty(obj, 'nonEnum', null, true);
		defineDataProperty(obj, 'nonWrit', null, false, true);
		defineDataProperty(obj, 'nonConf', null, false, false, true);

		st.deepEqual(
			getOwnPropertyDescriptors(obj),
			{
				existing: {
					configurable: true,
					enumerable: true,
					value: 'existing property',
					writable: true
				},
				nonEnum: {
					configurable: true,
					enumerable: false,
					value: null,
					writable: true
				},
				nonWrit: {
					configurable: true,
					enumerable: true,
					value: null,
					writable: false
				},
				nonConf: {
					configurable: false,
					enumerable: true,
					value: null,
					writable: true
				}
			},
			'obj has expected property descriptors'
		);

		st.end();
	});

	t.test('existing non-normal data property, ES5+', { skip: !hasPropertyDescriptors }, function (st) {
		// test case changing an existing non-normal property

		/** @type {Record<string, null | string>} */
		var obj = {};
		Object.defineProperty(obj, 'nonEnum', { configurable: true, enumerable: false, value: null, writable: true });
		Object.defineProperty(obj, 'nonWrit', { configurable: true, enumerable: true, value: null, writable: false });
		Object.defineProperty(obj, 'nonConf', { configurable: false, enumerable: true, value: null, writable: true });

		st.deepEqual(
			getOwnPropertyDescriptors(obj),
			{
				nonEnum: {
					configurable: true,
					enumerable: false,
					value: null,
					writable: true
				},
				nonWrit: {
					configurable: true,
					enumerable: true,
					value: null,
					writable: false
				},
				nonConf: {
					configurable: false,
					enumerable: true,
					value: null,
					writable: true
				}
			},
			'obj initially has expected property descriptors'
		);

		defineDataProperty(obj, 'nonEnum', 'new value', false);
		defineDataProperty(obj, 'nonWrit', 'new value', false, false);
		st['throws'](
			function () { defineDataProperty(obj, 'nonConf', 'new value', false, false, false); },
			TypeError,
			'can not alter a nonconfigurable property'
		);

		st.deepEqual(
			getOwnPropertyDescriptors(obj),
			{
				nonEnum: {
					configurable: true,
					enumerable: true,
					value: 'new value',
					writable: true
				},
				nonWrit: {
					configurable: true,
					enumerable: true,
					value: 'new value',
					writable: true
				},
				nonConf: {
					configurable: false,
					enumerable: true,
					value: null,
					writable: true
				}
			},
			'obj ends up with expected property descriptors'
		);

		st.end();
	});

	t.test('frozen object, ES5+', { skip: !hasPropertyDescriptors }, function (st) {
		var frozen = Object.freeze({ existing: true });

		st['throws'](
			function () { defineDataProperty(frozen, 'existing', 'new value'); },
			TypeError,
			'frozen object can not modify an existing property'
		);

		st['throws'](
			function () { defineDataProperty(frozen, 'new', 'new property'); },
			TypeError,
			'frozen object can not add a new property'
		);

		st.end();
	});

	t.test('sealed object, ES5+', { skip: !hasPropertyDescriptors }, function (st) {
		var sealed = Object.seal({ existing: true });
		st.deepEqual(
			Object.getOwnPropertyDescriptor(sealed, 'existing'),
			{
				configurable: false,
				enumerable: true,
				value: true,
				writable: true
			},
			'existing value on sealed object has expected descriptor'
		);

		defineDataProperty(sealed, 'existing', 'new value');

		st.deepEqual(
			Object.getOwnPropertyDescriptor(sealed, 'existing'),
			{
				configurable: false,
				enumerable: true,
				value: 'new value',
				writable: true
			},
			'existing value on sealed object has changed descriptor'
		);

		st['throws'](
			function () { defineDataProperty(sealed, 'new', 'new property'); },
			TypeError,
			'sealed object can not add a new property'
		);

		st.end();
	});

	t.test('nonextensible object, ES5+', { skip: !hasPropertyDescriptors }, function (st) {
		var nonExt = Object.preventExtensions({ existing: true });

		st.deepEqual(
			Object.getOwnPropertyDescriptor(nonExt, 'existing'),
			{
				configurable: true,
				enumerable: true,
				value: true,
				writable: true
			},
			'existing value on non-extensible object has expected descriptor'
		);

		defineDataProperty(nonExt, 'existing', 'new value', true);

		st.deepEqual(
			Object.getOwnPropertyDescriptor(nonExt, 'existing'),
			{
				configurable: true,
				enumerable: false,
				value: 'new value',
				writable: true
			},
			'existing value on non-extensible object has changed descriptor'
		);

		st['throws'](
			function () { defineDataProperty(nonExt, 'new', 'new property'); },
			TypeError,
			'non-extensible object can not add a new property'
		);

		st.end();
	});

	t.end();
});


code:
{
  "compilerOptions": {
    /* Visit https://aka.ms/tsconfig to read more about this file */

    /* Projects */

    /* Language and Environment */
    "target": "es2022",                                  /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */
    // "lib": [],                                        /* Specify a set of bundled library declaration files that describe the target runtime environment. */
    // "noLib": true,                                    /* Disable including any library files, including the default lib.d.ts. */
    "useDefineForClassFields": true,                     /* Emit ECMAScript-standard-compliant class fields. */
    // "moduleDetection": "auto",                        /* Control what method is used to detect module-format JS files. */

    /* Modules */
    "module": "commonjs",                                /* Specify what module code is generated. */
    // "rootDir": "./",                                  /* Specify the root folder within your source files. */
    // "moduleResolution": "node10",                     /* Specify how TypeScript looks up a file from a given module specifier. */
    // "baseUrl": "./",                                  /* Specify the base directory to resolve non-relative module names. */
    // "paths": {},                                      /* Specify a set of entries that re-map imports to additional lookup locations. */
    // "rootDirs": [],                                   /* Allow multiple folders to be treated as one when resolving modules. */
    "typeRoots": ["types"],                              /* Specify multiple folders that act like './node_modules/@types'. */
    "resolveJsonModule": true,                           /* Enable importing .json files. */

    /* JavaScript Support */
    "allowJs": true,                                    /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */
    "checkJs": true,                                    /* Enable error reporting in type-checked JavaScript files. */
    "maxNodeModuleJsDepth": 1,                          /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */

    /* Emit */
    "declaration": true,                                 /* Generate .d.ts files from TypeScript and JavaScript files in your project. */
    "declarationMap": true,                              /* Create sourcemaps for d.ts files. */
    // "emitDeclarationOnly": true,                      /* Only output d.ts files and not JavaScript files. */
    "noEmit": true,                                      /* Disable emitting files from a compilation. */

    /* Interop Constraints */
    "allowSyntheticDefaultImports": true,                /* Allow 'import x from y' when a module doesn't have a default export. */
    "esModuleInterop": true,                             /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */
    "forceConsistentCasingInFileNames": true,            /* Ensure that casing is correct in imports. */

    /* Type Checking */
    "strict": true,                                      /* Enable all strict type-checking options. */
    "noImplicitAny": true,                               /* Enable error reporting for expressions and declarations with an implied 'any' type. */
    "noImplicitThis": true,                              /* Enable error reporting when 'this' is given the type 'any'. */
    "useUnknownInCatchVariables": true,                  /* Default catch clause variables as 'unknown' instead of 'any'. */
    "noUnusedLocals": true,                              /* Enable error reporting when local variables aren't read. */
    "noUnusedParameters": true,                          /* Raise an error when a function parameter isn't read. */
    "noImplicitReturns": true,                           /* Enable error reporting for codepaths that do not explicitly return in a function. */
    "noFallthroughCasesInSwitch": true,                  /* Enable error reporting for fallthrough cases in switch statements. */
    "noUncheckedIndexedAccess": true,                    /* Add 'undefined' to a type when accessed using an index. */
    "noImplicitOverride": true,                          /* Ensure overriding members in derived classes are marked with an override modifier. */
    // "noPropertyAccessFromIndexSignature": true,       /* Enforces using indexed accessors for keys declared using an indexed type. */

    /* Completeness */
    // "skipLibCheck": true                                 /* Skip type checking all .d.ts files. */
  },
  "exclude": [
    "coverage"
  ]
}

license: mit


code:
/**
Define a [lazily evaluated](https://en.wikipedia.org/wiki/Lazy_evaluation) property on an object.

@param object - Object to add property to.
@param propertyName - Name of the property to add.
@param fn - Called the first time `propertyName` is accessed.

@example
```
import defineLazyProp = require('define-lazy-prop');

const unicorn = {
	// …
};

defineLazyProp(unicorn, 'rainbow', () => expensiveComputation());

app.on('user-action', () => {
	doSomething(unicorn.rainbow);
});
```
*/
declare function defineLazyProp<
	ObjectType extends {[key: string]: unknown},
	PropertyNameType extends string,
	PropertyValueType
>(
	object: ObjectType,
	propertyName: PropertyNameType,
	fn: () => PropertyValueType
): ObjectType & {[K in PropertyNameType]: PropertyValueType};

export = defineLazyProp;


code:
'use strict';
module.exports = (object, propertyName, fn) => {
	const define = value => Object.defineProperty(object, propertyName, {value, enumerable: true, writable: true});

	Object.defineProperty(object, propertyName, {
		configurable: true,
		enumerable: true,
		get() {
			const result = fn();
			define(result);
			return result;
		},
		set(value) {
			define(value);
		}
	});

	return object;
};


define-lazy-prop

description: Define a lazily evaluated property on an object

license: MIT

repository: sindresorhus/define-lazy-prop

test: xo && ava && tsd

keywords: lazy property properties prop define object value lazily laziness evaluation eval execute getter function fn memoize cache defer deferred


code:
# define-lazy-prop [![Build Status](https://travis-ci.org/sindresorhus/define-lazy-prop.svg?branch=master)](https://travis-ci.org/sindresorhus/define-lazy-prop)

> Define a [lazily evaluated](https://en.wikipedia.org/wiki/Lazy_evaluation) property on an object

Useful when the value of a property is expensive to generate, so you want to delay the computation until the property is needed. For example, improving startup performance by deferring nonessential operations.

## Install

```
$ npm install define-lazy-prop
```

## Usage

```js
const defineLazyProp = require('define-lazy-prop');

const unicorn = {
	// …
};

defineLazyProp(unicorn, 'rainbow', () => expensiveComputation());

app.on('user-action', () => {
	doSomething(unicorn.rainbow);
});
```

## API

### defineLazyProp(object, propertyName, fn)

#### object

Type: `Object`

Object to add property to.

#### propertyName

Type: `string`

Name of the property to add.

#### fn

Type: `Function`

Called the first time `propertyName` is accessed. Expected to return a value.

## Related

- [lazy-value](https://github.com/sindresorhus/lazy-value) - Create a lazily evaluated value
- [import-lazy](https://github.com/sindresorhus/import-lazy) - Import a module lazily
- [p-lazy](https://github.com/sindresorhus/p-lazy) - Create a lazy promise

## License

MIT © [Sindre Sorhus](https://sindresorhus.com)


code:
root = true

[*]
indent_style = tab;
insert_final_newline = true;
quote_type = auto;
space_after_anonymous_functions = true;
space_after_control_statements = true;
spaces_around_operators = true;
trim_trailing_whitespace = true;
spaces_in_brackets = false;
end_of_line = lf;


code:
{
	"root": true,

	"extends": "@ljharb",

	"rules": {
		"id-length": [2, { "min": 1, "max": 35 }],
		"max-params": [2, 4],
	},

	"overrides": [
		{
			"files": "test/**",
			"rules": {
				"max-lines-per-function": 0,
			},
		},
	],
}


code:
# These are supported funding model platforms

github: [ljharb]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: npm/define-properties
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']


reporter: text-summary text html json

exclude: coverage test


code:
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [v1.2.1](https://github.com/ljharb/define-properties/compare/v1.2.0...v1.2.1) - 2023-09-12

### Commits

- [Refactor] use `define-data-property` [`e7782a7`](https://github.com/ljharb/define-properties/commit/e7782a7480a62f8b6e141b49371e6de4df176c97)
- [actions] use reusable rebase action [`cd249c3`](https://github.com/ljharb/define-properties/commit/cd249c3920607bc8eeb7c0cd5b672b810983cac5)
- [Dev Deps] update `@ljharb/eslint-config`, `aud`, `tape` [`8205f97`](https://github.com/ljharb/define-properties/commit/8205f9734a4da8ee5b3b29798788567a09b330e8)

## [v1.2.0](https://github.com/ljharb/define-properties/compare/v1.1.4...v1.2.0) - 2023-02-10

### Commits

- [New] if the predicate is boolean `true`, it compares the existing value with `===` as the predicate [`d8dd6fc`](https://github.com/ljharb/define-properties/commit/d8dd6fca40d7c5878a4b643b91e66ae5a513a194)
- [meta] add `auto-changelog` [`7ebe2b0`](https://github.com/ljharb/define-properties/commit/7ebe2b0a0f90e62b842942cd45e86864fe75d9f6)
- [meta] use `npmignore` to autogenerate an npmignore file [`647478a`](https://github.com/ljharb/define-properties/commit/647478a8401fbf053fb633c0a3a7c982da6bad74)
- [Dev Deps] update `@ljharb/eslint-config`, `aud`, `tape` [`e620d70`](https://github.com/ljharb/define-properties/commit/e620d707d2e1118a38796f22a862200eb0a53fff)
- [Dev Deps] update `aud`, `tape` [`f1e5072`](https://github.com/ljharb/define-properties/commit/f1e507225c2551a99ed4fe40d3fe71b0f44acf88)
- [actions] update checkout action [`628b3af`](https://github.com/ljharb/define-properties/commit/628b3af5c74b8f0963296d811a8f6fa657baf964)

<!-- auto-changelog-above -->

1.1.4 / 2022-04-14
=================
 * [Refactor] use `has-property-descriptors`
 * [readme] add github actions/codecov badges
 * [Docs] fix header parsing; remove testling
 * [Deps] update `object-keys`
 * [meta] use `prepublishOnly` script for npm 7+
 * [meta] add `funding` field; create FUNDING.yml
 * [actions] add "Allow Edits" workflow; automatic rebasing / merge commit blocking
 * [actions] reuse common workflows
 * [actions] update codecov uploader
 * [actions] use `node/install` instead of `node/run`; use `codecov` action
 * [Tests] migrate tests to Github Actions
 * [Tests] run `nyc` on all tests; use `tape` runner
 * [Tests] use shared travis-ci config
 * [Tests] use `npx aud` instead of `nsp` or `npm audit` with hoops
 * [Tests] remove `jscs`
 * [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `safe-publish-latest`, `tape`; add `aud`, `safe-publish-latest`

1.1.3 / 2018-08-14
=================
 * [Refactor] use a for loop instead of `foreach` to make for smaller bundle sizes
 * [Robustness] cache `Array.prototype.concat` and `Object.defineProperty`
 * [Deps] update `object-keys`
 * [Dev Deps] update `eslint`, `@ljharb/eslint-config`, `nsp`, `tape`, `jscs`; remove unused eccheck script + dep
 * [Tests] use pretest/posttest for linting/security
 * [Tests] fix npm upgrades on older nodes

1.1.2 / 2015-10-14
=================
 * [Docs] Switch from vb.teelaun.ch to versionbadg.es for the npm version badge SVG
 * [Deps] Update `object-keys`
 * [Dev Deps] update `jscs`, `tape`, `eslint`, `@ljharb/eslint-config`, `nsp`
 * [Tests] up to `io.js` `v3.3`, `node` `v4.2`

1.1.1 / 2015-07-21
=================
 * [Deps] Update `object-keys`
 * [Dev Deps] Update `tape`, `eslint`
 * [Tests] Test on `io.js` `v2.4`

1.1.0 / 2015-07-01
=================
 * [New] Add support for symbol-valued properties.
 * [Dev Deps] Update `nsp`, `eslint`
 * [Tests] Test up to `io.js` `v2.3`

1.0.3 / 2015-05-30
=================
 * Using a more reliable check for supported property descriptors.

1.0.2 / 2015-05-23
=================
 * Test up to `io.js` `v2.0`
 * Update `tape`, `jscs`, `nsp`, `eslint`, `object-keys`, `editorconfig-tools`, `covert`

1.0.1 / 2015-01-06
=================
 * Update `object-keys` to fix ES3 support

1.0.0 / 2015-01-04
=================
  * v1.0.0


code:
# define-properties <sup>[![Version Badge][npm-version-svg]][package-url]</sup>

[![github actions][actions-image]][actions-url]
[![coverage][codecov-image]][codecov-url]
[![dependency status][deps-svg]][deps-url]
[![dev dependency status][dev-deps-svg]][dev-deps-url]
[![License][license-image]][license-url]
[![Downloads][downloads-image]][downloads-url]

[![npm badge][npm-badge-png]][package-url]

Define multiple non-enumerable properties at once. Uses `Object.defineProperty` when available; falls back to standard assignment in older engines.
Existing properties are not overridden. Accepts a map of property names to a predicate that, when true, force-overrides.

## Example

```js
var define = require('define-properties');
var assert = require('assert');

var obj = define({ a: 1, b: 2 }, {
	a: 10,
	b: 20,
	c: 30
});
assert(obj.a === 1);
assert(obj.b === 2);
assert(obj.c === 30);
if (define.supportsDescriptors) {
	assert.deepEqual(Object.keys(obj), ['a', 'b']);
	assert.deepEqual(Object.getOwnPropertyDescriptor(obj, 'c'), {
		configurable: true,
		enumerable: false,
		value: 30,
		writable: false
	});
}
```

Then, with predicates:
```js
var define = require('define-properties');
var assert = require('assert');

var obj = define({ a: 1, b: 2, c: 3 }, {
	a: 10,
	b: 20,
	c: 30
}, {
	a: function () { return false; },
	b: function () { return true; }
});
assert(obj.a === 1);
assert(obj.b === 20);
assert(obj.c === 3);
if (define.supportsDescriptors) {
	assert.deepEqual(Object.keys(obj), ['a', 'c']);
	assert.deepEqual(Object.getOwnPropertyDescriptor(obj, 'b'), {
		configurable: true,
		enumerable: false,
		value: 20,
		writable: false
	});
}
```

## Tests
Simply clone the repo, `npm install`, and run `npm test`

[package-url]: https://npmjs.org/package/define-properties
[npm-version-svg]: https://versionbadg.es/ljharb/define-properties.svg
[deps-svg]: https://david-dm.org/ljharb/define-properties.svg
[deps-url]: https://david-dm.org/ljharb/define-properties
[dev-deps-svg]: https://david-dm.org/ljharb/define-properties/dev-status.svg
[dev-deps-url]: https://david-dm.org/ljharb/define-properties#info=devDependencies
[npm-badge-png]: https://nodei.co/npm/define-properties.png?downloads=true&stars=true
[license-image]: https://img.shields.io/npm/l/define-properties.svg
[license-url]: LICENSE
[downloads-image]: https://img.shields.io/npm/dm/define-properties.svg
[downloads-url]: https://npm-stat.com/charts.html?package=define-properties
[codecov-image]: https://codecov.io/gh/ljharb/define-properties/branch/main/graphs/badge.svg
[codecov-url]: https://app.codecov.io/gh/ljharb/define-properties/
[actions-image]: https://img.shields.io/endpoint?url=https://github-actions-badge-u3jn4tfpocch.runkit.sh/ljharb/define-properties
[actions-url]: https://github.com/ljharb/define-properties/actions


code:
'use strict';

var keys = require('object-keys');
var hasSymbols = typeof Symbol === 'function' && typeof Symbol('foo') === 'symbol';

var toStr = Object.prototype.toString;
var concat = Array.prototype.concat;
var defineDataProperty = require('define-data-property');

var isFunction = function (fn) {
	return typeof fn === 'function' && toStr.call(fn) === '[object Function]';
};

var supportsDescriptors = require('has-property-descriptors')();

var defineProperty = function (object, name, value, predicate) {
	if (name in object) {
		if (predicate === true) {
			if (object[name] === value) {
				return;
			}
		} else if (!isFunction(predicate) || !predicate()) {
			return;
		}
	}

	if (supportsDescriptors) {
		defineDataProperty(object, name, value, true);
	} else {
		defineDataProperty(object, name, value);
	}
};

var defineProperties = function (object, map) {
	var predicates = arguments.length > 2 ? arguments[2] : {};
	var props = keys(map);
	if (hasSymbols) {
		props = concat.call(props, Object.getOwnPropertySymbols(map));
	}
	for (var i = 0; i < props.length; i += 1) {
		defineProperty(object, props[i], map[props[i]], predicates[props[i]]);
	}
};

defineProperties.supportsDescriptors = !!supportsDescriptors;

module.exports = defineProperties;


define-properties

author: Jordan Harband <ljharb@gmail.com>

description: Define multiple non-enumerable properties at once. Uses `Object.defineProperty` when available; falls back to standard assignment in older engines.

prepublish: not-in-publish || npm run prepublishOnly

prepublishOnly: safe-publish-latest

pretest: npm run lint

test: npm run tests-only

posttest: aud --production

tests-only: nyc tape 'test/**/*.js'

lint: eslint --ext=js,mjs .

version: auto-changelog && git add CHANGELOG.md

postversion: auto-changelog && git add CHANGELOG.md && git commit --no-edit --amend && git tag -f "v$(node -e "console.log(require('./package.json').version)")"

type: git

output: CHANGELOG.md

template: keepachangelog

ignore: .github/workflows test/


code:
2.0.0 / 2018-10-26
==================

  * Drop support for Node.js 0.6
  * Replace internal `eval` usage with `Function` constructor
  * Use instance methods on `process` to check for listeners

1.1.2 / 2018-01-11
==================

  * perf: remove argument reassignment
  * Support Node.js 0.6 to 9.x

1.1.1 / 2017-07-27
==================

  * Remove unnecessary `Buffer` loading
  * Support Node.js 0.6 to 8.x

1.1.0 / 2015-09-14
==================

  * Enable strict mode in more places
  * Support io.js 3.x
  * Support io.js 2.x
  * Support web browser loading
    - Requires bundler like Browserify or webpack

1.0.1 / 2015-04-07
==================

  * Fix `TypeError`s when under `'use strict'` code
  * Fix useless type name on auto-generated messages
  * Support io.js 1.x
  * Support Node.js 0.12

1.0.0 / 2014-09-17
==================

  * No changes

0.4.5 / 2014-09-09
==================

  * Improve call speed to functions using the function wrapper
  * Support Node.js 0.6

0.4.4 / 2014-07-27
==================

  * Work-around v8 generating empty stack traces

0.4.3 / 2014-07-26
==================

  * Fix exception when global `Error.stackTraceLimit` is too low

0.4.2 / 2014-07-19
==================

  * Correct call site for wrapped functions and properties

0.4.1 / 2014-07-19
==================

  * Improve automatic message generation for function properties

0.4.0 / 2014-07-19
==================

  * Add `TRACE_DEPRECATION` environment variable
  * Remove non-standard grey color from color output
  * Support `--no-deprecation` argument
  * Support `--trace-deprecation` argument
  * Support `deprecate.property(fn, prop, message)`

0.3.0 / 2014-06-16
==================

  * Add `NO_DEPRECATION` environment variable

0.2.0 / 2014-06-15
==================

  * Add `deprecate.property(obj, prop, message)`
  * Remove `supports-color` dependency for node.js 0.8

0.1.0 / 2014-06-15
==================

  * Add `deprecate.function(fn, message)`
  * Add `process.on('deprecation', fn)` emitter
  * Automatically generate message when omitted from `deprecate()`

0.0.1 / 2014-06-15
==================

  * Fix warning for dynamic calls at singe call site

0.0.0 / 2014-06-15
==================

  * Initial implementation


code:
# depd

[![NPM Version][npm-version-image]][npm-url]
[![NPM Downloads][npm-downloads-image]][npm-url]
[![Node.js Version][node-image]][node-url]
[![Linux Build][travis-image]][travis-url]
[![Windows Build][appveyor-image]][appveyor-url]
[![Coverage Status][coveralls-image]][coveralls-url]

Deprecate all the things

> With great modules comes great responsibility; mark things deprecated!

## Install

This module is installed directly using `npm`:

```sh
$ npm install depd
```

This module can also be bundled with systems like
[Browserify](http://browserify.org/) or [webpack](https://webpack.github.io/),
though by default this module will alter it's API to no longer display or
track deprecations.

## API

<!-- eslint-disable no-unused-vars -->

```js
var deprecate = require('depd')('my-module')
```

This library allows you to display deprecation messages to your users.
This library goes above and beyond with deprecation warnings by
introspection of the call stack (but only the bits that it is interested
in).

Instead of just warning on the first invocation of a deprecated
function and never again, this module will warn on the first invocation
of a deprecated function per unique call site, making it ideal to alert
users of all deprecated uses across the code base, rather than just
whatever happens to execute first.

The deprecation warnings from this module also include the file and line
information for the call into the module that the deprecated function was
in.

**NOTE** this library has a similar interface to the `debug` module, and
this module uses the calling file to get the boundary for the call stacks,
so you should always create a new `deprecate` object in each file and not
within some central file.

### depd(namespace)

Create a new deprecate function that uses the given namespace name in the
messages and will display the call site prior to the stack entering the
file this function was called from. It is highly suggested you use the
name of your module as the namespace.

### deprecate(message)

Call this function from deprecated code to display a deprecation message.
This message will appear once per unique caller site. Caller site is the
first call site in the stack in a different file from the caller of this
function.

If the message is omitted, a message is generated for you based on the site
of the `deprecate()` call and will display the name of the function called,
similar to the name displayed in a stack trace.

### deprecate.function(fn, message)

Call this function to wrap a given function in a deprecation message on any
call to the function. An optional message can be supplied to provide a custom
message.

### deprecate.property(obj, prop, message)

Call this function to wrap a given property on object in a deprecation message
on any accessing or setting of the property. An optional message can be supplied
to provide a custom message.

The method must be called on the object where the property belongs (not
inherited from the prototype).

If the property is a data descriptor, it will be converted to an accessor
descriptor in order to display the deprecation message.

### process.on('deprecation', fn)

This module will allow easy capturing of deprecation errors by emitting the
errors as the type "deprecation" on the global `process`. If there are no
listeners for this type, the errors are written to STDERR as normal, but if
there are any listeners, nothing will be written to STDERR and instead only
emitted. From there, you can write the errors in a different format or to a
logging source.

The error represents the deprecation and is emitted only once with the same
rules as writing to STDERR. The error has the following properties:

  - `message` - This is the message given by the library
  - `name` - This is always `'DeprecationError'`
  - `namespace` - This is the namespace the deprecation came from
  - `stack` - This is the stack of the call to the deprecated thing

Example `error.stack` output:

```
DeprecationError: my-cool-module deprecated oldfunction
    at Object.<anonymous> ([eval]-wrapper:6:22)
    at Module._compile (module.js:456:26)
    at evalScript (node.js:532:25)
    at startup (node.js:80:7)
    at node.js:902:3
```

### process.env.NO_DEPRECATION

As a user of modules that are deprecated, the environment variable `NO_DEPRECATION`
is provided as a quick solution to silencing deprecation warnings from being
output. The format of this is similar to that of `DEBUG`:

```sh
$ NO_DEPRECATION=my-module,othermod node app.js
```

This will suppress deprecations from being output for "my-module" and "othermod".
The value is a list of comma-separated namespaces. To suppress every warning
across all namespaces, use the value `*` for a namespace.

Providing the argument `--no-deprecation` to the `node` executable will suppress
all deprecations (only available in Node.js 0.8 or higher).

**NOTE** This will not suppress the deperecations given to any "deprecation"
event listeners, just the output to STDERR.

### process.env.TRACE_DEPRECATION

As a user of modules that are deprecated, the environment variable `TRACE_DEPRECATION`
is provided as a solution to getting more detailed location information in deprecation
warnings by including the entire stack trace. The format of this is the same as
`NO_DEPRECATION`:

```sh
$ TRACE_DEPRECATION=my-module,othermod node app.js
```

This will include stack traces for deprecations being output for "my-module" and
"othermod". The value is a list of comma-separated namespaces. To trace every
warning across all namespaces, use the value `*` for a namespace.

Providing the argument `--trace-deprecation` to the `node` executable will trace
all deprecations (only available in Node.js 0.8 or higher).

**NOTE** This will not trace the deperecations silenced by `NO_DEPRECATION`.

## Display

![message](files/message.png)

When a user calls a function in your library that you mark deprecated, they
will see the following written to STDERR (in the given colors, similar colors
and layout to the `debug` module):

```
bright cyan    bright yellow
|              |          reset       cyan
|              |          |           |
▼              ▼          ▼           ▼
my-cool-module deprecated oldfunction [eval]-wrapper:6:22
▲              ▲          ▲           ▲
|              |          |           |
namespace      |          |           location of mycoolmod.oldfunction() call
               |          deprecation message
               the word "deprecated"
```

If the user redirects their STDERR to a file or somewhere that does not support
colors, they see (similar layout to the `debug` module):

```
Sun, 15 Jun 2014 05:21:37 GMT my-cool-module deprecated oldfunction at [eval]-wrapper:6:22
▲                             ▲              ▲          ▲              ▲
|                             |              |          |              |
timestamp of message          namespace      |          |             location of mycoolmod.oldfunction() call
                                             |          deprecation message
                                             the word "deprecated"
```

## Examples

### Deprecating all calls to a function

This will display a deprecated message about "oldfunction" being deprecated
from "my-module" on STDERR.

```js
var deprecate = require('depd')('my-cool-module')

// message automatically derived from function name
// Object.oldfunction
exports.oldfunction = deprecate.function(function oldfunction () {
  // all calls to function are deprecated
})

// specific message
exports.oldfunction = deprecate.function(function () {
  // all calls to function are deprecated
}, 'oldfunction')
```

### Conditionally deprecating a function call

This will display a deprecated message about "weirdfunction" being deprecated
from "my-module" on STDERR when called with less than 2 arguments.

```js
var deprecate = require('depd')('my-cool-module')

exports.weirdfunction = function () {
  if (arguments.length < 2) {
    // calls with 0 or 1 args are deprecated
    deprecate('weirdfunction args < 2')
  }
}
```

When calling `deprecate` as a function, the warning is counted per call site
within your own module, so you can display different deprecations depending
on different situations and the users will still get all the warnings:

```js
var deprecate = require('depd')('my-cool-module')

exports.weirdfunction = function () {
  if (arguments.length < 2) {
    // calls with 0 or 1 args are deprecated
    deprecate('weirdfunction args < 2')
  } else if (typeof arguments[0] !== 'string') {
    // calls with non-string first argument are deprecated
    deprecate('weirdfunction non-string first arg')
  }
}
```

### Deprecating property access

This will display a deprecated message about "oldprop" being deprecated
from "my-module" on STDERR when accessed. A deprecation will be displayed
when setting the value and when getting the value.

```js
var deprecate = require('depd')('my-cool-module')

exports.oldprop = 'something'

// message automatically derives from property name
deprecate.property(exports, 'oldprop')

// explicit message
deprecate.property(exports, 'oldprop', 'oldprop >= 0.10')
```

## License

[MIT](LICENSE)

[appveyor-image]: https://badgen.net/appveyor/ci/dougwilson/nodejs-depd/master?label=windows
[appveyor-url]: https://ci.appveyor.com/project/dougwilson/nodejs-depd
[coveralls-image]: https://badgen.net/coveralls/c/github/dougwilson/nodejs-depd/master
[coveralls-url]: https://coveralls.io/r/dougwilson/nodejs-depd?branch=master
[node-image]: https://badgen.net/npm/node/depd
[node-url]: https://nodejs.org/en/download/
[npm-downloads-image]: https://badgen.net/npm/dm/depd
[npm-url]: https://npmjs.org/package/depd
[npm-version-image]: https://badgen.net/npm/v/depd
[travis-image]: https://badgen.net/travis/dougwilson/nodejs-depd/master?label=linux
[travis-url]: https://travis-ci.org/dougwilson/nodejs-depd


code:
/*!
 * depd
 * Copyright(c) 2014-2018 Douglas Christopher Wilson
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var relative = require('path').relative

/**
 * Module exports.
 */

module.exports = depd

/**
 * Get the path to base files on.
 */

var basePath = process.cwd()

/**
 * Determine if namespace is contained in the string.
 */

function containsNamespace (str, namespace) {
  var vals = str.split(/[ ,]+/)
  var ns = String(namespace).toLowerCase()

  for (var i = 0; i < vals.length; i++) {
    var val = vals[i]

    // namespace contained
    if (val && (val === '*' || val.toLowerCase() === ns)) {
      return true
    }
  }

  return false
}

/**
 * Convert a data descriptor to accessor descriptor.
 */

function convertDataDescriptorToAccessor (obj, prop, message) {
  var descriptor = Object.getOwnPropertyDescriptor(obj, prop)
  var value = descriptor.value

  descriptor.get = function getter () { return value }

  if (descriptor.writable) {
    descriptor.set = function setter (val) { return (value = val) }
  }

  delete descriptor.value
  delete descriptor.writable

  Object.defineProperty(obj, prop, descriptor)

  return descriptor
}

/**
 * Create arguments string to keep arity.
 */

function createArgumentsString (arity) {
  var str = ''

  for (var i = 0; i < arity; i++) {
    str += ', arg' + i
  }

  return str.substr(2)
}

/**
 * Create stack string from stack.
 */

function createStackString (stack) {
  var str = this.name + ': ' + this.namespace

  if (this.message) {
    str += ' deprecated ' + this.message
  }

  for (var i = 0; i < stack.length; i++) {
    str += '\n    at ' + stack[i].toString()
  }

  return str
}

/**
 * Create deprecate for namespace in caller.
 */

function depd (namespace) {
  if (!namespace) {
    throw new TypeError('argument namespace is required')
  }

  var stack = getStack()
  var site = callSiteLocation(stack[1])
  var file = site[0]

  function deprecate (message) {
    // call to self as log
    log.call(deprecate, message)
  }

  deprecate._file = file
  deprecate._ignored = isignored(namespace)
  deprecate._namespace = namespace
  deprecate._traced = istraced(namespace)
  deprecate._warned = Object.create(null)

  deprecate.function = wrapfunction
  deprecate.property = wrapproperty

  return deprecate
}

/**
 * Determine if event emitter has listeners of a given type.
 *
 * The way to do this check is done three different ways in Node.js >= 0.8
 * so this consolidates them into a minimal set using instance methods.
 *
 * @param {EventEmitter} emitter
 * @param {string} type
 * @returns {boolean}
 * @private
 */

function eehaslisteners (emitter, type) {
  var count = typeof emitter.listenerCount !== 'function'
    ? emitter.listeners(type).length
    : emitter.listenerCount(type)

  return count > 0
}

/**
 * Determine if namespace is ignored.
 */

function isignored (namespace) {
  if (process.noDeprecation) {
    // --no-deprecation support
    return true
  }

  var str = process.env.NO_DEPRECATION || ''

  // namespace ignored
  return containsNamespace(str, namespace)
}

/**
 * Determine if namespace is traced.
 */

function istraced (namespace) {
  if (process.traceDeprecation) {
    // --trace-deprecation support
    return true
  }

  var str = process.env.TRACE_DEPRECATION || ''

  // namespace traced
  return containsNamespace(str, namespace)
}

/**
 * Display deprecation message.
 */

function log (message, site) {
  var haslisteners = eehaslisteners(process, 'deprecation')

  // abort early if no destination
  if (!haslisteners && this._ignored) {
    return
  }

  var caller
  var callFile
  var callSite
  var depSite
  var i = 0
  var seen = false
  var stack = getStack()
  var file = this._file

  if (site) {
    // provided site
    depSite = site
    callSite = callSiteLocation(stack[1])
    callSite.name = depSite.name
    file = callSite[0]
  } else {
    // get call site
    i = 2
    depSite = callSiteLocation(stack[i])
    callSite = depSite
  }

  // get caller of deprecated thing in relation to file
  for (; i < stack.length; i++) {
    caller = callSiteLocation(stack[i])
    callFile = caller[0]

    if (callFile === file) {
      seen = true
    } else if (callFile === this._file) {
      file = this._file
    } else if (seen) {
      break
    }
  }

  var key = caller
    ? depSite.join(':') + '__' + caller.join(':')
    : undefined

  if (key !== undefined && key in this._warned) {
    // already warned
    return
  }

  this._warned[key] = true

  // generate automatic message from call site
  var msg = message
  if (!msg) {
    msg = callSite === depSite || !callSite.name
      ? defaultMessage(depSite)
      : defaultMessage(callSite)
  }

  // emit deprecation if listeners exist
  if (haslisteners) {
    var err = DeprecationError(this._namespace, msg, stack.slice(i))
    process.emit('deprecation', err)
    return
  }

  // format and write message
  var format = process.stderr.isTTY
    ? formatColor
    : formatPlain
  var output = format.call(this, msg, caller, stack.slice(i))
  process.stderr.write(output + '\n', 'utf8')
}

/**
 * Get call site location as array.
 */

function callSiteLocation (callSite) {
  var file = callSite.getFileName() || '<anonymous>'
  var line = callSite.getLineNumber()
  var colm = callSite.getColumnNumber()

  if (callSite.isEval()) {
    file = callSite.getEvalOrigin() + ', ' + file
  }

  var site = [file, line, colm]

  site.callSite = callSite
  site.name = callSite.getFunctionName()

  return site
}

/**
 * Generate a default message from the site.
 */

function defaultMessage (site) {
  var callSite = site.callSite
  var funcName = site.name

  // make useful anonymous name
  if (!funcName) {
    funcName = '<anonymous@' + formatLocation(site) + '>'
  }

  var context = callSite.getThis()
  var typeName = context && callSite.getTypeName()

  // ignore useless type name
  if (typeName === 'Object') {
    typeName = undefined
  }

  // make useful type name
  if (typeName === 'Function') {
    typeName = context.name || typeName
  }

  return typeName && callSite.getMethodName()
    ? typeName + '.' + funcName
    : funcName
}

/**
 * Format deprecation message without color.
 */

function formatPlain (msg, caller, stack) {
  var timestamp = new Date().toUTCString()

  var formatted = timestamp +
    ' ' + this._namespace +
    ' deprecated ' + msg

  // add stack trace
  if (this._traced) {
    for (var i = 0; i < stack.length; i++) {
      formatted += '\n    at ' + stack[i].toString()
    }

    return formatted
  }

  if (caller) {
    formatted += ' at ' + formatLocation(caller)
  }

  return formatted
}

/**
 * Format deprecation message with color.
 */

function formatColor (msg, caller, stack) {
  var formatted = '\x1b[36;1m' + this._namespace + '\x1b[22;39m' + // bold cyan
    ' \x1b[33;1mdeprecated\x1b[22;39m' + // bold yellow
    ' \x1b[0m' + msg + '\x1b[39m' // reset

  // add stack trace
  if (this._traced) {
    for (var i = 0; i < stack.length; i++) {
      formatted += '\n    \x1b[36mat ' + stack[i].toString() + '\x1b[39m' // cyan
    }

    return formatted
  }

  if (caller) {
    formatted += ' \x1b[36m' + formatLocation(caller) + '\x1b[39m' // cyan
  }

  return formatted
}

/**
 * Format call site location.
 */

function formatLocation (callSite) {
  return relative(basePath, callSite[0]) +
    ':' + callSite[1] +
    ':' + callSite[2]
}

/**
 * Get the stack as array of call sites.
 */

function getStack () {
  var limit = Error.stackTraceLimit
  var obj = {}
  var prep = Error.prepareStackTrace

  Error.prepareStackTrace = prepareObjectStackTrace
  Error.stackTraceLimit = Math.max(10, limit)

  // capture the stack
  Error.captureStackTrace(obj)

  // slice this function off the top
  var stack = obj.stack.slice(1)

  Error.prepareStackTrace = prep
  Error.stackTraceLimit = limit

  return stack
}

/**
 * Capture call site stack from v8.
 */

function prepareObjectStackTrace (obj, stack) {
  return stack
}

/**
 * Return a wrapped function in a deprecation message.
 */

function wrapfunction (fn, message) {
  if (typeof fn !== 'function') {
    throw new TypeError('argument fn must be a function')
  }

  var args = createArgumentsString(fn.length)
  var stack = getStack()
  var site = callSiteLocation(stack[1])

  site.name = fn.name

  // eslint-disable-next-line no-new-func
  var deprecatedfn = new Function('fn', 'log', 'deprecate', 'message', 'site',
    '"use strict"\n' +
    'return function (' + args + ') {' +
    'log.call(deprecate, message, site)\n' +
    'return fn.apply(this, arguments)\n' +
    '}')(fn, log, this, message, site)

  return deprecatedfn
}

/**
 * Wrap property in a deprecation message.
 */

function wrapproperty (obj, prop, message) {
  if (!obj || (typeof obj !== 'object' && typeof obj !== 'function')) {
    throw new TypeError('argument obj must be object')
  }

  var descriptor = Object.getOwnPropertyDescriptor(obj, prop)

  if (!descriptor) {
    throw new TypeError('must call property on owner object')
  }

  if (!descriptor.configurable) {
    throw new TypeError('property must be configurable')
  }

  var deprecate = this
  var stack = getStack()
  var site = callSiteLocation(stack[1])

  // set site name
  site.name = prop

  // convert data descriptor
  if ('value' in descriptor) {
    descriptor = convertDataDescriptorToAccessor(obj, prop, message)
  }

  var get = descriptor.get
  var set = descriptor.set

  // wrap getter
  if (typeof get === 'function') {
    descriptor.get = function getter () {
      log.call(deprecate, message, site)
      return get.apply(this, arguments)
    }
  }

  // wrap setter
  if (typeof set === 'function') {
    descriptor.set = function setter () {
      log.call(deprecate, message, site)
      return set.apply(this, arguments)
    }
  }

  Object.defineProperty(obj, prop, descriptor)
}

/**
 * Create DeprecationError for deprecation
 */

function DeprecationError (namespace, message, stack) {
  var error = new Error()
  var stackString

  Object.defineProperty(error, 'constructor', {
    value: DeprecationError
  })

  Object.defineProperty(error, 'message', {
    configurable: true,
    enumerable: false,
    value: message,
    writable: true
  })

  Object.defineProperty(error, 'name', {
    enumerable: false,
    configurable: true,
    value: 'DeprecationError',
    writable: true
  })

  Object.defineProperty(error, 'namespace', {
    configurable: true,
    enumerable: false,
    value: namespace,
    writable: true
  })

  Object.defineProperty(error, 'stack', {
    configurable: true,
    enumerable: false,
    get: function () {
      if (stackString !== undefined) {
        return stackString
      }

      // prepare stack trace
      return (stackString = createStackString.call(this, stack))
    },
    set: function setter (val) {
      stackString = val
    }
  })

  return error
}


code:
/*!
 * depd
 * Copyright(c) 2015 Douglas Christopher Wilson
 * MIT Licensed
 */

'use strict'

/**
 * Module exports.
 * @public
 */

module.exports = depd

/**
 * Create deprecate for namespace in caller.
 */

function depd (namespace) {
  if (!namespace) {
    throw new TypeError('argument namespace is required')
  }

  function deprecate (message) {
    // no-op in browser
  }

  deprecate._file = undefined
  deprecate._ignored = true
  deprecate._namespace = namespace
  deprecate._traced = false
  deprecate._warned = Object.create(null)

  deprecate.function = wrapfunction
  deprecate.property = wrapproperty

  return deprecate
}

/**
 * Return a wrapped function in a deprecation message.
 *
 * This is a no-op version of the wrapper, which does nothing but call
 * validation.
 */

function wrapfunction (fn, message) {
  if (typeof fn !== 'function') {
    throw new TypeError('argument fn must be a function')
  }

  return fn
}

/**
 * Wrap property in a deprecation message.
 *
 * This is a no-op version of the wrapper, which does nothing but call
 * validation.
 */

function wrapproperty (obj, prop, message) {
  if (!obj || (typeof obj !== 'object' && typeof obj !== 'function')) {
    throw new TypeError('argument obj must be object')
  }

  var descriptor = Object.getOwnPropertyDescriptor(obj, prop)

  if (!descriptor) {
    throw new TypeError('must call property on owner object')
  }

  if (!descriptor.configurable) {
    throw new TypeError('property must be configurable')
  }
}


depd

description: Deprecate all the things

author: Douglas Christopher Wilson <doug@somethingdoug.com>

keywords: deprecate deprecated

repository: dougwilson/nodejs-depd

bench: node benchmark/index.js

lint: eslint --plugin markdown --ext js,md .

test: mocha --reporter spec --bail test/

test-ci: istanbul cover --print=none node_modules/mocha/bin/_mocha -- --reporter spec test/ && istanbul report lcovonly text-summary

test-cov: istanbul cover --print=none node_modules/mocha/bin/_mocha -- --reporter dot test/ && istanbul report lcov text-summary


code:
# destroy

[![NPM version][npm-image]][npm-url]
[![Build Status][github-actions-ci-image]][github-actions-ci-url]
[![Test coverage][coveralls-image]][coveralls-url]
[![License][license-image]][license-url]
[![Downloads][downloads-image]][downloads-url]

Destroy a stream.

This module is meant to ensure a stream gets destroyed, handling different APIs
and Node.js bugs.

## API

```js
var destroy = require('destroy')
```

### destroy(stream [, suppress])

Destroy the given stream, and optionally suppress any future `error` events.

In most cases, this is identical to a simple `stream.destroy()` call. The rules
are as follows for a given stream:

  1. If the `stream` is an instance of `ReadStream`, then call `stream.destroy()`
     and add a listener to the `open` event to call `stream.close()` if it is
     fired. This is for a Node.js bug that will leak a file descriptor if
     `.destroy()` is called before `open`.
  2. If the `stream` is an instance of a zlib stream, then call `stream.destroy()`
     and close the underlying zlib handle if open, otherwise call `stream.close()`.
     This is for consistency across Node.js versions and a Node.js bug that will
     leak a native zlib handle.
  3. If the `stream` is not an instance of `Stream`, then nothing happens.
  4. If the `stream` has a `.destroy()` method, then call it.

The function returns the `stream` passed in as the argument.

## Example

```js
var destroy = require('destroy')

var fs = require('fs')
var stream = fs.createReadStream('package.json')

// ... and later
destroy(stream)
```

[npm-image]: https://img.shields.io/npm/v/destroy.svg?style=flat-square
[npm-url]: https://npmjs.org/package/destroy
[github-tag]: http://img.shields.io/github/tag/stream-utils/destroy.svg?style=flat-square
[github-url]: https://github.com/stream-utils/destroy/tags
[coveralls-image]: https://img.shields.io/coveralls/stream-utils/destroy.svg?style=flat-square
[coveralls-url]: https://coveralls.io/r/stream-utils/destroy?branch=master
[license-image]: http://img.shields.io/npm/l/destroy.svg?style=flat-square
[license-url]: LICENSE.md
[downloads-image]: http://img.shields.io/npm/dm/destroy.svg?style=flat-square
[downloads-url]: https://npmjs.org/package/destroy
[github-actions-ci-image]: https://img.shields.io/github/workflow/status/stream-utils/destroy/ci/master?label=ci&style=flat-square
[github-actions-ci-url]: https://github.com/stream-utils/destroy/actions/workflows/ci.yml


code:
/*!
 * destroy
 * Copyright(c) 2014 Jonathan Ong
 * Copyright(c) 2015-2022 Douglas Christopher Wilson
 * MIT Licensed
 */

'use strict'

/**
 * Module dependencies.
 * @private
 */

var EventEmitter = require('events').EventEmitter
var ReadStream = require('fs').ReadStream
var Stream = require('stream')
var Zlib = require('zlib')

/**
 * Module exports.
 * @public
 */

module.exports = destroy

/**
 * Destroy the given stream, and optionally suppress any future `error` events.
 *
 * @param {object} stream
 * @param {boolean} suppress
 * @public
 */

function destroy (stream, suppress) {
  if (isFsReadStream(stream)) {
    destroyReadStream(stream)
  } else if (isZlibStream(stream)) {
    destroyZlibStream(stream)
  } else if (hasDestroy(stream)) {
    stream.destroy()
  }

  if (isEventEmitter(stream) && suppress) {
    stream.removeAllListeners('error')
    stream.addListener('error', noop)
  }

  return stream
}

/**
 * Destroy a ReadStream.
 *
 * @param {object} stream
 * @private
 */

function destroyReadStream (stream) {
  stream.destroy()

  if (typeof stream.close === 'function') {
    // node.js core bug work-around
    stream.on('open', onOpenClose)
  }
}

/**
 * Close a Zlib stream.
 *
 * Zlib streams below Node.js 4.5.5 have a buggy implementation
 * of .close() when zlib encountered an error.
 *
 * @param {object} stream
 * @private
 */

function closeZlibStream (stream) {
  if (stream._hadError === true) {
    var prop = stream._binding === null
      ? '_binding'
      : '_handle'

    stream[prop] = {
      close: function () { this[prop] = null }
    }
  }

  stream.close()
}

/**
 * Destroy a Zlib stream.
 *
 * Zlib streams don't have a destroy function in Node.js 6. On top of that
 * simply calling destroy on a zlib stream in Node.js 8+ will result in a
 * memory leak. So until that is fixed, we need to call both close AND destroy.
 *
 * PR to fix memory leak: https://github.com/nodejs/node/pull/23734
 *
 * In Node.js 6+8, it's important that destroy is called before close as the
 * stream would otherwise emit the error 'zlib binding closed'.
 *
 * @param {object} stream
 * @private
 */

function destroyZlibStream (stream) {
  if (typeof stream.destroy === 'function') {
    // node.js core bug work-around
    // istanbul ignore if: node.js 0.8
    if (stream._binding) {
      // node.js < 0.10.0
      stream.destroy()
      if (stream._processing) {
        stream._needDrain = true
        stream.once('drain', onDrainClearBinding)
      } else {
        stream._binding.clear()
      }
    } else if (stream._destroy && stream._destroy !== Stream.Transform.prototype._destroy) {
      // node.js >= 12, ^11.1.0, ^10.15.1
      stream.destroy()
    } else if (stream._destroy && typeof stream.close === 'function') {
      // node.js 7, 8
      stream.destroyed = true
      stream.close()
    } else {
      // fallback
      // istanbul ignore next
      stream.destroy()
    }
  } else if (typeof stream.close === 'function') {
    // node.js < 8 fallback
    closeZlibStream(stream)
  }
}

/**
 * Determine if stream has destroy.
 * @private
 */

function hasDestroy (stream) {
  return stream instanceof Stream &&
    typeof stream.destroy === 'function'
}

/**
 * Determine if val is EventEmitter.
 * @private
 */

function isEventEmitter (val) {
  return val instanceof EventEmitter
}

/**
 * Determine if stream is fs.ReadStream stream.
 * @private
 */

function isFsReadStream (stream) {
  return stream instanceof ReadStream
}

/**
 * Determine if stream is Zlib stream.
 * @private
 */

function isZlibStream (stream) {
  return stream instanceof Zlib.Gzip ||
    stream instanceof Zlib.Gunzip ||
    stream instanceof Zlib.Deflate ||
    stream instanceof Zlib.DeflateRaw ||
    stream instanceof Zlib.Inflate ||
    stream instanceof Zlib.InflateRaw ||
    stream instanceof Zlib.Unzip
}

/**
 * No-op function.
 * @private
 */

function noop () {}

/**
 * On drain handler to clear binding.
 * @private
 */

// istanbul ignore next: node.js 0.8
function onDrainClearBinding () {
  this._binding.clear()
}

/**
 * On open handler to close stream.
 * @private
 */

function onOpenClose () {
  if (typeof this.fd === 'number') {
    // actually close down the fd
    this.close()
  }
}


destroy

description: destroy a stream if possible

contributors: Douglas Christopher Wilson <doug@somethingdoug.com>

repository: stream-utils/destroy

lint: eslint .

test: mocha --reporter spec

test-ci: nyc --reporter=lcovonly --reporter=text npm test

test-cov: nyc --reporter=html --reporter=text npm test

keywords: stream streams destroy cleanup leak fd


code:
### Install

```shell
npm install --save detect-node
```

### Usage:

```js
var isNode = require('detect-node');

if (isNode) {
  console.log("Running under Node.JS");
} else {
  alert("Hello from browser (or whatever not-a-node env)");
}
```

The check is performed as:
```js
module.exports = false;

// Only Node.JS has a process variable that is of [[Class]] process
try {
 module.exports = Object.prototype.toString.call(global.process) === '[object process]'
} catch(e) {}

```

Thanks to Ingvar Stepanyan for the initial idea. This check is both **the most reliable I could find** and it does not use `process` env directly, which would cause browserify to include it into the build.


code:
// Only Node.JS has a process variable that is of [[Class]] process
export default Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]';


code:
// Only Node.JS has a process variable that is of [[Class]] process
module.exports = Object.prototype.toString.call(typeof process !== 'undefined' ? process : 0) === '[object process]';


detect-node

description: Detect Node.JS (as opposite to browser environment) (reliable)

test: echo "Error: no test specified" && exit 1

keywords: detect node

author: Ilya Kantor


code:
'use strict';
const path = require('path');
const pathType = require('path-type');

const getExtensions = extensions => extensions.length > 1 ? `{${extensions.join(',')}}` : extensions[0];

const getPath = (filepath, cwd) => {
	const pth = filepath[0] === '!' ? filepath.slice(1) : filepath;
	return path.isAbsolute(pth) ? pth : path.join(cwd, pth);
};

const addExtensions = (file, extensions) => {
	if (path.extname(file)) {
		return `**/${file}`;
	}

	return `**/${file}.${getExtensions(extensions)}`;
};

const getGlob = (directory, options) => {
	if (options.files && !Array.isArray(options.files)) {
		throw new TypeError(`Expected \`files\` to be of type \`Array\` but received type \`${typeof options.files}\``);
	}

	if (options.extensions && !Array.isArray(options.extensions)) {
		throw new TypeError(`Expected \`extensions\` to be of type \`Array\` but received type \`${typeof options.extensions}\``);
	}

	if (options.files && options.extensions) {
		return options.files.map(x => path.posix.join(directory, addExtensions(x, options.extensions)));
	}

	if (options.files) {
		return options.files.map(x => path.posix.join(directory, `**/${x}`));
	}

	if (options.extensions) {
		return [path.posix.join(directory, `**/*.${getExtensions(options.extensions)}`)];
	}

	return [path.posix.join(directory, '**')];
};

module.exports = async (input, options) => {
	options = {
		cwd: process.cwd(),
		...options
	};

	if (typeof options.cwd !== 'string') {
		throw new TypeError(`Expected \`cwd\` to be of type \`string\` but received type \`${typeof options.cwd}\``);
	}

	const globs = await Promise.all([].concat(input).map(async x => {
		const isDirectory = await pathType.isDirectory(getPath(x, options.cwd));
		return isDirectory ? getGlob(x, options) : x;
	}));

	return [].concat.apply([], globs); // eslint-disable-line prefer-spread
};

module.exports.sync = (input, options) => {
	options = {
		cwd: process.cwd(),
		...options
	};

	if (typeof options.cwd !== 'string') {
		throw new TypeError(`Expected \`cwd\` to be of type \`string\` but received type \`${typeof options.cwd}\``);
	}

	const globs = [].concat(input).map(x => pathType.isDirectorySync(getPath(x, options.cwd)) ? getGlob(x, options) : x);

	return [].concat.apply([], globs); // eslint-disable-line prefer-spread
};


dir-glob

description: Convert directories to glob compatible strings

repository: kevva/dir-glob

test: xo && ava

keywords: convert directory extensions files glob


code:
# dir-glob [![Build Status](https://travis-ci.org/kevva/dir-glob.svg?branch=master)](https://travis-ci.org/kevva/dir-glob)

> Convert directories to glob compatible strings

## Install

```
$ npm install dir-glob
```

## Usage

```js
const dirGlob = require('dir-glob');

(async () => {
	console.log(await dirGlob(['index.js', 'test.js', 'fixtures']));
	//=> ['index.js', 'test.js', 'fixtures/**']

	console.log(await dirGlob(['index.js', 'inner_folder'], {cwd: 'fixtures'}));
	//=> ['index.js', 'inner_folder/**']

	console.log(await dirGlob(['lib/**', 'fixtures'], {
		files: ['test', 'unicorn']
		extensions: ['js']
	}));
	//=> ['lib/**', 'fixtures/**/test.js', 'fixtures/**/unicorn.js']

	console.log(await dirGlob(['lib/**', 'fixtures'], {
		files: ['test', 'unicorn', '*.jsx'],
		extensions: ['js', 'png']
	}));
	//=> ['lib/**', 'fixtures/**/test.{js,png}', 'fixtures/**/unicorn.{js,png}', 'fixtures/**/*.jsx']
})();
```

## API

### dirGlob(input, options?)

Returns a `Promise<string[]>` with globs.

### dirGlob.sync(input, options?)

Returns a `string[]` with globs.

#### input

Type: `string | string[]`

Paths.

#### options

Type: `object`

##### extensions

Type: `string[]`

Append extensions to the end of your globs.

##### files

Type: `string[]`

Only glob for certain files.

##### cwd

Type: `string[]`

Test in specific directory.


code:
# dns-packet
[![](https://img.shields.io/npm/v/dns-packet.svg?style=flat)](https://www.npmjs.org/package/dns-packet) [![](https://img.shields.io/npm/dm/dns-packet.svg)](https://www.npmjs.org/package/dns-packet) [![](https://github.com/github/mafintosh/dns-packet/workflows/ci.yml/badge.svg)](https://github.com/github/mafintosh/dns-packet/workflows/ci.yml) [![Coverage Status](https://coveralls.io/repos/github/mafintosh/dns-packet/badge.svg?branch=master)](https://coveralls.io/github/mafintosh/dns-packet?branch=master)

An [abstract-encoding](https://github.com/mafintosh/abstract-encoding) compliant module for encoding / decoding DNS packets. Lifted out of [multicast-dns](https://github.com/mafintosh/multicast-dns) as a separate module.

```
npm install dns-packet
```

## UDP Usage

``` js
const dnsPacket = require('dns-packet')
const dgram = require('dgram')

const socket = dgram.createSocket('udp4')

const buf = dnsPacket.encode({
  type: 'query',
  id: 1,
  flags: dnsPacket.RECURSION_DESIRED,
  questions: [{
    type: 'A',
    name: 'google.com'
  }]
})

socket.on('message', message => {
  console.log(dnsPacket.decode(message)) // prints out a response from google dns
})

socket.send(buf, 0, buf.length, 53, '8.8.8.8')
```

Also see [the UDP example](examples/udp.js).

## TCP, TLS, HTTPS

While DNS has traditionally been used over a datagram transport, it is increasingly being carried over TCP for larger responses commonly including DNSSEC responses and TLS or HTTPS for enhanced security. See below examples on how to use `dns-packet` to wrap DNS packets in these protocols:

- [TCP](examples/tcp.js)
- [DNS over TLS](examples/tls.js)
- [DNS over HTTPS](examples/doh.js)

## API

#### `var buf = packets.encode(packet, [buf], [offset])`

Encodes a DNS packet into a buffer containing a UDP payload.

#### `var packet = packets.decode(buf, [offset])`

Decode a DNS packet from a buffer containing a UDP payload.

#### `var buf = packets.streamEncode(packet, [buf], [offset])`

Encodes a DNS packet into a buffer containing a TCP payload.

#### `var packet = packets.streamDecode(buf, [offset])`

Decode a DNS packet from a buffer containing a TCP payload.

#### `var len = packets.encodingLength(packet)`

Returns how many bytes are needed to encode the DNS packet

## Packets

Packets look like this

``` js
{
  type: 'query|response',
  id: optionalIdNumber,
  flags: optionalBitFlags,
  questions: [...],
  answers: [...],
  additionals: [...],
  authorities: [...]
}
```

The bit flags available are

``` js
packet.RECURSION_DESIRED
packet.RECURSION_AVAILABLE
packet.TRUNCATED_RESPONSE
packet.AUTHORITATIVE_ANSWER
packet.AUTHENTIC_DATA
packet.CHECKING_DISABLED
```

To use more than one flag bitwise-or them together

``` js
var flags = packet.RECURSION_DESIRED | packet.RECURSION_AVAILABLE
```

And to check for a flag use bitwise-and

``` js
var isRecursive = message.flags & packet.RECURSION_DESIRED
```

A question looks like this

``` js
{
  type: 'A', // or SRV, AAAA, etc
  class: 'IN', // one of IN, CS, CH, HS, ANY. Default: IN
  name: 'google.com' // which record are you looking for
}
```

And an answer, additional, or authority looks like this

``` js
{
  type: 'A', // or SRV, AAAA, etc
  class: 'IN', // one of IN, CS, CH, HS
  name: 'google.com', // which name is this record for
  ttl: optionalTimeToLiveInSeconds,
  (record specific data, see below)
}
```

## Supported record types

#### `A`

``` js
{
  data: 'IPv4 address' // fx 127.0.0.1
}
```

#### `AAAA`

``` js
{
  data: 'IPv6 address' // fx fe80::1
}
```

#### `CAA`

``` js
{
  flags: 128, // octet
  tag: 'issue|issuewild|iodef',
  value: 'ca.example.net',
  issuerCritical: false
}
```

#### `CNAME`

``` js
{
  data: 'cname.to.another.record'
}
```

#### `DNAME`

``` js
{
  data: 'dname.to.another.record'
}
```

#### `DNSKEY`

``` js
{
  flags: 257, // 16 bits
  algorithm: 1, // octet
  key: Buffer
}
```

#### `DS`

``` js
{
  keyTag: 12345,
  algorithm: 8,
  digestType: 1,
  digest: Buffer
}
```

#### `HINFO`

``` js
{
  data: {
    cpu: 'cpu info',
    os: 'os info'
  }
}
```

#### `MX`

``` js
{
  preference: 10,
  exchange: 'mail.example.net'
}
```

#### `NAPTR`

``` js
{
  data:
    {
      order: 100,
      preference: 10,
      flags: 's',
      services: 'SIP+D2U',
      regexp: '!^.*$!sip:customer-service@example.com!',
      replacement: '_sip._udp.example.com'
    }
}
```

#### `NS`

``` js
{
  data: nameServer
}
```

#### `NSEC`

``` js
{
  nextDomain: 'a.domain',
  rrtypes: ['A', 'TXT', 'RRSIG']
}
```

#### `NSEC3`

``` js
{
  algorithm: 1,
  flags: 0,
  iterations: 2,
  salt: Buffer,
  nextDomain: Buffer, // Hashed per RFC5155
  rrtypes: ['A', 'TXT', 'RRSIG']
}
```

#### `NULL`

``` js
{
  data: Buffer('any binary data')
}
```

#### `OPT`

[EDNS0](https://tools.ietf.org/html/rfc6891) options.

``` js
{
  type: 'OPT',
  name: '.',
  udpPayloadSize: 4096,
  flags: packet.DNSSEC_OK,
  options: [{
    // pass in any code/data for generic EDNS0 options
    code: 12,
    data: Buffer.alloc(31)
  }, {
    // Several EDNS0 options have enhanced support
    code: 'PADDING',
    length: 31,
  }, {
    code: 'CLIENT_SUBNET',
    family: 2, // 1 for IPv4, 2 for IPv6
    sourcePrefixLength: 64, // used to truncate IP address
    scopePrefixLength: 0,
    ip: 'fe80::',
  }, {
    code: 'TCP_KEEPALIVE',
    timeout: 150 // increments of 100ms.  This means 15s.
  }, {
    code: 'KEY_TAG',
    tags: [1, 2, 3],
  }]
}
```

The options `PADDING`, `CLIENT_SUBNET`, `TCP_KEEPALIVE` and `KEY_TAG` support enhanced de/encoding. See [optionscodes.js](https://github.com/mafintosh/dns-packet/blob/master/optioncodes.js) for all supported option codes. If the `data` property is present on a option, it takes precedence. On decoding, `data` will always be defined.

#### `PTR`

``` js
{
  data: 'points.to.another.record'
}
```

#### `RP`

``` js
{
  mbox: 'admin.example.com',
  txt: 'txt.example.com'
}
```

#### `SSHFP`

``` js
{
  algorithm: 1,
  hash: 1,
  fingerprint: 'A108C9F834354D5B37AF988141C9294822F5BC00'
}
````

#### `RRSIG`

``` js
{
  typeCovered: 'A',
  algorithm: 8,
  labels: 1,
  originalTTL: 3600,
  expiration: timestamp,
  inception: timestamp,
  keyTag: 12345,
  signersName: 'a.name',
  signature: Buffer
}
```

#### `SOA`

``` js
{
  data:
    {
      mname: domainName,
      rname: mailbox,
      serial: zoneSerial,
      refresh: refreshInterval,
      retry: retryInterval,
      expire: expireInterval,
      minimum: minimumTTL
    }
}
```

#### `SRV`

``` js
{
  data: {
    port: servicePort,
    target: serviceHostName,
    priority: optionalServicePriority,
    weight: optionalServiceWeight
  }
}
```

#### `TLSA`

``` js
{
  usage: 3,
  selector: 1,
  matchingType: 1,
  certificate: Buffer
}
```

#### `TXT`

``` js
{
  data: 'text' || Buffer || [ Buffer || 'text' ]
}
```

When encoding, scalar values are converted to an array and strings are converted to UTF-8 encoded Buffers. When decoding, the return value will always be an array of Buffer.

If you need another record type, open an issue and we'll try to add it.

## License

MIT


code:
'use strict'

exports.toString = function (klass) {
  switch (klass) {
    case 1: return 'IN'
    case 2: return 'CS'
    case 3: return 'CH'
    case 4: return 'HS'
    case 255: return 'ANY'
  }
  return 'UNKNOWN_' + klass
}

exports.toClass = function (name) {
  switch (name.toUpperCase()) {
    case 'IN': return 1
    case 'CS': return 2
    case 'CH': return 3
    case 'HS': return 4
    case 'ANY': return 255
  }
  return 0
}