@graftland/cli 0.3.3 → 0.4.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.
Files changed (57) hide show
  1. package/README.md +3 -2
  2. package/README.zh-CN.md +2 -2
  3. package/README.zh-TW.md +2 -2
  4. package/dist/Application.d.ts +27 -0
  5. package/dist/Application.d.ts.map +1 -0
  6. package/dist/Application.js +27 -0
  7. package/dist/Application.js.map +1 -0
  8. package/dist/Commands.d.ts +34 -0
  9. package/dist/Commands.d.ts.map +1 -0
  10. package/dist/Commands.js +31 -0
  11. package/dist/Commands.js.map +1 -0
  12. package/dist/Manage.d.ts +7 -10
  13. package/dist/Manage.d.ts.map +1 -1
  14. package/dist/Manage.js +61 -15
  15. package/dist/Manage.js.map +1 -1
  16. package/dist/Start.d.ts +2 -1
  17. package/dist/Start.d.ts.map +1 -1
  18. package/dist/Start.js +25 -9
  19. package/dist/Start.js.map +1 -1
  20. package/dist/bin.js +39 -16
  21. package/dist/bin.js.map +1 -1
  22. package/dist/index.d.ts +3 -1
  23. package/dist/index.js +3 -1
  24. package/dist/internal/commandConfig.js +62 -0
  25. package/dist/internal/commandConfig.js.map +1 -0
  26. package/dist/internal/commandHost.js +80 -0
  27. package/dist/internal/commandHost.js.map +1 -0
  28. package/dist/internal/commandRegistry.js +59 -0
  29. package/dist/internal/commandRegistry.js.map +1 -0
  30. package/dist/internal/configSchema.d.ts +25 -4
  31. package/dist/internal/configSchema.d.ts.map +1 -1
  32. package/dist/internal/configSchema.js +6 -34
  33. package/dist/internal/configSchema.js.map +1 -1
  34. package/dist/internal/env.js.map +1 -1
  35. package/dist/internal/importer.js +18 -0
  36. package/dist/internal/importer.js.map +1 -0
  37. package/dist/internal/intercepts.js.map +1 -1
  38. package/dist/internal/protocolOutput.js +67 -0
  39. package/dist/internal/protocolOutput.js.map +1 -0
  40. package/dist/internal/watch.js.map +1 -1
  41. package/package.json +10 -7
  42. package/schema.json +2321 -0
  43. package/src/Application.ts +55 -0
  44. package/src/Commands.ts +47 -0
  45. package/src/Manage.ts +78 -19
  46. package/src/Start.ts +100 -28
  47. package/src/bin.ts +81 -34
  48. package/src/index.ts +3 -0
  49. package/src/internal/commandConfig.ts +91 -0
  50. package/src/internal/commandHost.ts +216 -0
  51. package/src/internal/commandRegistry.ts +100 -0
  52. package/src/internal/configSchema.ts +10 -70
  53. package/src/internal/env.ts +3 -2
  54. package/src/internal/importer.ts +28 -0
  55. package/src/internal/intercepts.ts +2 -1
  56. package/src/internal/protocolOutput.ts +101 -0
  57. package/src/internal/watch.ts +4 -2
package/README.md CHANGED
@@ -11,8 +11,9 @@ The `graft` command: `start`, `create`, `add` and `remove`.
11
11
  npm install @graftland/cli effect
12
12
  ```
13
13
 
14
- Create a project with `npx @graftland/cli create my-app --install`. Then run it
15
- with `npx graft start --watch`. You need Node.js 22.19 or later.
14
+ Create a project with `npm create @graftland@latest my-app`, which runs the same
15
+ `create` command. Then run it with `npm run dev`. You need Node.js 22.19 or
16
+ later.
16
17
 
17
18
  ## Documentation
18
19
 
package/README.zh-CN.md CHANGED
@@ -10,8 +10,8 @@
10
10
  npm install @graftland/cli effect
11
11
  ```
12
12
 
13
- 用 `npx @graftland/cli create my-app --install` 创建项目,然后用
14
- `npx graft start --watch` 运行它。需要 Node.js 22.19 或更高版本。
13
+ 用 `npm create @graftland@latest my-app` 创建项目,它运行的就是同一个 `create`
14
+ 命令。然后用 `npm run dev` 运行它。需要 Node.js 22.19 或更高版本。
15
15
 
16
16
  ## 文档
17
17
 
package/README.zh-TW.md CHANGED
@@ -10,8 +10,8 @@
10
10
  npm install @graftland/cli effect
