declastruct 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/run +4 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/package.json +6 -1
- package/readme.md +211 -35
package/bin/run
ADDED
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './contract/sdk';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./contract/sdk"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,iDAA+B"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "declastruct",
|
|
3
3
|
"author": "ehmpathy",
|
|
4
4
|
"description": "Add declarative control to any resource constructs. Declare, plan, and apply within an observable pit-of-success.",
|
|
5
|
-
"version": "1.1.
|
|
5
|
+
"version": "1.1.2",
|
|
6
6
|
"repository": "ehmpathy/declastruct",
|
|
7
7
|
"homepage": "https://github.com/ehmpathy/declastruct",
|
|
8
8
|
"keywords": [
|
|
@@ -17,7 +17,12 @@
|
|
|
17
17
|
"engines": {
|
|
18
18
|
"node": ">=8.0.0"
|
|
19
19
|
},
|
|
20
|
+
"types": "dist/index.d.ts",
|
|
21
|
+
"bin": {
|
|
22
|
+
"declastruct": "./bin/run"
|
|
23
|
+
},
|
|
20
24
|
"files": [
|
|
25
|
+
"/bin",
|
|
21
26
|
"/dist"
|
|
22
27
|
],
|
|
23
28
|
"scripts": {
|
package/readme.md
CHANGED
|
@@ -3,74 +3,250 @@
|
|
|
3
3
|

|
|
4
4
|

|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
declarative control for any resource constructs, batteries included
|
|
7
|
+
|
|
8
|
+
# intro
|
|
9
|
+
|
|
10
|
+
Add declarative control to any resource construct. Declare, plan, and apply within an observable pit-of-success.
|
|
7
11
|
|
|
8
12
|
Declare the structures you want. Plan to see the changes required. Apply to make it so 🪄
|
|
9
13
|
|
|
10
|
-
|
|
14
|
+
|
|
15
|
+
## what is it?
|
|
16
|
+
|
|
17
|
+
`declastruct` is a framework for managing any resource construct declaratively using TypeScript.
|
|
18
|
+
|
|
19
|
+
declare what you want, plan the changes, and apply them safely — all without managing separate state files or learning a new language.
|
|
20
|
+
|
|
21
|
+
works with:
|
|
22
|
+
- **infrastructure** — AWS, GCP, Azure resources
|
|
23
|
+
- **SaaS platforms** — Stripe customers, GitHub repos, Slack channels, etc
|
|
24
|
+
- **databases** — application data models
|
|
25
|
+
- **any API** — anything with a remote state you want to control
|
|
26
|
+
|
|
27
|
+
think Terraform, but:
|
|
28
|
+
- **no state files to manage** — compares directly against live remote state
|
|
29
|
+
- **no new language to learn** — uses TypeScript and your existing domain objects
|
|
30
|
+
- **pit-of-success by default** — enforces idempotency, clear unique keys, and safe operations
|
|
31
|
+
- **not just infrastructure** — works with any resource construct (saas, databases, apis, etc)
|
|
32
|
+
|
|
33
|
+
# usage
|
|
34
|
+
|
|
35
|
+
## install
|
|
11
36
|
|
|
12
37
|
```sh
|
|
13
38
|
npm install declastruct --save-dev
|
|
14
39
|
```
|
|
15
40
|
|
|
16
|
-
|
|
41
|
+
## use
|
|
17
42
|
|
|
18
|
-
### 1. declare ✨
|
|
43
|
+
### 1. **declare** your desired state ✨
|
|
19
44
|
|
|
20
|
-
|
|
45
|
+
define resource constructs with strongly-typed domain objects:
|
|
21
46
|
|
|
22
47
|
```ts
|
|
23
48
|
import { getDeclastructAwsProvider, DeclaredAwsS3Bucket } from 'declastruct-aws';
|
|
49
|
+
import { getDeclastructStripeProvider, DeclaredStripeCustomer } from 'declastruct-stripe';
|
|
24
50
|
|
|
25
|
-
//
|
|
51
|
+
// define which providers support your resource constructs
|
|
26
52
|
export const getProviders = async () => [
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
53
|
+
await getDeclastructAwsProvider({
|
|
54
|
+
profile: process.env.AWS_PROFILE,
|
|
55
|
+
}),
|
|
56
|
+
await getDeclastructStripeProvider({
|
|
57
|
+
apiKey: process.env.STRIPE_SECRET_KEY,
|
|
58
|
+
}),
|
|
59
|
+
];
|
|
60
|
+
|
|
61
|
+
// declare the resource constructs you want and their desired state
|
|
33
62
|
export const getResources = async () => {
|
|
34
63
|
const bucket = DeclaredAwsS3Bucket.as({
|
|
35
64
|
name: 'your-s3-bucket',
|
|
65
|
+
versioning: true,
|
|
66
|
+
encryption: 'AES256',
|
|
36
67
|
});
|
|
37
|
-
// declare other resources you wish to have
|
|
38
68
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
}
|
|
69
|
+
const customer = DeclaredStripeCustomer.as({
|
|
70
|
+
email: 'user@example.com',
|
|
71
|
+
name: 'John Doe',
|
|
72
|
+
metadata: { source: 'app-web' },
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
return [bucket, customer];
|
|
76
|
+
};
|
|
44
77
|
```
|
|
45
78
|
|
|
46
|
-
### 2. plan 🔮
|
|
79
|
+
### 2. **plan** the required changes 🔮
|
|
47
80
|
|
|
48
|
-
|
|
81
|
+
see exactly what will change before applying:
|
|
49
82
|
|
|
50
83
|
```sh
|
|
51
|
-
npx declastruct plan
|
|
84
|
+
npx declastruct plan \
|
|
85
|
+
--wish provision/resources.ts \
|
|
86
|
+
--into provision/.temp/plan.json
|
|
52
87
|
```
|
|
53
88
|
|
|
54
|
-
|
|
89
|
+
output:
|
|
90
|
+
```
|
|
91
|
+
planned changes:
|
|
92
|
+
CREATE: DeclaredAwsS3Bucket.your-s3-bucket
|
|
93
|
+
+ name: "your-s3-bucket"
|
|
94
|
+
+ versioning: true
|
|
95
|
+
+ encryption: "AES256"
|
|
96
|
+
|
|
97
|
+
CREATE: DeclaredStripeCustomer.user@example.com
|
|
98
|
+
+ email: "user@example.com"
|
|
99
|
+
+ name: "John Doe"
|
|
100
|
+
+ metadata: { source: "app-web" }
|
|
101
|
+
```
|
|
55
102
|
|
|
56
|
-
apply the plan
|
|
103
|
+
### 3. **apply** the plan 🪄
|
|
104
|
+
|
|
105
|
+
execute the plan to make your desired state reality:
|
|
57
106
|
|
|
58
107
|
```sh
|
|
59
108
|
npx declastruct apply --plan provision/.temp/plan.json
|
|
60
109
|
```
|
|
61
110
|
|
|
62
|
-
# benefits
|
|
111
|
+
# benefits - why declastruct?
|
|
112
|
+
|
|
113
|
+
## summary
|
|
114
|
+
|
|
115
|
+
✅ **stateless** — no state files to manage, compare directly against reality
|
|
116
|
+
|
|
117
|
+
✅ **type-safe** — full TypeScript support with domain objects
|
|
118
|
+
|
|
119
|
+
✅ **idempotent** — safe to run plans multiple times
|
|
120
|
+
|
|
121
|
+
✅ **observable** — see exactly what will change before applying
|
|
122
|
+
|
|
123
|
+
✅ **composable** — reuse domain objects and operations across application code and resource management
|
|
124
|
+
|
|
125
|
+
✅ **pit-of-success** — enforced best practices via idempotent dao interfaces
|
|
126
|
+
|
|
127
|
+
✅ **universal** — works with any resource construct (infrastructure, saas platforms, databases, apis, etc)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
## details
|
|
131
|
+
|
|
132
|
+
### no state file management
|
|
133
|
+
|
|
134
|
+
traditional declarative tools (like Terraform) require maintaining a separate state file that tracks what resources exist. this creates problems:
|
|
135
|
+
- state files can drift from reality
|
|
136
|
+
- state locking issues in team environments
|
|
137
|
+
- state files must be carefully secured and backed up
|
|
138
|
+
|
|
139
|
+
**declastruct eliminates state files entirely.** it compares your desired resource constructs directly against live remote state using unique keys, so the source of truth is always reality itself.
|
|
140
|
+
|
|
141
|
+
### use your existing domain language
|
|
142
|
+
|
|
143
|
+
instead of learning HCL, YAML, or another DSL:
|
|
144
|
+
- declare resource constructs as TypeScript using `domain-objects`
|
|
145
|
+
- reuse the same domain objects across your application code and remote resource management
|
|
146
|
+
- leverage TypeScript's type safety, IDE autocomplete, and refactoring tools
|
|
147
|
+
- compose and test resource definitions like any other code
|
|
148
|
+
|
|
149
|
+
### enforced best practices
|
|
150
|
+
|
|
151
|
+
declastruct providers follow a pit-of-success pattern that guarantees:
|
|
152
|
+
|
|
153
|
+
**idempotency** — all operations can be safely retried
|
|
154
|
+
- `finsert`: find-or-insert (safe create)
|
|
155
|
+
- `upsert`: update-or-insert (safe update)
|
|
156
|
+
- running the same plan multiple times produces the same result
|
|
157
|
+
|
|
158
|
+
**explicit unique keys** — every resource declares how to uniquely identify it
|
|
159
|
+
- prevents accidental duplicates
|
|
160
|
+
- enables accurate comparison against live state
|
|
161
|
+
- makes resource relationships clear, typesafe, and composable
|
|
162
|
+
|
|
163
|
+
**observable change plans** — see exactly what will change before applying
|
|
164
|
+
- diff view shows before & after for each resource
|
|
165
|
+
- change actions: CREATE, UPDATE, KEEP, DESTROY
|
|
166
|
+
- no surprises in production
|
|
167
|
+
|
|
168
|
+
### provider ecosystem
|
|
169
|
+
|
|
170
|
+
declastruct is designed to support any resource construct through adapters:
|
|
171
|
+
|
|
172
|
+
**available providers:**
|
|
173
|
+
- `declastruct-aws` — AWS infrastructure (S3, Lambda, RDS, EC2, etc.)
|
|
174
|
+
- `declastruct-stripe` — Stripe SaaS resources (customers, subscriptions, products, etc.)
|
|
175
|
+
- `declastruct-github` — Github resources (repos, branches, protection, etc.)
|
|
176
|
+
- etc
|
|
177
|
+
|
|
178
|
+
**build your own provider** for any resource construct (GitHub repos, Slack channels, database records, etc.) by implementing the `DeclastructDao` and `DeclastructProvider` interfaces.
|
|
179
|
+
|
|
180
|
+
## use cases
|
|
181
|
+
|
|
182
|
+
- **infrastructure as code** — manage AWS, GCP, Azure resources declaratively
|
|
183
|
+
- **SaaS platform management** — manage Stripe customers, GitHub repos, Slack channels, etc declaratively
|
|
184
|
+
- **database state management** — control database resource states declaratively
|
|
185
|
+
- **api state management** — control remote resource state through api's declaratively
|
|
186
|
+
- **multi-platform orchestration** — coordinate resources across different providers in one plan
|
|
187
|
+
|
|
188
|
+
|
|
189
|
+
# concepts
|
|
190
|
+
|
|
191
|
+
## domain
|
|
192
|
+
|
|
193
|
+
### DeclastructDao
|
|
194
|
+
|
|
195
|
+
the core abstraction that defines how to interact with a resource type:
|
|
196
|
+
|
|
197
|
+
```ts
|
|
198
|
+
interface DeclastructDao<TResource, TResourceClass, TContext> {
|
|
199
|
+
get: {
|
|
200
|
+
byUnique: (ref: RefByUnique, context) => Promise<TResource | null>;
|
|
201
|
+
byPrimary?: (ref: RefByPrimary, context) => Promise<TResource | null>;
|
|
202
|
+
byRef: (ref: Ref, context) => Promise<TResource | null>;
|
|
203
|
+
};
|
|
204
|
+
set: {
|
|
205
|
+
finsert: (resource: TResource, context) => Promise<TResource>;
|
|
206
|
+
upsert?: (resource: TResource, context) => Promise<TResource>;
|
|
207
|
+
delete?: (ref: Ref, context) => Promise<void>;
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
every resource class gets a DeclastructDao that enforces safe, idempotent operations.
|
|
213
|
+
|
|
214
|
+
### DeclastructProvider
|
|
215
|
+
|
|
216
|
+
bundles related DAOs and provider context:
|
|
217
|
+
|
|
218
|
+
```ts
|
|
219
|
+
interface DeclastructProvider<TDaos, TContext> {
|
|
220
|
+
name: string; // provider identifier
|
|
221
|
+
daos: TDaos; // map of resource types to DAOs
|
|
222
|
+
context: TContext; // auth, region, etc.
|
|
223
|
+
hooks: {
|
|
224
|
+
beforeAll: () => Promise<void>;
|
|
225
|
+
afterAll: () => Promise<void>;
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
### DeclastructPlan
|
|
231
|
+
|
|
232
|
+
captures the changes needed to achieve desired state:
|
|
233
|
+
|
|
234
|
+
```ts
|
|
235
|
+
interface DeclastructPlan {
|
|
236
|
+
changes: DeclastructChange[]; // ordered list of changes
|
|
237
|
+
createdAt: IsoTimestamp; // when plan was created
|
|
238
|
+
hash: string; // fingerprint for validation
|
|
239
|
+
}
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
each `DeclastructChange` includes:
|
|
243
|
+
- `action`: CREATE | UPDATE | KEEP | DESTROY
|
|
244
|
+
- `forResource`: which resource this affects
|
|
245
|
+
- `state.desired`: what you want
|
|
246
|
+
- `state.remote`: what exists now
|
|
247
|
+
- `state.difference`: human-readable diff
|
|
63
248
|
|
|
64
|
-
- no dedicated state required
|
|
65
|
-
- looks at the source of truth directly
|
|
66
|
-
- leverages unique keys of resources to understand remote state automatically and eliminate the middleman
|
|
67
249
|
|
|
68
|
-
|
|
69
|
-
- no awkward new-language limitations
|
|
70
|
-
- reuse your existing domain language to manage your resources
|
|
250
|
+
## inspiration
|
|
71
251
|
|
|
72
|
-
|
|
73
|
-
- each repo that implements a declastruct adapter to control their remote state follows a pit of success
|
|
74
|
-
- idempotency is required on operations, to guarantee they operate safely
|
|
75
|
-
- clear declaration of unique and primary keys is required, to guarantee readability, composability, and true comparisons against reality
|
|
76
|
-
- not only can you use them via declastruct, you can leverage them directly as well
|
|
252
|
+
inspired by Terraform's declarative approach, but designed to eliminate state management overhead, work with any resource construct, and leverage TypeScript's type system for safer declarative resource management.
|