@gershy/lilac 0.0.15 → 0.0.16

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/cmp/cjs/main.d.ts CHANGED
@@ -20,6 +20,7 @@ export declare class Flower {
20
20
  constructor();
21
21
  getDependencies(): Generator<Flower>;
22
22
  getPetals(ctx: Context): SuperIterable<PetalTerraform.Base>;
23
+ cultivate(): Promise<void>;
23
24
  }
24
25
  type RegistryFlowers<R extends Registry<any>, M extends 'real' | 'test'> = R extends Registry<infer Flowers> ? {
25
26
  [K in keyof Flowers]: Flowers[K][M];
@@ -48,7 +49,7 @@ export declare class Garden<Reg extends Registry<any>> {
48
49
  define: Garden<Reg>['def'];
49
50
  });
50
51
  private getPetals;
51
- genTerraform(deployTarget: Soil.Base): Promise<Obj<Fact>>;
52
+ genTerraform(soil: Soil.Base): Promise<Obj<Fact>>;
52
53
  private terraformInit;
53
54
  private terraformPlan;
54
55
  private terraformApply;
package/cmp/cjs/main.js CHANGED
@@ -32,6 +32,7 @@ const nodejs_proc_1 = __importDefault(require("@gershy/nodejs-proc"));
32
32
  const { isCls, skip } = cl;
33
33
  const toArr = cl.toArr;
34
34
  const allObj = cl.allObj;
35
+ const allArr = cl.allArr;
35
36
  const has = cl.has;
36
37
  const map = cl.map;
37
38
  const mod = cl.mod;
@@ -55,6 +56,11 @@ class Flower {
55
56
  getPetals(ctx) {
56
57
  throw Error('not implemented');
57
58
  }
59
+ async cultivate() {
60
+ // This function is called once all Flowers for a given Garden have been constructed. The main
61
+ // purpose of this phase is to allow Flowers which reference each other via functions to run
62
+ // such functions without running into uninitialized values.
63
+ }
58
64
  }
59
65
  exports.Flower = Flower;
60
66
  ;