11
11
  ```
12
12
 
13
- 用 `npx @graftland/cli create my-app --install` 建立專案,然後用
14
- `npx graft start --watch` 執行它。需要 Node.js 22.19 或更新版本。
13
+ 用 `npm create @graftland@latest my-app` 建立專案,它執行的是同一個 `create`
14
+ 命令。然後用 `npm run dev` 執行它。需要 Node.js 22.19 或更新版本。
15
15
 
16
16
  ## 文件
17
17
 
@@ -0,0 +1,27 @@
1
+ import { Context, Effect, Exit, Layer, Schema, Scope } from "effect";
2
+ import { NodeServices } from "@effect/platform-node";
3
+ import { Digest, SecureRandom, Signature } from "effect/crypto";
4
+ declare namespace Application_d_exports {
5
+ export { Application, ApplicationError, ProtocolOutput, platform };
6
+ }
7
+ /** Set before argument parsing when stdout belongs to a byte protocol. */
8
+ export declare const ProtocolOutput: Context.Reference<boolean>;
9
+ declare const ApplicationError_base: Schema.Class<ApplicationError, Schema.TaggedStruct<"ApplicationError", {
10
+ readonly cause: Schema.Cause<Schema.Unknown, Schema.Unknown>;
11
+ }>, import("effect/Cause").YieldableError & {
12
+ readonly brand: unique symbol;
13
+ }>;
14
+ /** An application requested a failed process exit, preserving its original cause. */
15
+ export declare class ApplicationError extends ApplicationError_base {}
16
+ declare const Application_base: Context.ServiceClass<Application, "@graftland/cli/Application", {
17
+ /** Exclusively reserves the process protocol channel until the caller releases its scope. */
18
+ readonly claimProtocol: Effect.Effect<void, ApplicationError, Scope.Scope>;
19
+ readonly finish: (exit: Exit.Exit<void, unknown>) => Effect.Effect<void>;
20
+ readonly onExit: (release: Effect.Effect<void>) => Effect.Effect<void>;
21
+ }>;
22
+ /** Applications can request process completion and report cleanup independently of loader diagnostics. */
23
+ export declare class Application extends Application_base {}
24
+ /** Node capabilities shared by application and command hosts. */
25
+ export declare const platform: Layer.Layer<Digest.Digest | import("effect/http/HttpClient").HttpClient | SecureRandom.SecureRandom | Signature.Signature | NodeServices.NodeServices, never, never>;
26
+ export { Application_d_exports };
27
+ //# sourceMappingURL=Application.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Application.d.ts","names":[],"sources":["../src/Application.ts"],"mappings":";;;;;;;qBAiBa,gBAAc,QAAA;;;;WAQR;;;qBAFN,yBAAyB;;;WAYZ,eAAA,OAAO,aAAa,kBAAkB,MAAM;WACnD,SAAC,MAAM,KAAK,wBAAwB,OAAO;WAC3C,SAAC,SAAS,OAAO,iBAAiB,OAAO;;;qBAN/C,oBAAoB;;qBAWpB,UAAQ,MAAA,MAAA,OAAA,0CAAA,aAAA,aAAA,eAAA,UAAA,YAAA,aAAA"}
@@ -0,0 +1,27 @@
1
+ import { __exportAll } from "./_virtual/_rolldown/runtime.js";
2
+ import { ProtocolStdio } from "./internal/protocolOutput.js";
3
+ import { Context, Effect, Layer, Option, Schema, Stdio } from "effect";
4
+ import { NodeServices } from "@effect/platform-node";
5
+ import { Digest, SecureRandom, Signature } from "effect/crypto";
6
+ import { FetchHttpClient } from "effect/http";
7
+ // src/Application.ts
8
+ var Application_exports = /* @__PURE__ */ __exportAll({
9
+ Application: () => Application,
10
+ ApplicationError: () => ApplicationError,
11
+ ProtocolOutput: () => ProtocolOutput,
12
+ platform: () => platform
13
+ });
14
+ /** Set before argument parsing when stdout belongs to a byte protocol. */
15
+ const ProtocolOutput = Context.Reference("@graftland/cli/ProtocolOutput", { defaultValue: () => false });
16
+ /** An application requested a failed process exit, preserving its original cause. */
17
+ var ApplicationError = class extends Schema.TaggedError()("ApplicationError", { cause: Schema.Cause(Schema.Unknown, Schema.Unknown) }) {};
18
+ /** Applications can request process completion and report cleanup independently of loader diagnostics. */
19
+ var Application = class extends Context.Service()("@graftland/cli/Application") {};
20
+ /** Node capabilities shared by application and command hosts. */
21
+ const platform = Layer.mergeAll(Layer.effect(Stdio.Stdio, Effect.gen(function* () {
22
+ const reserved = yield* ProtocolStdio;
23
+ return Option.isSome(reserved) ? reserved.value : yield* Stdio.Stdio;
24
+ })).pipe(Layer.provideMerge(NodeServices.layer)), FetchHttpClient.layer, Digest.layerWebCrypto, SecureRandom.layerWebCrypto, Signature.layerWebCrypto.pipe(Layer.provide(SecureRandom.layerWebCrypto)));
25
+ export { Application, ApplicationError, Application_exports, ProtocolOutput, platform };
26
+
27
+ //# sourceMappingURL=Application.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Application.js","names":[],"sources":["../src/Application.ts"],"sourcesContent":["import {\n\tContext,\n\tEffect,\n\tExit,\n\tLayer,\n\tOption,\n\tSchema,\n\tScope,\n\tStdio,\n} from \"effect\"\nimport { Digest, SecureRandom, Signature } from \"effect/crypto\"\nimport { FetchHttpClient } from \"effect/http\"\nimport { NodeServices } from \"@effect/platform-node\"\n\nimport { ProtocolStdio } from \"./internal/protocolOutput\"\n\n/** Set before argument parsing when stdout belongs to a byte protocol. */\nexport const ProtocolOutput = Context.Reference(\n\t\"@graftland/cli/ProtocolOutput\",\n\t{ defaultValue: () => false },\n)\n\n/** An application requested a failed process exit, preserving its original cause. */\nexport class ApplicationError extends Schema.TaggedError<\n\tApplicationError,\n\t{ readonly brand: unique symbol }\n>()(\"ApplicationError\", {\n\tcause: Schema.Cause(Schema.Unknown, Schema.Unknown),\n}) {}\n\n/** Applications can request process completion and report cleanup independently of loader diagnostics. */\nexport class Application extends Context.Service<\n\tApplication,\n\t{\n\t\t/** Exclusively reserves the process protocol channel until the caller releases its scope. */\n\t\treadonly claimProtocol: Effect.Effect<void, ApplicationError, Scope.Scope>\n\t\treadonly finish: (exit: Exit.Exit<void, unknown>) => Effect.Effect<void>\n\t\treadonly onExit: (release: Effect.Effect<void>) => Effect.Effect<void>\n\t}\n>()(\"@graftland/cli/Application\") {}\n\n/** Node capabilities shared by application and command hosts. */\nexport const platform = Layer.mergeAll(\n\tLayer.effect(\n\t\tStdio.Stdio,\n\t\tEffect.gen(function* () {\n\t\t\tconst reserved = yield* ProtocolStdio\n\t\t\treturn Option.isSome(reserved) ? reserved.value : yield* Stdio.Stdio\n\t\t}),\n\t).pipe(Layer.provideMerge(NodeServices.layer)),\n\tFetchHttpClient.layer,\n\tDigest.layerWebCrypto,\n\tSecureRandom.layerWebCrypto,\n\tSignature.layerWebCrypto.pipe(Layer.provide(SecureRandom.layerWebCrypto)),\n)\n"],"mappings":";;;;;;;;;;;;;;AAiBA,MAAa,iBAAiB,QAAQ,UACrC,iCACA,EAAE,oBAAoB,MAAM,CAC7B;;AAGA,IAAa,mBAAb,cAAsC,OAAO,YAG3C,CAAC,CAAC,oBAAoB,EACvB,OAAO,OAAO,MAAM,OAAO,SAAS,OAAO,OAAO,EACnD,CAAC,CAAC,CAAC,CAAC;;AAGJ,IAAa,cAAb,cAAiC,QAAQ,QAQvC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC;;AAGnC,MAAa,WAAW,MAAM,SAC7B,MAAM,OACL,MAAM,OACN,OAAO,IAAI,aAAa;CACvB,MAAM,WAAW,OAAO;CACxB,OAAO,OAAO,OAAO,QAAQ,IAAI,SAAS,QAAQ,OAAO,MAAM;AAChE,CAAC,CACF,CAAC,CAAC,KAAK,MAAM,aAAa,aAAa,KAAK,CAAC,GAC7C,gBAAgB,OAChB,OAAO,gBACP,aAAa,gBACb,UAAU,eAAe,KAAK,MAAM,QAAQ,aAAa,cAAc,CAAC,CACzE"}
@@ -0,0 +1,34 @@
1
+ import { Context, Effect, Schema, Scope } from "effect";
2
+ import { CliError, Command } from "effect/cli";
3
+ declare namespace Commands_d_exports {
4
+ export { CommandConfigError, CommandRegistrationError, Commands, Environment };
5
+ }
6
+ /** Services available when a registered command runs. Provide other services on the command itself. */
7
+ export type Environment = Command.Environment | Scope.Scope;
8
+ declare const CommandRegistrationError_base: Schema.Class<CommandRegistrationError, Schema.TaggedStruct<"CommandRegistrationError", {
9
+ readonly command: Schema.String;
10
+ readonly detail: Schema.String;
11
+ }>, import("effect/Cause").YieldableError & {
12
+ readonly brand: unique symbol;
13
+ }>;
14
+ /** A command name, alias, or registration lifetime conflicts with the host. */
15
+ export declare class CommandRegistrationError extends CommandRegistrationError_base {
16
+ get message(): string;
17
+ }
18
+ declare const Commands_base: Context.ServiceClass<Commands, "@graftland/cli/Commands", {
19
+ readonly register: <const Name extends string, Input, ContextInput, E extends CliError.CliError, R extends Environment>(command: Command.Command<Name, Input, ContextInput, E, R>) => Effect.Effect<void, CommandRegistrationError, Scope.Scope>;
20
+ }>;
21
+ /** Register one native Effect CLI command tree during the plugin's activation. */
22
+ export declare class Commands extends Commands_base {}
23
+ declare const CommandConfigError_base: Schema.Class<CommandConfigError, Schema.TaggedStruct<"CommandConfigError", {
24
+ readonly file: Schema.String;
25
+ readonly cause: Schema.Unknown;
26
+ }>, import("effect/Cause").YieldableError & {
27
+ readonly brand: unique symbol;
28
+ }>;
29
+ /** A declared command plugin could not be decoded from its config file. */
30
+ export declare class CommandConfigError extends CommandConfigError_base {
31
+ get message(): string;
32
+ }
33
+ export { Commands_d_exports };
34
+ //# sourceMappingURL=Commands.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Commands.d.ts","names":[],"sources":["../src/Commands.ts"],"mappings":";;;;;;YAIY,cAAc,QAAQ,cAAc,MAAM;;;;;WAKnC;;;qBAFN,iCAAiC;MAOhC;;;WASO,iBACZ,qBACN,OACA,cACA,UAAU,SAAS,UACnB,UAAU,aAEV,SAAS,QAAQ,QAAQ,MAAM,OAAO,cAAc,GAAG,OACnD,OAAO,aAAa,0BAA0B,MAAM;;;qBAX9C,iBAAiB;;;;;WAkBX;;;qBAFN,2BAA2B;MAO1B"}
@@ -0,0 +1,31 @@
1
+ import { __exportAll } from "./_virtual/_rolldown/runtime.js";
2
+ import { Context, Schema } from "effect";
3
+ // src/Commands.ts
4
+ var Commands_exports = /* @__PURE__ */ __exportAll({
5
+ CommandConfigError: () => CommandConfigError,
6
+ CommandRegistrationError: () => CommandRegistrationError,
7
+ Commands: () => Commands
8
+ });
9
+ /** A command name, alias, or registration lifetime conflicts with the host. */
10
+ var CommandRegistrationError = class extends Schema.TaggedError()("CommandRegistrationError", {
11
+ command: Schema.String,
12
+ detail: Schema.String
13
+ }) {
14
+ get message() {
15
+ return `${this.command}: ${this.detail}`;
16
+ }
17
+ };
18
+ /** Register one native Effect CLI command tree during the plugin's activation. */
19
+ var Commands = class extends Context.Service()("@graftland/cli/Commands") {};
20
+ /** A declared command plugin could not be decoded from its config file. */
21
+ var CommandConfigError = class extends Schema.TaggedError()("CommandConfigError", {
22
+ file: Schema.String,
23
+ cause: Schema.Unknown
24
+ }) {
25
+ get message() {
26
+ return `Cannot read command plugins from ${this.file}`;
27
+ }
28
+ };
29
+ export { CommandConfigError, CommandRegistrationError, Commands, Commands_exports };
30
+
31
+ //# sourceMappingURL=Commands.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Commands.js","names":[],"sources":["../src/Commands.ts"],"sourcesContent":["import { Context, Effect, Schema, Scope } from \"effect\"\nimport type { CliError, Command } from \"effect/cli\"\n\n/** Services available when a registered command runs. Provide other services on the command itself. */\nexport type Environment = Command.Environment | Scope.Scope\n\n/** A command name, alias, or registration lifetime conflicts with the host. */\nexport class CommandRegistrationError extends Schema.TaggedError<\n\tCommandRegistrationError,\n\t{ readonly brand: unique symbol }\n>()(\"CommandRegistrationError\", {\n\tcommand: Schema.String,\n\tdetail: Schema.String,\n}) {\n\toverride get message() {\n\t\treturn `${this.command}: ${this.detail}`\n\t}\n}\n\n/** Register one native Effect CLI command tree during the plugin's activation. */\nexport class Commands extends Context.Service<\n\tCommands,\n\t{\n\t\treadonly register: <\n\t\t\tconst Name extends string,\n\t\t\tInput,\n\t\t\tContextInput,\n\t\t\tE extends CliError.CliError,\n\t\t\tR extends Environment,\n\t\t>(\n\t\t\tcommand: Command.Command<Name, Input, ContextInput, E, R>,\n\t\t) => Effect.Effect<void, CommandRegistrationError, Scope.Scope>\n\t}\n>()(\"@graftland/cli/Commands\") {}\n\n/** A declared command plugin could not be decoded from its config file. */\nexport class CommandConfigError extends Schema.TaggedError<\n\tCommandConfigError,\n\t{ readonly brand: unique symbol }\n>()(\"CommandConfigError\", {\n\tfile: Schema.String,\n\tcause: Schema.Unknown,\n}) {\n\toverride get message() {\n\t\treturn `Cannot read command plugins from ${this.file}`\n\t}\n}\n"],"mappings":";;;;;;;;;AAOA,IAAa,2BAAb,cAA8C,OAAO,YAGnD,CAAC,CAAC,4BAA4B;CAC/B,SAAS,OAAO;CAChB,QAAQ,OAAO;AAChB,CAAC,CAAC,CAAC;CACF,IAAa,UAAU;EACtB,OAAO,GAAG,KAAK,QAAQ,IAAI,KAAK;CACjC;AACD;;AAGA,IAAa,WAAb,cAA8B,QAAQ,QAapC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC;;AAGhC,IAAa,qBAAb,cAAwC,OAAO,YAG7C,CAAC,CAAC,sBAAsB;CACzB,MAAM,OAAO;CACb,OAAO,OAAO;AACf,CAAC,CAAC,CAAC;CACF,IAAa,UAAU;EACtB,OAAO,oCAAoC,KAAK;CACjD;AACD"}
package/dist/Manage.d.ts CHANGED
@@ -1,15 +1,12 @@
1
- import * as Create from "@graftland/create";
1
+ import { CommandConfigError } from "./Commands.js";
2
+ import { Config, Effect, FileSystem, Path } from "effect";
2
3
  import * as PackageManager from "@graftland/package-manager";
3
- import { Config, Effect, Option } from "effect";
4
4
  declare namespace Manage_d_exports {
5
- export { add, create, remove };
5
+ export { add, addPlugin, remove };
6
6
  }
7
- export declare const create: (options: {
8
- readonly directory: string;
9
- readonly name: Option.Option<string>;
10
- readonly install: boolean;
11
- }) => Effect.Effect<void, Config.ConfigError | Create.CreateError | Create.InvalidName | Create.InvalidPackageManager | PackageManager.Error, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | import("effect/FileSystem").FileSystem | import("effect/Path").Path>;
12
- export declare const add: (specs: readonly string[]) => Effect.Effect<void, Config.ConfigError | PackageManager.Error, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | import("effect/FileSystem").FileSystem | import("effect/Path").Path>;
13
- export declare const remove: (names: ReadonlyArray<string>) => Effect.Effect<void, Config.ConfigError | PackageManager.Error, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | import("effect/FileSystem").FileSystem | import("effect/Path").Path>;
7
+ export declare const add: (specs: readonly string[]) => Effect.Effect<void, Config.ConfigError | PackageManager.Error, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | FileSystem.FileSystem | Path.Path>;
8
+ export declare const remove: (names: ReadonlyArray<string>) => Effect.Effect<void, Config.ConfigError | PackageManager.Error, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | FileSystem.FileSystem | Path.Path>;
9
+ /** Install a command plugin and explicitly enable its /cli entry. */
10
+ export declare const addPlugin: (name: string, global?: boolean | undefined) => Effect.Effect<void, CommandConfigError | Config.ConfigError | PackageManager.Error, import("effect/process/ChildProcessSpawner").ChildProcessSpawner | FileSystem.FileSystem | Path.Path>;
14
11
  export { Manage_d_exports };
15
12
  //# sourceMappingURL=Manage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Manage.d.ts","names":[],"sources":["../src/Manage.ts"],"mappings":";;;;;;qBA4Da,SAAM;WACE;WACL,MAAA,OAAO;WACJ;MAWjB,OAAA,aAAA,OAAA,cAAA,OAAA,cAAA,OAAA,cAAA,OAAA,wBAAA,eAAA,oDAAA,kDAAA,mCAAA;qBAEW,MAAG,6BAAA,OAAA,aAAA,OAAA,cAAA,eAAA,oDAAA,kDAAA,mCAAA;qBAgBH,SAAM,OAAW,0BAAqB,OAAA,aAAA,OAAA,cAAA,eAAA,oDAAA,kDAAA,mCAAA"}
1
+ {"version":3,"file":"Manage.d.ts","names":[],"sources":["../src/Manage.ts"],"mappings":";;;;;;qBAoEa,MAAG,6BAAA,OAAA,aAAA,OAAA,cAAA,eAAA,oDAAA,sBAAA,WAAA,aAAA,KAAA;qBAgBH,SAAM,OAAW,0BAAqB,OAAA,aAAA,OAAA,cAAA,eAAA,oDAAA,sBAAA,WAAA,aAAA,KAAA;;qBAuDtC,YAAS,cAAA,iCAAA,OAAA,aAAA,qBAAA,OAAA,cAAA,eAAA,oDAAA,sBAAA,WAAA,aAAA,KAAA"}
package/dist/Manage.js CHANGED
@@ -1,14 +1,17 @@
1
1
  import { __exportAll } from "./_virtual/_rolldown/runtime.js";
2
+ import { CommandConfigError } from "./Commands.js";
3
+ import { home } from "./internal/commandConfig.js";
4
+ import { Array, Config, Effect, FileSystem, Option, Path, Predicate, Record, Schema } from "effect";
2
5
  import * as Create from "@graftland/create";
3
6
  import * as PackageManager from "@graftland/package-manager";
4
- import { Array, Config, Effect, Option, Predicate, Record, Schema } from "effect";
7
+ import { parseDocument } from "yaml";
5
8
  // src/Manage.ts
6
9
  /**
7
- * Creating projects and changing their dependencies.
10
+ * Changing a project's dependencies.
8
11
  */
9
12
  var Manage_exports = /* @__PURE__ */ __exportAll({
10
13
  add: () => add,
11
- create: () => create,
14
+ addPlugin: () => addPlugin,
12
15
  remove: () => remove
13
16
  });
14
17
  const report = (result) => Effect.logInfo(`${result.agent}: ${result.added.length} added, ${result.updated.length} updated, ${result.removed.length} removed`).pipe(Effect.andThen(Option.match(result.snapshotCleanupFailure, {
@@ -34,22 +37,65 @@ const install = Effect.fn("Manage.install")(function* (directory, changes) {
34
37
  })).install(decoded);
35
38
  yield* report(result);
36
39
  });
37
- const create = Effect.fn("Manage.create")(function* (options) {
38
- const project = yield* Create.create({
39
- directory: options.directory,
40
- ...Option.match(options.name, {
41
- onNone: () => ({}),
42
- onSome: (name) => ({ name })
43
- })
44
- });
45
- yield* Effect.logInfo(`Created ${project.name} in ${project.directory}`);
46
- if (options.install) yield* install(project.directory, {});
47
- });
48
40
  const add = Effect.fn("Manage.add")(function* (specs) {
49
41
  const decoded = yield* decodeSpecs(specs);
50
42
  yield* install(".", Record.fromEntries(Array.map(decoded, (spec) => Predicate.isString(spec) ? [spec, "latest"] : [spec[0], spec[2]])));
51
43
  });
52
44
  const remove = (names) => install(".", Record.fromEntries(Array.map(names, (name) => [name, null])));
53
- export { Manage_exports, add, create, remove };
45
+ const enabledConfig = Effect.fnUntraced(function* (file, module) {
46
+ const fs = yield* FileSystem.FileSystem;
47
+ const text = (yield* fs.exists(file)) ? yield* fs.readFileString(file) : "[]\n";
48
+ const document = yield* Effect.try({
49
+ try: () => {
50
+ const document = parseDocument(text);
51
+ const error = document.errors[0];
52
+ if (error !== void 0) throw error;
53
+ if (document.toJS() === null) document.contents = document.createNode([]);
54
+ return document;
55
+ },
56
+ catch: (cause) => CommandConfigError.make({
57
+ file,
58
+ cause
59
+ })
60
+ });
61
+ const entries = yield* Schema.decodeUnknownEffect(Schema.Array(Schema.Unknown))(document.toJS());
62
+ const existing = Array.findFirstIndex(entries, (entry) => Predicate.hasProperty(entry, "name") && entry.name === module && Predicate.hasProperty(entry, "cli") && entry.cli === true);
63
+ return yield* Effect.try({
64
+ try: () => {
65
+ if (Option.isSome(existing)) document.setIn([existing.value, "disabled"], false);
66
+ else document.add({
67
+ name: module,
68
+ cli: true
69
+ });
70
+ return document.toString();
71
+ },
72
+ catch: (cause) => CommandConfigError.make({
73
+ file,
74
+ cause
75
+ })
76
+ });
77
+ });
78
+ const prepareHome = Effect.fnUntraced(function* (directory) {
79
+ const fs = yield* FileSystem.FileSystem;
80
+ const path = yield* Path.Path;
81
+ yield* fs.makeDirectory(directory, { recursive: true });
82
+ const manifest = path.join(directory, "package.json");
83
+ if (!(yield* fs.exists(manifest))) yield* fs.writeFileString(manifest, "{\"private\":true,\"type\":\"module\"}\n");
84
+ }, Effect.uninterruptible);
85
+ /** Install a command plugin and explicitly enable its /cli entry. */
86
+ const addPlugin = Effect.fn("Manage.addPlugin")(function* (name, global = false) {
87
+ const path = yield* Path.Path;
88
+ const fs = yield* FileSystem.FileSystem;
89
+ const directory = global ? yield* home : path.resolve(".");
90
+ const packageName = Create.pluginPackage(name);
91
+ const module = `${packageName}/cli`;
92
+ const file = path.join(directory, "graft.yml");
93
+ const text = yield* enabledConfig(file, module);
94
+ if (global) yield* prepareHome(directory);
95
+ yield* install(directory, Record.singleton(packageName, "latest"));
96
+ yield* fs.writeFileString(file, text).pipe(Effect.uninterruptible);
97
+ yield* Effect.logInfo(`Enabled ${module} in ${file}`);
98
+ });
99
+ export { Manage_exports, add, addPlugin, remove };
54
100
 
55
101
  //# sourceMappingURL=Manage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Manage.js","names":[],"sources":["../src/Manage.ts"],"sourcesContent":["/**\n * Creating projects and changing their dependencies.\n */\nimport * as Create from \"@graftland/create\"\nimport * as PackageManager from \"@graftland/package-manager\"\nimport {\n\tArray,\n\tConfig,\n\tEffect,\n\tOption,\n\tPredicate,\n\tRecord,\n\tSchema,\n} from \"effect\"\n\nconst report = (result: PackageManager.InstallResult) =>\n\tEffect.logInfo(\n\t\t`${result.agent}: ${result.added.length} added, ${result.updated.length} updated, ${result.removed.length} removed`,\n\t).pipe(\n\t\tEffect.andThen(\n\t\t\tOption.match(result.snapshotCleanupFailure, {\n\t\t\t\tonNone: () => Effect.void,\n\t\t\t\tonSome: ({ cause, snapshotDirectory }) =>\n\t\t\t\t\tEffect.logWarning(\n\t\t\t\t\t\t\"Installation committed; snapshot cleanup failed. Retry removing the retained snapshot.\",\n\t\t\t\t\t\tcause,\n\t\t\t\t\t\t{ snapshotDirectory },\n\t\t\t\t\t),\n\t\t\t}),\n\t\t),\n\t)\n\n/**\n * `name@range`, split at the last `@` so a scope's `@` stays in the name. A\n * bare name means the latest version.\n */\nconst Spec = Schema.Union([\n\tSchema.TemplateLiteralParser([\n\t\tPackageManager.PackageName,\n\t\t\"@\",\n\t\tSchema.String,\n\t]),\n\tPackageManager.PackageName,\n])\nconst decodeSpecs = Schema.decodeEffect(Schema.Array(Spec))\n\nconst install = Effect.fn(\"Manage.install\")(function* (\n\tdirectory: string,\n\tchanges: Readonly<Record<string, string | null>>,\n) {\n\tconst decoded = yield* Schema.decodeEffect(PackageManager.Changes)(changes)\n\t// Set by npm, pnpm and Yarn when they run graft, such as through `pnpm dlx`.\n\tconst userAgent = yield* Config.String(\"npm_config_user_agent\").pipe(\n\t\tConfig.withDefault(\"\"),\n\t)\n\tconst manager = yield* PackageManager.make({ directory, userAgent })\n\tconst result = yield* manager.install(decoded)\n\tyield* report(result)\n})\n\nexport const create = Effect.fn(\"Manage.create\")(function* (options: {\n\treadonly directory: string\n\treadonly name: Option.Option<string>\n\treadonly install: boolean\n}) {\n\tconst project = yield* Create.create({\n\t\tdirectory: options.directory,\n\t\t...Option.match(options.name, {\n\t\t\tonNone: () => ({}),\n\t\t\tonSome: (name) => ({ name }),\n\t\t}),\n\t})\n\tyield* Effect.logInfo(`Created ${project.name} in ${project.directory}`)\n\tif (options.install) yield* install(project.directory, {})\n})\n\nexport const add = Effect.fn(\"Manage.add\")(function* (\n\tspecs: ReadonlyArray<string>,\n) {\n\tconst decoded = yield* decodeSpecs(specs)\n\tyield* install(\n\t\t\".\",\n\t\tRecord.fromEntries(\n\t\t\tArray.map(decoded, (spec) =>\n\t\t\t\tPredicate.isString(spec)\n\t\t\t\t\t? ([spec, \"latest\"] as const)\n\t\t\t\t\t: ([spec[0], spec[2]] as const),\n\t\t\t),\n\t\t),\n\t)\n})\n\nexport const remove = (names: ReadonlyArray<string>) =>\n\tinstall(\n\t\t\".\",\n\t\tRecord.fromEntries(Array.map(names, (name) => [name, null] as const)),\n\t)\n"],"mappings":";;;;;;;;;;;;;AAeA,MAAM,UAAU,WACf,OAAO,QACN,GAAG,OAAO,MAAM,IAAI,OAAO,MAAM,OAAO,UAAU,OAAO,QAAQ,OAAO,YAAY,OAAO,QAAQ,OAAO,SAC3G,CAAC,CAAC,KACD,OAAO,QACN,OAAO,MAAM,OAAO,wBAAwB;CAC3C,cAAc,OAAO;CACrB,SAAS,EAAE,OAAO,wBACjB,OAAO,WACN,0FACA,OACA,EAAE,kBAAkB,CACrB;AACF,CAAC,CACF,CACD;;;;;AAMD,MAAM,OAAO,OAAO,MAAM,CACzB,OAAO,sBAAsB;CAC5B,eAAe;CACf;CACA,OAAO;AACR,CAAC,GACD,eAAe,WAChB,CAAC;AACD,MAAM,cAAc,OAAO,aAAa,OAAO,MAAM,IAAI,CAAC;AAE1D,MAAM,UAAU,OAAO,GAAG,gBAAgB,CAAC,CAAC,WAC3C,WACA,SACC;CACD,MAAM,UAAU,OAAO,OAAO,aAAa,eAAe,OAAO,CAAC,CAAC,OAAO;CAE1E,MAAM,YAAY,OAAO,OAAO,OAAO,uBAAuB,CAAC,CAAC,KAC/D,OAAO,YAAY,EAAE,CACtB;CAEA,MAAM,SAAS,QAAO,OADC,eAAe,KAAK;EAAE;EAAW;CAAU,CAAC,EAAA,CACrC,QAAQ,OAAO;CAC7C,OAAO,OAAO,MAAM;AACrB,CAAC;AAED,MAAa,SAAS,OAAO,GAAG,eAAe,CAAC,CAAC,WAAW,SAIzD;CACF,MAAM,UAAU,OAAO,OAAO,OAAO;EACpC,WAAW,QAAQ;EACnB,GAAG,OAAO,MAAM,QAAQ,MAAM;GAC7B,eAAe,CAAC;GAChB,SAAS,UAAU,EAAE,KAAK;EAC3B,CAAC;CACF,CAAC;CACD,OAAO,OAAO,QAAQ,WAAW,QAAQ,KAAK,MAAM,QAAQ,WAAW;CACvE,IAAI,QAAQ,SAAS,OAAO,QAAQ,QAAQ,WAAW,CAAC,CAAC;AAC1D,CAAC;AAED,MAAa,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,WAC1C,OACC;CACD,MAAM,UAAU,OAAO,YAAY,KAAK;CACxC,OAAO,QACN,KACA,OAAO,YACN,MAAM,IAAI,UAAU,SACnB,UAAU,SAAS,IAAI,IACnB,CAAC,MAAM,QAAQ,IACf,CAAC,KAAK,IAAI,KAAK,EAAE,CACtB,CACD,CACD;AACD,CAAC;AAED,MAAa,UAAU,UACtB,QACC,KACA,OAAO,YAAY,MAAM,IAAI,QAAQ,SAAS,CAAC,MAAM,IAAI,CAAU,CAAC,CACrE"}
1
+ {"version":3,"file":"Manage.js","names":[],"sources":["../src/Manage.ts"],"sourcesContent":["/**\n * Changing a project's dependencies.\n */\nimport {\n\tArray,\n\tConfig,\n\tEffect,\n\tFileSystem,\n\tOption,\n\tPath,\n\tPredicate,\n\tRecord,\n\tSchema,\n} from \"effect\"\n\nimport * as Create from \"@graftland/create\"\nimport * as PackageManager from \"@graftland/package-manager\"\n\nimport { parseDocument, type Document } from \"yaml\"\n\nimport { CommandConfigError } from \"./Commands\"\nimport { home } from \"./internal/commandConfig\"\n\nconst report = (result: PackageManager.InstallResult) =>\n\tEffect.logInfo(\n\t\t`${result.agent}: ${result.added.length} added, ${result.updated.length} updated, ${result.removed.length} removed`,\n\t).pipe(\n\t\tEffect.andThen(\n\t\t\tOption.match(result.snapshotCleanupFailure, {\n\t\t\t\tonNone: () => Effect.void,\n\t\t\t\tonSome: ({ cause, snapshotDirectory }) =>\n\t\t\t\t\tEffect.logWarning(\n\t\t\t\t\t\t\"Installation committed; snapshot cleanup failed. Retry removing the retained snapshot.\",\n\t\t\t\t\t\tcause,\n\t\t\t\t\t\t{ snapshotDirectory },\n\t\t\t\t\t),\n\t\t\t}),\n\t\t),\n\t)\n\n/**\n * `name@range`, split at the last `@` so a scope's `@` stays in the name. A\n * bare name means the latest version.\n */\nconst Spec = Schema.Union([\n\tSchema.TemplateLiteralParser([\n\t\tPackageManager.PackageName,\n\t\t\"@\",\n\t\tSchema.String,\n\t]),\n\tPackageManager.PackageName,\n])\nconst decodeSpecs = Schema.decodeEffect(Schema.Array(Spec))\n\nconst install = Effect.fn(\"Manage.install\")(function* (\n\tdirectory: string,\n\tchanges: Readonly<Record<string, string | null>>,\n) {\n\tconst decoded = yield* Schema.decodeEffect(PackageManager.Changes)(changes)\n\t// Set by npm, pnpm and Yarn when they run graft, such as through `pnpm dlx`.\n\tconst userAgent = yield* Config.String(\"npm_config_user_agent\").pipe(\n\t\tConfig.withDefault(\"\"),\n\t)\n\tconst manager = yield* PackageManager.make({ directory, userAgent })\n\tconst result = yield* manager.install(decoded)\n\tyield* report(result)\n})\n\nexport const add = Effect.fn(\"Manage.add\")(function* (\n\tspecs: ReadonlyArray<string>,\n) {\n\tconst decoded = yield* decodeSpecs(specs)\n\tyield* install(\n\t\t\".\",\n\t\tRecord.fromEntries(\n\t\t\tArray.map(decoded, (spec) =>\n\t\t\t\tPredicate.isString(spec)\n\t\t\t\t\t? ([spec, \"latest\"] as const)\n\t\t\t\t\t: ([spec[0], spec[2]] as const),\n\t\t\t),\n\t\t),\n\t)\n})\n\nexport const remove = (names: ReadonlyArray<string>) =>\n\tinstall(\n\t\t\".\",\n\t\tRecord.fromEntries(Array.map(names, (name) => [name, null] as const)),\n\t)\n\nconst enabledConfig = Effect.fnUntraced(function* (\n\tfile: string,\n\tmodule: string,\n) {\n\tconst fs = yield* FileSystem.FileSystem\n\tconst text = (yield* fs.exists(file))\n\t\t? yield* fs.readFileString(file)\n\t\t: \"[]\\n\"\n\tconst document = yield* Effect.try({\n\t\ttry: () => {\n\t\t\tconst document: Document = parseDocument(text)\n\t\t\tconst error = document.errors[0]\n\t\t\tif (error !== undefined) throw error\n\t\t\tif (document.toJS() === null) document.contents = document.createNode([])\n\t\t\treturn document\n\t\t},\n\t\tcatch: (cause) => CommandConfigError.make({ file, cause }),\n\t})\n\tconst entries = yield* Schema.decodeUnknownEffect(\n\t\tSchema.Array(Schema.Unknown),\n\t)(document.toJS())\n\tconst existing = Array.findFirstIndex(\n\t\tentries,\n\t\t(entry) =>\n\t\t\tPredicate.hasProperty(entry, \"name\") &&\n\t\t\tentry.name === module &&\n\t\t\tPredicate.hasProperty(entry, \"cli\") &&\n\t\t\tentry.cli === true,\n\t)\n\treturn yield* Effect.try({\n\t\ttry: () => {\n\t\t\tif (Option.isSome(existing))\n\t\t\t\tdocument.setIn([existing.value, \"disabled\"], false)\n\t\t\telse document.add({ name: module, cli: true })\n\t\t\treturn document.toString()\n\t\t},\n\t\tcatch: (cause) => CommandConfigError.make({ file, cause }),\n\t})\n})\nconst prepareHome = Effect.fnUntraced(function* (directory: string) {\n\tconst fs = yield* FileSystem.FileSystem\n\tconst path = yield* Path.Path\n\tyield* fs.makeDirectory(directory, { recursive: true })\n\tconst manifest = path.join(directory, \"package.json\")\n\tif (!(yield* fs.exists(manifest)))\n\t\tyield* fs.writeFileString(manifest, '{\"private\":true,\"type\":\"module\"}\\n')\n}, Effect.uninterruptible)\n\n/** Install a command plugin and explicitly enable its /cli entry. */\nexport const addPlugin = Effect.fn(\"Manage.addPlugin\")(function* (\n\tname: string,\n\tglobal: boolean = false,\n) {\n\tconst path = yield* Path.Path\n\tconst fs = yield* FileSystem.FileSystem\n\tconst directory = global ? yield* home : path.resolve(\".\")\n\tconst packageName = Create.pluginPackage(name)\n\tconst module = `${packageName}/cli`\n\tconst file = path.join(directory, \"graft.yml\")\n\tconst text = yield* enabledConfig(file, module)\n\tif (global) yield* prepareHome(directory)\n\tyield* install(directory, Record.singleton(packageName, \"latest\"))\n\t// Once accepted, the native write must finish before command cleanup can proceed.\n\tyield* fs.writeFileString(file, text).pipe(Effect.uninterruptible)\n\tyield* Effect.logInfo(`Enabled ${module} in ${file}`)\n})\n"],"mappings":"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"}
package/dist/Start.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { ApplicationError } from "./Application.js";
1
2
  import { Effect, PlatformError, Schema } from "effect";
2
3
  import { Graft } from "@graftland/graft";
3
4
  import { Loader, Tree } from "@graftland/loader";
@@ -20,6 +21,6 @@ export interface Options {
20
21
  * modules are imported through the hot reloader, so bare specifiers resolve
21
22
  * from the application directory whether or not `watch` is on.
22
23
  */
23
- export declare const run: (options: Options) => Effect.Effect<never, Graft.ServiceConflict | PlatformError.BadArgument | PlatformError.PlatformError | Schema.SchemaError | Loader.StoreError | Tree.InvalidOperation>;
24
+ export declare const run: (options: Options) => Effect.Effect<void, ApplicationError | Graft.ServiceConflict | PlatformError.BadArgument | PlatformError.PlatformError | Schema.SchemaError | Loader.StoreError | Tree.InvalidOperation>;
24
25
  export { Start_d_exports };
25
26
  //# sourceMappingURL=Start.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Start.d.ts","names":[],"sources":["../src/Start.ts"],"mappings":";;;;;;iBAciB;;WAEP;;WAEA;;;;;WAKA;;;;;;;qBAQG,MACZ,SAAS,YACL,OAAO,cAET,MAAM,kBACN,cAAc,cACd,cAAc,gBACd,OAAO,cACP,OAAO,aACP,KAAK"}
1
+ {"version":3,"file":"Start.d.ts","names":[],"sources":["../src/Start.ts"],"mappings":";;;;;;;iBAoCiB;;WAEP;;WAEA;;;;;WAKA;;;;;;;qBAQG,MAAG,SACN,YACP,OAAO,aAEP,mBACA,MAAM,kBACN,cAAc,cACd,cAAc,gBACd,OAAO,cACP,OAAO,aACP,KAAK"}
package/dist/Start.js CHANGED
@@ -1,13 +1,13 @@
1
1
  import { __exportAll } from "./_virtual/_rolldown/runtime.js";
2
+ import { Application, ApplicationError, platform } from "./Application.js";
2
3
  import { EnvFile, layer, watchEnvFile } from "./internal/env.js";
3
4
  import { layer as layer$1 } from "./internal/intercepts.js";
4
5
  import { watchModules } from "./internal/watch.js";
5
- import { Effect, FileSystem, Layer, Logger, Path } from "effect";
6
+ import { Array, Cause, Deferred, Effect, Exit, FileSystem, Layer, Logger, Option, Path, Scope, Semaphore } from "effect";
6
7
  import { NodeServices } from "@effect/platform-node";
7
- import { SecureRandom } from "effect/crypto";
8
8
  import { Graft, Plugin } from "@graftland/graft";
9
9
  import * as Hmr from "@graftland/hmr";
10
- import { Include, Loader, ModuleResolver } from "@graftland/loader";
10
+ import { Entry, Include, Loader, ModuleResolver } from "@graftland/loader";
11
11
  // src/Start.ts
12
12
  /**
13
13
  * Runs a Graft application from its config file.
@@ -18,7 +18,15 @@ var Start_exports = /* @__PURE__ */ __exportAll({ run: () => run });
18
18
  * modules are imported through the hot reloader, so bare specifiers resolve
19
19
  * from the application directory whether or not `watch` is on.
20
20
  */
21
- const run = Effect.fn("Start.run")(function* (options) {
21
+ const run = (options) => Effect.gen(function* () {
22
+ const scope = yield* Effect.scope;
23
+ const done = yield* Deferred.make();
24
+ const protocol = yield* Semaphore.make(1);
25
+ yield* Graft.provide(Application, {
26
+ claimProtocol: Effect.acquireRelease(protocol.takeIfAvailable(1).pipe(Effect.flatMap((acquired) => acquired ? Effect.void : Effect.fail(ApplicationError.make({ cause: Cause.fail("Only one runner may own the process stdio channel") })))), () => protocol.release(1)),
27
+ finish: (exit) => Deferred.done(done, Exit.isFailure(exit) ? Exit.fail(ApplicationError.make({ cause: exit.cause })) : Exit.void).pipe(Effect.asVoid),
28
+ onExit: (release) => Scope.addFinalizer(scope, release)
29
+ });
22
30
  const path = yield* Path.Path;
23
31
  const file = path.resolve(options.config);
24
32
  const directory = path.dirname(file);
@@ -30,16 +38,24 @@ const run = Effect.fn("Start.run")(function* (options) {
30
38
  });
31
39
  const modules = yield* ModuleResolver.make({
32
40
  base: directory,
33
- importer: hmr.importModule
41
+ importer: options.watch ? hmr.importModuleScoped : hmr.importModule
34
42
  });
35
43
  yield* Graft.provide(ModuleResolver.ModuleResolver, {
36
44
  resolve: resolver.resolve,
37
45
  importModule: modules.importModule
38
46
  });
47
+ const fs = yield* FileSystem.FileSystem;
48
+ const observe = hmr.observation.pipe(Effect.provideService(FileSystem.FileSystem, fs), Effect.map((source) => ({
49
+ ...source,
50
+ watch: (files, activation) => source.watch(files, activation).pipe(Effect.mapError((cause) => ModuleResolver.ModuleInvalid.make({
51
+ specifier: Array.join(files, ", "),
52
+ cause
53
+ })))
54
+ })));
39
55
  yield* (yield* Graft.plugin(Include.Include, {
40
56
  path: file,
41
57
  watch: options.watch
42
- })).await;
58
+ }).pipe(Effect.provideService(ModuleResolver.Watch, options.watch ? Option.some(observe) : Option.none()))).await;
43
59
  if (options.watch) {
44
60
  const { reload } = yield* EnvFile;
45
61
  const envFile = options.envFile;
@@ -50,7 +66,7 @@ const run = Effect.fn("Start.run")(function* (options) {
50
66
  FileSystem.FileSystem,
51
67
  Path.Path
52
68
  ],
53
- apply: Effect.fnUntraced(function* () {
69
+ apply: () => Effect.gen(function* () {
54
70
  const loader = yield* Loader.Loader;
55
71
  yield* watchModules(hmr, directory, loader.retry).pipe(Effect.forkScoped);
56
72
  if (envFile !== void 0) yield* watchEnvFile(envFile, reload, loader.retry).pipe(Effect.forkScoped);
@@ -59,8 +75,8 @@ const run = Effect.fn("Start.run")(function* (options) {
59
75
  yield* Graft.plugin(reloader);
60
76
  }
61
77
  yield* Effect.logInfo(`Running ${path.relative(process.cwd(), file) || file}`);
62
- return yield* Effect.never;
63
- }, Effect.scoped, (effect, options) => Effect.provide(effect, Layer.provideMerge(Graft.layer, Layer.mergeAll(SecureRandom.layerWebCrypto, NodeServices.layer, layer$1, layer(options.envFile).pipe(Layer.provide(NodeServices.layer)), Logger.layer([Logger.consolePretty()])))));
78
+ return yield* Deferred.await(done);
79
+ }).pipe(Effect.scoped, Effect.provideService(Entry.Select, (entry) => entry["cli"] !== true), Effect.provide(Layer.provideMerge(Graft.layer, Layer.mergeAll(platform, layer$1, layer(options.envFile).pipe(Layer.provide(NodeServices.layer)), Logger.layer([Logger.consolePretty()])))));
64
80
  export { Start_exports, run };
65
81
 
66
82
  //# sourceMappingURL=Start.js.map
package/dist/Start.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"Start.js","names":["intercepts","env"],"sources":["../src/Start.ts"],"sourcesContent":["/**\n * Runs a Graft application from its config file.\n */\nimport { NodeServices } from \"@effect/platform-node\"\nimport { SecureRandom } from \"effect/crypto\"\nimport { Graft, Plugin } from \"@graftland/graft\"\nimport * as Hmr from \"@graftland/hmr\"\nimport { Include, Loader, ModuleResolver, type Tree } from \"@graftland/loader\"\nimport type { PlatformError, Schema } from \"effect\"\nimport { Effect, FileSystem, Layer, Logger, Path } from \"effect\"\nimport { EnvFile, layer as env, watchEnvFile } from \"./internal/env\"\nimport { layer as intercepts } from \"./internal/intercepts\"\nimport { watchModules } from \"./internal/watch\"\n\nexport interface Options {\n\t/** Path of the config file. */\n\treadonly config: string\n\t/** Reload plugin modules and the config file when they change. */\n\treadonly watch: boolean\n\t/**\n\t * A `.env` file that `!env` reads when the process environment does not set\n\t * a variable. With `watch`, changes to it are read again.\n\t */\n\treadonly envFile?: string | undefined\n}\n\n/**\n * Loads the entries of the config file and runs until interrupted. Plugin\n * modules are imported through the hot reloader, so bare specifiers resolve\n * from the application directory whether or not `watch` is on.\n */\nexport const run: (\n\toptions: Options,\n) => Effect.Effect<\n\tnever,\n\t| Graft.ServiceConflict\n\t| PlatformError.BadArgument\n\t| PlatformError.PlatformError\n\t| Schema.SchemaError\n\t| Loader.StoreError\n\t| Tree.InvalidOperation\n> = Effect.fn(\"Start.run\")(\n\tfunction* (options: Options) {\n\t\tconst path = yield* Path.Path\n\t\tconst file = path.resolve(options.config)\n\t\tconst directory = path.dirname(file)\n\t\tconst base = yield* path.toFileUrl(file)\n\t\tconst hmr = yield* Hmr.make({ base: base.href })\n\t\tconst resolver = yield* ModuleResolver.make({\n\t\t\tbase: directory,\n\t\t\timporter: hmr.importerScoped,\n\t\t})\n\t\tconst modules = yield* ModuleResolver.make({\n\t\t\tbase: directory,\n\t\t\timporter: hmr.importModule,\n\t\t})\n\t\tyield* Graft.provide(ModuleResolver.ModuleResolver, {\n\t\t\tresolve: resolver.resolve,\n\t\t\timportModule: modules.importModule,\n\t\t})\n\t\tconst included = yield* Graft.plugin(Include.Include, {\n\t\t\tpath: file,\n\t\t\twatch: options.watch,\n\t\t})\n\t\tyield* included.await\n\t\tif (options.watch) {\n\t\t\tconst { reload } = yield* EnvFile\n\t\t\tconst envFile = options.envFile\n\t\t\tconst reloader = Plugin.make({\n\t\t\t\tname: \"reloader\",\n\t\t\t\tinject: [Loader.Loader, FileSystem.FileSystem, Path.Path],\n\t\t\t\tapply: Effect.fnUntraced(function* () {\n\t\t\t\t\tconst loader = yield* Loader.Loader\n\t\t\t\t\tyield* watchModules(hmr, directory, loader.retry).pipe(\n\t\t\t\t\t\tEffect.forkScoped,\n\t\t\t\t\t)\n\t\t\t\t\tif (envFile !== undefined)\n\t\t\t\t\t\tyield* watchEnvFile(envFile, reload, loader.retry).pipe(\n\t\t\t\t\t\t\tEffect.forkScoped,\n\t\t\t\t\t\t)\n\t\t\t\t}),\n\t\t\t})\n\t\t\tyield* Graft.plugin(reloader)\n\t\t}\n\n\t\tyield* Effect.logInfo(\n\t\t\t`Running ${path.relative(process.cwd(), file) || file}`,\n\t\t)\n\t\treturn yield* Effect.never\n\t},\n\tEffect.scoped,\n\t(effect, options) =>\n\t\t// @effect-diagnostics-next-line strictEffectProvide:off -- this runs the whole application, so it is an entry point\n\t\tEffect.provide(\n\t\t\teffect,\n\t\t\tLayer.provideMerge(\n\t\t\t\tGraft.layer,\n\t\t\t\tLayer.mergeAll(\n\t\t\t\t\tSecureRandom.layerWebCrypto,\n\t\t\t\t\tNodeServices.layer,\n\t\t\t\t\tintercepts,\n\t\t\t\t\tenv(options.envFile).pipe(Layer.provide(NodeServices.layer)),\n\t\t\t\t\tLogger.layer([Logger.consolePretty()]),\n\t\t\t\t),\n\t\t\t),\n\t\t),\n)\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AA+BA,MAAa,MAUT,OAAO,GAAG,WAAW,CAAC,CACzB,WAAW,SAAkB;CAC5B,MAAM,OAAO,OAAO,KAAK;CACzB,MAAM,OAAO,KAAK,QAAQ,QAAQ,MAAM;CACxC,MAAM,YAAY,KAAK,QAAQ,IAAI;CACnC,MAAM,OAAO,OAAO,KAAK,UAAU,IAAI;CACvC,MAAM,MAAM,OAAO,IAAI,KAAK,EAAE,MAAM,KAAK,KAAK,CAAC;CAC/C,MAAM,WAAW,OAAO,eAAe,KAAK;EAC3C,MAAM;EACN,UAAU,IAAI;CACf,CAAC;CACD,MAAM,UAAU,OAAO,eAAe,KAAK;EAC1C,MAAM;EACN,UAAU,IAAI;CACf,CAAC;CACD,OAAO,MAAM,QAAQ,eAAe,gBAAgB;EACnD,SAAS,SAAS;EAClB,cAAc,QAAQ;CACvB,CAAC;CAKD,QAAO,OAJiB,MAAM,OAAO,QAAQ,SAAS;EACrD,MAAM;EACN,OAAO,QAAQ;CAChB,CAAC,EAAA,CACe;CAChB,IAAI,QAAQ,OAAO;EAClB,MAAM,EAAE,WAAW,OAAO;EAC1B,MAAM,UAAU,QAAQ;EACxB,MAAM,WAAW,OAAO,KAAK;GAC5B,MAAM;GACN,QAAQ;IAAC,OAAO;IAAQ,WAAW;IAAY,KAAK;GAAI;GACxD,OAAO,OAAO,WAAW,aAAa;IACrC,MAAM,SAAS,OAAO,OAAO;IAC7B,OAAO,aAAa,KAAK,WAAW,OAAO,KAAK,CAAC,CAAC,KACjD,OAAO,UACR;IACA,IAAI,YAAY,KAAA,GACf,OAAO,aAAa,SAAS,QAAQ,OAAO,KAAK,CAAC,CAAC,KAClD,OAAO,UACR;GACF,CAAC;EACF,CAAC;EACD,OAAO,MAAM,OAAO,QAAQ;CAC7B;CAEA,OAAO,OAAO,QACb,WAAW,KAAK,SAAS,QAAQ,IAAI,GAAG,IAAI,KAAK,MAClD;CACA,OAAO,OAAO,OAAO;AACtB,GACA,OAAO,SACN,QAAQ,YAER,OAAO,QACN,QACA,MAAM,aACL,MAAM,OACN,MAAM,SACL,aAAa,gBACb,aAAa,OACbA,SACAC,MAAI,QAAQ,OAAO,CAAC,CAAC,KAAK,MAAM,QAAQ,aAAa,KAAK,CAAC,GAC3D,OAAO,MAAM,CAAC,OAAO,cAAc,CAAC,CAAC,CACtC,CACD,CACD,CACF"}
1
+ {"version":3,"file":"Start.js","names":["intercepts","env"],"sources":["../src/Start.ts"],"sourcesContent":["/**\n * Runs a Graft application from its config file.\n */\nimport {\n\tArray,\n\tCause,\n\tDeferred,\n\tEffect,\n\tExit,\n\tFileSystem,\n\tLayer,\n\tLogger,\n\tOption,\n\tPath,\n\tScope,\n\tSemaphore,\n\ttype PlatformError,\n\ttype Schema,\n} from \"effect\"\nimport { NodeServices } from \"@effect/platform-node\"\n\nimport { Graft, Plugin } from \"@graftland/graft\"\nimport * as Hmr from \"@graftland/hmr\"\nimport {\n\tEntry,\n\tInclude,\n\tLoader,\n\tModuleResolver,\n\ttype Tree,\n} from \"@graftland/loader\"\n\nimport { Application, ApplicationError, platform } from \"./Application\"\nimport { layer as env, EnvFile, watchEnvFile } from \"./internal/env\"\nimport { layer as intercepts } from \"./internal/intercepts\"\nimport { watchModules } from \"./internal/watch\"\n\nexport interface Options {\n\t/** Path of the config file. */\n\treadonly config: string\n\t/** Reload plugin modules and the config file when they change. */\n\treadonly watch: boolean\n\t/**\n\t * A `.env` file that `!env` reads when the process environment does not set\n\t * a variable. With `watch`, changes to it are read again.\n\t */\n\treadonly envFile?: string | undefined\n}\n\n/**\n * Loads the entries of the config file and runs until interrupted. Plugin\n * modules are imported through the hot reloader, so bare specifiers resolve\n * from the application directory whether or not `watch` is on.\n */\nexport const run = (\n\toptions: Options,\n): Effect.Effect<\n\tvoid,\n\t| ApplicationError\n\t| Graft.ServiceConflict\n\t| PlatformError.BadArgument\n\t| PlatformError.PlatformError\n\t| Schema.SchemaError\n\t| Loader.StoreError\n\t| Tree.InvalidOperation\n> =>\n\tEffect.gen(function* () {\n\t\tconst scope = yield* Effect.scope\n\t\tconst done = yield* Deferred.make<void, ApplicationError>()\n\t\tconst protocol = yield* Semaphore.make(1)\n\t\tyield* Graft.provide(Application, {\n\t\t\tclaimProtocol: Effect.acquireRelease(\n\t\t\t\tprotocol.takeIfAvailable(1).pipe(\n\t\t\t\t\tEffect.flatMap((acquired) =>\n\t\t\t\t\t\tacquired\n\t\t\t\t\t\t\t? Effect.void\n\t\t\t\t\t\t\t: Effect.fail(\n\t\t\t\t\t\t\t\t\tApplicationError.make({\n\t\t\t\t\t\t\t\t\t\tcause: Cause.fail(\n\t\t\t\t\t\t\t\t\t\t\t\"Only one runner may own the process stdio channel\",\n\t\t\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t\t() => protocol.release(1),\n\t\t\t),\n\t\t\tfinish: (exit) =>\n\t\t\t\tDeferred.done(\n\t\t\t\t\tdone,\n\t\t\t\t\tExit.isFailure(exit)\n\t\t\t\t\t\t? Exit.fail(ApplicationError.make({ cause: exit.cause }))\n\t\t\t\t\t\t: Exit.void,\n\t\t\t\t).pipe(Effect.asVoid),\n\t\t\tonExit: (release) => Scope.addFinalizer(scope, release),\n\t\t})\n\t\tconst path = yield* Path.Path\n\t\tconst file = path.resolve(options.config)\n\t\tconst directory = path.dirname(file)\n\t\tconst base = yield* path.toFileUrl(file)\n\t\tconst hmr = yield* Hmr.make({ base: base.href })\n\t\tconst resolver = yield* ModuleResolver.make({\n\t\t\tbase: directory,\n\t\t\timporter: hmr.importerScoped,\n\t\t})\n\t\tconst modules = yield* ModuleResolver.make({\n\t\t\tbase: directory,\n\t\t\timporter: options.watch ? hmr.importModuleScoped : hmr.importModule,\n\t\t})\n\t\tyield* Graft.provide(ModuleResolver.ModuleResolver, {\n\t\t\tresolve: resolver.resolve,\n\t\t\timportModule: modules.importModule,\n\t\t})\n\t\tconst fs = yield* FileSystem.FileSystem\n\t\tconst observe = hmr.observation.pipe(\n\t\t\tEffect.provideService(FileSystem.FileSystem, fs),\n\t\t\tEffect.map((source) => ({\n\t\t\t\t...source,\n\t\t\t\twatch: (files: ReadonlyArray<string>, activation: Scope.Scope) =>\n\t\t\t\t\tsource.watch(files, activation).pipe(\n\t\t\t\t\t\tEffect.mapError((cause) =>\n\t\t\t\t\t\t\tModuleResolver.ModuleInvalid.make({\n\t\t\t\t\t\t\t\tspecifier: Array.join(files, \", \"),\n\t\t\t\t\t\t\t\tcause,\n\t\t\t\t\t\t\t}),\n\t\t\t\t\t\t),\n\t\t\t\t\t),\n\t\t\t})),\n\t\t)\n\t\tconst included = yield* Graft.plugin(Include.Include, {\n\t\t\tpath: file,\n\t\t\twatch: options.watch,\n\t\t}).pipe(\n\t\t\tEffect.provideService(\n\t\t\t\tModuleResolver.Watch,\n\t\t\t\toptions.watch ? Option.some(observe) : Option.none(),\n\t\t\t),\n\t\t)\n\t\tyield* included.await\n\t\tif (options.watch) {\n\t\t\tconst { reload } = yield* EnvFile\n\t\t\tconst envFile = options.envFile\n\t\t\tconst reloader = Plugin.make({\n\t\t\t\tname: \"reloader\",\n\t\t\t\tinject: [Loader.Loader, FileSystem.FileSystem, Path.Path],\n\t\t\t\tapply: () =>\n\t\t\t\t\tEffect.gen(function* () {\n\t\t\t\t\t\tconst loader = yield* Loader.Loader\n\t\t\t\t\t\tyield* watchModules(hmr, directory, loader.retry).pipe(\n\t\t\t\t\t\t\tEffect.forkScoped,\n\t\t\t\t\t\t)\n\t\t\t\t\t\tif (envFile !== undefined)\n\t\t\t\t\t\t\tyield* watchEnvFile(envFile, reload, loader.retry).pipe(\n\t\t\t\t\t\t\t\tEffect.forkScoped,\n\t\t\t\t\t\t\t)\n\t\t\t\t\t}),\n\t\t\t})\n\t\t\tyield* Graft.plugin(reloader)\n\t\t}\n\n\t\tyield* Effect.logInfo(\n\t\t\t`Running ${path.relative(process.cwd(), file) || file}`,\n\t\t)\n\t\treturn yield* Deferred.await(done)\n\t}).pipe(\n\t\tEffect.scoped,\n\t\tEffect.provideService(Entry.Select, (entry) => entry[\"cli\"] !== true),\n\t\t// @effect-diagnostics-next-line strictEffectProvide:off -- this runs the whole application, so it is an entry point\n\t\tEffect.provide(\n\t\t\tLayer.provideMerge(\n\t\t\t\tGraft.layer,\n\t\t\t\tLayer.mergeAll(\n\t\t\t\t\tplatform,\n\t\t\t\t\tintercepts,\n\t\t\t\t\tenv(options.envFile).pipe(Layer.provide(NodeServices.layer)),\n\t\t\t\t\tLogger.layer([Logger.consolePretty()]),\n\t\t\t\t),\n\t\t\t),\n\t\t),\n\t)\n"],"mappings":"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"}
package/dist/bin.js CHANGED
@@ -1,8 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import { version } from "./package.js";
3
- import { Effect, Option } from "effect";
4
- import { NodeRuntime, NodeServices } from "@effect/platform-node";
5
- import { Argument, Command, Flag } from "effect/cli";
3
+ import { platform } from "./Application.js";
4
+ import { output, run } from "./internal/commandHost.js";
5
+ import { Array, Effect, Layer, Logger, Option, Stdio } from "effect";
6
+ import { NodeRuntime } from "@effect/platform-node";
7
+ import { Graft } from "@graftland/graft";
8
+ import { Argument, CliError, Command, Flag } from "effect/cli";
9
+ import { command } from "@graftland/create/Command";
6
10
  // src/bin.ts
7
11
  /**
8
12
  * The `graft` executable. Running this module starts the program.
@@ -15,20 +19,39 @@ const start = Command.make("start", {
15
19
  ...options,
16
20
  envFile: Option.getOrUndefined(options.envFile)
17
21
  })))).pipe(Command.withDescription("Run the application described by a config file"));
18
- const create = Command.make("create", {
19
- directory: Argument.String("directory").pipe(Argument.withDescription("Where to create the project")),
20
- name: Flag.String("name").pipe(Flag.withDescription("Package name; defaults to the directory name"), Flag.optional),
21
- install: Flag.Boolean("install").pipe(Flag.withDescription("Install dependencies afterwards"), Flag.withDefault(false))
22
- }, (options) => Effect.promise(() => import("./Manage.js")).pipe(Effect.uninterruptible, Effect.flatMap((Manage) => Manage.create(options)))).pipe(Command.withDescription("Create a new Graft project"));
23
- const add = Command.make("add", { packages: Argument.variadic(Argument.String("package")) }, ({ packages }) => Effect.promise(() => import("./Manage.js")).pipe(Effect.uninterruptible, Effect.flatMap((Manage) => Manage.add(packages)))).pipe(Command.withDescription("Add dependencies, restoring the project if installing fails"));
22
+ const add = Command.make("add", {
23
+ packages: Argument.variadic(Argument.String("package")),
24
+ plugin: Flag.String("plugin").pipe(Flag.optional),
25
+ global: Flag.Boolean("global").pipe(Flag.withDefault(false))
26
+ }, Effect.fnUntraced(function* ({ packages, plugin, global }) {
27
+ if (global && Option.isNone(plugin) || Option.isSome(plugin) && packages.length > 0) return yield* CliError.UserError.make({
28
+ cause: "Conflicting install options",
29
+ userMessage: "Use add --plugin <name> [--global] without package arguments"
30
+ });
31
+ const Manage = yield* Effect.promise(() => import("./Manage.js")).pipe(Effect.uninterruptible);
32
+ return yield* Option.isSome(plugin) ? Manage.addPlugin(plugin.value, global) : Manage.add(packages);
33
+ })).pipe(Command.withDescription("Add dependencies, restoring the project if installing fails"));
24
34
  const remove = Command.make("remove", { packages: Argument.variadic(Argument.String("package")) }, ({ packages }) => Effect.promise(() => import("./Manage.js")).pipe(Effect.uninterruptible, Effect.flatMap((Manage) => Manage.remove(packages)))).pipe(Command.withDescription("Remove dependencies, restoring the project if installing fails"));
25
- const graft = Command.make("graft").pipe(Command.withDescription("Run and manage Graft applications"), Command.withSubcommands([
26
- start,
27
- create,
28
- add,
29
- remove
30
- ]));
31
- Command.run(graft, { version }).pipe(Effect.provide(NodeServices.layer), NodeRuntime.runMain);
35
+ const graft = Command.make("graft").pipe(Command.withDescription("Run and manage Graft applications"), Command.withSharedFlags({
36
+ stdio: Flag.Boolean("stdio").pipe(Flag.withDefault(false)),
37
+ noPlugins: Flag.Boolean("no-plugins").pipe(Flag.withDefault(false))
38
+ }));
39
+ const program = Effect.gen(function* () {
40
+ const args = yield* (yield* Stdio.Stdio).args;
41
+ return yield* output(Effect.scoped(Effect.gen(function* () {
42
+ const context = yield* Layer.build(Graft.layer);
43
+ return yield* run([
44
+ start,
45
+ command,
46
+ add,
47
+ remove
48
+ ], graft, version, args).pipe(Effect.provideContext(context));
49
+ })), args);
50
+ });
51
+ NodeRuntime.runMain(Effect.scoped(Effect.gen(function* () {
52
+ const context = yield* Layer.build(platform);
53
+ return yield* program.pipe(Effect.provideContext(context));
54
+ })).pipe((effect) => Effect.withFiber((main) => effect.pipe(Effect.tapCause((cause) => Array.every(cause.reasons, (reason) => reason._tag === "Interrupt" && reason.fiberId === main.id) || Array.every(cause.reasons, (reason) => reason._tag === "Fail" && CliError.isCliError(reason.error)) ? Effect.void : Effect.logError(cause)))), Effect.provideService(Logger.LogToStderr, true)), { disableErrorReporting: true });
32
55
  export {};
33
56
 
34
57
  //# sourceMappingURL=bin.js.map
package/dist/bin.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"bin.js","names":[],"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * The `graft` executable. Running this module starts the program.\n */\nimport { NodeRuntime, NodeServices } from \"@effect/platform-node\"\nimport { Effect, Option } from \"effect\"\nimport { Argument, Command, Flag } from \"effect/cli\"\nimport { version } from \"../package.json\" with { type: \"json\" }\n\nconst start = Command.make(\n\t\"start\",\n\t{\n\t\tconfig: Argument.String(\"config\").pipe(\n\t\t\tArgument.withDescription(\"Path of the config file\"),\n\t\t\tArgument.withDefault(\"graft.yml\"),\n\t\t),\n\t\twatch: Flag.Boolean(\"watch\").pipe(\n\t\t\tFlag.withAlias(\"w\"),\n\t\t\tFlag.withDescription(\"Reload plugins and config when files change\"),\n\t\t\tFlag.withDefault(false),\n\t\t),\n\t\tenvFile: Flag.String(\"env-file\").pipe(\n\t\t\tFlag.withDescription(\n\t\t\t\t\"Read variables for !env from a .env file; the process environment takes precedence\",\n\t\t\t),\n\t\t\tFlag.optional,\n\t\t),\n\t},\n\t(options) =>\n\t\tEffect.promise(() => import(\"./Start\")).pipe(\n\t\t\tEffect.uninterruptible,\n\t\t\tEffect.flatMap((Start) =>\n\t\t\t\tStart.run({\n\t\t\t\t\t...options,\n\t\t\t\t\tenvFile: Option.getOrUndefined(options.envFile),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n).pipe(\n\tCommand.withDescription(\"Run the application described by a config file\"),\n)\n\nconst create = Command.make(\n\t\"create\",\n\t{\n\t\tdirectory: Argument.String(\"directory\").pipe(\n\t\t\tArgument.withDescription(\"Where to create the project\"),\n\t\t),\n\t\tname: Flag.String(\"name\").pipe(\n\t\t\tFlag.withDescription(\"Package name; defaults to the directory name\"),\n\t\t\tFlag.optional,\n\t\t),\n\t\tinstall: Flag.Boolean(\"install\").pipe(\n\t\t\tFlag.withDescription(\"Install dependencies afterwards\"),\n\t\t\tFlag.withDefault(false),\n\t\t),\n\t},\n\t(options) =>\n\t\tEffect.promise(() => import(\"./Manage\")).pipe(\n\t\t\tEffect.uninterruptible,\n\t\t\tEffect.flatMap((Manage) => Manage.create(options)),\n\t\t),\n).pipe(Command.withDescription(\"Create a new Graft project\"))\n\nconst add = Command.make(\n\t\"add\",\n\t{ packages: Argument.variadic(Argument.String(\"package\")) },\n\t({ packages }) =>\n\t\tEffect.promise(() => import(\"./Manage\")).pipe(\n\t\t\tEffect.uninterruptible,\n\t\t\tEffect.flatMap((Manage) => Manage.add(packages)),\n\t\t),\n).pipe(\n\tCommand.withDescription(\n\t\t\"Add dependencies, restoring the project if installing fails\",\n\t),\n)\n\nconst remove = Command.make(\n\t\"remove\",\n\t{ packages: Argument.variadic(Argument.String(\"package\")) },\n\t({ packages }) =>\n\t\tEffect.promise(() => import(\"./Manage\")).pipe(\n\t\t\tEffect.uninterruptible,\n\t\t\tEffect.flatMap((Manage) => Manage.remove(packages)),\n\t\t),\n).pipe(\n\tCommand.withDescription(\n\t\t\"Remove dependencies, restoring the project if installing fails\",\n\t),\n)\n\nconst graft = Command.make(\"graft\").pipe(\n\tCommand.withDescription(\"Run and manage Graft applications\"),\n\tCommand.withSubcommands([start, create, add, remove]),\n)\n\nCommand.run(graft, { version }).pipe(\n\tEffect.provide(NodeServices.layer),\n\tNodeRuntime.runMain,\n)\n"],"mappings":";;;;;;;;;AASA,MAAM,QAAQ,QAAQ,KACrB,SACA;CACC,QAAQ,SAAS,OAAO,QAAQ,CAAC,CAAC,KACjC,SAAS,gBAAgB,yBAAyB,GAClD,SAAS,YAAY,WAAW,CACjC;CACA,OAAO,KAAK,QAAQ,OAAO,CAAC,CAAC,KAC5B,KAAK,UAAU,GAAG,GAClB,KAAK,gBAAgB,6CAA6C,GAClE,KAAK,YAAY,KAAK,CACvB;CACA,SAAS,KAAK,OAAO,UAAU,CAAC,CAAC,KAChC,KAAK,gBACJ,oFACD,GACA,KAAK,QACN;AACD,IACC,YACA,OAAO,cAAc,OAAO,aAAU,CAAC,CAAC,KACvC,OAAO,iBACP,OAAO,SAAS,UACf,MAAM,IAAI;CACT,GAAG;CACH,SAAS,OAAO,eAAe,QAAQ,OAAO;AAC/C,CAAC,CACF,CACD,CACF,CAAC,CAAC,KACD,QAAQ,gBAAgB,gDAAgD,CACzE;AAEA,MAAM,SAAS,QAAQ,KACtB,UACA;CACC,WAAW,SAAS,OAAO,WAAW,CAAC,CAAC,KACvC,SAAS,gBAAgB,6BAA6B,CACvD;CACA,MAAM,KAAK,OAAO,MAAM,CAAC,CAAC,KACzB,KAAK,gBAAgB,8CAA8C,GACnE,KAAK,QACN;CACA,SAAS,KAAK,QAAQ,SAAS,CAAC,CAAC,KAChC,KAAK,gBAAgB,iCAAiC,GACtD,KAAK,YAAY,KAAK,CACvB;AACD,IACC,YACA,OAAO,cAAc,OAAO,cAAW,CAAC,CAAC,KACxC,OAAO,iBACP,OAAO,SAAS,WAAW,OAAO,OAAO,OAAO,CAAC,CAClD,CACF,CAAC,CAAC,KAAK,QAAQ,gBAAgB,4BAA4B,CAAC;AAE5D,MAAM,MAAM,QAAQ,KACnB,OACA,EAAE,UAAU,SAAS,SAAS,SAAS,OAAO,SAAS,CAAC,EAAE,IACzD,EAAE,eACF,OAAO,cAAc,OAAO,cAAW,CAAC,CAAC,KACxC,OAAO,iBACP,OAAO,SAAS,WAAW,OAAO,IAAI,QAAQ,CAAC,CAChD,CACF,CAAC,CAAC,KACD,QAAQ,gBACP,6DACD,CACD;AAEA,MAAM,SAAS,QAAQ,KACtB,UACA,EAAE,UAAU,SAAS,SAAS,SAAS,OAAO,SAAS,CAAC,EAAE,IACzD,EAAE,eACF,OAAO,cAAc,OAAO,cAAW,CAAC,CAAC,KACxC,OAAO,iBACP,OAAO,SAAS,WAAW,OAAO,OAAO,QAAQ,CAAC,CACnD,CACF,CAAC,CAAC,KACD,QAAQ,gBACP,gEACD,CACD;AAEA,MAAM,QAAQ,QAAQ,KAAK,OAAO,CAAC,CAAC,KACnC,QAAQ,gBAAgB,mCAAmC,GAC3D,QAAQ,gBAAgB;CAAC;CAAO;CAAQ;CAAK;AAAM,CAAC,CACrD;AAEA,QAAQ,IAAI,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC,KAC/B,OAAO,QAAQ,aAAa,KAAK,GACjC,YAAY,OACb"}
1
+ {"version":3,"file":"bin.js","names":["Host.output","Host.run","create"],"sources":["../src/bin.ts"],"sourcesContent":["#!/usr/bin/env node\n/**\n * The `graft` executable. Running this module starts the program.\n */\nimport { Array, Effect, Layer, Logger, Option, Stdio } from \"effect\"\nimport { Argument, CliError, Command, Flag } from \"effect/cli\"\nimport { NodeRuntime } from \"@effect/platform-node\"\n\nimport { command as create } from \"@graftland/create/Command\"\nimport { Graft } from \"@graftland/graft\"\n\nimport { version } from \"../package.json\" with { type: \"json\" }\nimport { platform } from \"./Application\"\nimport * as Host from \"./internal/commandHost\"\n\nconst start = Command.make(\n\t\"start\",\n\t{\n\t\tconfig: Argument.String(\"config\").pipe(\n\t\t\tArgument.withDescription(\"Path of the config file\"),\n\t\t\tArgument.withDefault(\"graft.yml\"),\n\t\t),\n\t\twatch: Flag.Boolean(\"watch\").pipe(\n\t\t\tFlag.withAlias(\"w\"),\n\t\t\tFlag.withDescription(\"Reload plugins and config when files change\"),\n\t\t\tFlag.withDefault(false),\n\t\t),\n\t\tenvFile: Flag.String(\"env-file\").pipe(\n\t\t\tFlag.withDescription(\n\t\t\t\t\"Read variables for !env from a .env file; the process environment takes precedence\",\n\t\t\t),\n\t\t\tFlag.optional,\n\t\t),\n\t},\n\t(options) =>\n\t\tEffect.promise(() => import(\"./Start\")).pipe(\n\t\t\tEffect.uninterruptible,\n\t\t\tEffect.flatMap((Start) =>\n\t\t\t\tStart.run({\n\t\t\t\t\t...options,\n\t\t\t\t\tenvFile: Option.getOrUndefined(options.envFile),\n\t\t\t\t}),\n\t\t\t),\n\t\t),\n).pipe(\n\tCommand.withDescription(\"Run the application described by a config file\"),\n)\n\nconst add = Command.make(\n\t\"add\",\n\t{\n\t\tpackages: Argument.variadic(Argument.String(\"package\")),\n\t\tplugin: Flag.String(\"plugin\").pipe(Flag.optional),\n\t\tglobal: Flag.Boolean(\"global\").pipe(Flag.withDefault(false)),\n\t},\n\tEffect.fnUntraced(function* ({ packages, plugin, global }) {\n\t\tif (\n\t\t\t(global && Option.isNone(plugin)) ||\n\t\t\t(Option.isSome(plugin) && packages.length > 0)\n\t\t)\n\t\t\treturn yield* CliError.UserError.make({\n\t\t\t\tcause: \"Conflicting install options\",\n\t\t\t\tuserMessage:\n\t\t\t\t\t\"Use add --plugin <name> [--global] without package arguments\",\n\t\t\t})\n\t\tconst Manage = yield* Effect.promise(() => import(\"./Manage\")).pipe(\n\t\t\tEffect.uninterruptible,\n\t\t)\n\t\treturn yield* Option.isSome(plugin)\n\t\t\t? Manage.addPlugin(plugin.value, global)\n\t\t\t: Manage.add(packages)\n\t}),\n).pipe(\n\tCommand.withDescription(\n\t\t\"Add dependencies, restoring the project if installing fails\",\n\t),\n)\n\nconst remove = Command.make(\n\t\"remove\",\n\t{ packages: Argument.variadic(Argument.String(\"package\")) },\n\t({ packages }) =>\n\t\tEffect.promise(() => import(\"./Manage\")).pipe(\n\t\t\tEffect.uninterruptible,\n\t\t\tEffect.flatMap((Manage) => Manage.remove(packages)),\n\t\t),\n).pipe(\n\tCommand.withDescription(\n\t\t\"Remove dependencies, restoring the project if installing fails\",\n\t),\n)\n\nconst graft = Command.make(\"graft\").pipe(\n\tCommand.withDescription(\"Run and manage Graft applications\"),\n\tCommand.withSharedFlags({\n\t\tstdio: Flag.Boolean(\"stdio\").pipe(Flag.withDefault(false)),\n\t\tnoPlugins: Flag.Boolean(\"no-plugins\").pipe(Flag.withDefault(false)),\n\t}),\n)\n\nconst program = Effect.gen(function* () {\n\tconst stdio = yield* Stdio.Stdio\n\tconst args = yield* stdio.args\n\treturn yield* Host.output(\n\t\tEffect.scoped(\n\t\t\tEffect.gen(function* () {\n\t\t\t\tconst context = yield* Layer.build(Graft.layer)\n\t\t\t\treturn yield* Host.run(\n\t\t\t\t\t[start, create, add, remove],\n\t\t\t\t\tgraft,\n\t\t\t\t\tversion,\n\t\t\t\t\targs,\n\t\t\t\t).pipe(Effect.provideContext(context))\n\t\t\t}),\n\t\t),\n\t\targs,\n\t)\n})\nNodeRuntime.runMain(\n\tEffect.scoped(\n\t\tEffect.gen(function* () {\n\t\t\tconst context = yield* Layer.build(platform)\n\t\t\treturn yield* program.pipe(Effect.provideContext(context))\n\t\t}),\n\t).pipe(\n\t\t(effect) =>\n\t\t\tEffect.withFiber((main) =>\n\t\t\t\teffect.pipe(\n\t\t\t\t\tEffect.tapCause((cause) =>\n\t\t\t\t\t\tArray.every(\n\t\t\t\t\t\t\tcause.reasons,\n\t\t\t\t\t\t\t(reason) =>\n\t\t\t\t\t\t\t\treason._tag === \"Interrupt\" && reason.fiberId === main.id,\n\t\t\t\t\t\t) ||\n\t\t\t\t\t\tArray.every(\n\t\t\t\t\t\t\tcause.reasons,\n\t\t\t\t\t\t\t(reason) =>\n\t\t\t\t\t\t\t\treason._tag === \"Fail\" && CliError.isCliError(reason.error),\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\t? Effect.void\n\t\t\t\t\t\t\t: Effect.logError(cause),\n\t\t\t\t\t),\n\t\t\t\t),\n\t\t\t),\n\t\tEffect.provideService(Logger.LogToStderr, true),\n\t),\n\t{ disableErrorReporting: true },\n)\n"],"mappings":";;;;;;;;;;;;;AAeA,MAAM,QAAQ,QAAQ,KACrB,SACA;CACC,QAAQ,SAAS,OAAO,QAAQ,CAAC,CAAC,KACjC,SAAS,gBAAgB,yBAAyB,GAClD,SAAS,YAAY,WAAW,CACjC;CACA,OAAO,KAAK,QAAQ,OAAO,CAAC,CAAC,KAC5B,KAAK,UAAU,GAAG,GAClB,KAAK,gBAAgB,6CAA6C,GAClE,KAAK,YAAY,KAAK,CACvB;CACA,SAAS,KAAK,OAAO,UAAU,CAAC,CAAC,KAChC,KAAK,gBACJ,oFACD,GACA,KAAK,QACN;AACD,IACC,YACA,OAAO,cAAc,OAAO,aAAU,CAAC,CAAC,KACvC,OAAO,iBACP,OAAO,SAAS,UACf,MAAM,IAAI;CACT,GAAG;CACH,SAAS,OAAO,eAAe,QAAQ,OAAO;AAC/C,CAAC,CACF,CACD,CACF,CAAC,CAAC,KACD,QAAQ,gBAAgB,gDAAgD,CACzE;AAEA,MAAM,MAAM,QAAQ,KACnB,OACA;CACC,UAAU,SAAS,SAAS,SAAS,OAAO,SAAS,CAAC;CACtD,QAAQ,KAAK,OAAO,QAAQ,CAAC,CAAC,KAAK,KAAK,QAAQ;CAChD,QAAQ,KAAK,QAAQ,QAAQ,CAAC,CAAC,KAAK,KAAK,YAAY,KAAK,CAAC;AAC5D,GACA,OAAO,WAAW,WAAW,EAAE,UAAU,QAAQ,UAAU;CAC1D,IACE,UAAU,OAAO,OAAO,MAAM,KAC9B,OAAO,OAAO,MAAM,KAAK,SAAS,SAAS,GAE5C,OAAO,OAAO,SAAS,UAAU,KAAK;EACrC,OAAO;EACP,aACC;CACF,CAAC;CACF,MAAM,SAAS,OAAO,OAAO,cAAc,OAAO,cAAW,CAAC,CAAC,KAC9D,OAAO,eACR;CACA,OAAO,OAAO,OAAO,OAAO,MAAM,IAC/B,OAAO,UAAU,OAAO,OAAO,MAAM,IACrC,OAAO,IAAI,QAAQ;AACvB,CAAC,CACF,CAAC,CAAC,KACD,QAAQ,gBACP,6DACD,CACD;AAEA,MAAM,SAAS,QAAQ,KACtB,UACA,EAAE,UAAU,SAAS,SAAS,SAAS,OAAO,SAAS,CAAC,EAAE,IACzD,EAAE,eACF,OAAO,cAAc,OAAO,cAAW,CAAC,CAAC,KACxC,OAAO,iBACP,OAAO,SAAS,WAAW,OAAO,OAAO,QAAQ,CAAC,CACnD,CACF,CAAC,CAAC,KACD,QAAQ,gBACP,gEACD,CACD;AAEA,MAAM,QAAQ,QAAQ,KAAK,OAAO,CAAC,CAAC,KACnC,QAAQ,gBAAgB,mCAAmC,GAC3D,QAAQ,gBAAgB;CACvB,OAAO,KAAK,QAAQ,OAAO,CAAC,CAAC,KAAK,KAAK,YAAY,KAAK,CAAC;CACzD,WAAW,KAAK,QAAQ,YAAY,CAAC,CAAC,KAAK,KAAK,YAAY,KAAK,CAAC;AACnE,CAAC,CACF;AAEA,MAAM,UAAU,OAAO,IAAI,aAAa;CAEvC,MAAM,OAAO,QAAO,OADC,MAAM,MAAA,CACD;CAC1B,OAAO,OAAOA,OACb,OAAO,OACN,OAAO,IAAI,aAAa;EACvB,MAAM,UAAU,OAAO,MAAM,MAAM,MAAM,KAAK;EAC9C,OAAO,OAAOC,IACb;GAAC;GAAOC;GAAQ;GAAK;EAAM,GAC3B,OACA,SACA,IACD,CAAC,CAAC,KAAK,OAAO,eAAe,OAAO,CAAC;CACtC,CAAC,CACF,GACA,IACD;AACD,CAAC;AACD,YAAY,QACX,OAAO,OACN,OAAO,IAAI,aAAa;CACvB,MAAM,UAAU,OAAO,MAAM,MAAM,QAAQ;CAC3C,OAAO,OAAO,QAAQ,KAAK,OAAO,eAAe,OAAO,CAAC;AAC1D,CAAC,CACF,CAAC,CAAC,MACA,WACA,OAAO,WAAW,SACjB,OAAO,KACN,OAAO,UAAU,UAChB,MAAM,MACL,MAAM,UACL,WACA,OAAO,SAAS,eAAe,OAAO,YAAY,KAAK,EACzD,KACA,MAAM,MACL,MAAM,UACL,WACA,OAAO,SAAS,UAAU,SAAS,WAAW,OAAO,KAAK,CAC5D,IACG,OAAO,OACP,OAAO,SAAS,KAAK,CACzB,CACD,CACD,GACD,OAAO,eAAe,OAAO,aAAa,IAAI,CAC/C,GACA,EAAE,uBAAuB,KAAK,CAC/B"}