declastruct 1.5.2 → 1.7.0
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/dist/contract/cli/apply.js +10 -3
- package/dist/contract/cli/apply.js.map +1 -1
- package/dist/contract/cli/plan.js +8 -3
- package/dist/contract/cli/plan.js.map +1 -1
- package/dist/contract/sdk/index.d.ts +3 -0
- package/dist/contract/sdk/index.js +7 -1
- package/dist/contract/sdk/index.js.map +1 -1
- package/dist/domain/symbols.d.ts +5 -0
- package/dist/domain/symbols.js +9 -0
- package/dist/domain/symbols.js.map +1 -0
- package/dist/domain.objects/DeclastructDao.d.ts +10 -10
- package/dist/domain.objects/DeclastructDao.js.map +1 -1
- package/dist/domain.objects/genDeclastructDao.d.ts +79 -0
- package/dist/domain.objects/genDeclastructDao.js +73 -0
- package/dist/domain.objects/genDeclastructDao.js.map +1 -0
- package/dist/domain.operations/del/del.d.ts +27 -0
- package/dist/domain.operations/del/del.js +33 -0
- package/dist/domain.operations/del/del.js.map +1 -0
- package/dist/domain.operations/plan/planChanges.js +4 -1
- package/dist/domain.operations/plan/planChanges.js.map +1 -1
- package/dist/domain.operations/ref/getRefByPrimary.d.ts +1 -1
- package/dist/domain.operations/ref/getRefByPrimary.js +2 -4
- package/dist/domain.operations/ref/getRefByPrimary.js.map +1 -1
- package/dist/domain.operations/ref/getRefByUnique.d.ts +1 -1
- package/dist/domain.operations/ref/getRefByUnique.js +2 -4
- package/dist/domain.operations/ref/getRefByUnique.js.map +1 -1
- package/package.json +12 -10
- package/readme.md +142 -0
|
@@ -33,6 +33,7 @@ const fs_1 = require("fs");
|
|
|
33
33
|
const promises_1 = require("fs/promises");
|
|
34
34
|
const helpful_errors_1 = require("helpful-errors");
|
|
35
35
|
const path_1 = require("path");
|
|
36
|
+
const rhachet_artifact_git_1 = require("rhachet-artifact-git");
|
|
36
37
|
const DeclastructPlan_1 = require("../../domain.objects/DeclastructPlan");
|
|
37
38
|
const applyChanges_1 = require("../../domain.operations/apply/applyChanges");
|
|
38
39
|
const log = console;
|
|
@@ -76,12 +77,18 @@ const executeApplyCommand = async (input) => {
|
|
|
76
77
|
// validate wish file exists
|
|
77
78
|
if (!(0, fs_1.existsSync)(resolvedWishPath))
|
|
78
79
|
throw new helpful_errors_1.BadRequestError(`Wish file not found: ${resolvedWishPath}`);
|
|
80
|
+
// get git root for relative path display
|
|
81
|
+
const gitRoot = await (0, rhachet_artifact_git_1.getGitRepoRoot)({ from: process.cwd() });
|
|
82
|
+
const relativePlanPath = resolvedPlanPath
|
|
83
|
+
? (0, path_1.relative)(gitRoot, resolvedPlanPath)
|
|
84
|
+
: null;
|
|
85
|
+
const relativeWishPath = (0, path_1.relative)(gitRoot, resolvedWishPath);
|
|
79
86
|
// log header
|
|
80
87
|
log.info('');
|
|
81
88
|
log.info('🌊 declastruct apply');
|
|
82
|
-
if (
|
|
83
|
-
log.info(` plan: ${
|
|
84
|
-
log.info(` wish: ${
|
|
89
|
+
if (relativePlanPath)
|
|
90
|
+
log.info(` plan: ${relativePlanPath}`);
|
|
91
|
+
log.info(` wish: ${relativeWishPath}`);
|
|
85
92
|
log.info('');
|
|
86
93
|
// import wish file
|
|
87
94
|
const wish = await Promise.resolve(`${resolvedWishPath}`).then(s => __importStar(require(s)));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../../src/contract/cli/apply.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,4DAAoC;AACpC,2BAAgC;AAChC,0CAAuC;AACvC,mDAAiD;AACjD,+
|
|
1
|
+
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../../src/contract/cli/apply.ts"],"names":[],"mappings":"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"}
|
|
@@ -33,6 +33,7 @@ const fs_1 = require("fs");
|
|
|
33
33
|
const promises_1 = require("fs/promises");
|
|
34
34
|
const helpful_errors_1 = require("helpful-errors");
|
|
35
35
|
const path_1 = require("path");
|
|
36
|
+
const rhachet_artifact_git_1 = require("rhachet-artifact-git");
|
|
36
37
|
const planChanges_1 = require("../../domain.operations/plan/planChanges");
|
|
37
38
|
const log = console;
|
|
38
39
|
/**
|
|
@@ -44,14 +45,18 @@ const executePlanCommand = async ({ wishFilePath, planFilePath, }) => {
|
|
|
44
45
|
// resolve paths
|
|
45
46
|
const resolvedWishPath = (0, path_1.resolve)(process.cwd(), wishFilePath);
|
|
46
47
|
const resolvedPlanPath = (0, path_1.resolve)(process.cwd(), planFilePath);
|
|
48
|
+
// get git root for relative path display
|
|
49
|
+
const gitRoot = await (0, rhachet_artifact_git_1.getGitRepoRoot)({ from: process.cwd() });
|
|
50
|
+
const relativeWishPath = (0, path_1.relative)(gitRoot, resolvedWishPath);
|
|
51
|
+
const relativePlanPath = (0, path_1.relative)(gitRoot, resolvedPlanPath);
|
|
47
52
|
// validate wish file exists
|
|
48
53
|
if (!(0, fs_1.existsSync)(resolvedWishPath)) {
|
|
49
54
|
throw new helpful_errors_1.BadRequestError(`Wish file not found: ${resolvedWishPath}`);
|
|
50
55
|
}
|
|
51
56
|
log.info('');
|
|
52
57
|
log.info('🌊 declastruct plan');
|
|
53
|
-
log.info(` wish: ${
|
|
54
|
-
log.info(` plan: ${
|
|
58
|
+
log.info(` wish: ${relativeWishPath}`);
|
|
59
|
+
log.info(` plan: ${relativePlanPath}`);
|
|
55
60
|
log.info('');
|
|
56
61
|
// import wish file
|
|
57
62
|
const wish = await Promise.resolve(`${resolvedWishPath}`).then(s => __importStar(require(s)));
|
|
@@ -91,7 +96,7 @@ const executePlanCommand = async ({ wishFilePath, planFilePath, }) => {
|
|
|
91
96
|
// log summary
|
|
92
97
|
log.info('');
|
|
93
98
|
log.info(`🌊 planned for ${plan.changes.length} resources`);
|
|
94
|
-
log.info(` into ${
|
|
99
|
+
log.info(` into ${relativePlanPath}`);
|
|
95
100
|
log.info('');
|
|
96
101
|
};
|
|
97
102
|
exports.executePlanCommand = executePlanCommand;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../src/contract/cli/plan.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,4DAAoC;AACpC,2BAAgC;AAChC,0CAA+C;AAC/C,mDAAiD;AACjD,+
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../../src/contract/cli/plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,6 +4,9 @@ export { DeclastructChange, DeclastructChangeAction, } from '../../domain.object
|
|
|
4
4
|
export { DeclastructDao } from '../../domain.objects/DeclastructDao';
|
|
5
5
|
export { DeclastructPlan } from '../../domain.objects/DeclastructPlan';
|
|
6
6
|
export { DeclastructProvider } from '../../domain.objects/DeclastructProvider';
|
|
7
|
+
export type { DeclastructDaoInput, DeclastructDaoWithRef, DeclastructDaoWoutRef, } from '../../domain.objects/genDeclastructDao';
|
|
8
|
+
export { genDeclastructDao } from '../../domain.objects/genDeclastructDao';
|
|
7
9
|
export type { IsoTimestamp } from '../../domain.objects/IsoTimestamp';
|
|
10
|
+
export { del, isMarkedForDeletion } from '../../domain.operations/del/del';
|
|
8
11
|
export { getRefByPrimary } from '../../domain.operations/ref/getRefByPrimary';
|
|
9
12
|
export { getRefByUnique } from '../../domain.operations/ref/getRefByUnique';
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// domain objects
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
-
exports.getRefByUnique = exports.getRefByPrimary = exports.DeclastructProvider = exports.DeclastructPlan = exports.DeclastructDao = exports.DeclastructChangeAction = exports.DeclastructChange = void 0;
|
|
4
|
+
exports.getRefByUnique = exports.getRefByPrimary = exports.isMarkedForDeletion = exports.del = exports.genDeclastructDao = exports.DeclastructProvider = exports.DeclastructPlan = exports.DeclastructDao = exports.DeclastructChangeAction = exports.DeclastructChange = void 0;
|
|
5
5
|
var DeclastructChange_1 = require("../../domain.objects/DeclastructChange");
|
|
6
6
|
Object.defineProperty(exports, "DeclastructChange", { enumerable: true, get: function () { return DeclastructChange_1.DeclastructChange; } });
|
|
7
7
|
Object.defineProperty(exports, "DeclastructChangeAction", { enumerable: true, get: function () { return DeclastructChange_1.DeclastructChangeAction; } });
|
|
@@ -11,7 +11,13 @@ var DeclastructPlan_1 = require("../../domain.objects/DeclastructPlan");
|
|
|
11
11
|
Object.defineProperty(exports, "DeclastructPlan", { enumerable: true, get: function () { return DeclastructPlan_1.DeclastructPlan; } });
|
|
12
12
|
var DeclastructProvider_1 = require("../../domain.objects/DeclastructProvider");
|
|
13
13
|
Object.defineProperty(exports, "DeclastructProvider", { enumerable: true, get: function () { return DeclastructProvider_1.DeclastructProvider; } });
|
|
14
|
+
// factories
|
|
15
|
+
var genDeclastructDao_1 = require("../../domain.objects/genDeclastructDao");
|
|
16
|
+
Object.defineProperty(exports, "genDeclastructDao", { enumerable: true, get: function () { return genDeclastructDao_1.genDeclastructDao; } });
|
|
14
17
|
// domain operations
|
|
18
|
+
var del_1 = require("../../domain.operations/del/del");
|
|
19
|
+
Object.defineProperty(exports, "del", { enumerable: true, get: function () { return del_1.del; } });
|
|
20
|
+
Object.defineProperty(exports, "isMarkedForDeletion", { enumerable: true, get: function () { return del_1.isMarkedForDeletion; } });
|
|
15
21
|
var getRefByPrimary_1 = require("../../domain.operations/ref/getRefByPrimary");
|
|
16
22
|
Object.defineProperty(exports, "getRefByPrimary", { enumerable: true, get: function () { return getRefByPrimary_1.getRefByPrimary; } });
|
|
17
23
|
var getRefByUnique_1 = require("../../domain.operations/ref/getRefByUnique");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/contract/sdk/index.ts"],"names":[],"mappings":";AAAA,iBAAiB;;;AAIjB,4EAGgD;AAF9C,sHAAA,iBAAiB,OAAA;AACjB,4HAAA,uBAAuB,OAAA;AAEzB,sEAAqE;AAA5D,gHAAA,cAAc,OAAA;AACvB,wEAAuE;AAA9D,kHAAA,eAAe,OAAA;AACxB,gFAA+E;AAAtE,0HAAA,mBAAmB,OAAA;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/contract/sdk/index.ts"],"names":[],"mappings":";AAAA,iBAAiB;;;AAIjB,4EAGgD;AAF9C,sHAAA,iBAAiB,OAAA;AACjB,4HAAA,uBAAuB,OAAA;AAEzB,sEAAqE;AAA5D,gHAAA,cAAc,OAAA;AACvB,wEAAuE;AAA9D,kHAAA,eAAe,OAAA;AACxB,gFAA+E;AAAtE,0HAAA,mBAAmB,OAAA;AAM5B,YAAY;AACZ,4EAA2E;AAAlE,sHAAA,iBAAiB,OAAA;AAE1B,oBAAoB;AACpB,uDAA2E;AAAlE,0FAAA,GAAG,OAAA;AAAE,0GAAA,mBAAmB,OAAA;AACjC,+EAA8E;AAArE,kHAAA,eAAe,OAAA;AACxB,6EAA4E;AAAnE,gHAAA,cAAc,OAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DECLASTRUCT_DELETE = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* .what = symbol used to mark resources for declarative deletion
|
|
6
|
+
* .why = enables del() wrapper to mark resources without polluting their interface
|
|
7
|
+
*/
|
|
8
|
+
exports.DECLASTRUCT_DELETE = Symbol.for('declastruct.delete');
|
|
9
|
+
//# sourceMappingURL=symbols.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symbols.js","sourceRoot":"","sources":["../../src/domain/symbols.ts"],"names":[],"mappings":";;;AAAA;;;GAGG;AACU,QAAA,kBAAkB,GAAG,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC"}
|
|
@@ -34,9 +34,9 @@ export interface DeclastructDao<TResourceClass extends Refable<any, any, any>, T
|
|
|
34
34
|
* .what = fetch by primary keys
|
|
35
35
|
* .why = enables efficient lookups when primary key is known
|
|
36
36
|
*
|
|
37
|
-
* .note =
|
|
37
|
+
* .note = undefined if resource lacks primary keys; would be null, but that breaks bivariance
|
|
38
38
|
*/
|
|
39
|
-
byPrimary
|
|
39
|
+
byPrimary?(input: RefByPrimary<TResourceClass>, context: TContext): Promise<InstanceType<TResourceClass> | null>;
|
|
40
40
|
/**
|
|
41
41
|
* .what = fetch by any supported reference type
|
|
42
42
|
* .why = enables flexible lookups when ref type is not known at compile time
|
|
@@ -54,16 +54,16 @@ export interface DeclastructDao<TResourceClass extends Refable<any, any, any>, T
|
|
|
54
54
|
* .what = resolve any ref to RefByPrimary
|
|
55
55
|
* .why = enables getting primary key from any ref type
|
|
56
56
|
*
|
|
57
|
-
* .note =
|
|
57
|
+
* .note = undefined if resource lacks primary keys; would be null, but that breaks bivariance
|
|
58
58
|
*/
|
|
59
|
-
byPrimary
|
|
59
|
+
byPrimary?(input: Ref<TResourceClass>, context: TContext): Promise<RefByPrimary<TResourceClass> | null>;
|
|
60
60
|
/**
|
|
61
61
|
* .what = resolve any ref to RefByUnique
|
|
62
62
|
* .why = enables getting unique key from any ref type
|
|
63
63
|
*
|
|
64
|
-
* .note =
|
|
64
|
+
* .note = undefined if resource lacks primary keys; would be null, but that breaks bivariance
|
|
65
65
|
*/
|
|
66
|
-
byUnique
|
|
66
|
+
byUnique?(input: Ref<TResourceClass>, context: TContext): Promise<RefByUnique<TResourceClass> | null>;
|
|
67
67
|
};
|
|
68
68
|
};
|
|
69
69
|
/**
|
|
@@ -80,16 +80,16 @@ export interface DeclastructDao<TResourceClass extends Refable<any, any, any>, T
|
|
|
80
80
|
* .what = create or update resource
|
|
81
81
|
* .why = idempotent upsert - creates if not found, updates if found
|
|
82
82
|
*
|
|
83
|
-
* .note =
|
|
83
|
+
* .note = undefined if resource does not support updates; would be null, but that breaks bivariance
|
|
84
84
|
*/
|
|
85
|
-
upsert
|
|
85
|
+
upsert?(input: InstanceType<TResourceClass>, context: TContext): Promise<HasMetadata<InstanceType<TResourceClass>>>;
|
|
86
86
|
/**
|
|
87
87
|
* .what = delete resource
|
|
88
88
|
* .why = removes resource from remote state
|
|
89
89
|
*
|
|
90
|
-
* .note =
|
|
90
|
+
* .note = undefined if resource does not support deletion; would be null, but that breaks bivariance
|
|
91
91
|
*/
|
|
92
|
-
delete
|
|
92
|
+
delete?(input: Ref<TResourceClass>, context: TContext): Promise<void>;
|
|
93
93
|
};
|
|
94
94
|
}
|
|
95
95
|
export declare class DeclastructDao<TResourceClass extends Refable<any, any, any>, TContext> extends DomainLiteral<DeclastructDao<TResourceClass, TContext>> implements DeclastructDao<TResourceClass, TContext> {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DeclastructDao.js","sourceRoot":"","sources":["../../src/domain.objects/DeclastructDao.ts"],"names":[],"mappings":";;;AAAA,mDAMwB;
|
|
1
|
+
{"version":3,"file":"DeclastructDao.js","sourceRoot":"","sources":["../../src/domain.objects/DeclastructDao.ts"],"names":[],"mappings":";;;AAAA,mDAMwB;AAgIxB,MAAa,cAIX,SAAQ,8BAAuD;CACT;AALxD,wCAKwD"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { type Ref, type Refable, type RefByPrimary, type RefByUnique } from 'domain-objects';
|
|
2
|
+
import type { DeclastructDao } from './DeclastructDao';
|
|
3
|
+
/**
|
|
4
|
+
* .what = input type for genDeclastructDao without get.ref and get.one.byRef (auto-wired by factory)
|
|
5
|
+
* .why = derives from DeclastructDao to stay in sync, omits auto-wired methods
|
|
6
|
+
* .note = uses `| null` syntax to force explicit decision on nullable methods
|
|
7
|
+
*/
|
|
8
|
+
export type DeclastructDaoInput<TResourceClass extends Refable<any, any, any>, TContext> = Omit<DeclastructDao<TResourceClass, TContext>, 'get' | 'set'> & {
|
|
9
|
+
get: {
|
|
10
|
+
one: Omit<DeclastructDao<TResourceClass, TContext>['get']['one'], 'byRef' | 'byPrimary'> & {
|
|
11
|
+
byPrimary: ((input: RefByPrimary<TResourceClass>, context: TContext) => Promise<InstanceType<TResourceClass> | null>) | null;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
set: Omit<DeclastructDao<TResourceClass, TContext>['set'], 'upsert' | 'delete'> & {
|
|
15
|
+
upsert: ((input: InstanceType<TResourceClass>, context: TContext) => Promise<InstanceType<TResourceClass>>) | null;
|
|
16
|
+
delete: ((input: Ref<TResourceClass>, context: TContext) => Promise<void>) | null;
|
|
17
|
+
};
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* .what = input type for daos with byPrimary defined
|
|
21
|
+
* .why = enables overload to distinguish daos with primary key support
|
|
22
|
+
*/
|
|
23
|
+
export type DeclastructDaoInputWithPrimary<TResourceClass extends Refable<any, any, any>, TContext> = Omit<DeclastructDaoInput<TResourceClass, TContext>, 'get'> & {
|
|
24
|
+
get: {
|
|
25
|
+
one: Omit<DeclastructDao<TResourceClass, TContext>['get']['one'], 'byPrimary' | 'byRef'> & {
|
|
26
|
+
byPrimary: NonNullable<DeclastructDao<TResourceClass, TContext>['get']['one']['byPrimary']>;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* .what = input type for daos without byPrimary
|
|
32
|
+
* .why = enables overload to distinguish daos without primary key support
|
|
33
|
+
*/
|
|
34
|
+
export type DeclastructDaoInputWoutPrimary<TResourceClass extends Refable<any, any, any>, TContext> = Omit<DeclastructDaoInput<TResourceClass, TContext>, 'get'> & {
|
|
35
|
+
get: {
|
|
36
|
+
one: Omit<DeclastructDao<TResourceClass, TContext>['get']['one'], 'byPrimary' | 'byRef'> & {
|
|
37
|
+
byPrimary: null;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* .what = output type for daos with ref methods defined
|
|
43
|
+
* .why = enables type-safe access to ref resolution methods
|
|
44
|
+
* .note = uses method syntax for bivariance (enables assignment to DeclastructDao<any>)
|
|
45
|
+
*/
|
|
46
|
+
export type DeclastructDaoWithRef<TResourceClass extends Refable<any, any, any>, TContext> = Omit<DeclastructDao<TResourceClass, TContext>, 'get'> & {
|
|
47
|
+
get: {
|
|
48
|
+
one: DeclastructDao<TResourceClass, TContext>['get']['one'];
|
|
49
|
+
ref: {
|
|
50
|
+
byPrimary(input: Ref<TResourceClass>, context: TContext): Promise<RefByPrimary<TResourceClass> | null>;
|
|
51
|
+
byUnique(input: Ref<TResourceClass>, context: TContext): Promise<RefByUnique<TResourceClass> | null>;
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
};
|
|
55
|
+
/**
|
|
56
|
+
* .what = output type for daos without ref methods
|
|
57
|
+
* .why = ref methods are undefined when byPrimary is not supported
|
|
58
|
+
*/
|
|
59
|
+
export type DeclastructDaoWoutRef<TResourceClass extends Refable<any, any, any>, TContext> = Omit<DeclastructDao<TResourceClass, TContext>, 'get'> & {
|
|
60
|
+
get: {
|
|
61
|
+
one: DeclastructDao<TResourceClass, TContext>['get']['one'];
|
|
62
|
+
ref: {
|
|
63
|
+
byPrimary: undefined;
|
|
64
|
+
byUnique: undefined;
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* .what = factory to create DeclastructDao with auto-wired ref methods
|
|
70
|
+
* .why = enforces that ref methods are defined iff byPrimary is defined
|
|
71
|
+
* .note = TContext must be explicitly provided as a generic parameter to avoid hazardous Record<string, any> inference
|
|
72
|
+
*
|
|
73
|
+
* @overload input with byPrimary defined → output with ref methods defined
|
|
74
|
+
*/
|
|
75
|
+
export declare function genDeclastructDao<TResourceClass extends Refable<any, any, any>, TContext extends Record<string, any> = never>(input: DeclastructDaoInputWithPrimary<TResourceClass, TContext>): DeclastructDaoWithRef<TResourceClass, TContext>;
|
|
76
|
+
/**
|
|
77
|
+
* @overload input without byPrimary → output with ref methods null
|
|
78
|
+
*/
|
|
79
|
+
export declare function genDeclastructDao<TResourceClass extends Refable<any, any, any>, TContext extends Record<string, any> = never>(input: DeclastructDaoInputWoutPrimary<TResourceClass, TContext>): DeclastructDaoWoutRef<TResourceClass, TContext>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.genDeclastructDao = void 0;
|
|
4
|
+
const domain_objects_1 = require("domain-objects");
|
|
5
|
+
const helpful_errors_1 = require("helpful-errors");
|
|
6
|
+
const getRefByPrimary_1 = require("../domain.operations/ref/getRefByPrimary");
|
|
7
|
+
const getRefByUnique_1 = require("../domain.operations/ref/getRefByUnique");
|
|
8
|
+
/**
|
|
9
|
+
* .impl = creates dao with byRef and ref methods auto-wired based on byPrimary presence
|
|
10
|
+
*/
|
|
11
|
+
function genDeclastructDao(input) {
|
|
12
|
+
const hasPrimary = input.get.one.byPrimary !== null;
|
|
13
|
+
// build byRef from byUnique + byPrimary
|
|
14
|
+
const byRef = async (ref, context) => {
|
|
15
|
+
// check primary key first (only if resource declares .primary)
|
|
16
|
+
if (hasPrimary && (0, domain_objects_1.isRefByPrimary)({ of: input.dobj })(ref))
|
|
17
|
+
return input.get.one.byPrimary(ref, context);
|
|
18
|
+
// check unique key
|
|
19
|
+
if ((0, domain_objects_1.isRefByUnique)({ of: input.dobj })(ref))
|
|
20
|
+
return input.get.one.byUnique(ref, context);
|
|
21
|
+
throw new helpful_errors_1.BadRequestError('get.one.byRef called with neither a RefByUnique nor RefByPrimary', { ref });
|
|
22
|
+
};
|
|
23
|
+
// convert null → undefined for optional methods
|
|
24
|
+
const upsert = input.set.upsert ?? undefined;
|
|
25
|
+
const del = input.set.delete ?? undefined;
|
|
26
|
+
if (hasPrimary) {
|
|
27
|
+
// auto-wire ref methods using the helper functions
|
|
28
|
+
// convert null → undefined for byPrimary (input requires null, output uses undefined)
|
|
29
|
+
const byPrimary = input.get.one.byPrimary ?? undefined;
|
|
30
|
+
const dao = {
|
|
31
|
+
...input,
|
|
32
|
+
get: {
|
|
33
|
+
one: {
|
|
34
|
+
byUnique: input.get.one.byUnique,
|
|
35
|
+
byPrimary,
|
|
36
|
+
byRef,
|
|
37
|
+
},
|
|
38
|
+
ref: {
|
|
39
|
+
byPrimary: (ref, context) => (0, getRefByPrimary_1.getRefByPrimary)({ ref }, { dao, ...context }),
|
|
40
|
+
byUnique: (ref, context) => (0, getRefByUnique_1.getRefByUnique)({ ref }, { dao, ...context }),
|
|
41
|
+
},
|
|
42
|
+
},
|
|
43
|
+
set: {
|
|
44
|
+
finsert: input.set.finsert,
|
|
45
|
+
upsert,
|
|
46
|
+
delete: del,
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
return dao;
|
|
50
|
+
}
|
|
51
|
+
// no primary key support - ref methods are undefined
|
|
52
|
+
return {
|
|
53
|
+
...input,
|
|
54
|
+
get: {
|
|
55
|
+
one: {
|
|
56
|
+
byUnique: input.get.one.byUnique,
|
|
57
|
+
byPrimary: undefined,
|
|
58
|
+
byRef,
|
|
59
|
+
},
|
|
60
|
+
ref: {
|
|
61
|
+
byPrimary: undefined,
|
|
62
|
+
byUnique: undefined,
|
|
63
|
+
},
|
|
64
|
+
},
|
|
65
|
+
set: {
|
|
66
|
+
finsert: input.set.finsert,
|
|
67
|
+
upsert,
|
|
68
|
+
delete: del,
|
|
69
|
+
},
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
exports.genDeclastructDao = genDeclastructDao;
|
|
73
|
+
//# sourceMappingURL=genDeclastructDao.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"genDeclastructDao.js","sourceRoot":"","sources":["../../src/domain.objects/genDeclastructDao.ts"],"names":[],"mappings":";;;AAAA,mDAOwB;AACxB,mDAAiD;AAEjD,8EAA2E;AAC3E,4EAAyE;AAqJzE;;GAEG;AACH,SAAgB,iBAAiB,CAI/B,KAAoD;IAEpD,MAAM,UAAU,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,KAAK,IAAI,CAAC;IAEpD,wCAAwC;IACxC,MAAM,KAAK,GAAG,KAAK,EACjB,GAAwB,EACxB,OAAiB,EAC6B,EAAE;QAChD,+DAA+D;QAC/D,IAAI,UAAU,IAAI,IAAA,+BAAc,EAAC,EAAE,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC;YACvD,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,SAAU,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAEhD,mBAAmB;QACnB,IAAI,IAAA,8BAAa,EAAC,EAAE,EAAE,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC;YACxC,OAAO,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAE9C,MAAM,IAAI,gCAAe,CACvB,kEAAkE,EAClE,EAAE,GAAG,EAAE,CACR,CAAC;IACJ,CAAC,CAAC;IAEF,gDAAgD;IAChD,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,IAAI,SAAS,CAAC;IAC7C,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,IAAI,SAAS,CAAC;IAE1C,IAAI,UAAU,EAAE,CAAC;QACf,mDAAmD;QACnD,sFAAsF;QACtF,MAAM,SAAS,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,IAAI,SAAS,CAAC;QACvD,MAAM,GAAG,GAA6C;YACpD,GAAG,KAAK;YACR,GAAG,EAAE;gBACH,GAAG,EAAE;oBACH,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ;oBAChC,SAAS;oBACT,KAAK;iBACN;gBACD,GAAG,EAAE;oBACH,SAAS,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAC1B,IAAA,iCAAe,EAAC,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;oBAC/C,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CACzB,IAAA,+BAAc,EAAC,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC;iBAC/C;aACF;YACD,GAAG,EAAE;gBACH,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO;gBAC1B,MAAM;gBACN,MAAM,EAAE,GAAG;aACZ;SACF,CAAC;QACF,OAAO,GAAG,CAAC;IACb,CAAC;IAED,qDAAqD;IACrD,OAAO;QACL,GAAG,KAAK;QACR,GAAG,EAAE;YACH,GAAG,EAAE;gBACH,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ;gBAChC,SAAS,EAAE,SAAS;gBACpB,KAAK;aACN;YACD,GAAG,EAAE;gBACH,SAAS,EAAE,SAAS;gBACpB,QAAQ,EAAE,SAAS;aACpB;SACF;QACD,GAAG,EAAE;YACH,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,OAAO;YAC1B,MAAM;YACN,MAAM,EAAE,GAAG;SACZ;KACF,CAAC;AACJ,CAAC;AA/ED,8CA+EC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { DECLASTRUCT_DELETE } from '../../domain/symbols';
|
|
2
|
+
import type { DeclaredResource } from '../../domain.objects/DeclaredResource';
|
|
3
|
+
/**
|
|
4
|
+
* .what = marks a resource for deletion via declarative instruction
|
|
5
|
+
* .why = enables users to express deletion intent
|
|
6
|
+
*
|
|
7
|
+
* .how = attaches a symbol-keyed property to the resource object
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* const getResources = async () => {
|
|
12
|
+
* const tokens = await getAllIamAuthTokens(...);
|
|
13
|
+
* return tokens.map(token => del(token)); // mark all for deletion
|
|
14
|
+
* }
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare const del: <T extends DeclaredResource>(resource: T) => T & {
|
|
18
|
+
[DECLASTRUCT_DELETE]: true;
|
|
19
|
+
};
|
|
20
|
+
/**
|
|
21
|
+
* .what = checks if a resource is marked for deletion
|
|
22
|
+
* .why = enables planChanges to detect deletion intent
|
|
23
|
+
* .note = type guard narrows to the marked type for downstream type safety
|
|
24
|
+
*/
|
|
25
|
+
export declare const isMarkedForDeletion: <T extends DeclaredResource>(resource: T) => resource is T & {
|
|
26
|
+
[DECLASTRUCT_DELETE]: true;
|
|
27
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isMarkedForDeletion = exports.del = void 0;
|
|
4
|
+
const symbols_1 = require("../../domain/symbols");
|
|
5
|
+
/**
|
|
6
|
+
* .what = marks a resource for deletion via declarative instruction
|
|
7
|
+
* .why = enables users to express deletion intent
|
|
8
|
+
*
|
|
9
|
+
* .how = attaches a symbol-keyed property to the resource object
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```ts
|
|
13
|
+
* const getResources = async () => {
|
|
14
|
+
* const tokens = await getAllIamAuthTokens(...);
|
|
15
|
+
* return tokens.map(token => del(token)); // mark all for deletion
|
|
16
|
+
* }
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
19
|
+
const del = (resource) => {
|
|
20
|
+
return Object.assign(resource, { [symbols_1.DECLASTRUCT_DELETE]: true });
|
|
21
|
+
};
|
|
22
|
+
exports.del = del;
|
|
23
|
+
/**
|
|
24
|
+
* .what = checks if a resource is marked for deletion
|
|
25
|
+
* .why = enables planChanges to detect deletion intent
|
|
26
|
+
* .note = type guard narrows to the marked type for downstream type safety
|
|
27
|
+
*/
|
|
28
|
+
const isMarkedForDeletion = (resource) => {
|
|
29
|
+
// biome-ignore lint/suspicious/noExplicitAny: symbol access requires any cast
|
|
30
|
+
return resource[symbols_1.DECLASTRUCT_DELETE] === true;
|
|
31
|
+
};
|
|
32
|
+
exports.isMarkedForDeletion = isMarkedForDeletion;
|
|
33
|
+
//# sourceMappingURL=del.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"del.js","sourceRoot":"","sources":["../../../src/domain.operations/del/del.ts"],"names":[],"mappings":";;;AAAA,kDAA0D;AAG1D;;;;;;;;;;;;;GAaG;AACI,MAAM,GAAG,GAAG,CACjB,QAAW,EACyB,EAAE;IACtC,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC,4BAAkB,CAAC,EAAE,IAAa,EAAE,CAAC,CAAC;AAC1E,CAAC,CAAC;AAJW,QAAA,GAAG,OAId;AAEF;;;;GAIG;AACI,MAAM,mBAAmB,GAAG,CACjC,QAAW,EACqC,EAAE;IAClD,8EAA8E;IAC9E,OAAQ,QAAgB,CAAC,4BAAkB,CAAC,KAAK,IAAI,CAAC;AACxD,CAAC,CAAC;AALW,QAAA,mBAAmB,uBAK9B"}
|
|
@@ -4,6 +4,7 @@ exports.planChanges = void 0;
|
|
|
4
4
|
const domain_objects_1 = require("domain-objects");
|
|
5
5
|
const DeclastructChange_1 = require("../../domain.objects/DeclastructChange");
|
|
6
6
|
const DeclastructPlan_1 = require("../../domain.objects/DeclastructPlan");
|
|
7
|
+
const del_1 = require("../../domain.operations/del/del");
|
|
7
8
|
const asIsoTimestamp_1 = require("../../infra/asIsoTimestamp");
|
|
8
9
|
const colorizeAction_1 = require("../../infra/colorizeAction");
|
|
9
10
|
const withSpinner_1 = require("../../infra/withSpinner");
|
|
@@ -42,9 +43,11 @@ const planChanges = async (input, context) => {
|
|
|
42
43
|
// log done (replaces spinner)
|
|
43
44
|
const durationSec = (durationMs / 1000).toFixed(2);
|
|
44
45
|
context.log.info(` ├─ ✔ done in ${durationSec}s`);
|
|
46
|
+
// determine desired state - null if marked for deletion
|
|
47
|
+
const desiredState = (0, del_1.isMarkedForDeletion)(resource) ? null : resource;
|
|
45
48
|
// compute change
|
|
46
49
|
const computed = (0, computeChange_1.computeChange)({
|
|
47
|
-
desired:
|
|
50
|
+
desired: desiredState,
|
|
48
51
|
remote: remoteState,
|
|
49
52
|
});
|
|
50
53
|
// log decision
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"planChanges.js","sourceRoot":"","sources":["../../../src/domain.operations/plan/planChanges.ts"],"names":[],"mappings":";;;AAAA,mDAA4E;AAI5E,8EAAiF;AACjF,0EAAuE;AAEvE,+DAA4D;AAC5D,+DAA4D;AAC5D,yDAAsD;AACtD,mDAAgD;AAChD,yDAAsD;AACtD,+CAA4C;AAE5C;;;;GAIG;AACI,MAAM,WAAW,GAAG,KAAK,EAC9B,KAIC,EACD,OAA6C,EACnB,EAAE;IAC5B,wBAAwB;IACxB,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAErB,kCAAkC;IAClC,MAAM,UAAU,GACd,QAAQ,IAAI,OAAO,CAAC,UAAU;QAC5B,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM;QAC3B,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC;IAEzB,0DAA0D;IAC1D,MAAM,OAAO,GAAG,EAAE,CAAC;IACnB,KAAK,MAAM,QAAQ,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACvC,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,KAAK,IAAI,EAAE;YAClD,kDAAkD;YAClD,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,eAAe,EAAE,GAAG,IAAA,mCAAgB,EAAC;gBACzD,QAAQ;gBACR,SAAS,EAAE,KAAK,CAAC,SAAS;aAC3B,CAAC,CAAC;YAEH,iCAAiC;YACjC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,IAAA,wCAAuB,EAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;YAE3D,iEAAiE;YACjE,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,MAAM,IAAA,yBAAW,EAAC;gBAC5D,OAAO,EAAE,UAAU;gBACnB,SAAS,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,eAAe,CAAC;aACjE,CAAC,CAAC;YAEH,8BAA8B;YAC9B,MAAM,WAAW,GAAG,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACnD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,mBAAmB,WAAW,GAAG,CAAC,CAAC;YAEpD,iBAAiB;YACjB,MAAM,QAAQ,GAAG,IAAA,6BAAa,EAAC;gBAC7B,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"planChanges.js","sourceRoot":"","sources":["../../../src/domain.operations/plan/planChanges.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,4 +9,4 @@ export declare const getRefByPrimary: <TResourceClass extends Refable<any, any,
|
|
|
9
9
|
ref: Ref<TResourceClass>;
|
|
10
10
|
}, context: {
|
|
11
11
|
dao: DeclastructDao<TResourceClass, TContext>;
|
|
12
|
-
} & TContext) => Promise<RefByPrimary<TResourceClass
|
|
12
|
+
} & TContext) => Promise<RefByPrimary<TResourceClass> | null>;
|
|
@@ -16,11 +16,9 @@ const getRefByPrimary = async (input, context) => {
|
|
|
16
16
|
if ((0, domain_objects_1.isRefByUnique)({ of: context.dao.dobj })(input.ref)) {
|
|
17
17
|
// fetch the resource by unique key
|
|
18
18
|
const resource = await context.dao.get.one.byUnique(input.ref, context);
|
|
19
|
-
//
|
|
19
|
+
// return null if resource not found (resource may not exist yet)
|
|
20
20
|
if (!resource)
|
|
21
|
-
|
|
22
|
-
ref: input.ref,
|
|
23
|
-
});
|
|
21
|
+
return null;
|
|
24
22
|
// extract primary key from the resource
|
|
25
23
|
return (0, domain_objects_1.refByPrimary)(resource);
|
|
26
24
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getRefByPrimary.js","sourceRoot":"","sources":["../../../src/domain.operations/ref/getRefByPrimary.ts"],"names":[],"mappings":";;;AAAA,mDAOwB;AACxB,
|
|
1
|
+
{"version":3,"file":"getRefByPrimary.js","sourceRoot":"","sources":["../../../src/domain.operations/ref/getRefByPrimary.ts"],"names":[],"mappings":";;;AAAA,mDAOwB;AACxB,mDAAyD;AAIzD;;;;GAIG;AACI,MAAM,eAAe,GAAG,KAAK,EAIlC,KAEC,EACD,OAEY,EACkC,EAAE;IAChD,wDAAwD;IACxD,IAAI,IAAA,+BAAc,EAAC,EAAE,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC;IAE1E,yDAAyD;IACzD,IAAI,IAAA,8BAAa,EAAC,EAAE,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACvD,mCAAmC;QACnC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAExE,iEAAiE;QACjE,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QAE3B,wCAAwC;QACxC,OAAO,IAAA,6BAAY,EAAiB,QAAQ,CAAC,CAAC;IAChD,CAAC;IAED,iCAAiC;IACjC,MAAM,IAAI,wCAAuB,CAAC,kBAAkB,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;AAC5E,CAAC,CAAC;AA5BW,QAAA,eAAe,mBA4B1B"}
|
|
@@ -9,4 +9,4 @@ export declare const getRefByUnique: <TResourceClass extends Refable<any, any, a
|
|
|
9
9
|
ref: Ref<TResourceClass>;
|
|
10
10
|
}, context: {
|
|
11
11
|
dao: DeclastructDao<TResourceClass, TContext>;
|
|
12
|
-
} & TContext) => Promise<RefByUnique<TResourceClass
|
|
12
|
+
} & TContext) => Promise<RefByUnique<TResourceClass> | null>;
|
|
@@ -19,11 +19,9 @@ const getRefByUnique = async (input, context) => {
|
|
|
19
19
|
throw new helpful_errors_1.UnexpectedCodePathError('dao does not support byPrimary lookup', { ref: input.ref });
|
|
20
20
|
// fetch the resource by primary key
|
|
21
21
|
const resource = await context.dao.get.one.byPrimary(input.ref, context);
|
|
22
|
-
//
|
|
22
|
+
// return null if resource not found (resource may not exist yet)
|
|
23
23
|
if (!resource)
|
|
24
|
-
|
|
25
|
-
ref: input.ref,
|
|
26
|
-
});
|
|
24
|
+
return null;
|
|
27
25
|
// extract unique key from the resource
|
|
28
26
|
return (0, domain_objects_1.refByUnique)(resource);
|
|
29
27
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getRefByUnique.js","sourceRoot":"","sources":["../../../src/domain.operations/ref/getRefByUnique.ts"],"names":[],"mappings":";;;AAAA,mDAOwB;AACxB,
|
|
1
|
+
{"version":3,"file":"getRefByUnique.js","sourceRoot":"","sources":["../../../src/domain.operations/ref/getRefByUnique.ts"],"names":[],"mappings":";;;AAAA,mDAOwB;AACxB,mDAAyD;AAIzD;;;;GAIG;AACI,MAAM,cAAc,GAAG,KAAK,EAIjC,KAEC,EACD,OAEY,EACiC,EAAE;IAC/C,uDAAuD;IACvD,IAAI,IAAA,8BAAa,EAAC,EAAE,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC;IAEzE,yDAAyD;IACzD,IAAI,IAAA,+BAAc,EAAC,EAAE,EAAE,EAAE,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACxD,gCAAgC;QAChC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS;YAChC,MAAM,IAAI,wCAAuB,CAC/B,uCAAuC,EACvC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CACnB,CAAC;QAEJ,oCAAoC;QACpC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAEzE,iEAAiE;QACjE,IAAI,CAAC,QAAQ;YAAE,OAAO,IAAI,CAAC;QAE3B,uCAAuC;QACvC,OAAO,IAAA,4BAAW,EAAiB,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED,iCAAiC;IACjC,MAAM,IAAI,wCAAuB,CAAC,kBAAkB,EAAE,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;AAC5E,CAAC,CAAC;AAnCW,QAAA,cAAc,kBAmCzB"}
|
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.
|
|
5
|
+
"version": "1.7.0",
|
|
6
6
|
"repository": "ehmpathy/declastruct",
|
|
7
7
|
"homepage": "https://github.com/ehmpathy/declastruct",
|
|
8
8
|
"keywords": [
|
|
@@ -28,9 +28,10 @@
|
|
|
28
28
|
"scripts": {
|
|
29
29
|
"build:ts": "tsc -p ./tsconfig.build.json",
|
|
30
30
|
"commit:with-cli": "npx cz",
|
|
31
|
-
"fix:format:biome": "biome check --write
|
|
31
|
+
"fix:format:biome": "biome check --write",
|
|
32
32
|
"fix:format": "npm run fix:format:biome",
|
|
33
|
-
"fix:lint": "biome check --write
|
|
33
|
+
"fix:lint": "biome check --write",
|
|
34
|
+
"fix": "npm run fix:format && npm run fix:lint",
|
|
34
35
|
"build:clean": "rm dist/ -rf",
|
|
35
36
|
"build:compile": "tsc -p ./tsconfig.build.json",
|
|
36
37
|
"build": "npm run build:clean && npm run build:compile",
|
|
@@ -38,9 +39,9 @@
|
|
|
38
39
|
"test:types": "tsc -p ./tsconfig.json --noEmit",
|
|
39
40
|
"test:format": "npm run test:format:biome",
|
|
40
41
|
"test:lint:deps": "npx depcheck -c ./.depcheckrc.yml",
|
|
41
|
-
"test:format:biome": "biome format
|
|
42
|
-
"test:lint:biome": "biome check
|
|
43
|
-
"test:lint:biome:all": "biome check
|
|
42
|
+
"test:format:biome": "biome format",
|
|
43
|
+
"test:lint:biome": "biome check --diagnostic-level=error",
|
|
44
|
+
"test:lint:biome:all": "biome check",
|
|
44
45
|
"test:lint": "npm run test:lint:biome && npm run test:lint:deps",
|
|
45
46
|
"test:unit": "jest -c ./jest.unit.config.ts --forceExit --verbose --passWithNoTests $([ -z $THOROUGH ] && echo '--changedSince=main')",
|
|
46
47
|
"test:integration": "jest -c ./jest.integration.config.ts --forceExit --verbose --passWithNoTests $([ -z $THOROUGH ] && echo '--changedSince=main')",
|
|
@@ -52,7 +53,7 @@
|
|
|
52
53
|
"preversion": "npm run prepush",
|
|
53
54
|
"postversion": "git push origin HEAD --tags --no-verify",
|
|
54
55
|
"prepare:husky": "npx husky install && chmod ug+x .husky/*",
|
|
55
|
-
"prepare": "[ -
|
|
56
|
+
"prepare": "[ -e .git ] && npm run prepare:husky || exit 0"
|
|
56
57
|
},
|
|
57
58
|
"dependencies": {
|
|
58
59
|
"bottleneck": "2.19.5",
|
|
@@ -60,6 +61,7 @@
|
|
|
60
61
|
"commander": "14.0.2",
|
|
61
62
|
"helpful-errors": "1.5.3",
|
|
62
63
|
"jest-diff": "30.0.2",
|
|
64
|
+
"rhachet-artifact-git": "1.1.3",
|
|
63
65
|
"simple-log-methods": "0.6.2",
|
|
64
66
|
"tsx": "4.20.6",
|
|
65
67
|
"type-fns": "1.21.0",
|
|
@@ -80,9 +82,9 @@
|
|
|
80
82
|
"@types/node": "22.15.29",
|
|
81
83
|
"cz-conventional-changelog": "3.3.0",
|
|
82
84
|
"declapract": "^0.13.0",
|
|
83
|
-
"declapract-typescript-ehmpathy": "
|
|
84
|
-
"declastruct": "
|
|
85
|
-
"declastruct-github": "
|
|
85
|
+
"declapract-typescript-ehmpathy": "0.43.16",
|
|
86
|
+
"declastruct": "1.5.1",
|
|
87
|
+
"declastruct-github": "1.0.7",
|
|
86
88
|
"depcheck": "1.4.3",
|
|
87
89
|
"esbuild-register": "3.6.0",
|
|
88
90
|
"husky": "8.0.3",
|
package/readme.md
CHANGED
|
@@ -270,3 +270,145 @@ each `DeclastructChange` includes:
|
|
|
270
270
|
## inspiration
|
|
271
271
|
|
|
272
272
|
inspired by Terraform's declarative approach, but designed to eliminate state file overhead, work with any resource construct, be reusable across both prod codepaths and cicd control, and leverage TypeScript's type system for safer declarative instructions.
|
|
273
|
+
|
|
274
|
+
|
|
275
|
+
# plugin
|
|
276
|
+
|
|
277
|
+
build your own provider to control any resource construct via declastruct.
|
|
278
|
+
|
|
279
|
+
## 1. declare your resource
|
|
280
|
+
|
|
281
|
+
define your resource as a [`domain-object`](https://github.com/ehmpathy/domain-objects) with key attributes:
|
|
282
|
+
|
|
283
|
+
```ts
|
|
284
|
+
import { DomainEntity } from 'domain-objects';
|
|
285
|
+
|
|
286
|
+
interface DeclaredStripeCustomer {
|
|
287
|
+
id?: string;
|
|
288
|
+
email: string;
|
|
289
|
+
name: string;
|
|
290
|
+
status?: string;
|
|
291
|
+
}
|
|
292
|
+
class DeclaredStripeCustomer
|
|
293
|
+
extends DomainEntity<DeclaredStripeCustomer>
|
|
294
|
+
implements DeclaredStripeCustomer
|
|
295
|
+
{
|
|
296
|
+
// primary key: the surrogate key identifier for this resource
|
|
297
|
+
public static primary = ['id'] as const;
|
|
298
|
+
|
|
299
|
+
// unique key: the natural key identifier for this resource (i.e., the non-primary unique key)
|
|
300
|
+
public static unique = ['email'] as const;
|
|
301
|
+
|
|
302
|
+
// metadata keys: readonly persistance-specific fields - excluded from change detection
|
|
303
|
+
// if unspecified, the defaults of 'id', 'uuid', 'createdAt', 'updatedAt', 'effectiveAt' will be assumed
|
|
304
|
+
public static metadata = ['id'] as const;
|
|
305
|
+
|
|
306
|
+
// readonly keys: readonly domain-intrinsic fields - excluded from change detection
|
|
307
|
+
// note: all metadata is implicitly readonly, so you only need to specify non-metadata readonly keys here
|
|
308
|
+
public static readonly = ['status'] as const;
|
|
309
|
+
}
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
key attributes to consider:
|
|
313
|
+
- **primary key** (`static primary`): surrogate identifier for efficient lookups after creation
|
|
314
|
+
- **unique key** (`static unique`): natural key that uniquely identifies the resource, used for idempotent operations
|
|
315
|
+
- **metadata keys** (`static metadata`): readonly persistence-layer fields that describe *how* the object is stored (e.g., `uuid`, `createdAt`). note, metadata is a specific subset of readonly
|
|
316
|
+
- **readonly keys** (`static readonly`): readonly domain-layer fields that describe *what* the object is (e.g., `status`). note, you only need to declare the readonly attributes that are not already flagged as metadata here
|
|
317
|
+
|
|
318
|
+
## 2. generate your dao
|
|
319
|
+
|
|
320
|
+
use `genDeclastructDao` to create a type-safe DAO with auto-wired ref resolution:
|
|
321
|
+
|
|
322
|
+
```ts
|
|
323
|
+
import { genDeclastructDao } from 'declastruct';
|
|
324
|
+
import Stripe from 'stripe';
|
|
325
|
+
|
|
326
|
+
// define the context type for your provider
|
|
327
|
+
interface StripeContext {
|
|
328
|
+
stripe: Stripe;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const daoStripeCustomer = genDeclastructDao<
|
|
332
|
+
typeof DeclaredStripeCustomer,
|
|
333
|
+
StripeContext
|
|
334
|
+
>({
|
|
335
|
+
dobj: DeclaredStripeCustomer,
|
|
336
|
+
get: {
|
|
337
|
+
one: {
|
|
338
|
+
byUnique: async ({ email }, context) => {
|
|
339
|
+
// lookup by natural key (email)
|
|
340
|
+
const customer = await context.stripe.customers.list({ email });
|
|
341
|
+
return customer.data[0] ? toResource(customer.data[0]) : null;
|
|
342
|
+
},
|
|
343
|
+
byPrimary: async ({ id }, context) => {
|
|
344
|
+
// lookup by stripe-assigned id
|
|
345
|
+
const customer = await context.stripe.customers.retrieve(id);
|
|
346
|
+
return customer ? toResource(customer) : null;
|
|
347
|
+
},
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
set: {
|
|
351
|
+
finsert: async (resource, context) => {
|
|
352
|
+
// find-or-insert: idempotent create
|
|
353
|
+
const foundBefore = await daoStripeCustomer.get.one.byUnique(
|
|
354
|
+
{ email: resource.email },
|
|
355
|
+
context,
|
|
356
|
+
);
|
|
357
|
+
if (foundBefore) return foundBefore;
|
|
358
|
+
|
|
359
|
+
const created = await context.stripe.customers.create({
|
|
360
|
+
email: resource.email,
|
|
361
|
+
name: resource.name,
|
|
362
|
+
});
|
|
363
|
+
return toResource(created);
|
|
364
|
+
},
|
|
365
|
+
upsert: async (resource, context) => {
|
|
366
|
+
// update-or-insert: idempotent update
|
|
367
|
+
const foundBefore = await daoStripeCustomer.get.one.byUnique(
|
|
368
|
+
{ email: resource.email },
|
|
369
|
+
context,
|
|
370
|
+
);
|
|
371
|
+
if (foundBefore) {
|
|
372
|
+
const updated = await context.stripe.customers.update(foundBefore.id, {
|
|
373
|
+
name: resource.name,
|
|
374
|
+
});
|
|
375
|
+
return toResource(updated);
|
|
376
|
+
}
|
|
377
|
+
return daoStripeCustomer.set.finsert(resource, context);
|
|
378
|
+
},
|
|
379
|
+
delete: async (ref, context) => {
|
|
380
|
+
const foundBefore = await daoStripeCustomer.get.one.byRef(ref, context);
|
|
381
|
+
if (foundBefore) await context.stripe.customers.del(foundBefore.id);
|
|
382
|
+
},
|
|
383
|
+
},
|
|
384
|
+
});
|
|
385
|
+
```
|
|
386
|
+
|
|
387
|
+
the factory automatically:
|
|
388
|
+
- **builds get.one.byRef**: `get.one.byRef` is built for you, based on `get.one.byUnique` and `get.one.byPrimary`
|
|
389
|
+
- **builds get.ref.byPrimary,.byUnique**: if `byPrimary` is defined, `get.ref.byPrimary` and `get.ref.byUnique` are built for you, based on `get.one.byUnique` and `get.one.byPrimary`
|
|
390
|
+
- **enforces type safety**: if `byPrimary` is null, `get.ref.*` are typed as null (prevents accidental calls)
|
|
391
|
+
|
|
392
|
+
## 3. create your provider
|
|
393
|
+
|
|
394
|
+
bundle your DAOs into a provider:
|
|
395
|
+
|
|
396
|
+
```ts
|
|
397
|
+
import { DeclastructProvider } from 'declastruct';
|
|
398
|
+
|
|
399
|
+
export const stripeProvider = new DeclastructProvider({
|
|
400
|
+
name: 'stripe',
|
|
401
|
+
daos: {
|
|
402
|
+
DeclaredStripeCustomer: daoStripeCustomer,
|
|
403
|
+
},
|
|
404
|
+
context: {
|
|
405
|
+
stripe, // stripe client instance
|
|
406
|
+
},
|
|
407
|
+
hooks: {
|
|
408
|
+
beforeAll: async () => { /* setup */ },
|
|
409
|
+
afterAll: async () => { /* cleanup */ },
|
|
410
|
+
},
|
|
411
|
+
});
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
now users can declare stripe customers and use `plan` + `apply` to control them declaratively.
|