@@ -112,21 +118,22 @@ class Garden {
112
118
  // conditionally calling `this.registry.get('fake')`...
113
119
  const seenFlowers = new Set();
114
120
  const seenPetals = new Set();
115
- for await (const topLevelFlower of await this.def(this.ctx, this.reg.get('real'))) {
116
- for (const flower of topLevelFlower.getDependencies()) {
117
- if (seenFlowers.has(flower))
118
- continue;
121
+ for await (const topLevelFlower of await this.def(this.ctx, this.reg.get('real')))
122
+ for (const flower of topLevelFlower.getDependencies())
119
123
  seenFlowers.add(flower);
120
- for await (const petal of await flower.getPetals(this.ctx)) {
121
- if (seenPetals.has(petal))
122
- continue;
123
- yield petal;
124
- }
124
+ // Now we've exhaustively referenced all Flowers - we can cultivate them
125
+ await Promise.all(seenFlowers[toArr](f => f.cultivate()));
126
+ for (const flower of seenFlowers) {
127
+ for await (const petal of await flower.getPetals(this.ctx)) {
128
+ if (seenPetals.has(petal))
129
+ continue;
130
+ seenPetals.add(petal);
131
+ yield petal;
125
132
  }
126
133
  }
127
134
  }
128
- async genTerraform(deployTarget) {
129
- const soilTfPetalsPrm = deployTarget.getTerraformPetals(this.ctx);
135
+ async genTerraform(soil) {
136
+ const soilTfPetalsPrm = soil.getTerraformPetals(this.ctx);
130
137
  return this.ctx.logger.scope('garden.genTerraform', {}, async (logger) => {
131
138
  const setupTfProj = async (args) => args.logger.scope('tf', { proj: this.ctx.name, tf: args.term }, async (logger) => {
132
139
  // Allows a terraform project to be defined in terms of a function which writes to main.tf,
@@ -148,8 +155,7 @@ class Garden {
148
155
  const stream = await args.fact.kid(['main.tf']).getDataHeadStream();
149
156
  await args.setup(args.fact, stream, async (petal) => {
150
157
  // Include a utility function the caller can use to easily write petals
151
- const { tf, files = {} } = await petal.getResult()
152
- .then(tf => isCls(tf, String) ? { tf } : tf);
158
+ const { tf, files = {} } = await petal.getResult().then(tf => isCls(tf, String) ? { tf } : tf);
153
159
  if (tf)
154
160
  await stream.write(`${tf}\n`);
155
161
  await Promise.all(files[toArr]((data, kfp) => args.fact.kid(kfp.split('/')).setData(data)));
@@ -22,6 +22,7 @@ export declare namespace Soil {
22
22
  protected logger: Logger;
23
23
  protected registry: Registry<any>;
24
24
  constructor(args: BaseArgs);
25
+ getRegion(): string;
25
26
  getTerraformPetals(ctx: Context): Promise<PetalProjResult>;
26
27
  }
27
28
  type LocalStackArgs = BaseArgs & {
@@ -39,6 +40,7 @@ export declare namespace Soil {
39
40
  private aws;
40
41
  private localStackDocker;
41
42
  constructor(args: LocalStackArgs);
43
+ getRegion(): "ca-central-1" | "us-east-1" | "us-east-2" | "us-west-1" | "us-west-2";
42
44
  private getAwsServices;
43
45
  private getDockerContainers;
44
46
  run(): Promise<{
@@ -77,6 +79,7 @@ export declare namespace Soil {
77
79
  class AwsCloud extends Base {
78
80
  private aws;
79
81
  constructor(args: AwsCloudArgs);
82
+ getRegion(): "ca-central-1" | "us-east-1" | "us-east-2" | "us-west-1" | "us-west-2";
80
83
  getTerraformPetals(ctx: Context): Promise<{
81
84
  boot: () => Generator<PetalTerraform.Terraform | PetalTerraform.Provider | PetalTerraform.File, void, unknown>;
82
85
  main: (args: any) => Generator<PetalTerraform.Terraform | PetalTerraform.Provider | PetalTerraform.File, void, unknown>;
@@ -34,8 +34,11 @@ var Soil;
34
34
  this.logger = args.logger;
35
35
  this.registry = args.registry;
36
36
  }
37
+ getRegion() {
38
+ throw Error('method definition missing');
39
+ }
37
40
  async getTerraformPetals(ctx) {
38
- throw Error('not implemented');
41
+ throw Error('method definition missing');
39
42
  }
40
43
  }
41
44
  Soil.Base = Base;
@@ -53,6 +56,7 @@ var Soil;
53
56
  containerName: 'gershyLilacLocalStack'
54
57
  }[merge](args.localStackDocker ?? {});
55
58
  }
59
+ getRegion() { return this.aws.region; }
56
60
  getAwsServices() {
57
61
  // Note that "overhead" services are essential for initializing localstack:
58
62
  // - s3 + ddb used for terraform state locking
@@ -243,6 +247,7 @@ var Soil;
243
247
  super(args);
244
248
  this.aws = args.aws;
245
249
  }
250
+ getRegion() { return this.aws.region; }
246
251
  async getTerraformPetals(ctx) {
247
252
  const { aws } = this;
248
253
  return {
package/cmp/mjs/main.d.ts CHANGED
@@ -20,6 +20,7 @@ export declare class Flower {
20
20
  constructor();
21
21
  getDependencies(): Generator<Flower>;
22
22
  getPetals(ctx: Context): SuperIterable<PetalTerraform.Base>;
23
+ cultivate(): Promise<void>;
23
24
  }
24
25
  type RegistryFlowers<R extends Registry<any>, M extends 'real' | 'test'> = R extends Registry<infer Flowers> ? {
25
26
  [K in keyof Flowers]: Flowers[K][M];
@@ -48,7 +49,7 @@ export declare class Garden<Reg extends Registry<any>> {
48
49
  define: Garden<Reg>['def'];
49
50
  });
50
51
  private getPetals;
51
- genTerraform(deployTarget: Soil.Base): Promise<Obj<Fact>>;
52
+ genTerraform(soil: Soil.Base): Promise<Obj<Fact>>;
52
53
  private terraformInit;
53
54
  private terraformPlan;
54
55
  private terraformApply;
package/cmp/mjs/main.js CHANGED
@@ -12,6 +12,7 @@ import proc from '@gershy/nodejs-proc';
12
12
  const { isCls, skip } = cl;
13
13
  const toArr = cl.toArr;
14
14
  const allObj = cl.allObj;
15
+ const allArr = cl.allArr;
15
16
  const has = cl.has;
16
17
  const map = cl.map;
17
18
  const mod = cl.mod;
@@ -35,6 +36,11 @@ export class Flower {
35
36
  getPetals(ctx) {
36
37
  throw Error('not implemented');
37
38
  }
39
+ async cultivate() {
40
+ // This function is called once all Flowers for a given Garden have been constructed. The main
41
+ // purpose of this phase is to allow Flowers which reference each other via functions to run
42
+ // such functions without running into uninitialized values.
43
+ }
38
44
  }
39
45
  ;
40
46
  export class Registry {
@@ -90,21 +96,22 @@ export class Garden {
90
96
  // conditionally calling `this.registry.get('fake')`...
91
97
  const seenFlowers = new Set();
92
98
  const seenPetals = new Set();
93
- for await (const topLevelFlower of await this.def(this.ctx, this.reg.get('real'))) {
94
- for (const flower of topLevelFlower.getDependencies()) {
95
- if (seenFlowers.has(flower))
96
- continue;
99
+ for await (const topLevelFlower of await this.def(this.ctx, this.reg.get('real')))
100
+ for (const flower of topLevelFlower.getDependencies())
97
101
  seenFlowers.add(flower);
98
- for await (const petal of await flower.getPetals(this.ctx)) {
99
- if (seenPetals.has(petal))
100
- continue;
101
- yield petal;
102
- }
102
+ // Now we've exhaustively referenced all Flowers - we can cultivate them
103
+ await Promise.all(seenFlowers[toArr](f => f.cultivate()));
104
+ for (const flower of seenFlowers) {
105
+ for await (const petal of await flower.getPetals(this.ctx)) {
106
+ if (seenPetals.has(petal))
107
+ continue;
108
+ seenPetals.add(petal);
109
+ yield petal;
103
110
  }
104
111
  }
105
112
  }
106
- async genTerraform(deployTarget) {
107
- const soilTfPetalsPrm = deployTarget.getTerraformPetals(this.ctx);
113
+ async genTerraform(soil) {
114
+ const soilTfPetalsPrm = soil.getTerraformPetals(this.ctx);
108
115
  return this.ctx.logger.scope('garden.genTerraform', {}, async (logger) => {
109
116
  const setupTfProj = async (args) => args.logger.scope('tf', { proj: this.ctx.name, tf: args.term }, async (logger) => {
110
117
  // Allows a terraform project to be defined in terms of a function which writes to main.tf,
@@ -126,8 +133,7 @@ export class Garden {
126
133
  const stream = await args.fact.kid(['main.tf']).getDataHeadStream();
127
134
  await args.setup(args.fact, stream, async (petal) => {
128
135
  // Include a utility function the caller can use to easily write petals
129
- const { tf, files = {} } = await petal.getResult()
130
- .then(tf => isCls(tf, String) ? { tf } : tf);
136
+ const { tf, files = {} } = await petal.getResult().then(tf => isCls(tf, String) ? { tf } : tf);
131
137
  if (tf)
132
138
  await stream.write(`${tf}\n`);
133
139
  await Promise.all(files[toArr]((data, kfp) => args.fact.kid(kfp.split('/')).setData(data)));
@@ -22,6 +22,7 @@ export declare namespace Soil {
22
22
  protected logger: Logger;
23
23
  protected registry: Registry<any>;
24
24
  constructor(args: BaseArgs);
25
+ getRegion(): string;
25
26
  getTerraformPetals(ctx: Context): Promise<PetalProjResult>;
26
27
  }
27
28
  type LocalStackArgs = BaseArgs & {
@@ -39,6 +40,7 @@ export declare namespace Soil {
39
40
  private aws;
40
41
  private localStackDocker;
41
42
  constructor(args: LocalStackArgs);
43
+ getRegion(): "ca-central-1" | "us-east-1" | "us-east-2" | "us-west-1" | "us-west-2";
42
44
  private getAwsServices;
43
45
  private getDockerContainers;
44
46
  run(): Promise<{
@@ -77,6 +79,7 @@ export declare namespace Soil {
77
79
  class AwsCloud extends Base {
78
80
  private aws;
79
81
  constructor(args: AwsCloudArgs);
82
+ getRegion(): "ca-central-1" | "us-east-1" | "us-east-2" | "us-west-1" | "us-west-2";
80
83
  getTerraformPetals(ctx: Context): Promise<{
81
84
  boot: () => Generator<PetalTerraform.Terraform | PetalTerraform.Provider | PetalTerraform.File, void, unknown>;
82
85
  main: (args: any) => Generator<PetalTerraform.Terraform | PetalTerraform.Provider | PetalTerraform.File, void, unknown>;
@@ -28,8 +28,11 @@ export var Soil;
28
28
  this.logger = args.logger;
29
29
  this.registry = args.registry;
30
30
  }
31
+ getRegion() {
32
+ throw Error('method definition missing');
33
+ }
31
34
  async getTerraformPetals(ctx) {
32
- throw Error('not implemented');
35
+ throw Error('method definition missing');
33
36
  }
34
37
  }
35
38
  Soil.Base = Base;
@@ -47,6 +50,7 @@ export var Soil;
47
50
  containerName: 'gershyLilacLocalStack'
48
51
  }[merge](args.localStackDocker ?? {});
49
52
  }
53
+ getRegion() { return this.aws.region; }
50
54
  getAwsServices() {
51
55
  // Note that "overhead" services are essential for initializing localstack:
52
56
  // - s3 + ddb used for terraform state locking
@@ -237,6 +241,7 @@ export var Soil;
237
241
  super(args);
238
242
  this.aws = args.aws;
239
243
  }
244
+ getRegion() { return this.aws.region; }
240
245
  async getTerraformPetals(ctx) {
241
246
  const { aws } = this;
242
247
  return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gershy/lilac",
3
- "version": "0.0.15",
3
+ "version": "0.0.16",
4
4
  "description": "Luscious infrastructure Living as Code - an opinionated approach to IAC",
5
5
  "keywords": [
6
6
  "lilac",
@@ -23,7 +23,7 @@
23
23
  },
24
24
  "devDependencies": {
25
25
  "@gershy/disk": "^0.0.13",
26
- "@gershy/entry": "^0.0.6",
26
+ "@gershy/entry": "^0.0.7",
27
27
  "@gershy/logger": "^0.0.8",
28
28
  "@gershy/util-hash": "^0.0.5",
29
29
  "@types/node": "^24.10.1",