@kensio/yulin 1.6.1 → 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/README.md +72 -0
- package/dist/cli/sim-cli.d.ts +20 -0
- package/dist/cli/sim-cli.d.ts.map +1 -0
- package/dist/cli/sim-cli.js +42 -0
- package/dist/cli/sim-cli.js.map +1 -0
- package/dist/cli/watch/sim-watch-arguments.d.ts +30 -0
- package/dist/cli/watch/sim-watch-arguments.d.ts.map +1 -0
- package/dist/cli/watch/sim-watch-arguments.js +67 -0
- package/dist/cli/watch/sim-watch-arguments.js.map +1 -0
- package/dist/cli/watch/sim-watch-child-environment.d.ts +30 -0
- package/dist/cli/watch/sim-watch-child-environment.d.ts.map +1 -0
- package/dist/cli/watch/sim-watch-child-environment.js +51 -0
- package/dist/cli/watch/sim-watch-child-environment.js.map +1 -0
- package/dist/cli/watch/sim-watch-child-message.d.ts +19 -0
- package/dist/cli/watch/sim-watch-child-message.d.ts.map +1 -0
- package/dist/cli/watch/sim-watch-child-message.js +42 -0
- package/dist/cli/watch/sim-watch-child-message.js.map +1 -0
- package/dist/cli/watch/sim-watch-child-process.d.ts +22 -0
- package/dist/cli/watch/sim-watch-child-process.d.ts.map +1 -0
- package/dist/cli/watch/sim-watch-child-process.js +33 -0
- package/dist/cli/watch/sim-watch-child-process.js.map +1 -0
- package/dist/cli/watch/sim-watch-child-shutdown.d.ts +28 -0
- package/dist/cli/watch/sim-watch-child-shutdown.d.ts.map +1 -0
- package/dist/cli/watch/sim-watch-child-shutdown.js +59 -0
- package/dist/cli/watch/sim-watch-child-shutdown.js.map +1 -0
- package/dist/cli/watch/sim-watch-child.d.ts +42 -0
- package/dist/cli/watch/sim-watch-child.d.ts.map +1 -0
- package/dist/cli/watch/sim-watch-child.js +62 -0
- package/dist/cli/watch/sim-watch-child.js.map +1 -0
- package/dist/cli/watch/sim-watch-command.d.ts +22 -0
- package/dist/cli/watch/sim-watch-command.d.ts.map +1 -0
- package/dist/cli/watch/sim-watch-command.js +41 -0
- package/dist/cli/watch/sim-watch-command.js.map +1 -0
- package/dist/cli/watch/sim-watch-event-path.d.ts +27 -0
- package/dist/cli/watch/sim-watch-event-path.d.ts.map +1 -0
- package/dist/cli/watch/sim-watch-event-path.js +48 -0
- package/dist/cli/watch/sim-watch-event-path.js.map +1 -0
- package/dist/cli/watch/sim-watch-ignore.d.ts +15 -0
- package/dist/cli/watch/sim-watch-ignore.d.ts.map +1 -0
- package/dist/cli/watch/sim-watch-ignore.js +64 -0
- package/dist/cli/watch/sim-watch-ignore.js.map +1 -0
- package/dist/cli/watch/sim-watch-loop-guard.d.ts +35 -0
- package/dist/cli/watch/sim-watch-loop-guard.d.ts.map +1 -0
- package/dist/cli/watch/sim-watch-loop-guard.js +51 -0
- package/dist/cli/watch/sim-watch-loop-guard.js.map +1 -0
- package/dist/cli/watch/sim-watch-reporter.d.ts +38 -0
- package/dist/cli/watch/sim-watch-reporter.d.ts.map +1 -0
- package/dist/cli/watch/sim-watch-reporter.js +65 -0
- package/dist/cli/watch/sim-watch-reporter.js.map +1 -0
- package/dist/cli/watch/sim-watch-restarts.d.ts +30 -0
- package/dist/cli/watch/sim-watch-restarts.d.ts.map +1 -0
- package/dist/cli/watch/sim-watch-restarts.js +62 -0
- package/dist/cli/watch/sim-watch-restarts.js.map +1 -0
- package/dist/cli/watch/sim-watch-supervisor.d.ts +52 -0
- package/dist/cli/watch/sim-watch-supervisor.d.ts.map +1 -0
- package/dist/cli/watch/sim-watch-supervisor.js +127 -0
- package/dist/cli/watch/sim-watch-supervisor.js.map +1 -0
- package/dist/cli/watch/sim-watch-watcher.d.ts +69 -0
- package/dist/cli/watch/sim-watch-watcher.d.ts.map +1 -0
- package/dist/cli/watch/sim-watch-watcher.js +144 -0
- package/dist/cli/watch/sim-watch-watcher.js.map +1 -0
- package/dist/cli/yulin.d.ts +3 -0
- package/dist/cli/yulin.d.ts.map +1 -0
- package/dist/cli/yulin.js +14 -0
- package/dist/cli/yulin.js.map +1 -0
- package/dist/serve/http/live-reload/sim-live-reload-client.d.ts +32 -0
- package/dist/serve/http/live-reload/sim-live-reload-client.d.ts.map +1 -0
- package/dist/serve/http/live-reload/sim-live-reload-client.js +55 -0
- package/dist/serve/http/live-reload/sim-live-reload-client.js.map +1 -0
- package/dist/serve/http/live-reload/sim-live-reload-injectable.d.ts +47 -0
- package/dist/serve/http/live-reload/sim-live-reload-injectable.d.ts.map +1 -0
- package/dist/serve/http/live-reload/sim-live-reload-injectable.js +86 -0
- package/dist/serve/http/live-reload/sim-live-reload-injectable.js.map +1 -0
- package/dist/serve/http/live-reload/sim-live-reload-injector.d.ts +22 -0
- package/dist/serve/http/live-reload/sim-live-reload-injector.d.ts.map +1 -0
- package/dist/serve/http/live-reload/sim-live-reload-injector.js +72 -0
- package/dist/serve/http/live-reload/sim-live-reload-injector.js.map +1 -0
- package/dist/serve/http/live-reload/sim-live-reload-report.d.ts +18 -0
- package/dist/serve/http/live-reload/sim-live-reload-report.d.ts.map +1 -0
- package/dist/serve/http/live-reload/sim-live-reload-report.js +27 -0
- package/dist/serve/http/live-reload/sim-live-reload-report.js.map +1 -0
- package/dist/serve/http/live-reload/sim-live-reload-script.d.ts +20 -0
- package/dist/serve/http/live-reload/sim-live-reload-script.d.ts.map +1 -0
- package/dist/serve/http/live-reload/sim-live-reload-script.js +45 -0
- package/dist/serve/http/live-reload/sim-live-reload-script.js.map +1 -0
- package/dist/serve/http/live-reload/sim-live-reload.config.d.ts +12 -0
- package/dist/serve/http/live-reload/sim-live-reload.config.d.ts.map +1 -0
- package/dist/serve/http/live-reload/sim-live-reload.config.js +19 -0
- package/dist/serve/http/live-reload/sim-live-reload.config.js.map +1 -0
- package/dist/serve/http/live-reload/sim-live-reload.d.ts +52 -0
- package/dist/serve/http/live-reload/sim-live-reload.d.ts.map +1 -0
- package/dist/serve/http/live-reload/sim-live-reload.js +82 -0
- package/dist/serve/http/live-reload/sim-live-reload.js.map +1 -0
- package/dist/serve/http/live-reload/sim-local-live-reload.d.ts +42 -0
- package/dist/serve/http/live-reload/sim-local-live-reload.d.ts.map +1 -0
- package/dist/serve/http/live-reload/sim-local-live-reload.js +60 -0
- package/dist/serve/http/live-reload/sim-local-live-reload.js.map +1 -0
- package/dist/serve/http/local-server/node-server-port-binder.d.ts +39 -0
- package/dist/serve/http/local-server/node-server-port-binder.d.ts.map +1 -0
- package/dist/serve/http/local-server/node-server-port-binder.js +71 -0
- package/dist/serve/http/local-server/node-server-port-binder.js.map +1 -0
- package/dist/serve/http/local-server/node-server-port.d.ts +10 -0
- package/dist/serve/http/local-server/node-server-port.d.ts.map +1 -0
- package/dist/serve/http/local-server/node-server-port.js +19 -0
- package/dist/serve/http/local-server/node-server-port.js.map +1 -0
- package/dist/serve/http/local-server/sim-aws-local-port.error.d.ts +13 -0
- package/dist/serve/http/local-server/sim-aws-local-port.error.d.ts.map +1 -0
- package/dist/serve/http/local-server/sim-aws-local-port.error.js +16 -0
- package/dist/serve/http/local-server/sim-aws-local-port.error.js.map +1 -0
- package/dist/serve/http/local-server/sim-aws-local-request-handler.d.ts +14 -1
- package/dist/serve/http/local-server/sim-aws-local-request-handler.d.ts.map +1 -1
- package/dist/serve/http/local-server/sim-aws-local-request-handler.js +20 -2
- package/dist/serve/http/local-server/sim-aws-local-request-handler.js.map +1 -1
- package/dist/serve/http/local-server/sim-aws-local-server.d.ts +23 -0
- package/dist/serve/http/local-server/sim-aws-local-server.d.ts.map +1 -1
- package/dist/serve/http/local-server/sim-aws-local-server.js +41 -16
- package/dist/serve/http/local-server/sim-aws-local-server.js.map +1 -1
- package/dist/serve/http/local-server/sim-aws-local.config.d.ts +2 -0
- package/dist/serve/http/local-server/sim-aws-local.config.d.ts.map +1 -1
- package/dist/serve/http/local-server/sim-aws-local.config.js +6 -0
- package/dist/serve/http/local-server/sim-aws-local.config.js.map +1 -1
- package/dist/serve/index.d.ts +3 -0
- package/dist/serve/index.d.ts.map +1 -1
- package/dist/serve/index.js +3 -0
- package/dist/serve/index.js.map +1 -1
- package/dist/service/cloudformation/authorize/sim-cloudformation-authorization.d.ts +44 -0
- package/dist/service/cloudformation/authorize/sim-cloudformation-authorization.d.ts.map +1 -0
- package/dist/service/cloudformation/authorize/sim-cloudformation-authorization.js +53 -0
- package/dist/service/cloudformation/authorize/sim-cloudformation-authorization.js.map +1 -0
- package/dist/service/cloudformation/command/update-stack/update-stack.handler.d.ts +7 -0
- package/dist/service/cloudformation/command/update-stack/update-stack.handler.d.ts.map +1 -1
- package/dist/service/cloudformation/command/update-stack/update-stack.handler.js +3 -1
- package/dist/service/cloudformation/command/update-stack/update-stack.handler.js.map +1 -1
- package/dist/service/cloudformation/deploy/sim-cfn-template-deployer.d.ts +19 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-deployer.d.ts.map +1 -1
- package/dist/service/cloudformation/deploy/sim-cfn-template-deployer.js +40 -1
- package/dist/service/cloudformation/deploy/sim-cfn-template-deployer.js.map +1 -1
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-deployment.d.ts +10 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-deployment.d.ts.map +1 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-deployment.js +14 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-deployment.js.map +1 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-loader.d.ts +11 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-loader.d.ts.map +1 -1
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-loader.js +5 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-loader.js.map +1 -1
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-updater.d.ts +49 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-updater.d.ts.map +1 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-updater.js +59 -0
- package/dist/service/cloudformation/deploy/sim-cfn-template-file-updater.js.map +1 -0
- package/dist/service/cloudformation/index.d.ts +1 -0
- package/dist/service/cloudformation/index.d.ts.map +1 -1
- package/dist/service/cloudformation/sim-cloudformation.d.ts +30 -5
- package/dist/service/cloudformation/sim-cloudformation.d.ts.map +1 -1
- package/dist/service/cloudformation/sim-cloudformation.js +45 -14
- package/dist/service/cloudformation/sim-cloudformation.js.map +1 -1
- package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.d.ts +10 -1
- package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.d.ts.map +1 -1
- package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.js +12 -1
- package/dist/service/cloudformation/stack/sim-cfn-stack-resource-operations.js.map +1 -1
- package/dist/service/cloudformation/stack/sim-cfn-stack.d.ts +14 -1
- package/dist/service/cloudformation/stack/sim-cfn-stack.d.ts.map +1 -1
- package/dist/service/cloudformation/stack/sim-cfn-stack.js +10 -1
- package/dist/service/cloudformation/stack/sim-cfn-stack.js.map +1 -1
- package/dist/service/cloudformation/stack/update/sim-cfn-stack-updater.d.ts +8 -0
- package/dist/service/cloudformation/stack/update/sim-cfn-stack-updater.d.ts.map +1 -1
- package/dist/service/cloudformation/stack/update/sim-cfn-stack-updater.js +9 -1
- package/dist/service/cloudformation/stack/update/sim-cfn-stack-updater.js.map +1 -1
- package/dist/service/cloudformation/watch/sim-cfn-template-file-events.d.ts +30 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-file-events.d.ts.map +1 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-file-events.js +51 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-file-events.js.map +1 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-file-watch.d.ts +39 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-file-watch.d.ts.map +1 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-file-watch.js +73 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-file-watch.js.map +1 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-file-watches.d.ts +46 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-file-watches.d.ts.map +1 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-file-watches.js +0 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-file-watches.js.map +1 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-watch-report.d.ts +25 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-watch-report.d.ts.map +1 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-watch-report.js +35 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-watch-report.js.map +1 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-watch-update.d.ts +44 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-watch-update.d.ts.map +1 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-watch-update.js +75 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-watch-update.js.map +1 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-watch.type.d.ts +30 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-watch.type.d.ts.map +1 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-watch.type.js +2 -0
- package/dist/service/cloudformation/watch/sim-cfn-template-watch.type.js.map +1 -0
- package/dist/service/s3/bucket/sim-s3-bucket-access.d.ts +4 -0
- package/dist/service/s3/bucket/sim-s3-bucket-access.d.ts.map +1 -1
- package/dist/service/s3/bucket/sim-s3-bucket-access.js +6 -0
- package/dist/service/s3/bucket/sim-s3-bucket-access.js.map +1 -1
- package/dist/watch/sim-watch-runtime.d.ts +76 -0
- package/dist/watch/sim-watch-runtime.d.ts.map +1 -0
- package/dist/watch/sim-watch-runtime.js +124 -0
- package/dist/watch/sim-watch-runtime.js.map +1 -0
- package/dist/watch/sim-watch-settle.d.ts +32 -0
- package/dist/watch/sim-watch-settle.d.ts.map +1 -0
- package/dist/watch/sim-watch-settle.js +43 -0
- package/dist/watch/sim-watch-settle.js.map +1 -0
- package/dist/watch/sim-watch.config.d.ts +22 -0
- package/dist/watch/sim-watch.config.d.ts.map +1 -0
- package/dist/watch/sim-watch.config.js +39 -0
- package/dist/watch/sim-watch.config.js.map +1 -0
- package/package.json +4 -1
package/README.md
CHANGED
|
@@ -38,6 +38,7 @@ npm i -D @kensio/yulin
|
|
|
38
38
|
## Feature specific docs
|
|
39
39
|
|
|
40
40
|
- [AWS SDK interception](./docs/sdk "Simulated AWS SDK docs")
|
|
41
|
+
- [Serving on localhost](./docs/serve "Serving simulated AWS on localhost docs")
|
|
41
42
|
- [Simulated time](./docs/time "Simulated time docs")
|
|
42
43
|
|
|
43
44
|
## Usage
|
|
@@ -185,6 +186,77 @@ console.log(bucketWebsiteUrl.toString());
|
|
|
185
186
|
const res = await fetch(new URL("/foo/", bucketWebsiteUrl));
|
|
186
187
|
```
|
|
187
188
|
|
|
189
|
+
#### Restarting a served environment
|
|
190
|
+
|
|
191
|
+
A served environment takes an available port by default, so the URL changes every time the process
|
|
192
|
+
starts. Pin a port to keep the URL the same across restarts:
|
|
193
|
+
|
|
194
|
+
```typescript
|
|
195
|
+
const srv = await serveSimAws({ simAws, port: 4599 });
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Closing the server ends the connections it is holding, so the process can exit rather than being
|
|
199
|
+
kept alive by a browser tab. Yulin does not install signal handlers, so call `close()` from your
|
|
200
|
+
own:
|
|
201
|
+
|
|
202
|
+
```typescript
|
|
203
|
+
process.on("SIGTERM", () => {
|
|
204
|
+
srv.close();
|
|
205
|
+
});
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
A restart usually overlaps the process it is replacing. `listen` waits a couple of seconds for a
|
|
209
|
+
pinned port that is still held, then throws `SimAwsLocalPortInUse` naming the port, which means
|
|
210
|
+
something other than the outgoing process owns it.
|
|
211
|
+
|
|
212
|
+
#### Reload the browser on a restart
|
|
213
|
+
|
|
214
|
+
Yulin is the only thing in the response path of a page it serves, so it can tell the browser to
|
|
215
|
+
reload. Turning `liveReload` on puts a small script into the HTML pages served to browsers, and the
|
|
216
|
+
page reloads itself when the process restarts:
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
const srv = await serveSimAws({ simAws, port: 4599, liveReload: true });
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
`srv.reload()` reloads connected browsers for a change that needs no restart. Live reload is off by
|
|
223
|
+
default, since an injected page is not byte for byte what the real service returns.
|
|
224
|
+
|
|
225
|
+
Run the dev script through `yulin watch` and a save is the whole loop, with the process restarted and
|
|
226
|
+
the page refreshed:
|
|
227
|
+
|
|
228
|
+
```bash
|
|
229
|
+
yulin watch -- tsx dev.ts
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
It watches the working directory, plus the paths Yulin is holding that a module graph never mentions:
|
|
233
|
+
a directory mounted into a Bucket, and a synthesized template. See the
|
|
234
|
+
[serving docs](./docs/serve "Serving simulated AWS on localhost docs") for what gets the script, what
|
|
235
|
+
is watched, and what is not.
|
|
236
|
+
|
|
237
|
+
#### Update a stack when its template changes
|
|
238
|
+
|
|
239
|
+
A synthesized template is data rather than code, so a change to one does not need the process
|
|
240
|
+
restarted. Deploy it with `watch` and Yulin applies the file again whenever it changes, updating the
|
|
241
|
+
stack in place:
|
|
242
|
+
|
|
243
|
+
```typescript
|
|
244
|
+
await simAws.cloudFormation().deployTemplateFile({
|
|
245
|
+
templatePath: "cdk.out/SiteStack.template.json",
|
|
246
|
+
watch: {
|
|
247
|
+
onUpdated: () => {
|
|
248
|
+
srv.reload();
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
});
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
Resources the change left alone keep what they hold, so simulated S3, DynamoDB and SQS survive a
|
|
255
|
+
`cdk synth`. Under `yulin watch` the template is left to the process watching it rather than being a
|
|
256
|
+
reason to restart. See the
|
|
257
|
+
[CloudFormation docs](./docs/services/cloudformation "Simulated CloudFormation docs") for what an
|
|
258
|
+
update does to each resource.
|
|
259
|
+
|
|
188
260
|
### Control simulated time
|
|
189
261
|
|
|
190
262
|
Each simulated AWS has its own clock, which you can freeze, set, or advance. This lets a test
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown for a command the CLI does not have.
|
|
3
|
+
*/
|
|
4
|
+
export declare class SimCliUnknownCommand extends Error {
|
|
5
|
+
readonly name = "SimCliUnknownCommand";
|
|
6
|
+
constructor(command: string);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The `yulin` command line.
|
|
10
|
+
*
|
|
11
|
+
* One command so far. It exists because a local dev loop needs a process
|
|
12
|
+
* outside the one being restarted, which is not something a library can be.
|
|
13
|
+
*/
|
|
14
|
+
export declare class SimCli {
|
|
15
|
+
/**
|
|
16
|
+
* Run the CLI, and report the exit code it should leave behind.
|
|
17
|
+
*/
|
|
18
|
+
run(argv: readonly string[]): Promise<number>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=sim-cli.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sim-cli.d.ts","sourceRoot":"","sources":["../../src/cli/sim-cli.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,SAAyB,IAAI,0BAA0B;IAEvD,YAAY,OAAO,EAAE,MAAM,EAE1B;CACF;AAED;;;;;GAKG;AACH,qBAAa,MAAM;IACjB;;OAEG;IACG,GAAG,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAkBlD;CACF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { SimWatchCommand } from "./watch/sim-watch-command.js";
|
|
2
|
+
const usage = `Usage: yulin <command>
|
|
3
|
+
|
|
4
|
+
Commands:
|
|
5
|
+
watch [--inspect[=port]] -- <command> Run a command, and run it again when project files change
|
|
6
|
+
`;
|
|
7
|
+
/**
|
|
8
|
+
* Thrown for a command the CLI does not have.
|
|
9
|
+
*/
|
|
10
|
+
export class SimCliUnknownCommand extends Error {
|
|
11
|
+
name = "SimCliUnknownCommand";
|
|
12
|
+
constructor(command) {
|
|
13
|
+
super(`Unknown command ${command}.\n\n${usage}`);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The `yulin` command line.
|
|
18
|
+
*
|
|
19
|
+
* One command so far. It exists because a local dev loop needs a process
|
|
20
|
+
* outside the one being restarted, which is not something a library can be.
|
|
21
|
+
*/
|
|
22
|
+
export class SimCli {
|
|
23
|
+
/**
|
|
24
|
+
* Run the CLI, and report the exit code it should leave behind.
|
|
25
|
+
*/
|
|
26
|
+
async run(argv) {
|
|
27
|
+
const [command, ...rest] = argv;
|
|
28
|
+
if (command === undefined) {
|
|
29
|
+
process.stdout.write(usage);
|
|
30
|
+
return 1;
|
|
31
|
+
}
|
|
32
|
+
if (["--help", "-h", "help"].includes(command)) {
|
|
33
|
+
process.stdout.write(usage);
|
|
34
|
+
return 0;
|
|
35
|
+
}
|
|
36
|
+
if (command !== "watch") {
|
|
37
|
+
throw new SimCliUnknownCommand(command);
|
|
38
|
+
}
|
|
39
|
+
return await new SimWatchCommand().run(rest);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=sim-cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sim-cli.js","sourceRoot":"","sources":["../../src/cli/sim-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAE/D,MAAM,KAAK,GAAG;;;;CAIb,CAAC;AAEF;;GAEG;AACH,MAAM,OAAO,oBAAqB,SAAQ,KAAK;IACpB,IAAI,GAAG,sBAAsB,CAAC;IAEvD,YAAY,OAAe;QACzB,KAAK,CAAC,mBAAmB,OAAO,QAAQ,KAAK,EAAE,CAAC,CAAC;IACnD,CAAC;CACF;AAED;;;;;GAKG;AACH,MAAM,OAAO,MAAM;IACjB;;OAEG;IACH,KAAK,CAAC,GAAG,CAAC,IAAuB;QAC/B,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;QAEhC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC5B,OAAO,CAAC,CAAC;QACX,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC5B,OAAO,CAAC,CAAC;QACX,CAAC;QAED,IAAI,OAAO,KAAK,OAAO,EAAE,CAAC;YACxB,MAAM,IAAI,oBAAoB,CAAC,OAAO,CAAC,CAAC;QAC1C,CAAC;QAED,OAAO,MAAM,IAAI,eAAe,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC;CACF"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thrown when `yulin watch` was not given something to run.
|
|
3
|
+
*/
|
|
4
|
+
export declare class SimWatchUsageError extends Error {
|
|
5
|
+
readonly name = "SimWatchUsageError";
|
|
6
|
+
constructor(message: string);
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* What `yulin watch` was asked to do.
|
|
10
|
+
*
|
|
11
|
+
* Everything after `--` is the command, passed through untouched. The CLI does
|
|
12
|
+
* not import the command, look for an exported setup function, or care whether
|
|
13
|
+
* the simulation it builds came from SDK commands, a template, or several
|
|
14
|
+
* `SimAws` instances at once. It runs it and runs it again.
|
|
15
|
+
*/
|
|
16
|
+
export declare class SimWatchArguments {
|
|
17
|
+
readonly command: string;
|
|
18
|
+
readonly commandArguments: readonly string[];
|
|
19
|
+
readonly inspect: string | undefined;
|
|
20
|
+
private constructor();
|
|
21
|
+
/**
|
|
22
|
+
* Read the arguments given after `yulin watch`.
|
|
23
|
+
*/
|
|
24
|
+
static parse(argv: readonly string[]): SimWatchArguments;
|
|
25
|
+
/**
|
|
26
|
+
* The command as it was written, for reporting.
|
|
27
|
+
*/
|
|
28
|
+
describe(): string;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=sim-watch-arguments.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sim-watch-arguments.d.ts","sourceRoot":"","sources":["../../../src/cli/watch/sim-watch-arguments.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,SAAyB,IAAI,wBAAwB;IAErD,YAAY,OAAO,EAAE,MAAM,EAE1B;CACF;AAED;;;;;;;GAOG;AACH,qBAAa,iBAAiB;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,gBAAgB,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7C,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAErC,OAAO,eAQN;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,iBAAiB,CAoBvD;IAED;;OAEG;IACH,QAAQ,IAAI,MAAM,CAEjB;CACF"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
const inspectorFlags = new Set([
|
|
2
|
+
"--inspect",
|
|
3
|
+
"--inspect-brk",
|
|
4
|
+
"--inspect-wait",
|
|
5
|
+
]);
|
|
6
|
+
/**
|
|
7
|
+
* Thrown when `yulin watch` was not given something to run.
|
|
8
|
+
*/
|
|
9
|
+
export class SimWatchUsageError extends Error {
|
|
10
|
+
name = "SimWatchUsageError";
|
|
11
|
+
constructor(message) {
|
|
12
|
+
super(`${message}\n\nUsage: yulin watch [--inspect[=port]] -- <command>`);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* What `yulin watch` was asked to do.
|
|
17
|
+
*
|
|
18
|
+
* Everything after `--` is the command, passed through untouched. The CLI does
|
|
19
|
+
* not import the command, look for an exported setup function, or care whether
|
|
20
|
+
* the simulation it builds came from SDK commands, a template, or several
|
|
21
|
+
* `SimAws` instances at once. It runs it and runs it again.
|
|
22
|
+
*/
|
|
23
|
+
export class SimWatchArguments {
|
|
24
|
+
command;
|
|
25
|
+
commandArguments;
|
|
26
|
+
inspect;
|
|
27
|
+
constructor(command, commandArguments, inspect) {
|
|
28
|
+
this.command = command;
|
|
29
|
+
this.commandArguments = commandArguments;
|
|
30
|
+
this.inspect = inspect;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Read the arguments given after `yulin watch`.
|
|
34
|
+
*/
|
|
35
|
+
static parse(argv) {
|
|
36
|
+
const separator = argv.indexOf("--");
|
|
37
|
+
if (separator === -1) {
|
|
38
|
+
throw new SimWatchUsageError("No command given. Put the command to run after --, so that its own options are not read as options to watch.");
|
|
39
|
+
}
|
|
40
|
+
const [command, ...rest] = argv.slice(separator + 1);
|
|
41
|
+
if (command === undefined) {
|
|
42
|
+
throw new SimWatchUsageError("No command given after --.");
|
|
43
|
+
}
|
|
44
|
+
return new SimWatchArguments(command, rest, inspectorFlag(argv.slice(0, separator)));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* The command as it was written, for reporting.
|
|
48
|
+
*/
|
|
49
|
+
describe() {
|
|
50
|
+
return [this.command, ...this.commandArguments].join(" ");
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* The inspector flag to pass through to each run, if one was asked for.
|
|
55
|
+
*/
|
|
56
|
+
function inspectorFlag(options) {
|
|
57
|
+
const unknown = options.find((option) => !isInspectorFlag(option));
|
|
58
|
+
if (unknown !== undefined) {
|
|
59
|
+
throw new SimWatchUsageError(`Unknown option ${unknown}.`);
|
|
60
|
+
}
|
|
61
|
+
return options.at(-1);
|
|
62
|
+
}
|
|
63
|
+
function isInspectorFlag(option) {
|
|
64
|
+
const [flag = ""] = option.split("=");
|
|
65
|
+
return inspectorFlags.has(flag);
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=sim-watch-arguments.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sim-watch-arguments.js","sourceRoot":"","sources":["../../../src/cli/watch/sim-watch-arguments.ts"],"names":[],"mappings":"AAAA,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,WAAW;IACX,eAAe;IACf,gBAAgB;CACjB,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAClB,IAAI,GAAG,oBAAoB,CAAC;IAErD,YAAY,OAAe;QACzB,KAAK,CAAC,GAAG,OAAO,wDAAwD,CAAC,CAAC;IAC5E,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,iBAAiB;IACnB,OAAO,CAAS;IAChB,gBAAgB,CAAoB;IACpC,OAAO,CAAqB;IAErC,YACE,OAAe,EACf,gBAAmC,EACnC,OAA2B;QAE3B,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;QACzC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;IAED;;OAEG;IACH,MAAM,CAAC,KAAK,CAAC,IAAuB;QAClC,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAErC,IAAI,SAAS,KAAK,CAAC,CAAC,EAAE,CAAC;YACrB,MAAM,IAAI,kBAAkB,CAC1B,8GAA8G,CAC/G,CAAC;QACJ,CAAC;QAED,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC;QAErD,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;YAC1B,MAAM,IAAI,kBAAkB,CAAC,4BAA4B,CAAC,CAAC;QAC7D,CAAC;QAED,OAAO,IAAI,iBAAiB,CAC1B,OAAO,EACP,IAAI,EACJ,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CACxC,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,QAAQ;QACN,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC5D,CAAC;CACF;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,OAA0B;IAC/C,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC;IAEnE,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,IAAI,kBAAkB,CAAC,kBAAkB,OAAO,GAAG,CAAC,CAAC;IAC7D,CAAC;IAED,OAAO,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACxB,CAAC;AAED,SAAS,eAAe,CAAC,MAAc;IACrC,MAAM,CAAC,IAAI,GAAG,EAAE,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAEtC,OAAO,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
interface SimWatchChildEnvironmentProperties {
|
|
2
|
+
readonly cwd: string;
|
|
3
|
+
readonly inspect?: string | undefined;
|
|
4
|
+
readonly environment?: NodeJS.ProcessEnv;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* The environment a supervised process runs in.
|
|
8
|
+
*
|
|
9
|
+
* Three things are added to the environment the supervisor was given. The
|
|
10
|
+
* project's own `node_modules/.bin` goes on `PATH`, so `yulin watch -- tsx
|
|
11
|
+
* dev.ts` works from a plain shell as well as from a package script. A marker
|
|
12
|
+
* says a supervisor is listening, which is what makes the runtime in the child
|
|
13
|
+
* report paths at all. An inspector flag goes through `NODE_OPTIONS` rather
|
|
14
|
+
* than on the command line, because the command being run is often not `node`
|
|
15
|
+
* itself.
|
|
16
|
+
*/
|
|
17
|
+
export declare class SimWatchChildEnvironment {
|
|
18
|
+
private readonly cwd;
|
|
19
|
+
private readonly inspect;
|
|
20
|
+
private readonly environment;
|
|
21
|
+
constructor(properties: SimWatchChildEnvironmentProperties);
|
|
22
|
+
/**
|
|
23
|
+
* Build the environment for one run of the supervised command.
|
|
24
|
+
*/
|
|
25
|
+
build(): NodeJS.ProcessEnv;
|
|
26
|
+
private pathWithLocalBin;
|
|
27
|
+
private nodeOptionsWithInspector;
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=sim-watch-child-environment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sim-watch-child-environment.d.ts","sourceRoot":"","sources":["../../../src/cli/watch/sim-watch-child-environment.ts"],"names":[],"mappings":"AAKA,UAAU,kCAAkC;IAC1C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;CAC1C;AAED;;;;;;;;;;GAUG;AACH,qBAAa,wBAAwB;IACnC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAqB;IAC7C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAoB;IAEhD,YAAY,UAAU,EAAE,kCAAkC,EAKzD;IAED;;OAEG;IACH,KAAK,IAAI,MAAM,CAAC,UAAU,CAUzB;IAED,OAAO,CAAC,gBAAgB;IAWxB,OAAO,CAAC,wBAAwB;CAKjC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import { simWatchConfig } from "../../watch/sim-watch.config.js";
|
|
3
|
+
const nodeOptionsName = "NODE_OPTIONS";
|
|
4
|
+
/**
|
|
5
|
+
* The environment a supervised process runs in.
|
|
6
|
+
*
|
|
7
|
+
* Three things are added to the environment the supervisor was given. The
|
|
8
|
+
* project's own `node_modules/.bin` goes on `PATH`, so `yulin watch -- tsx
|
|
9
|
+
* dev.ts` works from a plain shell as well as from a package script. A marker
|
|
10
|
+
* says a supervisor is listening, which is what makes the runtime in the child
|
|
11
|
+
* report paths at all. An inspector flag goes through `NODE_OPTIONS` rather
|
|
12
|
+
* than on the command line, because the command being run is often not `node`
|
|
13
|
+
* itself.
|
|
14
|
+
*/
|
|
15
|
+
export class SimWatchChildEnvironment {
|
|
16
|
+
cwd;
|
|
17
|
+
inspect;
|
|
18
|
+
environment;
|
|
19
|
+
constructor(properties) {
|
|
20
|
+
const { cwd, inspect, environment = process.env } = properties;
|
|
21
|
+
this.cwd = cwd;
|
|
22
|
+
this.inspect = inspect;
|
|
23
|
+
this.environment = environment;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Build the environment for one run of the supervised command.
|
|
27
|
+
*/
|
|
28
|
+
build() {
|
|
29
|
+
return {
|
|
30
|
+
...this.environment,
|
|
31
|
+
PATH: this.pathWithLocalBin(),
|
|
32
|
+
[simWatchConfig.environmentVariableName]: simWatchConfig.environmentVariableValue,
|
|
33
|
+
...(this.inspect !== undefined && {
|
|
34
|
+
[nodeOptionsName]: this.nodeOptionsWithInspector(this.inspect),
|
|
35
|
+
}),
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
pathWithLocalBin() {
|
|
39
|
+
const localBin = path.join(this.cwd, "node_modules", ".bin");
|
|
40
|
+
const existing = this.environment["PATH"] ?? "";
|
|
41
|
+
if (existing.split(path.delimiter).includes(localBin)) {
|
|
42
|
+
return existing;
|
|
43
|
+
}
|
|
44
|
+
return `${localBin}${path.delimiter}${existing}`;
|
|
45
|
+
}
|
|
46
|
+
nodeOptionsWithInspector(inspect) {
|
|
47
|
+
const existing = this.environment["NODE_OPTIONS"] ?? "";
|
|
48
|
+
return `${existing} ${inspect}`.trim();
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=sim-watch-child-environment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sim-watch-child-environment.js","sourceRoot":"","sources":["../../../src/cli/watch/sim-watch-child-environment.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,iCAAiC,CAAC;AAEjE,MAAM,eAAe,GAAG,cAAc,CAAC;AAQvC;;;;;;;;;;GAUG;AACH,MAAM,OAAO,wBAAwB;IAClB,GAAG,CAAS;IACZ,OAAO,CAAqB;IAC5B,WAAW,CAAoB;IAEhD,YAAY,UAA8C;QACxD,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,GAAG,EAAE,GAAG,UAAU,CAAC;QAC/D,IAAI,CAAC,GAAG,GAAG,GAAG,CAAC;QACf,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,KAAK;QACH,OAAO;YACL,GAAG,IAAI,CAAC,WAAW;YACnB,IAAI,EAAE,IAAI,CAAC,gBAAgB,EAAE;YAC7B,CAAC,cAAc,CAAC,uBAAuB,CAAC,EACtC,cAAc,CAAC,wBAAwB;YACzC,GAAG,CAAC,IAAI,CAAC,OAAO,KAAK,SAAS,IAAI;gBAChC,CAAC,eAAe,CAAC,EAAE,IAAI,CAAC,wBAAwB,CAAC,IAAI,CAAC,OAAO,CAAC;aAC/D,CAAC;SACH,CAAC;IACJ,CAAC;IAEO,gBAAgB;QACtB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,EAAE,MAAM,CAAC,CAAC;QAC7D,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QAEhD,IAAI,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACtD,OAAO,QAAQ,CAAC;QAClB,CAAC;QAED,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC,SAAS,GAAG,QAAQ,EAAE,CAAC;IACnD,CAAC;IAEO,wBAAwB,CAAC,OAAe;QAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QAExD,OAAO,GAAG,QAAQ,IAAI,OAAO,EAAE,CAAC,IAAI,EAAE,CAAC;IACzC,CAAC;CACF"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ChildProcess } from "node:child_process";
|
|
2
|
+
/**
|
|
3
|
+
* Whether an IPC message is one of the kind named.
|
|
4
|
+
*/
|
|
5
|
+
export declare function isWatchMessage(message: unknown, type: string): boolean;
|
|
6
|
+
/**
|
|
7
|
+
* Whether an IPC message names a path to watch.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isWatchPathMessage(message: unknown, type: string): message is {
|
|
10
|
+
readonly path: string;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Wait for a process to send a message of one kind, and give up after a while.
|
|
14
|
+
*
|
|
15
|
+
* A process not running Yulin's runtime never answers, so this is a short wait
|
|
16
|
+
* rather than a requirement.
|
|
17
|
+
*/
|
|
18
|
+
export declare function waitWatchMessage(childProcess: ChildProcess, type: string, withinMs: number): Promise<void>;
|
|
19
|
+
//# sourceMappingURL=sim-watch-child-message.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sim-watch-child-message.d.ts","sourceRoot":"","sources":["../../../src/cli/watch/sim-watch-child-message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD;;GAEG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAOtE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,GACX,OAAO,IAAI;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAQtC;AAED;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,YAAY,EAAE,YAAY,EAC1B,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,IAAI,CAAC,CAkBf"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether an IPC message is one of the kind named.
|
|
3
|
+
*/
|
|
4
|
+
export function isWatchMessage(message, type) {
|
|
5
|
+
return (typeof message === "object" &&
|
|
6
|
+
message !== null &&
|
|
7
|
+
"type" in message &&
|
|
8
|
+
message.type === type);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Whether an IPC message names a path to watch.
|
|
12
|
+
*/
|
|
13
|
+
export function isWatchPathMessage(message, type) {
|
|
14
|
+
return (isWatchMessage(message, type) &&
|
|
15
|
+
typeof message === "object" &&
|
|
16
|
+
message !== null &&
|
|
17
|
+
"path" in message &&
|
|
18
|
+
typeof message.path === "string");
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Wait for a process to send a message of one kind, and give up after a while.
|
|
22
|
+
*
|
|
23
|
+
* A process not running Yulin's runtime never answers, so this is a short wait
|
|
24
|
+
* rather than a requirement.
|
|
25
|
+
*/
|
|
26
|
+
export async function waitWatchMessage(childProcess, type, withinMs) {
|
|
27
|
+
await new Promise((resolve) => {
|
|
28
|
+
const done = () => {
|
|
29
|
+
clearTimeout(timer);
|
|
30
|
+
childProcess.off("message", onMessage);
|
|
31
|
+
resolve();
|
|
32
|
+
};
|
|
33
|
+
const onMessage = (message) => {
|
|
34
|
+
if (isWatchMessage(message, type)) {
|
|
35
|
+
done();
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
const timer = setTimeout(done, withinMs);
|
|
39
|
+
childProcess.on("message", onMessage);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=sim-watch-child-message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sim-watch-child-message.js","sourceRoot":"","sources":["../../../src/cli/watch/sim-watch-child-message.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,OAAgB,EAAE,IAAY;IAC3D,OAAO,CACL,OAAO,OAAO,KAAK,QAAQ;QAC3B,OAAO,KAAK,IAAI;QAChB,MAAM,IAAI,OAAO;QACjB,OAAO,CAAC,IAAI,KAAK,IAAI,CACtB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB,CAChC,OAAgB,EAChB,IAAY;IAEZ,OAAO,CACL,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC;QAC7B,OAAO,OAAO,KAAK,QAAQ;QAC3B,OAAO,KAAK,IAAI;QAChB,MAAM,IAAI,OAAO;QACjB,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CACjC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,YAA0B,EAC1B,IAAY,EACZ,QAAgB;IAEhB,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;QAClC,MAAM,IAAI,GAAG,GAAS,EAAE;YACtB,YAAY,CAAC,KAAK,CAAC,CAAC;YACpB,YAAY,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;YACvC,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC;QAEF,MAAM,SAAS,GAAG,CAAC,OAAgB,EAAQ,EAAE;YAC3C,IAAI,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;gBAClC,IAAI,EAAE,CAAC;YACT,CAAC;QACH,CAAC,CAAC;QAEF,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QAEzC,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC;IACxC,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { type ChildProcess } from "node:child_process";
|
|
2
|
+
interface SimWatchChildProcessProperties {
|
|
3
|
+
readonly command: string;
|
|
4
|
+
readonly args: readonly string[];
|
|
5
|
+
readonly cwd: string;
|
|
6
|
+
readonly env: NodeJS.ProcessEnv;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* A spawned command, and the two moments in its life a supervisor waits on.
|
|
10
|
+
*
|
|
11
|
+
* Standard input, output and error are the supervisor's own, so the process
|
|
12
|
+
* being watched prints where it would have printed if it had been started by
|
|
13
|
+
* hand. The fourth channel is what the runtime inside it reports paths over.
|
|
14
|
+
*/
|
|
15
|
+
export declare class SimWatchChildProcess {
|
|
16
|
+
readonly process: ChildProcess;
|
|
17
|
+
readonly spawned: Promise<void>;
|
|
18
|
+
readonly finished: Promise<void>;
|
|
19
|
+
constructor(properties: SimWatchChildProcessProperties);
|
|
20
|
+
}
|
|
21
|
+
export {};
|
|
22
|
+
//# sourceMappingURL=sim-watch-child-process.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sim-watch-child-process.d.ts","sourceRoot":"","sources":["../../../src/cli/watch/sim-watch-child-process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,YAAY,EAAS,MAAM,oBAAoB,CAAC;AAE9D,UAAU,8BAA8B;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;CACjC;AAED;;;;;;GAMG;AACH,qBAAa,oBAAoB;IAC/B,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjC,YAAY,UAAU,EAAE,8BAA8B,EAqBrD;CACF"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
/**
|
|
3
|
+
* A spawned command, and the two moments in its life a supervisor waits on.
|
|
4
|
+
*
|
|
5
|
+
* Standard input, output and error are the supervisor's own, so the process
|
|
6
|
+
* being watched prints where it would have printed if it had been started by
|
|
7
|
+
* hand. The fourth channel is what the runtime inside it reports paths over.
|
|
8
|
+
*/
|
|
9
|
+
export class SimWatchChildProcess {
|
|
10
|
+
process;
|
|
11
|
+
spawned;
|
|
12
|
+
finished;
|
|
13
|
+
constructor(properties) {
|
|
14
|
+
const { command, args, cwd, env } = properties;
|
|
15
|
+
this.process = spawn(command, [...args], {
|
|
16
|
+
cwd,
|
|
17
|
+
env,
|
|
18
|
+
stdio: ["inherit", "inherit", "inherit", "ipc"],
|
|
19
|
+
});
|
|
20
|
+
this.spawned = new Promise((resolve, reject) => {
|
|
21
|
+
this.process.once("spawn", resolve);
|
|
22
|
+
this.process.once("error", (error) => {
|
|
23
|
+
reject(new Error(`Could not run ${command}: ${error.message}`));
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
this.finished = new Promise((resolve) => {
|
|
27
|
+
this.process.once("exit", () => {
|
|
28
|
+
resolve();
|
|
29
|
+
});
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=sim-watch-child-process.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sim-watch-child-process.js","sourceRoot":"","sources":["../../../src/cli/watch/sim-watch-child-process.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAS9D;;;;;;GAMG;AACH,MAAM,OAAO,oBAAoB;IACtB,OAAO,CAAe;IACtB,OAAO,CAAgB;IACvB,QAAQ,CAAgB;IAEjC,YAAY,UAA0C;QACpD,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,UAAU,CAAC;QAE/C,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE;YACvC,GAAG;YACH,GAAG;YACH,KAAK,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,KAAK,CAAC;SAChD,CAAC,CAAC;QAEH,IAAI,CAAC,OAAO,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YACnD,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;YACpC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAY,EAAE,EAAE;gBAC1C,MAAM,CAAC,IAAI,KAAK,CAAC,iBAAiB,OAAO,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAClE,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,GAAG,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE;YAC5C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE;gBAC7B,OAAO,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ChildProcess } from "node:child_process";
|
|
2
|
+
interface SimWatchChildShutdownProperties {
|
|
3
|
+
readonly process: ChildProcess;
|
|
4
|
+
readonly finished: Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Takes a supervised process down, in the order that lets it say goodbye.
|
|
8
|
+
*
|
|
9
|
+
* A process running Yulin's runtime is warned first, so a served page hears
|
|
10
|
+
* that a reload is coming rather than only seeing its connection go, and is
|
|
11
|
+
* killed as soon as it says it has passed that on. One that does not answer,
|
|
12
|
+
* because it is serving nothing or is not a Yulin process at all, is killed
|
|
13
|
+
* when the short wait runs out. Either way it is killed, and killed harder if
|
|
14
|
+
* it will not go, because the port has to be free for the process replacing it.
|
|
15
|
+
*/
|
|
16
|
+
export declare class SimWatchChildShutdown {
|
|
17
|
+
private readonly process;
|
|
18
|
+
private readonly finished;
|
|
19
|
+
constructor(properties: SimWatchChildShutdownProperties);
|
|
20
|
+
/**
|
|
21
|
+
* Stop the process, and wait until it has gone.
|
|
22
|
+
*/
|
|
23
|
+
stop(): Promise<void>;
|
|
24
|
+
private warn;
|
|
25
|
+
private gone;
|
|
26
|
+
}
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=sim-watch-child-shutdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sim-watch-child-shutdown.d.ts","sourceRoot":"","sources":["../../../src/cli/watch/sim-watch-child-shutdown.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAOvD,UAAU,+BAA+B;IACvC,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;CAClC;AAED;;;;;;;;;GASG;AACH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IAEzC,YAAY,UAAU,EAAE,+BAA+B,EAItD;IAED;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAI1B;YAEa,IAAI;YA0BJ,IAAI;CAWnB"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { simWatchConfig, simWatchMessages, } from "../../watch/sim-watch.config.js";
|
|
2
|
+
import { waitWatchMessage } from "./sim-watch-child-message.js";
|
|
3
|
+
/**
|
|
4
|
+
* Takes a supervised process down, in the order that lets it say goodbye.
|
|
5
|
+
*
|
|
6
|
+
* A process running Yulin's runtime is warned first, so a served page hears
|
|
7
|
+
* that a reload is coming rather than only seeing its connection go, and is
|
|
8
|
+
* killed as soon as it says it has passed that on. One that does not answer,
|
|
9
|
+
* because it is serving nothing or is not a Yulin process at all, is killed
|
|
10
|
+
* when the short wait runs out. Either way it is killed, and killed harder if
|
|
11
|
+
* it will not go, because the port has to be free for the process replacing it.
|
|
12
|
+
*/
|
|
13
|
+
export class SimWatchChildShutdown {
|
|
14
|
+
process;
|
|
15
|
+
finished;
|
|
16
|
+
constructor(properties) {
|
|
17
|
+
const { process: childProcess, finished } = properties;
|
|
18
|
+
this.process = childProcess;
|
|
19
|
+
this.finished = finished;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Stop the process, and wait until it has gone.
|
|
23
|
+
*/
|
|
24
|
+
async stop() {
|
|
25
|
+
await this.warn();
|
|
26
|
+
this.process.kill("SIGTERM");
|
|
27
|
+
await this.gone();
|
|
28
|
+
}
|
|
29
|
+
async warn() {
|
|
30
|
+
if (!this.process.connected) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const acknowledged = Promise.race([
|
|
34
|
+
this.finished,
|
|
35
|
+
waitWatchMessage(this.process, simWatchMessages.stopped, simWatchConfig.stoppingMs),
|
|
36
|
+
]);
|
|
37
|
+
// The channel can close between being asked whether it is open and being
|
|
38
|
+
// written to, because the process is free to exit in between. The callback
|
|
39
|
+
// is where that failure goes; without one it reaches the process as an
|
|
40
|
+
// error event, and a warning that could not be delivered is not a reason to
|
|
41
|
+
// stop taking the process down.
|
|
42
|
+
this.process.send({ type: simWatchMessages.stopping }, () => {
|
|
43
|
+
// Nothing to do about a process that has already gone.
|
|
44
|
+
});
|
|
45
|
+
await acknowledged;
|
|
46
|
+
}
|
|
47
|
+
async gone() {
|
|
48
|
+
const timer = setTimeout(() => {
|
|
49
|
+
this.process.kill("SIGKILL");
|
|
50
|
+
}, simWatchConfig.exitMs);
|
|
51
|
+
try {
|
|
52
|
+
await this.finished;
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
clearTimeout(timer);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=sim-watch-child-shutdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sim-watch-child-shutdown.js","sourceRoot":"","sources":["../../../src/cli/watch/sim-watch-child-shutdown.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EACd,gBAAgB,GACjB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAOhE;;;;;;;;;GASG;AACH,MAAM,OAAO,qBAAqB;IACf,OAAO,CAAe;IACtB,QAAQ,CAAgB;IAEzC,YAAY,UAA2C;QACrD,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAC;QACvD,IAAI,CAAC,OAAO,GAAG,YAAY,CAAC;QAC5B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,IAAI;QACR,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC7B,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;IACpB,CAAC;IAEO,KAAK,CAAC,IAAI;QAChB,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;YAC5B,OAAO;QACT,CAAC;QAED,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;YAChC,IAAI,CAAC,QAAQ;YACb,gBAAgB,CACd,IAAI,CAAC,OAAO,EACZ,gBAAgB,CAAC,OAAO,EACxB,cAAc,CAAC,UAAU,CAC1B;SACF,CAAC,CAAC;QAEH,yEAAyE;QACzE,2EAA2E;QAC3E,uEAAuE;QACvE,4EAA4E;QAC5E,gCAAgC;QAChC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,gBAAgB,CAAC,QAAQ,EAAE,EAAE,GAAG,EAAE;YAC1D,uDAAuD;QACzD,CAAC,CAAC,CAAC;QAEH,MAAM,YAAY,CAAC;IACrB,CAAC;IAEO,KAAK,CAAC,IAAI;QAChB,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;YAC5B,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/B,CAAC,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;QAE1B,IAAI,CAAC;YACH,MAAM,IAAI,CAAC,QAAQ,CAAC;QACtB,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
interface SimWatchChildProperties {
|
|
2
|
+
readonly command: string;
|
|
3
|
+
readonly args: readonly string[];
|
|
4
|
+
readonly cwd: string;
|
|
5
|
+
readonly env: NodeJS.ProcessEnv;
|
|
6
|
+
readonly onPath: (reportedPath: string) => void;
|
|
7
|
+
readonly onHeldPath: (heldPath: string) => void;
|
|
8
|
+
readonly onExit: (code: number | null, signal: NodeJS.Signals | null) => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* One run of the supervised command.
|
|
12
|
+
*
|
|
13
|
+
* A restart is a new instance of this rather than anything swapped in place. A
|
|
14
|
+
* handler is a function reference out of the user's own module graph, and a new
|
|
15
|
+
* process re-imports it with no module cache to defeat, so a restart is correct
|
|
16
|
+
* by construction where an in-process swap would have to invalidate an import
|
|
17
|
+
* graph that ESM does not expose.
|
|
18
|
+
*/
|
|
19
|
+
export declare class SimWatchChild {
|
|
20
|
+
private readonly properties;
|
|
21
|
+
private readonly run;
|
|
22
|
+
private readonly startedAt;
|
|
23
|
+
private stopping;
|
|
24
|
+
private readonly onMessage;
|
|
25
|
+
private readonly onProcessExit;
|
|
26
|
+
constructor(properties: SimWatchChildProperties);
|
|
27
|
+
/**
|
|
28
|
+
* How long this process has been running.
|
|
29
|
+
*/
|
|
30
|
+
ranForMs(): number;
|
|
31
|
+
/**
|
|
32
|
+
* Fail if the command could not be run at all, rather than letting it look
|
|
33
|
+
* like a process that started and stopped.
|
|
34
|
+
*/
|
|
35
|
+
started(): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Stop this process, giving it a moment to tell its browsers first.
|
|
38
|
+
*/
|
|
39
|
+
stop(): Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
export {};
|
|
42
|
+
//# sourceMappingURL=sim-watch-child.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sim-watch-child.d.ts","sourceRoot":"","sources":["../../../src/cli/watch/sim-watch-child.ts"],"names":[],"mappings":"AAKA,UAAU,uBAAuB;IAC/B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,CAAC;IACjC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC,UAAU,CAAC;IAChC,QAAQ,CAAC,MAAM,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,QAAQ,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IAChD,QAAQ,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,IAAI,KAAK,IAAI,CAAC;CAC/E;AAED;;;;;;;;GAQG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAA0B;IACrD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAuB;IAC3C,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAc;IACxC,OAAO,CAAC,QAAQ,CAAS;IAEzB,OAAO,CAAC,QAAQ,CAAC,SAAS,CAQxB;IAEF,OAAO,CAAC,QAAQ,CAAC,aAAa,CAO5B;IAEF,YAAY,UAAU,EAAE,uBAAuB,EAM9C;IAED;;OAEG;IACH,QAAQ,IAAI,MAAM,CAEjB;IAED;;;OAGG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAE7B;IAED;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAO1B;CACF"}
|