declastruct 1.0.0 → 1.1.1
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/.test/assets/providers/demo.provider.d.ts +32 -0
- package/dist/.test/assets/providers/demo.provider.js +101 -0
- package/dist/.test/assets/providers/demo.provider.js.map +1 -0
- package/dist/contract/cli/apply.d.ts +9 -0
- package/dist/contract/cli/apply.integration.test.js +148 -0
- package/dist/contract/cli/apply.integration.test.js.map +1 -0
- package/dist/contract/cli/apply.js +90 -0
- package/dist/contract/cli/apply.js.map +1 -0
- package/dist/contract/cli/invoke.d.ts +8 -0
- package/dist/contract/cli/invoke.js +58 -0
- package/dist/contract/cli/invoke.js.map +1 -0
- package/dist/contract/cli/plan.d.ts +10 -0
- package/dist/contract/cli/plan.integration.test.js +107 -0
- package/dist/contract/cli/plan.integration.test.js.map +1 -0
- package/dist/contract/cli/plan.js +94 -0
- package/dist/contract/cli/plan.js.map +1 -0
- package/dist/contract/sdk/index.d.ts +15 -3
- package/dist/contract/sdk/index.js +31 -17
- package/dist/contract/sdk/index.js.map +1 -1
- package/dist/domain.objects/ContextDeclastruct.d.ts +15 -0
- package/dist/{domain/DeclastructContext.js → domain.objects/ContextDeclastruct.js} +1 -1
- package/dist/domain.objects/ContextDeclastruct.js.map +1 -0
- package/dist/domain.objects/ContextDeclastruct.test.js +41 -0
- package/dist/domain.objects/ContextDeclastruct.test.js.map +1 -0
- package/dist/domain.objects/DeclastructChange.d.ts +73 -0
- package/dist/domain.objects/DeclastructChange.js +35 -0
- package/dist/domain.objects/DeclastructChange.js.map +1 -0
- package/dist/domain.objects/DeclastructChange.test.js +59 -0
- package/dist/domain.objects/DeclastructChange.test.js.map +1 -0
- package/dist/domain.objects/DeclastructDao.d.ts +39 -0
- package/dist/domain.objects/DeclastructDao.js +8 -0
- package/dist/domain.objects/DeclastructDao.js.map +1 -0
- package/dist/domain.objects/DeclastructDao.test.js +42 -0
- package/dist/domain.objects/DeclastructDao.test.js.map +1 -0
- package/dist/domain.objects/DeclastructPlan.d.ts +35 -0
- package/dist/domain.objects/DeclastructPlan.js +11 -0
- package/dist/domain.objects/DeclastructPlan.js.map +1 -0
- package/dist/domain.objects/DeclastructPlan.test.js +31 -0
- package/dist/domain.objects/DeclastructPlan.test.js.map +1 -0
- package/dist/domain.objects/DeclastructProvider.d.ts +30 -0
- package/dist/domain.objects/DeclastructProvider.js +8 -0
- package/dist/domain.objects/DeclastructProvider.js.map +1 -0
- package/dist/domain.objects/DeclastructProvider.test.js +35 -0
- package/dist/domain.objects/DeclastructProvider.test.js.map +1 -0
- package/dist/domain.objects/IsoTimestamp.d.ts +6 -0
- package/dist/{domain/DeclaredResource.js → domain.objects/IsoTimestamp.js} +1 -1
- package/dist/domain.objects/IsoTimestamp.js.map +1 -0
- package/dist/domain.objects/IsoTimestamp.test.js +10 -0
- package/dist/domain.objects/IsoTimestamp.test.js.map +1 -0
- package/dist/domain.operations/apply/applyChange.d.ts +14 -0
- package/dist/domain.operations/apply/applyChange.js +64 -0
- package/dist/domain.operations/apply/applyChange.js.map +1 -0
- package/dist/domain.operations/apply/applyChange.test.d.ts +1 -0
- package/dist/domain.operations/apply/applyChange.test.js +247 -0
- package/dist/domain.operations/apply/applyChange.test.js.map +1 -0
- package/dist/domain.operations/apply/applyChanges.d.ts +18 -0
- package/dist/domain.operations/apply/applyChanges.integration.test.d.ts +1 -0
- package/dist/domain.operations/apply/applyChanges.integration.test.js +291 -0
- package/dist/domain.operations/apply/applyChanges.integration.test.js.map +1 -0
- package/dist/domain.operations/apply/applyChanges.js +53 -0
- package/dist/domain.operations/apply/applyChanges.js.map +1 -0
- package/dist/domain.operations/plan/computeChange.d.ts +11 -0
- package/dist/domain.operations/plan/computeChange.js +78 -0
- package/dist/domain.operations/plan/computeChange.js.map +1 -0
- package/dist/domain.operations/plan/computeChange.test.d.ts +1 -0
- package/dist/domain.operations/plan/computeChange.test.js +67 -0
- package/dist/domain.operations/plan/computeChange.test.js.map +1 -0
- package/dist/domain.operations/plan/extractResourcesFromPlan.d.ts +8 -0
- package/dist/domain.operations/plan/extractResourcesFromPlan.js +17 -0
- package/dist/domain.operations/plan/extractResourcesFromPlan.js.map +1 -0
- package/dist/domain.operations/plan/getDaoByResource.d.ts +12 -0
- package/dist/domain.operations/plan/getDaoByResource.js +41 -0
- package/dist/domain.operations/plan/getDaoByResource.js.map +1 -0
- package/dist/domain.operations/plan/getDaoByResource.test.d.ts +1 -0
- package/dist/domain.operations/plan/getDaoByResource.test.js +99 -0
- package/dist/domain.operations/plan/getDaoByResource.test.js.map +1 -0
- package/dist/domain.operations/plan/hashChanges.d.ts +7 -0
- package/dist/domain.operations/plan/hashChanges.js +18 -0
- package/dist/domain.operations/plan/hashChanges.js.map +1 -0
- package/dist/domain.operations/plan/planChanges.d.ts +15 -0
- package/dist/domain.operations/plan/planChanges.integration.test.d.ts +1 -0
- package/dist/domain.operations/plan/planChanges.integration.test.js +197 -0
- package/dist/domain.operations/plan/planChanges.integration.test.js.map +1 -0
- package/dist/domain.operations/plan/planChanges.js +50 -0
- package/dist/domain.operations/plan/planChanges.js.map +1 -0
- package/dist/domain.operations/plan/validate.d.ts +10 -0
- package/dist/domain.operations/plan/validate.js +21 -0
- package/dist/domain.operations/plan/validate.js.map +1 -0
- package/dist/infra/asIsoTimestamp.d.ts +6 -0
- package/dist/infra/asIsoTimestamp.js +12 -0
- package/dist/infra/asIsoTimestamp.js.map +1 -0
- package/package.json +8 -15
- package/readme.md +225 -29
- package/dist/__test_assets__/getExampleContext.d.ts +0 -33
- package/dist/__test_assets__/getExampleContext.js +0 -87
- package/dist/__test_assets__/getExampleContext.js.map +0 -1
- package/dist/contract/commands/command.apply.d.ts +0 -6
- package/dist/contract/commands/command.apply.js +0 -20
- package/dist/contract/commands/command.apply.js.map +0 -1
- package/dist/contract/commands/command.plan.d.ts +0 -6
- package/dist/contract/commands/command.plan.js +0 -20
- package/dist/contract/commands/command.plan.js.map +0 -1
- package/dist/contract/commands/utils/resolveCommandInputs.d.ts +0 -17
- package/dist/contract/commands/utils/resolveCommandInputs.js +0 -23
- package/dist/contract/commands/utils/resolveCommandInputs.js.map +0 -1
- package/dist/contract/sdk/refs.d.ts +0 -2
- package/dist/contract/sdk/refs.js +0 -19
- package/dist/contract/sdk/refs.js.map +0 -1
- package/dist/contract/sdk/sync/apply.d.ts +0 -22
- package/dist/contract/sdk/sync/apply.js +0 -29
- package/dist/contract/sdk/sync/apply.js.map +0 -1
- package/dist/contract/sdk/sync/plan.d.ts +0 -22
- package/dist/contract/sdk/sync/plan.js +0 -30
- package/dist/contract/sdk/sync/plan.js.map +0 -1
- package/dist/domain/DeclaredResource.d.ts +0 -2
- package/dist/domain/DeclaredResource.js.map +0 -1
- package/dist/domain/DeclaredResourceReference.d.ts +0 -66
- package/dist/domain/DeclaredResourceReference.js +0 -42
- package/dist/domain/DeclaredResourceReference.js.map +0 -1
- package/dist/domain/DeclastructChangeProposal.d.ts +0 -61
- package/dist/domain/DeclastructChangeProposal.js +0 -37
- package/dist/domain/DeclastructChangeProposal.js.map +0 -1
- package/dist/domain/DeclastructContext.d.ts +0 -24
- package/dist/domain/DeclastructContext.js.map +0 -1
- package/dist/domain/DeclastructProvider.d.ts +0 -58
- package/dist/domain/DeclastructProvider.js +0 -3
- package/dist/domain/DeclastructProvider.js.map +0 -1
- package/dist/domain/DeclastructProviderContext.d.ts +0 -30
- package/dist/domain/DeclastructProviderContext.js +0 -3
- package/dist/domain/DeclastructProviderContext.js.map +0 -1
- package/dist/domain/DeclastructProviderResourceRemoteStateInterface.d.ts +0 -156
- package/dist/domain/DeclastructProviderResourceRemoteStateInterface.js +0 -3
- package/dist/domain/DeclastructProviderResourceRemoteStateInterface.js.map +0 -1
- package/dist/logic/actions/execute/canUpdateResource.d.ts +0 -5
- package/dist/logic/actions/execute/canUpdateResource.js +0 -12
- package/dist/logic/actions/execute/canUpdateResource.js.map +0 -1
- package/dist/logic/actions/execute/executeProposal.d.ts +0 -5
- package/dist/logic/actions/execute/executeProposal.js +0 -52
- package/dist/logic/actions/execute/executeProposal.js.map +0 -1
- package/dist/logic/actions/propose/getColoredActionToken.d.ts +0 -4
- package/dist/logic/actions/propose/getColoredActionToken.js +0 -22
- package/dist/logic/actions/propose/getColoredActionToken.js.map +0 -1
- package/dist/logic/actions/propose/getColoredProposalTitle.d.ts +0 -4
- package/dist/logic/actions/propose/getColoredProposalTitle.js +0 -34
- package/dist/logic/actions/propose/getColoredProposalTitle.js.map +0 -1
- package/dist/logic/actions/propose/proposeChangeForResource.d.ts +0 -7
- package/dist/logic/actions/propose/proposeChangeForResource.js +0 -65
- package/dist/logic/actions/propose/proposeChangeForResource.js.map +0 -1
- package/dist/logic/actions/propose/proposeChangeForResource.test.js +0 -48
- package/dist/logic/actions/propose/proposeChangeForResource.test.js.map +0 -1
- package/dist/logic/commands/command.apply.d.ts +0 -8
- package/dist/logic/commands/command.apply.js +0 -77
- package/dist/logic/commands/command.apply.js.map +0 -1
- package/dist/logic/commands/command.plan.d.ts +0 -13
- package/dist/logic/commands/command.plan.js +0 -155
- package/dist/logic/commands/command.plan.js.map +0 -1
- package/dist/logic/commands/execute.d.ts +0 -15
- package/dist/logic/commands/execute.js +0 -63
- package/dist/logic/commands/execute.js.map +0 -1
- package/dist/logic/tools/compare/castReferenceToGrokableString.d.ts +0 -16
- package/dist/logic/tools/compare/castReferenceToGrokableString.js +0 -66
- package/dist/logic/tools/compare/castReferenceToGrokableString.js.map +0 -1
- package/dist/logic/tools/compare/castReferenceToGrokableString.test.js +0 -111
- package/dist/logic/tools/compare/castReferenceToGrokableString.test.js.map +0 -1
- package/dist/logic/tools/compare/detectDifferenceBetweenDesiredAndRemoteStateOfResource.d.ts +0 -11
- package/dist/logic/tools/compare/detectDifferenceBetweenDesiredAndRemoteStateOfResource.js +0 -61
- package/dist/logic/tools/compare/detectDifferenceBetweenDesiredAndRemoteStateOfResource.js.map +0 -1
- package/dist/logic/tools/compare/detectDifferenceBetweenDesiredAndRemoteStateOfResource.test.js +0 -31
- package/dist/logic/tools/compare/detectDifferenceBetweenDesiredAndRemoteStateOfResource.test.js.map +0 -1
- package/dist/logic/tools/compare/resolveReferenceToCommonComparableForm.d.ts +0 -21
- package/dist/logic/tools/compare/resolveReferenceToCommonComparableForm.js +0 -53
- package/dist/logic/tools/compare/resolveReferenceToCommonComparableForm.js.map +0 -1
- package/dist/logic/tools/compare/resolveReferenceToCommonComparableForm.test.js +0 -31
- package/dist/logic/tools/compare/resolveReferenceToCommonComparableForm.test.js.map +0 -1
- package/dist/logic/tools/compare/resolveReferencesToCommonComparableForm.d.ts +0 -10
- package/dist/logic/tools/compare/resolveReferencesToCommonComparableForm.js +0 -41
- package/dist/logic/tools/compare/resolveReferencesToCommonComparableForm.js.map +0 -1
- package/dist/logic/tools/compare/resolveReferencesToCommonComparableForm.test.js +0 -174
- package/dist/logic/tools/compare/resolveReferencesToCommonComparableForm.test.js.map +0 -1
- package/dist/logic/tools/context/createDeclastructContext.d.ts +0 -10
- package/dist/logic/tools/context/createDeclastructContext.js +0 -12
- package/dist/logic/tools/context/createDeclastructContext.js.map +0 -1
- package/dist/logic/tools/context/destroyDeclastructContext.d.ts +0 -4
- package/dist/logic/tools/context/destroyDeclastructContext.js +0 -10
- package/dist/logic/tools/context/destroyDeclastructContext.js.map +0 -1
- package/dist/logic/tools/provider/castProviderContextToGlobalContext.d.ts +0 -4
- package/dist/logic/tools/provider/castProviderContextToGlobalContext.js +0 -10
- package/dist/logic/tools/provider/castProviderContextToGlobalContext.js.map +0 -1
- package/dist/logic/tools/provider/getProviderContextFromGlobalContextForResourceClass.d.ts +0 -13
- package/dist/logic/tools/provider/getProviderContextFromGlobalContextForResourceClass.js +0 -29
- package/dist/logic/tools/provider/getProviderContextFromGlobalContextForResourceClass.js.map +0 -1
- package/dist/logic/tools/provider/getProviderResourceRemoteStateInterfaceExecutionDependenciesForResource.d.ts +0 -13
- package/dist/logic/tools/provider/getProviderResourceRemoteStateInterfaceExecutionDependenciesForResource.js +0 -24
- package/dist/logic/tools/provider/getProviderResourceRemoteStateInterfaceExecutionDependenciesForResource.js.map +0 -1
- package/dist/logic/tools/provider/getProviderResourceRemoteStateInterfaceFromContextForResourceClass.d.ts +0 -10
- package/dist/logic/tools/provider/getProviderResourceRemoteStateInterfaceFromContextForResourceClass.js +0 -21
- package/dist/logic/tools/provider/getProviderResourceRemoteStateInterfaceFromContextForResourceClass.js.map +0 -1
- package/dist/logic/tools/reference/buildPrimaryKeyTo.d.ts +0 -5
- package/dist/logic/tools/reference/buildPrimaryKeyTo.js +0 -40
- package/dist/logic/tools/reference/buildPrimaryKeyTo.js.map +0 -1
- package/dist/logic/tools/reference/buildReferenceTo.d.ts +0 -28
- package/dist/logic/tools/reference/buildReferenceTo.js +0 -92
- package/dist/logic/tools/reference/buildReferenceTo.js.map +0 -1
- package/dist/logic/tools/reference/buildReferenceTo.test.js +0 -119
- package/dist/logic/tools/reference/buildReferenceTo.test.js.map +0 -1
- package/dist/logic/tools/reference/buildUniqueKeyTo.d.ts +0 -5
- package/dist/logic/tools/reference/buildUniqueKeyTo.js +0 -40
- package/dist/logic/tools/reference/buildUniqueKeyTo.js.map +0 -1
- package/dist/logic/tools/reference/defineReferenceClassOf.d.ts +0 -5
- package/dist/logic/tools/reference/defineReferenceClassOf.js +0 -25
- package/dist/logic/tools/reference/defineReferenceClassOf.js.map +0 -1
- package/dist/logic/tools/reference/defineReferenceKeyConstituentsOf.d.ts +0 -13
- package/dist/logic/tools/reference/defineReferenceKeyConstituentsOf.js +0 -36
- package/dist/logic/tools/reference/defineReferenceKeyConstituentsOf.js.map +0 -1
- package/dist/logic/tools/reference/getByReference.d.ts +0 -15
- package/dist/logic/tools/reference/getByReference.js +0 -55
- package/dist/logic/tools/reference/getByReference.js.map +0 -1
- package/dist/logic/tools/reference/getByReference.test.js +0 -92
- package/dist/logic/tools/reference/getByReference.test.js.map +0 -1
- package/dist/logic/tools/reference/getByReferencedPrimaryKey.d.ts +0 -6
- package/dist/logic/tools/reference/getByReferencedPrimaryKey.js +0 -17
- package/dist/logic/tools/reference/getByReferencedPrimaryKey.js.map +0 -1
- package/dist/logic/tools/reference/getByReferencedUniqueKey.d.ts +0 -7
- package/dist/logic/tools/reference/getByReferencedUniqueKey.js +0 -42
- package/dist/logic/tools/reference/getByReferencedUniqueKey.js.map +0 -1
- package/dist/logic/tools/reference/getPrimaryKeyByReference.d.ts +0 -15
- package/dist/logic/tools/reference/getPrimaryKeyByReference.js +0 -36
- package/dist/logic/tools/reference/getPrimaryKeyByReference.js.map +0 -1
- package/dist/logic/tools/reference/getReferenceTo.d.ts +0 -18
- package/dist/logic/tools/reference/getReferenceTo.js +0 -55
- package/dist/logic/tools/reference/getReferenceTo.js.map +0 -1
- package/dist/logic/tools/reference/getReferenceTo.test.js +0 -95
- package/dist/logic/tools/reference/getReferenceTo.test.js.map +0 -1
- package/dist/logic/tools/reference/getUniqueKeyByReference.d.ts +0 -15
- package/dist/logic/tools/reference/getUniqueKeyByReference.js +0 -36
- package/dist/logic/tools/reference/getUniqueKeyByReference.js.map +0 -1
- package/dist/logic/tools/reference/isPrimaryKeyReference.d.ts +0 -6
- package/dist/logic/tools/reference/isPrimaryKeyReference.js +0 -7
- package/dist/logic/tools/reference/isPrimaryKeyReference.js.map +0 -1
- package/dist/logic/tools/reference/isUniqueKeyReference.d.ts +0 -6
- package/dist/logic/tools/reference/isUniqueKeyReference.js +0 -7
- package/dist/logic/tools/reference/isUniqueKeyReference.js.map +0 -1
- /package/dist/{logic/actions/propose/proposeChangeForResource.test.d.ts → contract/cli/apply.integration.test.d.ts} +0 -0
- /package/dist/{logic/tools/compare/castReferenceToGrokableString.test.d.ts → contract/cli/plan.integration.test.d.ts} +0 -0
- /package/dist/{logic/tools/compare/detectDifferenceBetweenDesiredAndRemoteStateOfResource.test.d.ts → domain.objects/ContextDeclastruct.test.d.ts} +0 -0
- /package/dist/{logic/tools/compare/resolveReferenceToCommonComparableForm.test.d.ts → domain.objects/DeclastructChange.test.d.ts} +0 -0
- /package/dist/{logic/tools/compare/resolveReferencesToCommonComparableForm.test.d.ts → domain.objects/DeclastructDao.test.d.ts} +0 -0
- /package/dist/{logic/tools/reference/buildReferenceTo.test.d.ts → domain.objects/DeclastructPlan.test.d.ts} +0 -0
- /package/dist/{logic/tools/reference/getByReference.test.d.ts → domain.objects/DeclastructProvider.test.d.ts} +0 -0
- /package/dist/{logic/tools/reference/getReferenceTo.test.d.ts → domain.objects/IsoTimestamp.test.d.ts} +0 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { DomainEntity } from 'domain-objects';
|
|
2
|
+
import { DeclastructDao } from '../../../domain.objects/DeclastructDao';
|
|
3
|
+
import { DeclastructProvider } from '../../../domain.objects/DeclastructProvider';
|
|
4
|
+
/**
|
|
5
|
+
* .what = demo resource for integration testing
|
|
6
|
+
*/
|
|
7
|
+
interface DemoResource {
|
|
8
|
+
exid: string;
|
|
9
|
+
name: string;
|
|
10
|
+
}
|
|
11
|
+
declare class DemoResource extends DomainEntity<DemoResource> implements DemoResource {
|
|
12
|
+
static unique: readonly ["exid"];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* .what = demo provider with on-disk persistence
|
|
16
|
+
* .why = enables full integration testing with real CRUD operations
|
|
17
|
+
*/
|
|
18
|
+
export declare const demoProvider: DeclastructProvider<{
|
|
19
|
+
DemoResource: DeclastructDao<DemoResource, typeof DemoResource, any>;
|
|
20
|
+
}, {}>;
|
|
21
|
+
/**
|
|
22
|
+
* .what = generates a sample DemoResource with automatic unique ID
|
|
23
|
+
* .why = simplifies test resource creation without managing IDs manually
|
|
24
|
+
* .note = use resource.clone({ name: 'New Name' }) to update properties while keeping same exid
|
|
25
|
+
*/
|
|
26
|
+
export declare const genSampleDemoResource: (input: {
|
|
27
|
+
name: string;
|
|
28
|
+
}) => import("domain-objects/dist/manipulation/immute/withImmute").WithImmute<DemoResource>;
|
|
29
|
+
/**
|
|
30
|
+
* .what = export DemoResource class for test usage
|
|
31
|
+
*/
|
|
32
|
+
export { DemoResource };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DemoResource = exports.genSampleDemoResource = exports.demoProvider = void 0;
|
|
4
|
+
const domain_objects_1 = require("domain-objects");
|
|
5
|
+
const fs_1 = require("fs");
|
|
6
|
+
const promises_1 = require("fs/promises");
|
|
7
|
+
const path_1 = require("path");
|
|
8
|
+
const uuid_fns_1 = require("uuid-fns");
|
|
9
|
+
const DeclastructProvider_1 = require("../../../domain.objects/DeclastructProvider");
|
|
10
|
+
class DemoResource extends domain_objects_1.DomainEntity {
|
|
11
|
+
}
|
|
12
|
+
exports.DemoResource = DemoResource;
|
|
13
|
+
DemoResource.unique = ['exid'];
|
|
14
|
+
/**
|
|
15
|
+
* .what = resolves file path for a resource on disk
|
|
16
|
+
* .why = centralizes file naming logic
|
|
17
|
+
*/
|
|
18
|
+
const getResourceFilePath = (id) => {
|
|
19
|
+
return (0, path_1.resolve)(process.cwd(), `.test/demo/provider/.temp/${id}.json`);
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* .what = demo DAO with on-disk JSON persistence
|
|
23
|
+
* .why = provides real persistence for integration tests
|
|
24
|
+
*/
|
|
25
|
+
const demoDao = {
|
|
26
|
+
get: {
|
|
27
|
+
byUnique: async (input) => {
|
|
28
|
+
const filePath = getResourceFilePath(input.exid);
|
|
29
|
+
// check if file exists
|
|
30
|
+
if (!(0, fs_1.existsSync)(filePath))
|
|
31
|
+
return null;
|
|
32
|
+
// read and parse file
|
|
33
|
+
const json = await (0, promises_1.readFile)(filePath, 'utf-8');
|
|
34
|
+
const data = JSON.parse(json);
|
|
35
|
+
return DemoResource.as(data);
|
|
36
|
+
},
|
|
37
|
+
byRef: async (ref) => {
|
|
38
|
+
// extract exid from ref
|
|
39
|
+
const exid = ref.exid;
|
|
40
|
+
if (!exid)
|
|
41
|
+
return null;
|
|
42
|
+
return demoDao.get.byUnique({ exid }, {});
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
set: {
|
|
46
|
+
finsert: async (resource) => {
|
|
47
|
+
const filePath = getResourceFilePath(resource.exid);
|
|
48
|
+
// write resource to disk
|
|
49
|
+
await (0, promises_1.writeFile)(filePath, JSON.stringify(resource, null, 2), 'utf-8');
|
|
50
|
+
return resource;
|
|
51
|
+
},
|
|
52
|
+
upsert: async (resource) => {
|
|
53
|
+
const filePath = getResourceFilePath(resource.exid);
|
|
54
|
+
// write resource to disk (overwrite if exists)
|
|
55
|
+
await (0, promises_1.writeFile)(filePath, JSON.stringify(resource, null, 2), 'utf-8');
|
|
56
|
+
return resource;
|
|
57
|
+
},
|
|
58
|
+
delete: async (ref) => {
|
|
59
|
+
const resource = await demoDao.get.byRef(ref, {});
|
|
60
|
+
if (!resource)
|
|
61
|
+
return;
|
|
62
|
+
const filePath = getResourceFilePath(resource.exid);
|
|
63
|
+
// remove file if it exists
|
|
64
|
+
if ((0, fs_1.existsSync)(filePath)) {
|
|
65
|
+
await (0, promises_1.rm)(filePath);
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* .what = demo provider with on-disk persistence
|
|
72
|
+
* .why = enables full integration testing with real CRUD operations
|
|
73
|
+
*/
|
|
74
|
+
exports.demoProvider = new DeclastructProvider_1.DeclastructProvider({
|
|
75
|
+
name: 'demo-provider',
|
|
76
|
+
daos: { DemoResource: demoDao },
|
|
77
|
+
context: {},
|
|
78
|
+
hooks: {
|
|
79
|
+
beforeAll: async () => {
|
|
80
|
+
// ensure temp directory exists
|
|
81
|
+
const tempDir = (0, path_1.resolve)(process.cwd(), '.test/demo/provider/.temp');
|
|
82
|
+
if (!(0, fs_1.existsSync)(tempDir)) {
|
|
83
|
+
await (0, promises_1.mkdir)(tempDir, { recursive: true });
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
afterAll: async () => { },
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
/**
|
|
90
|
+
* .what = generates a sample DemoResource with automatic unique ID
|
|
91
|
+
* .why = simplifies test resource creation without managing IDs manually
|
|
92
|
+
* .note = use resource.clone({ name: 'New Name' }) to update properties while keeping same exid
|
|
93
|
+
*/
|
|
94
|
+
const genSampleDemoResource = (input) => {
|
|
95
|
+
return DemoResource.as({
|
|
96
|
+
exid: (0, uuid_fns_1.getUuid)(),
|
|
97
|
+
name: input.name,
|
|
98
|
+
});
|
|
99
|
+
};
|
|
100
|
+
exports.genSampleDemoResource = genSampleDemoResource;
|
|
101
|
+
//# sourceMappingURL=demo.provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"demo.provider.js","sourceRoot":"","sources":["../../../../src/.test/assets/providers/demo.provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* .what = executes the apply command to apply an infrastructure change plan
|
|
4
|
+
* .why = provides CLI interface for applying infrastructure changes
|
|
5
|
+
* .note = loads plan from file and wish file from plan.wish.uri
|
|
6
|
+
*/
|
|
7
|
+
export declare const executeApplyCommand: ({ planFilePath, }: {
|
|
8
|
+
planFilePath: string;
|
|
9
|
+
}) => Promise<void>;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const fs_1 = require("fs");
|
|
4
|
+
const promises_1 = require("fs/promises");
|
|
5
|
+
const path_1 = require("path");
|
|
6
|
+
const uuid_fns_1 = require("uuid-fns");
|
|
7
|
+
const DeclastructPlan_1 = require("../../domain.objects/DeclastructPlan");
|
|
8
|
+
const apply_1 = require("./apply");
|
|
9
|
+
const plan_1 = require("./plan");
|
|
10
|
+
/**
|
|
11
|
+
* .what = creates an isolated wish file for a test
|
|
12
|
+
* .why = ensures stable resources within a single test while maintaining test isolation
|
|
13
|
+
*/
|
|
14
|
+
const createIsolatedWishFile = async () => {
|
|
15
|
+
const tempDir = (0, path_1.resolve)(process.cwd(), '.test/.temp');
|
|
16
|
+
const wishPath = (0, path_1.resolve)(tempDir, `wish-${(0, uuid_fns_1.getUuid)()}.ts`);
|
|
17
|
+
// ensure temp directory exists
|
|
18
|
+
if (!(0, fs_1.existsSync)(tempDir)) {
|
|
19
|
+
await (0, promises_1.mkdir)(tempDir, { recursive: true });
|
|
20
|
+
}
|
|
21
|
+
const exid1 = (0, uuid_fns_1.getUuid)();
|
|
22
|
+
const exid2 = (0, uuid_fns_1.getUuid)();
|
|
23
|
+
const wishContent = `
|
|
24
|
+
import { DomainEntity } from 'domain-objects';
|
|
25
|
+
import { DeclastructProvider } from '../../src/domain.objects/DeclastructProvider';
|
|
26
|
+
import { DemoResource, demoProvider } from '../../src/.test/assets/providers/demo.provider';
|
|
27
|
+
|
|
28
|
+
export const getResources = async (): Promise<DomainEntity<any>[]> => {
|
|
29
|
+
return [
|
|
30
|
+
DemoResource.as({ exid: '${exid1}', name: 'First Resource' }),
|
|
31
|
+
DemoResource.as({ exid: '${exid2}', name: 'Second Resource' }),
|
|
32
|
+
];
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const getProviders = async (): Promise<DeclastructProvider<any, any>[]> => {
|
|
36
|
+
return [demoProvider];
|
|
37
|
+
};
|
|
38
|
+
`;
|
|
39
|
+
await (0, promises_1.writeFile)(wishPath, wishContent, 'utf-8');
|
|
40
|
+
return wishPath;
|
|
41
|
+
};
|
|
42
|
+
describe('executeApplyCommand', () => {
|
|
43
|
+
const planFilePath = (0, path_1.resolve)(process.cwd(), 'src/.test/assets/apply.test.json');
|
|
44
|
+
afterEach(async () => {
|
|
45
|
+
// cleanup plan file after each test
|
|
46
|
+
if ((0, fs_1.existsSync)(planFilePath)) {
|
|
47
|
+
await (0, promises_1.rm)(planFilePath);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
it('should apply changes from a valid plan file', async () => {
|
|
51
|
+
// create isolated wish file for this test
|
|
52
|
+
const wishFilePath = await createIsolatedWishFile();
|
|
53
|
+
// first generate a plan
|
|
54
|
+
await (0, plan_1.executePlanCommand)({ wishFilePath, planFilePath });
|
|
55
|
+
// verify plan was created
|
|
56
|
+
expect((0, fs_1.existsSync)(planFilePath)).toBe(true);
|
|
57
|
+
// now apply the plan
|
|
58
|
+
await (0, apply_1.executeApplyCommand)({ planFilePath });
|
|
59
|
+
// verify plan still exists after apply
|
|
60
|
+
expect((0, fs_1.existsSync)(planFilePath)).toBe(true);
|
|
61
|
+
// read plan to verify structure
|
|
62
|
+
const planJson = await (0, promises_1.readFile)(planFilePath, 'utf-8');
|
|
63
|
+
const plan = new DeclastructPlan_1.DeclastructPlan(JSON.parse(planJson));
|
|
64
|
+
// verify plan has changes
|
|
65
|
+
expect(plan.changes.length).toBe(2);
|
|
66
|
+
});
|
|
67
|
+
it('should throw when plan file does not exist', async () => {
|
|
68
|
+
const nonexistentPlanPath = (0, path_1.resolve)(__dirname, 'nonexistent-plan.json');
|
|
69
|
+
await expect((0, apply_1.executeApplyCommand)({ planFilePath: nonexistentPlanPath })).rejects.toThrow('Plan file not found');
|
|
70
|
+
});
|
|
71
|
+
it('should throw when wish file referenced in plan does not exist', async () => {
|
|
72
|
+
// create plan with invalid wish path
|
|
73
|
+
const invalidPlan = {
|
|
74
|
+
hash: 'test-hash',
|
|
75
|
+
createdAt: new Date().toISOString(),
|
|
76
|
+
wish: { uri: '/nonexistent/wish.ts' },
|
|
77
|
+
changes: [],
|
|
78
|
+
};
|
|
79
|
+
await (0, promises_1.writeFile)(planFilePath, JSON.stringify(invalidPlan, null, 2));
|
|
80
|
+
await expect((0, apply_1.executeApplyCommand)({ planFilePath })).rejects.toThrow();
|
|
81
|
+
});
|
|
82
|
+
it('should throw when wish file does not export getProviders', async () => {
|
|
83
|
+
const badWishPath = (0, path_1.resolve)(process.cwd(), 'src/.test/assets/bad-apply-wish.ts');
|
|
84
|
+
// create bad wish file
|
|
85
|
+
await (0, promises_1.writeFile)(badWishPath, 'export const foo = "bar";', 'utf-8');
|
|
86
|
+
// create plan pointing to bad wish
|
|
87
|
+
const invalidPlan = {
|
|
88
|
+
hash: 'test-hash',
|
|
89
|
+
createdAt: new Date().toISOString(),
|
|
90
|
+
wish: { uri: badWishPath },
|
|
91
|
+
changes: [],
|
|
92
|
+
};
|
|
93
|
+
await (0, promises_1.writeFile)(planFilePath, JSON.stringify(invalidPlan, null, 2));
|
|
94
|
+
await expect((0, apply_1.executeApplyCommand)({ planFilePath })).rejects.toThrow('Wish file must export getProviders() function');
|
|
95
|
+
// cleanup
|
|
96
|
+
await (0, promises_1.rm)(badWishPath);
|
|
97
|
+
});
|
|
98
|
+
it('should successfully apply multiple CREATE actions', async () => {
|
|
99
|
+
// create isolated wish file for this test
|
|
100
|
+
const wishFilePath = await createIsolatedWishFile();
|
|
101
|
+
// generate plan
|
|
102
|
+
await (0, plan_1.executePlanCommand)({ wishFilePath, planFilePath });
|
|
103
|
+
// spy on console to verify logging
|
|
104
|
+
const logSpy = jest.spyOn(console, 'info');
|
|
105
|
+
// apply changes
|
|
106
|
+
await (0, apply_1.executeApplyCommand)({ planFilePath });
|
|
107
|
+
// verify success logging occurred
|
|
108
|
+
const logCalls = logSpy.mock.calls.map((call) => call.join(' '));
|
|
109
|
+
const successLogs = logCalls.filter((log) => log.includes('✔'));
|
|
110
|
+
// should have logged success for each CREATE action
|
|
111
|
+
expect(successLogs.length).toBeGreaterThan(0);
|
|
112
|
+
// cleanup spy
|
|
113
|
+
logSpy.mockRestore();
|
|
114
|
+
});
|
|
115
|
+
it('should handle KEEP actions without errors', async () => {
|
|
116
|
+
// create isolated wish file for this test
|
|
117
|
+
const wishFilePath = await createIsolatedWishFile();
|
|
118
|
+
// generate initial plan
|
|
119
|
+
await (0, plan_1.executePlanCommand)({ wishFilePath, planFilePath });
|
|
120
|
+
// apply changes
|
|
121
|
+
await (0, apply_1.executeApplyCommand)({ planFilePath });
|
|
122
|
+
// generate new plan (should now show KEEP actions)
|
|
123
|
+
await (0, promises_1.rm)(planFilePath);
|
|
124
|
+
await (0, plan_1.executePlanCommand)({ wishFilePath, planFilePath });
|
|
125
|
+
// read new plan
|
|
126
|
+
const planJson = await (0, promises_1.readFile)(planFilePath, 'utf-8');
|
|
127
|
+
const plan = new DeclastructPlan_1.DeclastructPlan(JSON.parse(planJson));
|
|
128
|
+
// verify we have KEEP actions
|
|
129
|
+
const keepActions = plan.changes.filter((c) => c.action === 'KEEP');
|
|
130
|
+
expect(keepActions.length).toBe(2);
|
|
131
|
+
// apply again (should handle KEEP without errors)
|
|
132
|
+
await (0, apply_1.executeApplyCommand)({ planFilePath });
|
|
133
|
+
});
|
|
134
|
+
it('should throw when plan is stale', async () => {
|
|
135
|
+
// create isolated wish file for this test
|
|
136
|
+
const wishFilePath = await createIsolatedWishFile();
|
|
137
|
+
// generate initial plan
|
|
138
|
+
await (0, plan_1.executePlanCommand)({ wishFilePath, planFilePath });
|
|
139
|
+
// modify the plan's hash to make it stale
|
|
140
|
+
const planJson = await (0, promises_1.readFile)(planFilePath, 'utf-8');
|
|
141
|
+
const plan = JSON.parse(planJson);
|
|
142
|
+
plan.hash = 'stale-hash-that-wont-match';
|
|
143
|
+
await (0, promises_1.writeFile)(planFilePath, JSON.stringify(plan, null, 2));
|
|
144
|
+
// applying stale plan should throw
|
|
145
|
+
await expect((0, apply_1.executeApplyCommand)({ planFilePath })).rejects.toThrow('plan is stale');
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
//# sourceMappingURL=apply.integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.integration.test.js","sourceRoot":"","sources":["../../../src/contract/cli/apply.integration.test.ts"],"names":[],"mappings":";;AAAA,2BAAgC;AAChC,0CAA6D;AAC7D,+BAA+B;AAC/B,uCAAmC;AAEnC,0EAAuE;AACvE,mCAA8C;AAC9C,iCAA4C;AAE5C;;;GAGG;AACH,MAAM,sBAAsB,GAAG,KAAK,IAAqB,EAAE;IACzD,MAAM,OAAO,GAAG,IAAA,cAAO,EAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,CAAC,CAAC;IACtD,MAAM,QAAQ,GAAG,IAAA,cAAO,EAAC,OAAO,EAAE,QAAQ,IAAA,kBAAO,GAAE,KAAK,CAAC,CAAC;IAE1D,+BAA+B;IAC/B,IAAI,CAAC,IAAA,eAAU,EAAC,OAAO,CAAC,EAAE,CAAC;QACzB,MAAM,IAAA,gBAAK,EAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC5C,CAAC;IAED,MAAM,KAAK,GAAG,IAAA,kBAAO,GAAE,CAAC;IACxB,MAAM,KAAK,GAAG,IAAA,kBAAO,GAAE,CAAC;IAExB,MAAM,WAAW,GAAG;;;;;;;+BAOS,KAAK;+BACL,KAAK;;;;;;;CAOnC,CAAC;IAEA,MAAM,IAAA,oBAAS,EAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC,CAAC;IAChD,OAAO,QAAQ,CAAC;AAClB,CAAC,CAAC;AAEF,QAAQ,CAAC,qBAAqB,EAAE,GAAG,EAAE;IACnC,MAAM,YAAY,GAAG,IAAA,cAAO,EAC1B,OAAO,CAAC,GAAG,EAAE,EACb,kCAAkC,CACnC,CAAC;IAEF,SAAS,CAAC,KAAK,IAAI,EAAE;QACnB,oCAAoC;QACpC,IAAI,IAAA,eAAU,EAAC,YAAY,CAAC,EAAE,CAAC;YAC7B,MAAM,IAAA,aAAE,EAAC,YAAY,CAAC,CAAC;QACzB,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,6CAA6C,EAAE,KAAK,IAAI,EAAE;QAC3D,0CAA0C;QAC1C,MAAM,YAAY,GAAG,MAAM,sBAAsB,EAAE,CAAC;QAEpD,wBAAwB;QACxB,MAAM,IAAA,yBAAkB,EAAC,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC,CAAC;QAEzD,0BAA0B;QAC1B,MAAM,CAAC,IAAA,eAAU,EAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE5C,qBAAqB;QACrB,MAAM,IAAA,2BAAmB,EAAC,EAAE,YAAY,EAAE,CAAC,CAAC;QAE5C,uCAAuC;QACvC,MAAM,CAAC,IAAA,eAAU,EAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAE5C,gCAAgC;QAChC,MAAM,QAAQ,GAAG,MAAM,IAAA,mBAAQ,EAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,IAAI,iCAAe,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;QAEvD,0BAA0B;QAC1B,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,KAAK,IAAI,EAAE;QAC1D,MAAM,mBAAmB,GAAG,IAAA,cAAO,EAAC,SAAS,EAAE,uBAAuB,CAAC,CAAC;QAExE,MAAM,MAAM,CACV,IAAA,2BAAmB,EAAC,EAAE,YAAY,EAAE,mBAAmB,EAAE,CAAC,CAC3D,CAAC,OAAO,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+DAA+D,EAAE,KAAK,IAAI,EAAE;QAC7E,qCAAqC;QACrC,MAAM,WAAW,GAAG;YAClB,IAAI,EAAE,WAAW;YACjB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,IAAI,EAAE,EAAE,GAAG,EAAE,sBAAsB,EAAE;YACrC,OAAO,EAAE,EAAE;SACZ,CAAC;QAEF,MAAM,IAAA,oBAAS,EAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAEpE,MAAM,MAAM,CAAC,IAAA,2BAAmB,EAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IACxE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,WAAW,GAAG,IAAA,cAAO,EACzB,OAAO,CAAC,GAAG,EAAE,EACb,oCAAoC,CACrC,CAAC;QAEF,uBAAuB;QACvB,MAAM,IAAA,oBAAS,EAAC,WAAW,EAAE,2BAA2B,EAAE,OAAO,CAAC,CAAC;QAEnE,mCAAmC;QACnC,MAAM,WAAW,GAAG;YAClB,IAAI,EAAE,WAAW;YACjB,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;YACnC,IAAI,EAAE,EAAE,GAAG,EAAE,WAAW,EAAE;YAC1B,OAAO,EAAE,EAAE;SACZ,CAAC;QAEF,MAAM,IAAA,oBAAS,EAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAEpE,MAAM,MAAM,CAAC,IAAA,2BAAmB,EAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CACjE,+CAA+C,CAChD,CAAC;QAEF,UAAU;QACV,MAAM,IAAA,aAAE,EAAC,WAAW,CAAC,CAAC;IACxB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;QACjE,0CAA0C;QAC1C,MAAM,YAAY,GAAG,MAAM,sBAAsB,EAAE,CAAC;QAEpD,gBAAgB;QAChB,MAAM,IAAA,yBAAkB,EAAC,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC,CAAC;QAEzD,mCAAmC;QACnC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAE3C,gBAAgB;QAChB,MAAM,IAAA,2BAAmB,EAAC,EAAE,YAAY,EAAE,CAAC,CAAC;QAE5C,kCAAkC;QAClC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACjE,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;QAEhE,oDAAoD;QACpD,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAE9C,cAAc;QACd,MAAM,CAAC,WAAW,EAAE,CAAC;IACvB,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,2CAA2C,EAAE,KAAK,IAAI,EAAE;QACzD,0CAA0C;QAC1C,MAAM,YAAY,GAAG,MAAM,sBAAsB,EAAE,CAAC;QAEpD,wBAAwB;QACxB,MAAM,IAAA,yBAAkB,EAAC,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC,CAAC;QAEzD,gBAAgB;QAChB,MAAM,IAAA,2BAAmB,EAAC,EAAE,YAAY,EAAE,CAAC,CAAC;QAE5C,mDAAmD;QACnD,MAAM,IAAA,aAAE,EAAC,YAAY,CAAC,CAAC;QACvB,MAAM,IAAA,yBAAkB,EAAC,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC,CAAC;QAEzD,gBAAgB;QAChB,MAAM,QAAQ,GAAG,MAAM,IAAA,mBAAQ,EAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,IAAI,iCAAe,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;QAEvD,8BAA8B;QAC9B,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;QACpE,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAEnC,kDAAkD;QAClD,MAAM,IAAA,2BAAmB,EAAC,EAAE,YAAY,EAAE,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,KAAK,IAAI,EAAE;QAC/C,0CAA0C;QAC1C,MAAM,YAAY,GAAG,MAAM,sBAAsB,EAAE,CAAC;QAEpD,wBAAwB;QACxB,MAAM,IAAA,yBAAkB,EAAC,EAAE,YAAY,EAAE,YAAY,EAAE,CAAC,CAAC;QAEzD,0CAA0C;QAC1C,MAAM,QAAQ,GAAG,MAAM,IAAA,mBAAQ,EAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACvD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAClC,IAAI,CAAC,IAAI,GAAG,4BAA4B,CAAC;QAEzC,MAAM,IAAA,oBAAS,EAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAE7D,mCAAmC;QACnC,MAAM,MAAM,CAAC,IAAA,2BAAmB,EAAC,EAAE,YAAY,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CACjE,eAAe,CAChB,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
"use strict";
|
|
3
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
4
|
+
if (k2 === undefined) k2 = k;
|
|
5
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
6
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
7
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
8
|
+
}
|
|
9
|
+
Object.defineProperty(o, k2, desc);
|
|
10
|
+
}) : (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
o[k2] = m[k];
|
|
13
|
+
}));
|
|
14
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
15
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
16
|
+
}) : function(o, v) {
|
|
17
|
+
o["default"] = v;
|
|
18
|
+
});
|
|
19
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
20
|
+
if (mod && mod.__esModule) return mod;
|
|
21
|
+
var result = {};
|
|
22
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
23
|
+
__setModuleDefault(result, mod);
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
26
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
27
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
28
|
+
};
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.executeApplyCommand = void 0;
|
|
31
|
+
const bottleneck_1 = __importDefault(require("bottleneck"));
|
|
32
|
+
const fs_1 = require("fs");
|
|
33
|
+
const promises_1 = require("fs/promises");
|
|
34
|
+
const helpful_errors_1 = require("helpful-errors");
|
|
35
|
+
const path_1 = require("path");
|
|
36
|
+
const DeclastructPlan_1 = require("../../domain.objects/DeclastructPlan");
|
|
37
|
+
const applyChanges_1 = require("../../domain.operations/apply/applyChanges");
|
|
38
|
+
const log = console;
|
|
39
|
+
/**
|
|
40
|
+
* .what = executes the apply command to apply an infrastructure change plan
|
|
41
|
+
* .why = provides CLI interface for applying infrastructure changes
|
|
42
|
+
* .note = loads plan from file and wish file from plan.wish.uri
|
|
43
|
+
*/
|
|
44
|
+
const executeApplyCommand = async ({ planFilePath, }) => {
|
|
45
|
+
// resolve path
|
|
46
|
+
const resolvedPlanPath = (0, path_1.resolve)(process.cwd(), planFilePath);
|
|
47
|
+
// validate plan file exists
|
|
48
|
+
if (!(0, fs_1.existsSync)(resolvedPlanPath)) {
|
|
49
|
+
throw new helpful_errors_1.BadRequestError(`Plan file not found: ${resolvedPlanPath}`);
|
|
50
|
+
}
|
|
51
|
+
log.info('🌊 declastruct apply');
|
|
52
|
+
log.info(` plan: ${resolvedPlanPath}`);
|
|
53
|
+
log.info('');
|
|
54
|
+
// load plan from file
|
|
55
|
+
const planJson = await (0, promises_1.readFile)(resolvedPlanPath, 'utf-8');
|
|
56
|
+
const plan = new DeclastructPlan_1.DeclastructPlan(JSON.parse(planJson));
|
|
57
|
+
// import wish file from plan
|
|
58
|
+
const wishPath = plan.wish.uri;
|
|
59
|
+
const wish = await Promise.resolve(`${wishPath}`).then(s => __importStar(require(s)));
|
|
60
|
+
// validate exports
|
|
61
|
+
if (typeof wish.getProviders !== 'function') {
|
|
62
|
+
throw new helpful_errors_1.BadRequestError('Wish file must export getProviders() function');
|
|
63
|
+
}
|
|
64
|
+
if (typeof wish.getResources !== 'function') {
|
|
65
|
+
throw new helpful_errors_1.BadRequestError('Wish file must export getResources() function');
|
|
66
|
+
}
|
|
67
|
+
// get resources and providers from wish file
|
|
68
|
+
const resources = await wish.getResources();
|
|
69
|
+
const providers = await wish.getProviders();
|
|
70
|
+
// initialize providers
|
|
71
|
+
log.info('✨ start providers...');
|
|
72
|
+
await Promise.all(providers.map((p) => p.hooks.beforeAll()));
|
|
73
|
+
// create context
|
|
74
|
+
const context = {
|
|
75
|
+
bottleneck: new bottleneck_1.default({ maxConcurrent: 1 }),
|
|
76
|
+
log,
|
|
77
|
+
};
|
|
78
|
+
// apply changes (logs emitted in real-time by applyChanges)
|
|
79
|
+
log.info('🪄 apply changes...');
|
|
80
|
+
log.info('');
|
|
81
|
+
const result = await (0, applyChanges_1.applyChanges)({ plan, resources, providers }, context);
|
|
82
|
+
// cleanup providers
|
|
83
|
+
log.info('✨ stop providers...');
|
|
84
|
+
await Promise.all(providers.map((p) => p.hooks.afterAll()));
|
|
85
|
+
// log summary
|
|
86
|
+
log.info('');
|
|
87
|
+
log.info(`🌊 applied ${result.appliedChanges.length} changes`);
|
|
88
|
+
};
|
|
89
|
+
exports.executeApplyCommand = executeApplyCommand;
|
|
90
|
+
//# sourceMappingURL=apply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"apply.js","sourceRoot":"","sources":["../../../src/contract/cli/apply.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* .what = invokes CLI commands based on user input
|
|
3
|
+
* .why = provides global entry point for declastruct CLI
|
|
4
|
+
* .note = uses commander for argument parsing and help text
|
|
5
|
+
*/
|
|
6
|
+
export declare const invoke: ({ args }: {
|
|
7
|
+
args: string[];
|
|
8
|
+
}) => Promise<void>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.invoke = void 0;
|
|
7
|
+
const commander_1 = require("commander");
|
|
8
|
+
const package_json_1 = __importDefault(require("../../../package.json"));
|
|
9
|
+
const apply_1 = require("./apply");
|
|
10
|
+
const plan_1 = require("./plan");
|
|
11
|
+
const log = console;
|
|
12
|
+
/**
|
|
13
|
+
* .what = invokes CLI commands based on user input
|
|
14
|
+
* .why = provides global entry point for declastruct CLI
|
|
15
|
+
* .note = uses commander for argument parsing and help text
|
|
16
|
+
*/
|
|
17
|
+
const invoke = async ({ args }) => {
|
|
18
|
+
const program = new commander_1.Command();
|
|
19
|
+
program
|
|
20
|
+
.name('declastruct')
|
|
21
|
+
.description('Declarative resource structure control')
|
|
22
|
+
.version(package_json_1.default.version);
|
|
23
|
+
program
|
|
24
|
+
.command('plan')
|
|
25
|
+
.description('Generate a change plan from a wish file')
|
|
26
|
+
.requiredOption('--wish <file>', 'Path to wish file')
|
|
27
|
+
.requiredOption('--into <file>', 'Path to output plan file')
|
|
28
|
+
.action(async (options) => {
|
|
29
|
+
try {
|
|
30
|
+
await (0, plan_1.executePlanCommand)({
|
|
31
|
+
wishFilePath: options.wish,
|
|
32
|
+
planFilePath: options.into,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
log.error('✖ Error during plan:', error);
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
program
|
|
41
|
+
.command('apply')
|
|
42
|
+
.description('Apply changes from a plan file')
|
|
43
|
+
.requiredOption('--plan <file>', 'Path to plan file')
|
|
44
|
+
.action(async (options) => {
|
|
45
|
+
try {
|
|
46
|
+
await (0, apply_1.executeApplyCommand)({
|
|
47
|
+
planFilePath: options.plan,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
log.error('✖ Error during apply:', error);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
await program.parseAsync(args, { from: 'user' });
|
|
56
|
+
};
|
|
57
|
+
exports.invoke = invoke;
|
|
58
|
+
//# sourceMappingURL=invoke.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invoke.js","sourceRoot":"","sources":["../../../src/contract/cli/invoke.ts"],"names":[],"mappings":";;;;;;AAAA,yCAAoC;AAEpC,yEAAwC;AACxC,mCAA8C;AAC9C,iCAA4C;AAE5C,MAAM,GAAG,GAAG,OAAO,CAAC;AAEpB;;;;GAIG;AACI,MAAM,MAAM,GAAG,KAAK,EAAE,EAAE,IAAI,EAAsB,EAAiB,EAAE;IAC1E,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;IAE9B,OAAO;SACJ,IAAI,CAAC,aAAa,CAAC;SACnB,WAAW,CAAC,wCAAwC,CAAC;SACrD,OAAO,CAAC,sBAAG,CAAC,OAAO,CAAC,CAAC;IAExB,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,yCAAyC,CAAC;SACtD,cAAc,CAAC,eAAe,EAAE,mBAAmB,CAAC;SACpD,cAAc,CAAC,eAAe,EAAE,0BAA0B,CAAC;SAC3D,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACxB,IAAI,CAAC;YACH,MAAM,IAAA,yBAAkB,EAAC;gBACvB,YAAY,EAAE,OAAO,CAAC,IAAI;gBAC1B,YAAY,EAAE,OAAO,CAAC,IAAI;aAC3B,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,GAAG,CAAC,KAAK,CAAC,sBAAsB,EAAE,KAAK,CAAC,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,gCAAgC,CAAC;SAC7C,cAAc,CAAC,eAAe,EAAE,mBAAmB,CAAC;SACpD,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,EAAE;QACxB,IAAI,CAAC;YACH,MAAM,IAAA,2BAAmB,EAAC;gBACxB,YAAY,EAAE,OAAO,CAAC,IAAI;aAC3B,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,GAAG,CAAC,KAAK,CAAC,uBAAuB,EAAE,KAAK,CAAC,CAAC;YAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;AACnD,CAAC,CAAC;AAzCW,QAAA,MAAM,UAyCjB"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#!/usr/bin/env tsx
|
|
2
|
+
/**
|
|
3
|
+
* .what = executes the plan command to generate an infrastructure change plan
|
|
4
|
+
* .why = provides CLI interface for planning infrastructure changes
|
|
5
|
+
* .note = requires wish file with getResources() and getProviders() exports
|
|
6
|
+
*/
|
|
7
|
+
export declare const executePlanCommand: ({ wishFilePath, planFilePath, }: {
|
|
8
|
+
wishFilePath: string;
|
|
9
|
+
planFilePath: string;
|
|
10
|
+
}) => Promise<void>;
|
|
@@ -0,0 +1,107 @@
|
|
|
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 __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
const fs_1 = require("fs");
|
|
27
|
+
const promises_1 = require("fs/promises");
|
|
28
|
+
const path_1 = require("path");
|
|
29
|
+
const DeclastructPlan_1 = require("../../domain.objects/DeclastructPlan");
|
|
30
|
+
const plan_1 = require("./plan");
|
|
31
|
+
describe('executePlanCommand', () => {
|
|
32
|
+
const wishFilePath = (0, path_1.resolve)(process.cwd(), 'src/.test/assets/wish.fixture.ts');
|
|
33
|
+
const planFilePath = (0, path_1.resolve)(process.cwd(), 'src/.test/assets/plan.test.json');
|
|
34
|
+
afterEach(async () => {
|
|
35
|
+
// cleanup plan file after each test
|
|
36
|
+
if ((0, fs_1.existsSync)(planFilePath)) {
|
|
37
|
+
await (0, promises_1.rm)(planFilePath);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
it('should generate a plan file with changes based on wish file', async () => {
|
|
41
|
+
// execute plan command
|
|
42
|
+
await (0, plan_1.executePlanCommand)({ wishFilePath, planFilePath });
|
|
43
|
+
// verify plan file was created
|
|
44
|
+
expect((0, fs_1.existsSync)(planFilePath)).toBe(true);
|
|
45
|
+
// read and parse plan
|
|
46
|
+
const planJson = await (0, promises_1.readFile)(planFilePath, 'utf-8');
|
|
47
|
+
const plan = new DeclastructPlan_1.DeclastructPlan(JSON.parse(planJson));
|
|
48
|
+
// verify plan structure
|
|
49
|
+
expect(plan.hash).toBeDefined();
|
|
50
|
+
expect(plan.createdAt).toBeDefined();
|
|
51
|
+
expect(plan.wish.uri).toBe(wishFilePath);
|
|
52
|
+
expect(plan.changes.length).toBe(2);
|
|
53
|
+
// verify changes are all CREATE (no remote state)
|
|
54
|
+
plan.changes.forEach((change) => {
|
|
55
|
+
expect(change.action).toBe('CREATE');
|
|
56
|
+
expect(change.forResource.class).toBe('DemoResource');
|
|
57
|
+
expect(change.state.desired).toBeDefined();
|
|
58
|
+
expect(change.state.remote).toBeNull();
|
|
59
|
+
});
|
|
60
|
+
// verify slugs exist and are unique
|
|
61
|
+
const slugs = plan.changes.map((c) => c.forResource.slug);
|
|
62
|
+
expect(slugs.length).toBe(2);
|
|
63
|
+
expect(slugs[0]).toBeDefined();
|
|
64
|
+
expect(slugs[1]).toBeDefined();
|
|
65
|
+
expect(slugs[0]).not.toBe(slugs[1]);
|
|
66
|
+
});
|
|
67
|
+
it('should throw when wish file does not exist', async () => {
|
|
68
|
+
const nonexistentWishPath = (0, path_1.resolve)(__dirname, 'nonexistent.ts');
|
|
69
|
+
await expect((0, plan_1.executePlanCommand)({
|
|
70
|
+
wishFilePath: nonexistentWishPath,
|
|
71
|
+
planFilePath,
|
|
72
|
+
})).rejects.toThrow('Wish file not found');
|
|
73
|
+
});
|
|
74
|
+
it('should throw when wish file does not export getResources', async () => {
|
|
75
|
+
const badWishPath = (0, path_1.resolve)(process.cwd(), 'src/.test/assets/bad-wish.ts');
|
|
76
|
+
// create bad wish file
|
|
77
|
+
const { writeFile } = await Promise.resolve().then(() => __importStar(require('fs/promises')));
|
|
78
|
+
await writeFile(badWishPath, 'export const getProviders = async () => [];', 'utf-8');
|
|
79
|
+
await expect((0, plan_1.executePlanCommand)({ wishFilePath: badWishPath, planFilePath })).rejects.toThrow('Wish file must export getResources() function');
|
|
80
|
+
// cleanup
|
|
81
|
+
await (0, promises_1.rm)(badWishPath);
|
|
82
|
+
});
|
|
83
|
+
it('should throw when wish file does not export getProviders', async () => {
|
|
84
|
+
const badWishPath = (0, path_1.resolve)(process.cwd(), 'src/.test/assets/bad-wish2.ts');
|
|
85
|
+
// create bad wish file
|
|
86
|
+
const { writeFile } = await Promise.resolve().then(() => __importStar(require('fs/promises')));
|
|
87
|
+
await writeFile(badWishPath, 'export const getResources = async () => [];', 'utf-8');
|
|
88
|
+
await expect((0, plan_1.executePlanCommand)({ wishFilePath: badWishPath, planFilePath })).rejects.toThrow('Wish file must export getProviders() function');
|
|
89
|
+
// cleanup
|
|
90
|
+
await (0, promises_1.rm)(badWishPath);
|
|
91
|
+
});
|
|
92
|
+
it('should detect KEEP action when resource already exists remotely', async () => {
|
|
93
|
+
// first run - create resources
|
|
94
|
+
await (0, plan_1.executePlanCommand)({ wishFilePath, planFilePath });
|
|
95
|
+
// read first plan
|
|
96
|
+
const firstPlanJson = await (0, promises_1.readFile)(planFilePath, 'utf-8');
|
|
97
|
+
const firstPlan = new DeclastructPlan_1.DeclastructPlan(JSON.parse(firstPlanJson));
|
|
98
|
+
// verify all CREATE
|
|
99
|
+
expect(firstPlan.changes.every((c) => c.action === 'CREATE')).toBe(true);
|
|
100
|
+
// cleanup and run again
|
|
101
|
+
await (0, promises_1.rm)(planFilePath);
|
|
102
|
+
// Note: In a real integration test, we would need to actually apply the changes
|
|
103
|
+
// to populate remote state. For now, this test just verifies the basic flow.
|
|
104
|
+
// A more complete test would require mocking or actual provider state.
|
|
105
|
+
});
|
|
106
|
+
});
|
|
107
|
+
//# sourceMappingURL=plan.integration.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.integration.test.js","sourceRoot":"","sources":["../../../src/contract/cli/plan.integration.test.ts"],"names":[],"mappings":"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"}
|