wardens 0.6.0-rc.4 → 0.6.0-rc.4-2024-07-28.92dafd2
Sign up to get free protection for your applications and to get access to all the features.
- package/dist/wardens.cjs +1 -1
- package/dist/wardens.js +37 -41
- package/package.json +17 -40
- package/src/__tests__/root-lifecycle.test.ts +1 -1
- package/src/__tests__/roots.test.ts +1 -1
- package/src/resource-lifecycle.ts +4 -1
- package/CHANGELOG.md +0 -104
package/dist/wardens.cjs
CHANGED
@@ -1 +1 @@
|
|
1
|
-
"use strict";var
|
1
|
+
"use strict";var B=Object.defineProperty;var j=e=>{throw TypeError(e)};var M=(e,t,r)=>t in e?B(e,t,{enumerable:!0,configurable:!0,writable:!0,value:r}):e[t]=r;var f=(e,t,r)=>M(e,typeof t!="symbol"?t+"":t,r),k=(e,t,r)=>t.has(e)||j("Cannot "+r);var s=(e,t,r)=>(k(e,t,"read from private field"),r?r.call(e):t.get(e)),d=(e,t,r)=>t.has(e)?j("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,r),h=(e,t,r,o)=>(k(e,t,"write to private field"),o?o.call(e,r):t.set(e,r),r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function A(e){const t=new WeakMap;return new Proxy(e,{get(r,o){const n=Reflect.get(r,o,r);if(typeof n=="function"){if(t.has(n)===!1){const a=n.bind(r);Object.defineProperties(a,Object.getOwnPropertyDescriptors(n)),t.set(n,a)}return t.get(n)}return n},set(r,o,n){return Reflect.set(r,o,n,r)}})}const g=new WeakMap,E=new WeakSet,P=new WeakSet;function T(e){return Proxy.revocable(e,{})}var C,w;class x{constructor(t){d(this,C,Symbol("Context ID"));d(this,w);h(this,w,t)}static getId(t){return s(t,C)}static getDefaultValue(t){var r;return s(r=t,w).call(r)}}C=new WeakMap,w=new WeakMap;const V=e=>new x(e);var y,l,p,i;class H{constructor(t,r,o){d(this,y,new WeakSet);d(this,l);d(this,p);d(this,i);f(this,"create",async(t,...r)=>{if(s(this,p).enforced)throw new Error("Cannot create new resources after teardown.");const o=Object.create(s(this,i)),n=await D(o,t,...r);return s(this,l).add(n),n});f(this,"destroy",async t=>{if(s(this,y).has(t))throw new Error("Resource already destroyed.");if(!s(this,l).has(t))throw new Error("You do not own this resource.");s(this,l).delete(t),s(this,y).add(t),await m(t)});f(this,"setContext",(t,r)=>(s(this,i)[x.getId(t)]=r,r));f(this,"getContext",t=>{const r=x.getId(t);return r in s(this,i)?s(this,i)[r]:x.getDefaultValue(t)});h(this,i,t),h(this,l,r),h(this,p,o)}}y=new WeakMap,l=new WeakMap,p=new WeakMap,i=new WeakMap;const D=async(e,t,...r)=>{const o={enforced:!1},n=new Set,a=new H(e,n,o);let c;try{c=await t(a,...r)}catch(S){const R=Array.from(n).reverse(),v=(await Promise.allSettled(R.map(u=>a.destroy(u)))).filter(u=>u.status==="rejected");throw v.length?W(v.map(u=>u.reason),{cause:S}):S}const I=c.value,{proxy:b,revoke:O}=T(I);return E.add(b),g.set(b,{curfew:o,resource:c,children:n,revoke:O}),b},m=async e=>{if(!E.has(e))throw new Error("Cannot destroy object. It is not a resource.");const t=g.get(e);if(t){g.delete(e),t.revoke();let r={status:"fulfilled",value:void 0};if(t.resource.destroy)try{await t.resource.destroy()}catch(c){r={status:"rejected",reason:c}}t.curfew.enforced=!0;const o=Array.from(t.children).reverse().map(m),n=await Promise.allSettled(o),a=[r].concat(n).filter(c=>c.status==="rejected");if(a.length)throw W(a.map(c=>c.reason))}},W=(e,t)=>e.length===1?e[0]:new U(e,t);class U extends Error{constructor(t,r){super("Some resources could not be destroyed. See the `failures` property for details.",r),this.failures=t}}const Y=async(e,...t)=>{const o=await D(Object.create(null),e,...t);return P.add(o),o},q=async e=>{if(g.has(e)&&!P.has(e))throw new Error("Cannot destroy child resource. It is owned by another scope.");return m(e)};exports.bindContext=A;exports.create=Y;exports.createContext=V;exports.destroy=q;
|
package/dist/wardens.js
CHANGED
@@ -1,15 +1,11 @@
|
|
1
|
-
var
|
2
|
-
var
|
3
|
-
|
4
|
-
if (!t.has(e))
|
5
|
-
throw TypeError("Cannot " + r);
|
1
|
+
var B = Object.defineProperty;
|
2
|
+
var j = (e) => {
|
3
|
+
throw TypeError(e);
|
6
4
|
};
|
7
|
-
var
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
}, f = (e, t, r, o) => (j(e, t, "write to private field"), o ? o.call(e, r) : t.set(e, r), r);
|
12
|
-
function U(e) {
|
5
|
+
var A = (e, t, r) => t in e ? B(e, t, { enumerable: !0, configurable: !0, writable: !0, value: r }) : e[t] = r;
|
6
|
+
var h = (e, t, r) => A(e, typeof t != "symbol" ? t + "" : t, r), k = (e, t, r) => t.has(e) || j("Cannot " + r);
|
7
|
+
var n = (e, t, r) => (k(e, t, "read from private field"), r ? r.call(e) : t.get(e)), d = (e, t, r) => t.has(e) ? j("Cannot add the same private member more than once") : t instanceof WeakSet ? t.add(e) : t.set(e, r), f = (e, t, r, o) => (k(e, t, "write to private field"), o ? o.call(e, r) : t.set(e, r), r);
|
8
|
+
function Y(e) {
|
13
9
|
const t = /* @__PURE__ */ new WeakMap();
|
14
10
|
return new Proxy(e, {
|
15
11
|
get(r, o) {
|
@@ -31,15 +27,15 @@ function U(e) {
|
|
31
27
|
}
|
32
28
|
});
|
33
29
|
}
|
34
|
-
const g = /* @__PURE__ */ new WeakMap(),
|
35
|
-
function
|
30
|
+
const g = /* @__PURE__ */ new WeakMap(), E = /* @__PURE__ */ new WeakSet(), D = /* @__PURE__ */ new WeakSet();
|
31
|
+
function M(e) {
|
36
32
|
return Proxy.revocable(e, {});
|
37
33
|
}
|
38
34
|
var m, w;
|
39
35
|
class x {
|
40
36
|
constructor(t) {
|
41
37
|
d(this, m, Symbol("Context ID"));
|
42
|
-
d(this, w
|
38
|
+
d(this, w);
|
43
39
|
f(this, w, t);
|
44
40
|
}
|
45
41
|
static getId(t) {
|
@@ -51,19 +47,19 @@ class x {
|
|
51
47
|
}
|
52
48
|
}
|
53
49
|
m = new WeakMap(), w = new WeakMap();
|
54
|
-
const
|
50
|
+
const q = (e) => new x(e);
|
55
51
|
var y, l, p, i;
|
56
|
-
class
|
52
|
+
class V {
|
57
53
|
constructor(t, r, o) {
|
58
54
|
d(this, y, /* @__PURE__ */ new WeakSet());
|
59
|
-
d(this, l
|
60
|
-
d(this, p
|
61
|
-
d(this, i
|
55
|
+
d(this, l);
|
56
|
+
d(this, p);
|
57
|
+
d(this, i);
|
62
58
|
/** Provision an owned resource and make sure it doesn't outlive us. */
|
63
59
|
h(this, "create", async (t, ...r) => {
|
64
60
|
if (n(this, p).enforced)
|
65
61
|
throw new Error("Cannot create new resources after teardown.");
|
66
|
-
const o = Object.create(n(this, i)), s = await
|
62
|
+
const o = Object.create(n(this, i)), s = await P(o, t, ...r);
|
67
63
|
return n(this, l).add(s), s;
|
68
64
|
});
|
69
65
|
/**
|
@@ -88,31 +84,31 @@ class M {
|
|
88
84
|
}
|
89
85
|
}
|
90
86
|
y = new WeakMap(), l = new WeakMap(), p = new WeakMap(), i = new WeakMap();
|
91
|
-
const
|
92
|
-
const o = { enforced: !1 }, s = /* @__PURE__ */ new Set(), a = new
|
87
|
+
const P = async (e, t, ...r) => {
|
88
|
+
const o = { enforced: !1 }, s = /* @__PURE__ */ new Set(), a = new V(e, s, o);
|
93
89
|
let c;
|
94
90
|
try {
|
95
91
|
c = await t(a, ...r);
|
96
92
|
} catch (S) {
|
97
|
-
const
|
98
|
-
|
93
|
+
const O = Array.from(s).reverse(), v = (await Promise.allSettled(
|
94
|
+
O.map((u) => a.destroy(u))
|
99
95
|
)).filter(
|
100
96
|
(u) => u.status === "rejected"
|
101
97
|
);
|
102
|
-
throw v.length ?
|
98
|
+
throw v.length ? W(
|
103
99
|
v.map((u) => u.reason),
|
104
100
|
{ cause: S }
|
105
101
|
) : S;
|
106
102
|
}
|
107
|
-
const
|
108
|
-
return
|
103
|
+
const I = c.value, { proxy: C, revoke: R } = M(I);
|
104
|
+
return E.add(C), g.set(C, {
|
109
105
|
curfew: o,
|
110
106
|
resource: c,
|
111
107
|
children: s,
|
112
|
-
revoke:
|
108
|
+
revoke: R
|
113
109
|
}), C;
|
114
110
|
}, b = async (e) => {
|
115
|
-
if (!
|
111
|
+
if (!E.has(e))
|
116
112
|
throw new Error("Cannot destroy object. It is not a resource.");
|
117
113
|
const t = g.get(e);
|
118
114
|
if (t) {
|
@@ -132,10 +128,10 @@ const D = async (e, t, ...r) => {
|
|
132
128
|
(c) => c.status === "rejected"
|
133
129
|
);
|
134
130
|
if (a.length)
|
135
|
-
throw
|
131
|
+
throw W(a.map((c) => c.reason));
|
136
132
|
}
|
137
|
-
},
|
138
|
-
class
|
133
|
+
}, W = (e, t) => e.length === 1 ? e[0] : new H(e, t);
|
134
|
+
class H extends Error {
|
139
135
|
constructor(t, r) {
|
140
136
|
super(
|
141
137
|
"Some resources could not be destroyed. See the `failures` property for details.",
|
@@ -143,19 +139,19 @@ class V extends Error {
|
|
143
139
|
), this.failures = t;
|
144
140
|
}
|
145
141
|
}
|
146
|
-
const
|
147
|
-
const o = await
|
148
|
-
return
|
149
|
-
},
|
150
|
-
if (g.has(e) && !
|
142
|
+
const z = async (e, ...t) => {
|
143
|
+
const o = await P(/* @__PURE__ */ Object.create(null), e, ...t);
|
144
|
+
return D.add(o), o;
|
145
|
+
}, F = async (e) => {
|
146
|
+
if (g.has(e) && !D.has(e))
|
151
147
|
throw new Error(
|
152
148
|
"Cannot destroy child resource. It is owned by another scope."
|
153
149
|
);
|
154
150
|
return b(e);
|
155
151
|
};
|
156
152
|
export {
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
153
|
+
Y as bindContext,
|
154
|
+
z as create,
|
155
|
+
q as createContext,
|
156
|
+
F as destroy
|
161
157
|
};
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "wardens",
|
3
|
-
"version": "0.6.0-rc.4",
|
3
|
+
"version": "0.6.0-rc.4-2024-07-28.92dafd2",
|
4
4
|
"description": "A framework for resource management",
|
5
5
|
"type": "module",
|
6
6
|
"main": "./dist/wardens.cjs",
|
@@ -31,12 +31,13 @@
|
|
31
31
|
],
|
32
32
|
"scripts": {
|
33
33
|
"prepack": "tsc && vite build",
|
34
|
-
"test": "./
|
34
|
+
"test": "./scripts/run-tests",
|
35
35
|
"test:lint": "eslint src --color",
|
36
|
-
"test:unit": "vitest --color",
|
37
|
-
"test:types": "vitest typecheck --color",
|
36
|
+
"test:unit": "vitest --color --typecheck",
|
38
37
|
"test:fmt": "prettier --check src --color",
|
39
|
-
"
|
38
|
+
"print-pkg-version": "echo ${npm_package_version}",
|
39
|
+
"release:candidate": "./scripts/publish-rc",
|
40
|
+
"release:stable": "./scripts/publish-stable"
|
40
41
|
},
|
41
42
|
"husky": {
|
42
43
|
"hooks": {
|
@@ -53,41 +54,17 @@
|
|
53
54
|
"singleQuote": true,
|
54
55
|
"trailingComma": "all"
|
55
56
|
},
|
56
|
-
"eslintConfig": {
|
57
|
-
"parser": "@typescript-eslint/parser",
|
58
|
-
"parserOptions": {
|
59
|
-
"sourceType": "module"
|
60
|
-
},
|
61
|
-
"overrides": [
|
62
|
-
{
|
63
|
-
"files": [
|
64
|
-
"./**/__tests__/*.ts{x,}"
|
65
|
-
],
|
66
|
-
"rules": {
|
67
|
-
"@typescript-eslint/no-explicit-any": "off"
|
68
|
-
}
|
69
|
-
}
|
70
|
-
],
|
71
|
-
"extends": [
|
72
|
-
"eslint:recommended",
|
73
|
-
"plugin:@typescript-eslint/recommended"
|
74
|
-
],
|
75
|
-
"rules": {
|
76
|
-
"@typescript-eslint/explicit-module-boundary-types": "off",
|
77
|
-
"@typescript-eslint/no-non-null-assertion": "off",
|
78
|
-
"@typescript-eslint/no-unused-vars": "error",
|
79
|
-
"no-prototype-builtins": "off"
|
80
|
-
}
|
81
|
-
},
|
82
57
|
"devDependencies": {
|
83
|
-
"@
|
84
|
-
"@
|
85
|
-
"
|
86
|
-
"
|
87
|
-
"
|
88
|
-
"
|
89
|
-
"
|
90
|
-
"
|
91
|
-
"
|
58
|
+
"@eslint/js": "^9.7.0",
|
59
|
+
"@types/eslint__js": "^8.42.3",
|
60
|
+
"@types/node": "^22.0.0",
|
61
|
+
"eslint": "^9.7.0",
|
62
|
+
"husky": "^9.1.3",
|
63
|
+
"lint-staged": "^15.2.7",
|
64
|
+
"prettier": "^3.3.3",
|
65
|
+
"typescript": "^5.5.4",
|
66
|
+
"typescript-eslint": "^8.0.0-alpha.54",
|
67
|
+
"vite": "^5.3.5",
|
68
|
+
"vitest": "^2.0.0"
|
92
69
|
}
|
93
70
|
}
|
@@ -119,7 +119,10 @@ const reduceToSingleError = (errors: Array<Error>, options?: ErrorOptions) => {
|
|
119
119
|
|
120
120
|
/** Happens when 2 or more child resources cannot be destroyed. */
|
121
121
|
class BulkDestroyError extends Error {
|
122
|
-
constructor(
|
122
|
+
constructor(
|
123
|
+
public failures: Array<unknown>,
|
124
|
+
options?: ErrorOptions,
|
125
|
+
) {
|
123
126
|
super(
|
124
127
|
'Some resources could not be destroyed. See the `failures` property for details.',
|
125
128
|
options,
|
package/CHANGELOG.md
DELETED
@@ -1,104 +0,0 @@
|
|
1
|
-
# Changelog
|
2
|
-
|
3
|
-
All notable changes to this project will be documented in this file.
|
4
|
-
|
5
|
-
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).
|
6
|
-
|
7
|
-
## [Unreleased]
|
8
|
-
|
9
|
-
### Added
|
10
|
-
|
11
|
-
- New context API carries state down the tree without plumbing through arguments.
|
12
|
-
- New `ContextType<Handle>` utility type which gets the value type of a context.
|
13
|
-
|
14
|
-
### Changed
|
15
|
-
|
16
|
-
- Renamed public type `ResourceContext` to `ResourceScope`.
|
17
|
-
- `destroy(...)` is no longer allowed to destroy child resources, only roots.
|
18
|
-
- Added tree-shaking metadata. This is useful for bundle analysis tools.
|
19
|
-
|
20
|
-
## [0.5.1] - 2023-08-12
|
21
|
-
|
22
|
-
### Fixed
|
23
|
-
|
24
|
-
- Added support for parametrized resources in `ResourceHandle<T>`.
|
25
|
-
|
26
|
-
## [0.5.0] - 2023-08-12
|
27
|
-
|
28
|
-
### Changed
|
29
|
-
|
30
|
-
- Wardens is now published with ESM (`type=module`). It should be backwards compatible.
|
31
|
-
- Now `destroy(...)` throws if you pass an object that wasn't constructed with `create(...)`.
|
32
|
-
|
33
|
-
### Fixed
|
34
|
-
|
35
|
-
- If a resource fails while initializing, now all intermediate child resources are destroyed as well.
|
36
|
-
- If a resource fails while being destroyed, now its child resources are destroyed as well.
|
37
|
-
- Resources can no longer provision child resources after teardown. This closes a loophole where resources could escape destruction.
|
38
|
-
|
39
|
-
### Added
|
40
|
-
|
41
|
-
- New `ResourceHandle<T>` utility type represents the value returned when creating a resource.
|
42
|
-
|
43
|
-
## [0.4.1] - 2023-01-14
|
44
|
-
|
45
|
-
### Fixed
|
46
|
-
|
47
|
-
- Newer versions of TypeScript complained about signatures in `bindContext(...)`.
|
48
|
-
|
49
|
-
## [0.4.0] - 2022-06-19
|
50
|
-
|
51
|
-
### Added
|
52
|
-
|
53
|
-
- Support for provisioning resources through async functions instead of `Resource` subclasses. This offers better type safety around null conditions.
|
54
|
-
- A new `Resource` utility type is exported. The new functional API expects you to return this interface.
|
55
|
-
|
56
|
-
### Removed
|
57
|
-
|
58
|
-
- The `Resource` abstract class was removed. Use async functions instead.
|
59
|
-
- The `Controls<...>` utility type was removed. Import the type you need from the module instead.
|
60
|
-
|
61
|
-
## [0.3.0] - 2022-06-04
|
62
|
-
|
63
|
-
### Changed
|
64
|
-
|
65
|
-
- Prevent use of `allocate(...)`/`deallocate(...)` outside a resource subclass.
|
66
|
-
- Renamed `enter()` and `leave()` to `create()` and `destroy()`.
|
67
|
-
- Renamed `mount()` and `unmount()` to `create()` and `destroy()`.
|
68
|
-
|
69
|
-
### Removed
|
70
|
-
|
71
|
-
- Second type parameter to `Resource` is gone. Arguments to `enter(...)` are now inferred.
|
72
|
-
- No more default implementations for `enter(...)`/`leave(...)` on resources.
|
73
|
-
|
74
|
-
## [0.2.0] - 2022-05-24
|
75
|
-
|
76
|
-
### Fixed
|
77
|
-
|
78
|
-
- `mount(...)` and `allocate(...)` no longer require a config argument if the resource doesn't explicitly define one.
|
79
|
-
|
80
|
-
### Added
|
81
|
-
|
82
|
-
- `enter(...)` now supports variable arguments.
|
83
|
-
|
84
|
-
### Changed
|
85
|
-
|
86
|
-
- The second generic parameter of `Resource` was a config parameter, but now it's an argument tuple.
|
87
|
-
- The `ExternalControls` utility type was renamed to `Controls`.
|
88
|
-
|
89
|
-
## [0.1.0] - 2022-05-22
|
90
|
-
|
91
|
-
### Added
|
92
|
-
|
93
|
-
- Resource class for modeling asynchronously provisioned resources
|
94
|
-
- `mount`/`unmount` hooks to provision resources
|
95
|
-
- `allocate`/`deallocate` for creating hierarchies of resources
|
96
|
-
|
97
|
-
[Unreleased]: https://github.com/PsychoLlama/wardens/compare/v0.5.1...HEAD
|
98
|
-
[0.5.1]: https://github.com/PsychoLlama/wardens/compare/v0.5.0...v0.5.1
|
99
|
-
[0.5.0]: https://github.com/PsychoLlama/wardens/compare/v0.4.1...v0.5.0
|
100
|
-
[0.4.1]: https://github.com/PsychoLlama/wardens/compare/v0.4.0...v0.4.1
|
101
|
-
[0.4.0]: https://github.com/PsychoLlama/wardens/compare/v0.3.0...v0.4.0
|
102
|
-
[0.3.0]: https://github.com/PsychoLlama/wardens/compare/v0.2.0...v0.3.0
|
103
|
-
[0.2.0]: https://github.com/PsychoLlama/wardens/compare/v0.1.0...v0.2.0
|
104
|
-
[0.1.0]: https://github.com/PsychoLlama/wardens/releases/tag/v0.1.0
|