@notation/cli 0.4.2 → 0.5.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/index.js CHANGED
@@ -4,8 +4,7 @@
4
4
  import { program } from "commander";
5
5
 
6
6
  // src/compile.ts
7
- import fs from "fs";
8
- import * as fflate from "fflate";
7
+ import chokidar from "chokidar";
9
8
  import { glob } from "glob";
10
9
  import { log } from "console";
11
10
  import esbuild from "esbuild";
@@ -14,15 +13,26 @@ import {
14
13
  functionRuntimePlugin
15
14
  } from "@notation/esbuild-plugins";
16
15
  import { filePaths } from "@notation/core";
17
- async function compile(entryPoint) {
18
- await compileInfra(entryPoint);
16
+ async function compile(entryPoint, watch2 = false) {
17
+ log(`${watch2 ? "Watching" : "Compiling"} infrastructure`, entryPoint);
18
+ await compileInfra(entryPoint, watch2);
19
+ log(`${watch2 ? "Watching" : "Compiling"} functions`);
19
20
  const fnEntryPoints = await glob("**/*.fn.ts");
20
- await compileFns(fnEntryPoints);
21
- await zipFns(fnEntryPoints);
21
+ let disposeFnCompiler = await compileFns(fnEntryPoints, watch2);
22
+ if (!watch2)
23
+ return;
24
+ chokidar.watch("**/*.fn.ts", {
25
+ ignored: /node_modules/,
26
+ persistent: true
27
+ }).on("all", async () => {
28
+ if (disposeFnCompiler)
29
+ disposeFnCompiler();
30
+ const fnEntryPoints2 = await glob("**/*.fn.ts");
31
+ disposeFnCompiler = await compileFns(fnEntryPoints2, watch2);
32
+ });
22
33
  }
23
- async function compileInfra(entryPoint) {
24
- log("Compiling infrastructure", entryPoint);
25
- await esbuild.build({
34
+ async function compileInfra(entryPoint, watch2 = false) {
35
+ const context = await esbuild.context({
26
36
  entryPoints: [entryPoint],
27
37
  plugins: [functionInfraPlugin()],
28
38
  outdir: "dist/infra",
@@ -34,11 +44,16 @@ async function compileInfra(entryPoint) {
34
44
  treeShaking: true,
35
45
  packages: "external"
36
46
  });
47
+ if (watch2) {
48
+ await context.watch();
49
+ } else {
50
+ await context.rebuild();
51
+ context.dispose();
52
+ }
37
53
  }
38
- async function compileFns(entryPoints) {
39
- log("Compiling functions");
54
+ async function compileFns(entryPoints, watch2 = false) {
40
55
  for (const entryPoint of entryPoints) {
41
- await esbuild.build({
56
+ const context = await esbuild.context({
42
57
  entryPoints: [entryPoint],
43
58
  plugins: [functionRuntimePlugin()],
44
59
  outfile: filePaths.dist.runtime.index(entryPoint),
@@ -48,46 +63,37 @@ async function compileFns(entryPoints) {
48
63
  platform: "node",
49
64
  treeShaking: true
50
65
  });
66
+ if (watch2) {
67
+ await context.watch();
68
+ return () => context.dispose();
69
+ } else {
70
+ await context.rebuild();
71
+ context.dispose();
72
+ }
51
73
  }
52
74
  }
53
- async function zipFns(entryPoints) {
54
- log("Compiling deployable packages");
55
- for (const entryPoint of entryPoints) {
56
- const inputFilePath = filePaths.dist.runtime.index(entryPoint);
57
- const inputFile = fs.readFileSync(inputFilePath);
58
- const zipFilePath = `${inputFilePath}.zip`;
59
- const archive = fflate.zipSync({ "index.mjs": inputFile }, { level: 9 });
60
- fs.writeFileSync(zipFilePath, archive);
61
- }
62
- }
63
-
64
- // src/utils.ts
65
- import path from "path";
66
- import { getResources, getResourceGroups, filePaths as filePaths2 } from "@notation/core";
67
- async function getResourceGraph(entryPoint) {
68
- const outFilePath = filePaths2.dist.infra(entryPoint);
69
- await import(path.join(process.cwd(), outFilePath));
70
- const resourceGroups = getResourceGroups();
71
- const resources = getResources();
72
- return { resourceGroups, resources };
73
- }
74
75
 
75
76
  // src/deploy.ts
77
+ import { deployApp } from "@notation/core";
76
78
  async function deploy(entryPoint) {
77
79
  await compile(entryPoint);
80
+ console.log(`Deploying ${entryPoint}`);
78
81
  await deployApp(entryPoint);
79
82
  }
80
- async function deployApp(entryPoint) {
81
- console.log(`Deploying ${entryPoint}`);
82
- const graph = await getResourceGraph(entryPoint);
83
- for (const resource of graph.resources) {
84
- await resource.runDeploy();
85
- console.log(`Deployed ${resource.type} ${resource.id}`);
86
- }
83
+
84
+ // src/destroy.ts
85
+ import { destroyApp } from "@notation/core";
86
+ async function destroy(entryPoint) {
87
+ await compile(entryPoint);
88
+ await destroyApp(entryPoint);
87
89
  }
88
90
 
89
91
  // src/visualise.ts
90
- import { createMermaidFlowChart, createMermaidLiveUrl } from "@notation/core";
92
+ import {
93
+ createMermaidFlowChart,
94
+ createMermaidLiveUrl,
95
+ getResourceGraph
96
+ } from "@notation/core";
91
97
  import { log as log2 } from "console";
92
98
  async function visualise(entryPoint) {
93
99
  await compileInfra(entryPoint);
@@ -102,30 +108,72 @@ async function generateGraph(entryPoint) {
102
108
  log2(chartUrl);
103
109
  }
104
110
 
111
+ // src/watch.ts
112
+ import chokidar2 from "chokidar";
113
+ import { deployApp as deployApp2 } from "@notation/core";
114
+ var dotFilesRe = /(^|[\/\\])\../;
115
+ async function watch(entryPoint) {
116
+ await compile(entryPoint, true);
117
+ const watcher = chokidar2.watch("dist", {
118
+ ignored: dotFilesRe,
119
+ persistent: true
120
+ });
121
+ watcher.on("all", debounceDeploy);
122
+ let isDeploying = false;
123
+ let deployQueued = false;
124
+ let timeoutId;
125
+ const debounceTime = 500;
126
+ function debounceDeploy() {
127
+ if (timeoutId) {
128
+ clearTimeout(timeoutId);
129
+ }
130
+ timeoutId = setTimeout(() => {
131
+ triggerDeploy();
132
+ }, debounceTime);
133
+ }
134
+ function triggerDeploy() {
135
+ if (isDeploying) {
136
+ deployQueued = true;
137
+ return;
138
+ }
139
+ isDeploying = true;
140
+ deployApp2(entryPoint, false).then(() => {
141
+ isDeploying = false;
142
+ if (deployQueued) {
143
+ deployQueued = false;
144
+ triggerDeploy();
145
+ }
146
+ }).catch((err) => {
147
+ console.error(err);
148
+ isDeploying = false;
149
+ });
150
+ }
151
+ }
152
+
105
153
  // src/scaffold.ts
106
- import path2 from "node:path";
154
+ import path from "node:path";
107
155
  import fse from "fs-extra";
108
156
  import { execSync } from "node:child_process";
109
157
  import whichPmRuns from "which-pm-runs";
110
- var dirname = path2.dirname(new URL(import.meta.url).pathname);
158
+ var dirname = path.dirname(new URL(import.meta.url).pathname);
111
159
  var packageManager = whichPmRuns()?.name || "npm";
112
160
  var packageManagerInstallCommand = getPmInstallCommand(packageManager);
113
161
  async function scaffoldApp(appName) {
114
162
  const cwd = process.cwd();
115
- const appDir = path2.join(cwd, appName);
163
+ const appDir = path.join(cwd, appName);
116
164
  await fse.ensureDir(appDir);
117
165
  const children = await fse.readdir(appDir);
118
166
  if (children.length) {
119
167
  console.error(
120
- `Directory ${path2.relative(process.cwd(), appDir)} is not empty`
168
+ `Directory ${path.relative(process.cwd(), appDir)} is not empty`
121
169
  );
122
170
  return;
123
171
  }
124
172
  console.log(`
125
173
  Creating app from template...`);
126
- const templateDir = path2.join(dirname, "../templates/starter");
174
+ const templateDir = path.join(dirname, "../templates/starter");
127
175
  await fse.copy(templateDir, appDir);
128
- const packageJsonPath = path2.join(appDir, "package.json");
176
+ const packageJsonPath = path.join(appDir, "package.json");
129
177
  const packageJsonContent = await fse.readFile(packageJsonPath, "utf8");
130
178
  const packageJson = JSON.parse(packageJsonContent);
131
179
  packageJson.name = appName;
@@ -180,4 +228,10 @@ program.command("viz").argument("<entryPoint>", "entryPoint").description("Visua
180
228
  program.command("deploy").argument("<entryPoint>", "entryPoint").description("Deploy Notation App").action(async (entryPoint) => {
181
229
  await deploy(entryPoint);
182
230
  });
231
+ program.command("destroy").argument("<entryPoint>", "entryPoint").description("Destroy Notation App").action(async (entryPoint) => {
232
+ await destroy(entryPoint);
233
+ });
234
+ program.command("watch").argument("<entryPoint>", "entryPoint").description("Watch Notation App").action(async (entryPoint) => {
235
+ await watch(entryPoint);
236
+ });
183
237
  program.parse(process.argv);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@notation/cli",
4
- "version": "0.4.2",
4
+ "version": "0.5.0",
5
5
  "files": [
6
6
  "dist",
7
7
  "templates"
@@ -10,16 +10,18 @@
10
10
  "notation": "dist/index.js"
11
11
  },
12
12
  "dependencies": {
13
- "@types/fs-extra": "^11.0.4",
14
- "@types/which-pm-runs": "^1.0.2",
13
+ "chokidar": "^3.5.3",
15
14
  "commander": "^11.0.0",
16
15
  "esbuild": "^0.19.3",
17
- "fflate": "0.8.1",
18
16
  "fs-extra": "^11.1.1",
19
17
  "glob": "^10.3.10",
20
18
  "which-pm-runs": "^1.1.0",
21
- "@notation/core": "0.3.1",
22
- "@notation/esbuild-plugins": "0.3.1"
19
+ "@notation/core": "0.4.0",
20
+ "@notation/esbuild-plugins": "0.3.2"
21
+ },
22
+ "devDependencies": {
23
+ "@types/fs-extra": "^11.0.4",
24
+ "@types/which-pm-runs": "^1.0.2"
23
25
  },
24
26
  "scripts": {
25
27
  "build": "tsup",
@@ -2,6 +2,8 @@
2
2
  "private": true,
3
3
  "name": "notation-starter",
4
4
  "scripts": {
5
- "viz": "notation viz src/api.ts"
5
+ "viz": "notation viz src/api.ts",
6
+ "deploy": "notation deploy src/api.ts",
7
+ "destroy": "notation destroy src/api.ts"
6
8
  }
7
9
  }