@passlock/cli 2.0.1 → 2.0.3

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 CHANGED
@@ -42,7 +42,7 @@ Install the CLI globally:
42
42
 
43
43
  or
44
44
 
45
- `pnpm add -g @passlock/api`
45
+ `pnpm add -g @passlock/cli`
46
46
 
47
47
  ### Create a cloud instance
48
48
 
@@ -42,7 +42,7 @@ Install the CLI globally:
42
42
 
43
43
  or
44
44
 
45
- `pnpm add -g @passlock/api`
45
+ `pnpm add -g @passlock/cli`
46
46
 
47
47
  ### Create a cloud instance
48
48
 
package/dist/cli.d.ts ADDED
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+ import { Effect } from "effect";
3
+ export type ParsedCommand = {
4
+ readonly _tag: "show-main";
5
+ } | {
6
+ readonly _tag: "show-main-help";
7
+ } | {
8
+ readonly _tag: "show-init-help";
9
+ } | {
10
+ readonly _tag: "show-version";
11
+ } | {
12
+ readonly _tag: "run-init";
13
+ readonly endpoint: string;
14
+ };
15
+ declare const CliParseError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
16
+ readonly _tag: "@error/CliParse";
17
+ } & Readonly<A>;
18
+ declare class CliParseError extends CliParseError_base<{
19
+ readonly message: string;
20
+ }> {
21
+ }
22
+ export declare const parseInitArgs: (args: ReadonlyArray<string>) => Effect.Effect<ParsedCommand, CliParseError>;
23
+ export declare const parseArgs: (argv: ReadonlyArray<string>) => Effect.Effect<ParsedCommand, CliParseError>;
24
+ export {};
25
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAOA,OAAO,EAAiB,MAAM,EAAQ,MAAM,QAAQ,CAAA;AAmCpD,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAA;CAAE,GAC9B;IAAE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAA;CAAE,GACnC;IAAE,QAAQ,CAAC,IAAI,EAAE,gBAAgB,CAAA;CAAE,GACnC;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;CAAE,GACjC;IAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAA;;;;AAE5D,cAAM,aAAc,SAAQ,mBAAoC;IAC9D,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB,CAAC;CAAG;AAOL,eAAO,MAAM,aAAa,GACxB,MAAM,aAAa,CAAC,MAAM,CAAC,KAC1B,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,aAAa,CAqDzC,CAAA;AAEJ,eAAO,MAAM,SAAS,GACpB,MAAM,aAAa,CAAC,MAAM,CAAC,KAC1B,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,aAAa,CAuBzC,CAAA"}
package/dist/cli.js ADDED
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env node
2
+ /*
3
+ * Originally built using @effect/cli but kept hitting
4
+ * peer resolution issues. This might get easier with
5
+ * Effect v4 so we might go back to cli later.
6
+ */
7
+ import { Console, Data, Effect, pipe } from "effect";
8
+ import { init } from "./init.js";
9
+ import { NetworkFetchLive } from "./network.js";
10
+ const VERSION = "2.0.3";
11
+ const DEFAULT_ENDPOINT = "https://api.passlock.dev";
12
+ const MAIN_HELP_TEXT = [
13
+ "Passlock CLI tools",
14
+ "",
15
+ "Usage:",
16
+ " passlock [command] [options]",
17
+ "",
18
+ "Commands:",
19
+ " init Setup a new Passlock cloud instance",
20
+ "",
21
+ "Options:",
22
+ " -h, --help Show this help message",
23
+ " -v, --version Show the current version",
24
+ "",
25
+ "Run 'passlock init --help' for command-specific options.",
26
+ ].join("\n");
27
+ const INIT_HELP_TEXT = [
28
+ "Setup a new Passlock cloud instance",
29
+ "",
30
+ "Usage:",
31
+ " passlock init [options]",
32
+ "",
33
+ "Options:",
34
+ " -e, --endpoint <url> Passlock API endpoint",
35
+ ` (default: ${DEFAULT_ENDPOINT})`,
36
+ " -h, --help Show this help message",
37
+ ].join("\n");
38
+ class CliParseError extends Data.TaggedError("@error/CliParse") {
39
+ }
40
+ const isHelpFlag = (arg) => arg === "--help" || arg === "-h";
41
+ const isVersionFlag = (arg) => arg === "--version" || arg === "-v";
42
+ export const parseInitArgs = (args) =>
43
+ // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: arg passing is hard
44
+ Effect.gen(function* () {
45
+ let endpoint = DEFAULT_ENDPOINT;
46
+ for (let i = 0; i < args.length; i += 1) {
47
+ const arg = args[i];
48
+ if (arg === undefined) {
49
+ continue;
50
+ }
51
+ if (isHelpFlag(arg)) {
52
+ return { _tag: "show-init-help" };
53
+ }
54
+ if (arg === "--endpoint" || arg === "-e") {
55
+ const value = args[i + 1];
56
+ if (value === undefined || value.startsWith("-")) {
57
+ return yield* new CliParseError({
58
+ message: "Missing value for --endpoint. Use --endpoint <url>.",
59
+ });
60
+ }
61
+ endpoint = value;
62
+ i += 1;
63
+ continue;
64
+ }
65
+ if (arg.startsWith("--endpoint=")) {
66
+ const value = arg.slice("--endpoint=".length);
67
+ if (value.length === 0) {
68
+ return yield* new CliParseError({
69
+ message: "Missing value for --endpoint. Use --endpoint <url>.",
70
+ });
71
+ }
72
+ endpoint = value;
73
+ continue;
74
+ }
75
+ if (arg.startsWith("-")) {
76
+ return yield* new CliParseError({
77
+ message: `Unknown option for init: ${arg}`,
78
+ });
79
+ }
80
+ return yield* new CliParseError({
81
+ message: `Unexpected argument for init: ${arg}`,
82
+ });
83
+ }
84
+ return { _tag: "run-init", endpoint };
85
+ });
86
+ export const parseArgs = (argv) => Effect.gen(function* () {
87
+ const [first, ...rest] = argv;
88
+ if (first === undefined) {
89
+ return { _tag: "show-main" };
90
+ }
91
+ if (isHelpFlag(first)) {
92
+ return { _tag: "show-main-help" };
93
+ }
94
+ if (isVersionFlag(first)) {
95
+ return { _tag: "show-version" };
96
+ }
97
+ if (first === "init") {
98
+ return yield* parseInitArgs(rest);
99
+ }
100
+ return yield* new CliParseError({
101
+ message: `Unknown command: ${first}`,
102
+ });
103
+ });
104
+ const runCommand = (command) => pipe(command, (parsed) => {
105
+ switch (parsed._tag) {
106
+ case "show-main":
107
+ return Console.log("Passlock CLI tools\nRun with --help for commands and options");
108
+ case "show-main-help":
109
+ return Console.log(MAIN_HELP_TEXT);
110
+ case "show-init-help":
111
+ return Console.log(INIT_HELP_TEXT);
112
+ case "show-version":
113
+ return Console.log(VERSION);
114
+ case "run-init":
115
+ return init(parsed.endpoint);
116
+ }
117
+ });
118
+ const program = pipe(parseArgs(process.argv.slice(2)), Effect.flatMap(runCommand), Effect.catchTag("@error/CliParse", ({ message }) => pipe(Console.error(message), Effect.zipRight(Console.log("Run 'passlock --help' for usage.")), Effect.zipRight(Effect.sync(() => {
119
+ process.exitCode = 1;
120
+ })))));
121
+ (async () => pipe(program, Effect.provide(NetworkFetchLive), Effect.runPromise))();
122
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["#!/usr/bin/env node\n\n/*\n * Originally built using @effect/cli but kept hitting\n * peer resolution issues. This might get easier with\n * Effect v4 so we might go back to cli later.\n */\nimport { Console, Data, Effect, pipe } from \"effect\"\nimport { init } from \"./init.js\"\nimport { type NetworkFetch, NetworkFetchLive } from \"./network.js\"\n\nconst VERSION = \"#{VERSION}#\"\nconst DEFAULT_ENDPOINT = \"https://api.passlock.dev\"\n\nconst MAIN_HELP_TEXT = [\n \"Passlock CLI tools\",\n \"\",\n \"Usage:\",\n \" passlock [command] [options]\",\n \"\",\n \"Commands:\",\n \" init Setup a new Passlock cloud instance\",\n \"\",\n \"Options:\",\n \" -h, --help Show this help message\",\n \" -v, --version Show the current version\",\n \"\",\n \"Run 'passlock init --help' for command-specific options.\",\n].join(\"\\n\")\n\nconst INIT_HELP_TEXT = [\n \"Setup a new Passlock cloud instance\",\n \"\",\n \"Usage:\",\n \" passlock init [options]\",\n \"\",\n \"Options:\",\n \" -e, --endpoint <url> Passlock API endpoint\",\n ` (default: ${DEFAULT_ENDPOINT})`,\n \" -h, --help Show this help message\",\n].join(\"\\n\")\n\nexport type ParsedCommand =\n | { readonly _tag: \"show-main\" }\n | { readonly _tag: \"show-main-help\" }\n | { readonly _tag: \"show-init-help\" }\n | { readonly _tag: \"show-version\" }\n | { readonly _tag: \"run-init\"; readonly endpoint: string }\n\nclass CliParseError extends Data.TaggedError(\"@error/CliParse\")<{\n readonly message: string\n}> {}\n\nconst isHelpFlag = (arg: string): boolean => arg === \"--help\" || arg === \"-h\"\n\nconst isVersionFlag = (arg: string): boolean =>\n arg === \"--version\" || arg === \"-v\"\n\nexport const parseInitArgs = (\n args: ReadonlyArray<string>\n): Effect.Effect<ParsedCommand, CliParseError> =>\n // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: arg passing is hard\n Effect.gen(function* () {\n let endpoint = DEFAULT_ENDPOINT\n\n for (let i = 0; i < args.length; i += 1) {\n const arg = args[i]\n if (arg === undefined) {\n continue\n }\n\n if (isHelpFlag(arg)) {\n return { _tag: \"show-init-help\" } as const\n }\n\n if (arg === \"--endpoint\" || arg === \"-e\") {\n const value = args[i + 1]\n\n if (value === undefined || value.startsWith(\"-\")) {\n return yield* new CliParseError({\n message: \"Missing value for --endpoint. Use --endpoint <url>.\",\n })\n }\n\n endpoint = value\n i += 1\n continue\n }\n\n if (arg.startsWith(\"--endpoint=\")) {\n const value = arg.slice(\"--endpoint=\".length)\n if (value.length === 0) {\n return yield* new CliParseError({\n message: \"Missing value for --endpoint. Use --endpoint <url>.\",\n })\n }\n\n endpoint = value\n continue\n }\n\n if (arg.startsWith(\"-\")) {\n return yield* new CliParseError({\n message: `Unknown option for init: ${arg}`,\n })\n }\n\n return yield* new CliParseError({\n message: `Unexpected argument for init: ${arg}`,\n })\n }\n\n return { _tag: \"run-init\", endpoint } as const\n })\n\nexport const parseArgs = (\n argv: ReadonlyArray<string>\n): Effect.Effect<ParsedCommand, CliParseError> =>\n Effect.gen(function* () {\n const [first, ...rest] = argv\n\n if (first === undefined) {\n return { _tag: \"show-main\" } as const\n }\n\n if (isHelpFlag(first)) {\n return { _tag: \"show-main-help\" } as const\n }\n\n if (isVersionFlag(first)) {\n return { _tag: \"show-version\" } as const\n }\n\n if (first === \"init\") {\n return yield* parseInitArgs(rest)\n }\n\n return yield* new CliParseError({\n message: `Unknown command: ${first}`,\n })\n })\n\nconst runCommand = (\n command: ParsedCommand\n): Effect.Effect<void, never, NetworkFetch> =>\n pipe(command, (parsed) => {\n switch (parsed._tag) {\n case \"show-main\":\n return Console.log(\n \"Passlock CLI tools\\nRun with --help for commands and options\"\n )\n case \"show-main-help\":\n return Console.log(MAIN_HELP_TEXT)\n case \"show-init-help\":\n return Console.log(INIT_HELP_TEXT)\n case \"show-version\":\n return Console.log(VERSION)\n case \"run-init\":\n return init(parsed.endpoint)\n }\n })\n\nconst program = pipe(\n parseArgs(process.argv.slice(2)),\n Effect.flatMap(runCommand),\n Effect.catchTag(\"@error/CliParse\", ({ message }) =>\n pipe(\n Console.error(message),\n Effect.zipRight(Console.log(\"Run 'passlock --help' for usage.\")),\n Effect.zipRight(\n Effect.sync(() => {\n process.exitCode = 1\n })\n )\n )\n )\n)\n\n;(async () =>\n pipe(program, Effect.provide(NetworkFetchLive), Effect.runPromise))()\n"]}
package/dist/init.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { HttpClient } from "@effect/platform";
2
1
  import { Effect, Schema } from "effect";
2
+ import { type NetworkFetch } from "./network.js";
3
3
  declare const SignupPayload: Schema.Struct<{
4
4
  email: typeof Schema.String;
5
5
  firstName: typeof Schema.String;
@@ -25,7 +25,7 @@ export declare const TenancyData: Schema.TaggedStruct<"TenancyData", {
25
25
  tenancyId: typeof Schema.String;
26
26
  }>;
27
27
  export type TenancyData = typeof TenancyData.Type;
28
- export declare const signup: (payload: SignupPayload) => Effect.Effect<TenancyData, InvalidEmail | DuplicateEmail, HttpClient.HttpClient>;
29
- export declare const init: Effect.Effect<void, never, HttpClient.HttpClient>;
28
+ export declare const signup: (payload: SignupPayload, endpoint: string) => Effect.Effect<TenancyData, InvalidEmail | DuplicateEmail, NetworkFetch>;
29
+ export declare const init: (endpoint: string) => Effect.Effect<void, never, NetworkFetch>;
30
30
  export {};
31
31
  //# sourceMappingURL=init.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AACA,OAAO,EAAY,UAAU,EAAsB,MAAM,kBAAkB,CAAA;AAC3E,OAAO,EAAQ,MAAM,EAAe,MAAM,EAAE,MAAM,QAAQ,CAAA;AAO1D,QAAA,MAAM,aAAa;;;;EAIjB,CAAA;AAEF,KAAK,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAA;;;;;;AAE9C,qBAAa,YAAa,SAAQ,iBAGjC;CAAG;;;;;;AAEJ,qBAAa,cAAe,SAAQ,mBAGnC;CAAG;AAEJ,eAAO,MAAM,WAAW;;;EAGtB,CAAA;AAEF,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,IAAI,CAAA;AAyDjD,eAAO,MAAM,MAAM,GACjB,SAAS,aAAa,KACrB,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,YAAY,GAAG,cAAc,EAAE,UAAU,CAAC,UAAU,CA+B/E,CAAA;AAEH,eAAO,MAAM,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,CA+ClE,CAAA"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"AASA,OAAO,EAAQ,MAAM,EAAe,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE1D,OAAO,EAGL,KAAK,YAAY,EAIlB,MAAM,cAAc,CAAA;AAMrB,QAAA,MAAM,aAAa;;;;EAIjB,CAAA;AAEF,KAAK,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAA;;;;;;AAE9C,qBAAa,YAAa,SAAQ,iBAEkB;CAAG;;;;;;AAEvD,qBAAa,cAAe,SAAQ,mBAEkB;CAAG;AAEzD,eAAO,MAAM,WAAW;;;EAGtB,CAAA;AAEF,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC,IAAI,CAAA;AA6DjD,eAAO,MAAM,MAAM,GACjB,SAAS,aAAa,EACtB,UAAU,MAAM,KACf,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,YAAY,GAAG,cAAc,EAAE,YAAY,CAoCtE,CAAA;AAEH,eAAO,MAAM,IAAI,GACf,UAAU,MAAM,KACf,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,KAAK,EAAE,YAAY,CAwDvC,CAAA"}
package/dist/init.js CHANGED
@@ -1,7 +1,7 @@
1
- import { confirm, intro, isCancel, log, outro, spinner, text } from "@clack/prompts";
2
- import { HttpBody, HttpClient, HttpClientResponse } from "@effect/platform";
1
+ import { confirm, intro, isCancel, log, outro, spinner, text, } from "@clack/prompts";
3
2
  import { Data, Effect, Match, pipe, Schema } from "effect";
4
3
  import kleur from "kleur";
4
+ import { fetchNetwork, matchStatus, } from "./network.js";
5
5
  class CancelError extends Data.TaggedError("@error/Abort") {
6
6
  }
7
7
  const emailRegex = /^[^@]+@[^@]+.[^@]+$/;
@@ -58,31 +58,31 @@ const captureData = Effect.gen(function* () {
58
58
  return yield* new CancelError({});
59
59
  return isConfirmed ? { email, firstName, lastName } : yield* captureData;
60
60
  });
61
- export const signup = (payload) => pipe(Effect.gen(function* () {
62
- const client = yield* HttpClient.HttpClient;
63
- const encodedPayload = yield* HttpBody.json(payload);
64
- const response = yield* pipe(
65
- // endpoint will be prepended by the HttpClient
66
- client.post("/signup", {
67
- body: encodedPayload,
68
- }));
69
- const encoded = yield* HttpClientResponse.matchStatus(response, {
70
- "2xx": () => HttpClientResponse.schemaBodyJson(TenancyData)(response),
71
- orElse: () => HttpClientResponse.schemaBodyJson(Schema.Union(InvalidEmail, DuplicateEmail))(response),
61
+ export const signup = (payload, endpoint) => pipe(Effect.gen(function* () {
62
+ const response = yield* fetchNetwork(new URL("/signup", endpoint), "post", payload);
63
+ const encoded = yield* matchStatus(response, {
64
+ "2xx": ({ json }) => pipe(json, Effect.flatMap(Schema.decodeUnknown(TenancyData))),
65
+ orElse: ({ json }) => pipe(json, Effect.flatMap(Schema.decodeUnknown(Schema.Union(InvalidEmail, DuplicateEmail)))),
72
66
  });
73
67
  return yield* pipe(Match.value(encoded), Match.tag("TenancyData", (principal) => Effect.succeed(principal)), Match.tag("@error/InvalidEmail", (err) => Effect.fail(err)), Match.tag("@error/DuplicateEmail", (err) => Effect.fail(err)), Match.exhaustive);
74
- }), Effect.catchTag("HttpBodyError", Effect.die), Effect.catchTag("ParseError", Effect.die), Effect.catchTag("RequestError", Effect.die), Effect.catchTag("ResponseError", Effect.die));
75
- export const init = pipe(Effect.gen(function* () {
68
+ }), Effect.catchTags({
69
+ "@error/NetworkPayload": (err) => Effect.die(err),
70
+ "@error/NetworkRequest": (err) => Effect.die(err),
71
+ "@error/NetworkResponse": (err) => Effect.die(err),
72
+ ParseError: (err) => Effect.die(err),
73
+ }));
74
+ export const init = (endpoint) => pipe(Effect.gen(function* () {
76
75
  intro(`Setting up new Passlock cloud instance...`);
77
76
  const signupData = yield* captureData;
78
77
  const s = spinner();
79
78
  s.start("Setting up instance");
80
- const { tenancyId, apiKey } = yield* pipe(signup(signupData), Effect.tapError(() => Effect.sync(() => {
79
+ const { tenancyId, apiKey } = yield* pipe(signup(signupData, endpoint), Effect.tapError(() => Effect.sync(() => {
81
80
  s.stop("Something went wrong");
82
81
  })));
83
82
  s.stop("Instance ready 🎉");
84
83
  log.success("Here are your development instance credentials.\nPlease keep them secure:");
85
- log.message(`Tenancy ID: ${kleur.green(tenancyId)}\n` + `API Key: ${kleur.green(apiKey)}`);
84
+ log.message(`Tenancy ID: ${kleur.green(tenancyId)}\n` +
85
+ `API Key: ${kleur.green(apiKey)}`);
86
86
  log.message(`Login to your Passlock console at\n${kleur.blue().underline("https://console.passlock.dev")}`);
87
87
  log.message("Check out the quick start guide at\n" +
88
88
  kleur.blue().underline("https://passlock.dev/getting-started/"));
@@ -92,7 +92,8 @@ export const init = pipe(Effect.gen(function* () {
92
92
  log.error("Operation cancelled");
93
93
  }),
94
94
  "@error/DuplicateEmail": () => Effect.sync(() => {
95
- log.error("Email already registered\n" + "Sign in at https://console.passlock.dev");
95
+ log.error("Email already registered\n" +
96
+ "Sign in at https://console.passlock.dev");
96
97
  }),
97
98
  "@error/InvalidEmail": () => Effect.sync(() => {
98
99
  log.error("Invalid email address");
package/dist/init.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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","sourcesContent":["import { confirm, intro, isCancel, log, outro, spinner, text } from \"@clack/prompts\"\nimport { HttpBody, HttpClient, HttpClientResponse } from \"@effect/platform\"\nimport { Data, Effect, Match, pipe, Schema } from \"effect\"\nimport kleur from \"kleur\"\n\nclass CancelError extends Data.TaggedError(\"@error/Abort\")<object> {}\n\nconst emailRegex = /^[^@]+@[^@]+.[^@]+$/\n\nconst SignupPayload = Schema.Struct({\n email: Schema.String,\n firstName: Schema.String,\n lastName: Schema.String,\n})\n\ntype SignupPayload = typeof SignupPayload.Type\n\nexport class InvalidEmail extends Schema.TaggedError<InvalidEmail>(\"@error/InvalidEmail\")(\n \"@error/InvalidEmail\",\n { message: Schema.String }\n) {}\n\nexport class DuplicateEmail extends Schema.TaggedError<DuplicateEmail>(\"@error/DuplicateEmail\")(\n \"@error/DuplicateEmail\",\n { message: Schema.String }\n) {}\n\nexport const TenancyData = Schema.TaggedStruct(\"TenancyData\", {\n apiKey: Schema.String,\n tenancyId: Schema.String,\n})\n\nexport type TenancyData = typeof TenancyData.Type\n\nconst captureData: Effect.Effect<SignupPayload, CancelError> = Effect.gen(function* () {\n const email = yield* Effect.promise(() =>\n text({\n message: \"Root account email? (we'll send a single use code to this address)\",\n\n placeholder: \"jdoe@gmail.com\",\n\n validate(value) {\n if (!value || value.length === 0) return `Value is required!`\n if (!emailRegex.test(value)) return `Please provide a valid email address!`\n },\n })\n )\n\n if (isCancel(email)) return yield* new CancelError({})\n\n const firstName = yield* Effect.promise(() =>\n text({\n message: \"Your first/given name\",\n\n placeholder: \"John\",\n\n validate(value) {\n if (!value || value.length === 0) return `Value is required!`\n },\n })\n )\n\n if (isCancel(firstName)) return yield* new CancelError({})\n\n const lastName = yield* Effect.promise(() =>\n text({\n message: \"Your last/family name\",\n\n placeholder: \"Doe\",\n\n validate(value) {\n if (!value || value.length === 0) return `Value is required!`\n },\n })\n )\n\n if (isCancel(lastName)) return yield* new CancelError({})\n\n const isConfirmed = yield* Effect.promise(() =>\n confirm({\n message: `Using ${firstName} ${lastName} <${email}>, continue?`,\n })\n )\n\n if (isCancel(isConfirmed)) return yield* new CancelError({})\n\n return isConfirmed ? { email, firstName, lastName } : yield* captureData\n})\n\nexport const signup = (\n payload: SignupPayload\n): Effect.Effect<TenancyData, InvalidEmail | DuplicateEmail, HttpClient.HttpClient> =>\n pipe(\n Effect.gen(function* () {\n const client = yield* HttpClient.HttpClient\n const encodedPayload = yield* HttpBody.json(payload)\n\n const response = yield* pipe(\n // endpoint will be prepended by the HttpClient\n client.post(\"/signup\", {\n body: encodedPayload,\n })\n )\n\n const encoded = yield* HttpClientResponse.matchStatus(response, {\n \"2xx\": () => HttpClientResponse.schemaBodyJson(TenancyData)(response),\n orElse: () =>\n HttpClientResponse.schemaBodyJson(Schema.Union(InvalidEmail, DuplicateEmail))(response),\n })\n\n return yield* pipe(\n Match.value(encoded),\n Match.tag(\"TenancyData\", (principal) => Effect.succeed(principal)),\n Match.tag(\"@error/InvalidEmail\", (err) => Effect.fail(err)),\n Match.tag(\"@error/DuplicateEmail\", (err) => Effect.fail(err)),\n Match.exhaustive\n )\n }),\n Effect.catchTag(\"HttpBodyError\", Effect.die),\n Effect.catchTag(\"ParseError\", Effect.die),\n Effect.catchTag(\"RequestError\", Effect.die),\n Effect.catchTag(\"ResponseError\", Effect.die)\n )\n\nexport const init: Effect.Effect<void, never, HttpClient.HttpClient> = pipe(\n Effect.gen(function* () {\n intro(`Setting up new Passlock cloud instance...`)\n\n const signupData = yield* captureData\n const s = spinner()\n s.start(\"Setting up instance\")\n\n const { tenancyId, apiKey } = yield* pipe(\n signup(signupData),\n Effect.tapError(() =>\n Effect.sync(() => {\n s.stop(\"Something went wrong\")\n })\n )\n )\n s.stop(\"Instance ready 🎉\")\n\n log.success(\"Here are your development instance credentials.\\nPlease keep them secure:\")\n\n log.message(`Tenancy ID: ${kleur.green(tenancyId)}\\n` + `API Key: ${kleur.green(apiKey)}`)\n\n log.message(\n `Login to your Passlock console at\\n${kleur.blue().underline(\"https://console.passlock.dev\")}`\n )\n\n log.message(\n \"Check out the quick start guide at\\n\" +\n kleur.blue().underline(\"https://passlock.dev/getting-started/\")\n )\n\n outro(\"You're all set!\")\n }),\n Effect.catchTags({\n \"@error/Abort\": () =>\n Effect.sync(() => {\n log.error(\"Operation cancelled\")\n }),\n \"@error/DuplicateEmail\": () =>\n Effect.sync(() => {\n log.error(\"Email already registered\\n\" + \"Sign in at https://console.passlock.dev\")\n }),\n \"@error/InvalidEmail\": () =>\n Effect.sync(() => {\n log.error(\"Invalid email address\")\n }),\n })\n)\n"]}
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../src/init.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n confirm,\n intro,\n isCancel,\n log,\n outro,\n spinner,\n text,\n} from \"@clack/prompts\"\nimport { Data, Effect, Match, pipe, Schema } from \"effect\"\nimport kleur from \"kleur\"\nimport {\n fetchNetwork,\n matchStatus,\n type NetworkFetch,\n type NetworkPayloadError,\n type NetworkRequestError,\n type NetworkResponseError,\n} from \"./network.js\"\n\nclass CancelError extends Data.TaggedError(\"@error/Abort\")<object> {}\n\nconst emailRegex = /^[^@]+@[^@]+.[^@]+$/\n\nconst SignupPayload = Schema.Struct({\n email: Schema.String,\n firstName: Schema.String,\n lastName: Schema.String,\n})\n\ntype SignupPayload = typeof SignupPayload.Type\n\nexport class InvalidEmail extends Schema.TaggedError<InvalidEmail>(\n \"@error/InvalidEmail\"\n)(\"@error/InvalidEmail\", { message: Schema.String }) {}\n\nexport class DuplicateEmail extends Schema.TaggedError<DuplicateEmail>(\n \"@error/DuplicateEmail\"\n)(\"@error/DuplicateEmail\", { message: Schema.String }) {}\n\nexport const TenancyData = Schema.TaggedStruct(\"TenancyData\", {\n apiKey: Schema.String,\n tenancyId: Schema.String,\n})\n\nexport type TenancyData = typeof TenancyData.Type\n\nconst captureData: Effect.Effect<SignupPayload, CancelError> = Effect.gen(\n function* () {\n const email = yield* Effect.promise(() =>\n text({\n message:\n \"Root account email? (we'll send a single use code to this address)\",\n\n placeholder: \"jdoe@gmail.com\",\n\n validate(value) {\n if (!value || value.length === 0) return `Value is required!`\n if (!emailRegex.test(value))\n return `Please provide a valid email address!`\n },\n })\n )\n\n if (isCancel(email)) return yield* new CancelError({})\n\n const firstName = yield* Effect.promise(() =>\n text({\n message: \"Your first/given name\",\n\n placeholder: \"John\",\n\n validate(value) {\n if (!value || value.length === 0) return `Value is required!`\n },\n })\n )\n\n if (isCancel(firstName)) return yield* new CancelError({})\n\n const lastName = yield* Effect.promise(() =>\n text({\n message: \"Your last/family name\",\n\n placeholder: \"Doe\",\n\n validate(value) {\n if (!value || value.length === 0) return `Value is required!`\n },\n })\n )\n\n if (isCancel(lastName)) return yield* new CancelError({})\n\n const isConfirmed = yield* Effect.promise(() =>\n confirm({\n message: `Using ${firstName} ${lastName} <${email}>, continue?`,\n })\n )\n\n if (isCancel(isConfirmed)) return yield* new CancelError({})\n\n return isConfirmed ? { email, firstName, lastName } : yield* captureData\n }\n)\n\nexport const signup = (\n payload: SignupPayload,\n endpoint: string\n): Effect.Effect<TenancyData, InvalidEmail | DuplicateEmail, NetworkFetch> =>\n pipe(\n Effect.gen(function* () {\n const response = yield* fetchNetwork(\n new URL(\"/signup\", endpoint),\n \"post\",\n payload\n )\n\n const encoded: TenancyData | InvalidEmail | DuplicateEmail =\n yield* matchStatus(response, {\n \"2xx\": ({ json }) =>\n pipe(json, Effect.flatMap(Schema.decodeUnknown(TenancyData))),\n orElse: ({ json }) =>\n pipe(\n json,\n Effect.flatMap(\n Schema.decodeUnknown(Schema.Union(InvalidEmail, DuplicateEmail))\n )\n ),\n })\n\n return yield* pipe(\n Match.value(encoded),\n Match.tag(\"TenancyData\", (principal) => Effect.succeed(principal)),\n Match.tag(\"@error/InvalidEmail\", (err) => Effect.fail(err)),\n Match.tag(\"@error/DuplicateEmail\", (err) => Effect.fail(err)),\n Match.exhaustive\n )\n }),\n Effect.catchTags({\n \"@error/NetworkPayload\": (err: NetworkPayloadError) => Effect.die(err),\n \"@error/NetworkRequest\": (err: NetworkRequestError) => Effect.die(err),\n \"@error/NetworkResponse\": (err: NetworkResponseError) => Effect.die(err),\n ParseError: (err) => Effect.die(err),\n })\n )\n\nexport const init = (\n endpoint: string\n): Effect.Effect<void, never, NetworkFetch> =>\n pipe(\n Effect.gen(function* () {\n intro(`Setting up new Passlock cloud instance...`)\n\n const signupData = yield* captureData\n const s = spinner()\n s.start(\"Setting up instance\")\n\n const { tenancyId, apiKey } = yield* pipe(\n signup(signupData, endpoint),\n Effect.tapError(() =>\n Effect.sync(() => {\n s.stop(\"Something went wrong\")\n })\n )\n )\n s.stop(\"Instance ready 🎉\")\n\n log.success(\n \"Here are your development instance credentials.\\nPlease keep them secure:\"\n )\n\n log.message(\n `Tenancy ID: ${kleur.green(tenancyId)}\\n` +\n `API Key: ${kleur.green(apiKey)}`\n )\n\n log.message(\n `Login to your Passlock console at\\n${kleur.blue().underline(\"https://console.passlock.dev\")}`\n )\n\n log.message(\n \"Check out the quick start guide at\\n\" +\n kleur.blue().underline(\"https://passlock.dev/getting-started/\")\n )\n\n outro(\"You're all set!\")\n }),\n Effect.catchTags({\n \"@error/Abort\": () =>\n Effect.sync(() => {\n log.error(\"Operation cancelled\")\n }),\n \"@error/DuplicateEmail\": () =>\n Effect.sync(() => {\n log.error(\n \"Email already registered\\n\" +\n \"Sign in at https://console.passlock.dev\"\n )\n }),\n \"@error/InvalidEmail\": () =>\n Effect.sync(() => {\n log.error(\"Invalid email address\")\n }),\n })\n )\n"]}
@@ -0,0 +1,134 @@
1
+ import { Context, Effect, Layer } from "effect";
2
+ /**
3
+ * Supported HTTP methods accepted by {@link fetchNetwork}.
4
+ */
5
+ export type NetworkMethod = "get" | "post" | "delete" | "patch";
6
+ /**
7
+ * Lightweight response model used by this package.
8
+ *
9
+ * Invariants:
10
+ * - `json` is lazy: parsing only happens when the effect is run.
11
+ * - `json` is memoized per response wrapper, so repeated evaluation does not
12
+ * parse the same payload multiple times.
13
+ */
14
+ export interface NetworkResponse {
15
+ readonly status: number;
16
+ readonly statusText: string;
17
+ readonly statusMessage: string;
18
+ readonly headers: Readonly<Record<string, string>>;
19
+ readonly json: Effect.Effect<unknown, NetworkResponseError>;
20
+ }
21
+ /**
22
+ * Accepted request header input formats.
23
+ */
24
+ export type NetworkHeaders = Headers | Readonly<Record<string, string>> | Array<[string, string]>;
25
+ /**
26
+ * Optional request options for {@link fetchNetwork}.
27
+ */
28
+ export interface FetchNetworkOptions {
29
+ readonly headers?: NetworkHeaders;
30
+ }
31
+ declare const NetworkFetch_base: Context.TagClass<NetworkFetch, "@passlock/node/network/Fetch", typeof fetch>;
32
+ /**
33
+ * Effect service tag for the fetch implementation.
34
+ *
35
+ * Supply this service with `Effect.provide` / layers to swap fetch behavior
36
+ * in tests or alternate runtimes.
37
+ */
38
+ export declare class NetworkFetch extends NetworkFetch_base {
39
+ }
40
+ /**
41
+ * Default live fetch layer backed by `globalThis.fetch`.
42
+ */
43
+ export declare const NetworkFetchLive: Layer.Layer<NetworkFetch>;
44
+ /**
45
+ * HTTP status buckets used by {@link matchStatus}.
46
+ */
47
+ export type NetworkResponseStatusCase = "2xx" | "3xx" | "4xx" | "5xx";
48
+ type MatchStatusHandler<Resp extends NetworkResponse = NetworkResponse, A = unknown, E = unknown> = (response: Resp) => Effect.Effect<A, E, never>;
49
+ type HandlerEffect<Cases extends MatchStatusCases<Resp>, Resp extends NetworkResponse, Case extends NetworkResponseStatusCase | "orElse"> = Case extends keyof Cases ? NonNullable<Cases[Case]> extends MatchStatusHandler<Resp> ? ReturnType<NonNullable<Cases[Case]>> : never : never;
50
+ type MatchStatusEffectUnion<Cases extends MatchStatusCases<Resp>, Resp extends NetworkResponse> = HandlerEffect<Cases, Resp, "2xx"> | HandlerEffect<Cases, Resp, "3xx"> | HandlerEffect<Cases, Resp, "4xx"> | HandlerEffect<Cases, Resp, "5xx"> | HandlerEffect<Cases, Resp, "orElse">;
51
+ type EffectSuccess<T> = T extends Effect.Effect<infer A, unknown, unknown> ? A : never;
52
+ type EffectError<T> = T extends Effect.Effect<unknown, infer E, unknown> ? E : never;
53
+ type EffectContext<T> = T extends Effect.Effect<unknown, unknown, infer R> ? R : never;
54
+ /**
55
+ * Handlers used by {@link matchStatus}.
56
+ *
57
+ * Invariants:
58
+ * - `orElse` is always required.
59
+ * - Specific status family handlers are optional and fall back to `orElse`
60
+ * when missing.
61
+ */
62
+ export interface MatchStatusCases<Resp extends NetworkResponse = NetworkResponse> {
63
+ readonly "2xx"?: MatchStatusHandler<Resp>;
64
+ readonly "3xx"?: MatchStatusHandler<Resp>;
65
+ readonly "4xx"?: MatchStatusHandler<Resp>;
66
+ readonly "5xx"?: MatchStatusHandler<Resp>;
67
+ readonly orElse: MatchStatusHandler<Resp>;
68
+ }
69
+ declare const NetworkRequestError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
70
+ readonly _tag: "@error/NetworkRequest";
71
+ } & Readonly<A>;
72
+ /**
73
+ * Raised when the underlying fetch call fails before a response is received.
74
+ */
75
+ export declare class NetworkRequestError extends NetworkRequestError_base<{
76
+ readonly method: NetworkMethod;
77
+ readonly url: string;
78
+ readonly message: string;
79
+ }> {
80
+ }
81
+ declare const NetworkPayloadError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
82
+ readonly _tag: "@error/NetworkPayload";
83
+ } & Readonly<A>;
84
+ /**
85
+ * Raised when request payload serialization fails.
86
+ */
87
+ export declare class NetworkPayloadError extends NetworkPayloadError_base<{
88
+ readonly method: NetworkMethod;
89
+ readonly message: string;
90
+ }> {
91
+ }
92
+ declare const NetworkResponseError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
93
+ readonly _tag: "@error/NetworkResponse";
94
+ } & Readonly<A>;
95
+ /**
96
+ * Raised when response body parsing fails.
97
+ */
98
+ export declare class NetworkResponseError extends NetworkResponseError_base<{
99
+ readonly method: NetworkMethod;
100
+ readonly url: string;
101
+ readonly message: string;
102
+ }> {
103
+ }
104
+ /**
105
+ * Convert an HTTP status code into its status family bucket.
106
+ *
107
+ * Returns `undefined` for codes outside the 2xx-5xx families.
108
+ */
109
+ export declare const statusToCase: (status: number) => NetworkResponseStatusCase | undefined;
110
+ /**
111
+ * Route a {@link NetworkResponse} to the first matching status-family handler.
112
+ *
113
+ * Invariants:
114
+ * - `2xx`/`3xx`/`4xx`/`5xx` handlers are matched by status family.
115
+ * - `orElse` is always used as a fallback when no specific family handler exists.
116
+ * - The returned effect type is inferred as the union of all handler effects.
117
+ */
118
+ export declare const matchStatus: <Resp extends NetworkResponse, Cases extends MatchStatusCases<Resp>>(response: Resp, cases: Cases) => Effect.Effect<EffectSuccess<MatchStatusEffectUnion<Cases, Resp>>, EffectError<MatchStatusEffectUnion<Cases, Resp>>, EffectContext<MatchStatusEffectUnion<Cases, Resp>>>;
119
+ /**
120
+ * Convert `Headers` into a readonly plain record.
121
+ */
122
+ export declare const headersToRecord: (headers: Headers) => Readonly<Record<string, string>>;
123
+ /**
124
+ * Execute a fetch request using the injected {@link NetworkFetch} service.
125
+ *
126
+ * Invariants:
127
+ * - method is always normalized to upper-case before dispatch.
128
+ * - JSON payload (if present) is serialized before request execution.
129
+ * - caller headers override payload-derived headers when keys overlap.
130
+ * - the returned `NetworkResponse.json` remains lazy.
131
+ */
132
+ export declare const fetchNetwork: (url: string | URL, method: NetworkMethod, payload?: unknown, options?: FetchNetworkOptions) => Effect.Effect<NetworkResponse, NetworkRequestError | NetworkPayloadError, NetworkFetch>;
133
+ export {};
134
+ //# sourceMappingURL=network.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../src/network.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,172 @@
1
+ import { Context, Data, Effect, Layer } from "effect";
2
+ /**
3
+ * Effect service tag for the fetch implementation.
4
+ *
5
+ * Supply this service with `Effect.provide` / layers to swap fetch behavior
6
+ * in tests or alternate runtimes.
7
+ */
8
+ export class NetworkFetch extends Context.Tag("@passlock/node/network/Fetch")() {
9
+ }
10
+ /**
11
+ * Default live fetch layer backed by `globalThis.fetch`.
12
+ */
13
+ export const NetworkFetchLive = Layer.succeed(NetworkFetch, globalThis.fetch);
14
+ /**
15
+ * Raised when the underlying fetch call fails before a response is received.
16
+ */
17
+ export class NetworkRequestError extends Data.TaggedError("@error/NetworkRequest") {
18
+ }
19
+ /**
20
+ * Raised when request payload serialization fails.
21
+ */
22
+ export class NetworkPayloadError extends Data.TaggedError("@error/NetworkPayload") {
23
+ }
24
+ /**
25
+ * Raised when response body parsing fails.
26
+ */
27
+ export class NetworkResponseError extends Data.TaggedError("@error/NetworkResponse") {
28
+ }
29
+ const formatMessage = (cause, fallback) => cause instanceof Error ? cause.message : fallback;
30
+ /**
31
+ * Convert an HTTP status code into its status family bucket.
32
+ *
33
+ * Returns `undefined` for codes outside the 2xx-5xx families.
34
+ */
35
+ export const statusToCase = (status) => {
36
+ if (status >= 200 && status <= 299)
37
+ return "2xx";
38
+ if (status >= 300 && status <= 399)
39
+ return "3xx";
40
+ if (status >= 400 && status <= 499)
41
+ return "4xx";
42
+ if (status >= 500 && status <= 599)
43
+ return "5xx";
44
+ return undefined;
45
+ };
46
+ const resolveStatusHandler = (response, cases) => {
47
+ const statusCase = statusToCase(response.status);
48
+ if (!statusCase)
49
+ return cases.orElse;
50
+ const handler = cases[statusCase];
51
+ return (handler ?? cases.orElse);
52
+ };
53
+ /**
54
+ * Route a {@link NetworkResponse} to the first matching status-family handler.
55
+ *
56
+ * Invariants:
57
+ * - `2xx`/`3xx`/`4xx`/`5xx` handlers are matched by status family.
58
+ * - `orElse` is always used as a fallback when no specific family handler exists.
59
+ * - The returned effect type is inferred as the union of all handler effects.
60
+ */
61
+ export const matchStatus = (response, cases) => Effect.suspend(() => {
62
+ const handler = resolveStatusHandler(response, cases);
63
+ return handler(response);
64
+ });
65
+ /**
66
+ * Serialize an optional payload into a JSON request body.
67
+ *
68
+ * Invariants:
69
+ * - `GET` requests cannot carry a payload and fail with `NetworkPayloadError`.
70
+ * - when a payload exists, `content-type: application/json` is emitted.
71
+ */
72
+ const serializePayload = (method, payload) => {
73
+ if (payload === undefined) {
74
+ return Effect.succeed(undefined);
75
+ }
76
+ if (method === "get") {
77
+ return Effect.fail(new NetworkPayloadError({
78
+ method,
79
+ message: "GET requests do not support a request body",
80
+ }));
81
+ }
82
+ return Effect.try({
83
+ try: () => ({
84
+ body: JSON.stringify(payload),
85
+ headers: { "content-type": "application/json" },
86
+ }),
87
+ catch: (cause) => new NetworkPayloadError({
88
+ method,
89
+ message: formatMessage(cause, "Unable to serialize payload to JSON"),
90
+ }),
91
+ });
92
+ };
93
+ /**
94
+ * Convert `Headers` into a readonly plain record.
95
+ */
96
+ export const headersToRecord = (headers) => Object.fromEntries(headers.entries());
97
+ const normalizeHeaders = (headers) => {
98
+ if (headers instanceof Headers) {
99
+ return new Headers(headers);
100
+ }
101
+ if (Array.isArray(headers)) {
102
+ return new Headers(headers);
103
+ }
104
+ return new Headers(headers);
105
+ };
106
+ const mergeHeaders = (...headers) => Object.assign({}, ...headers);
107
+ /**
108
+ * Build a lazy, memoized JSON parser effect from a response.
109
+ *
110
+ * Invariants:
111
+ * - parsing happens on effect execution, not during response construction.
112
+ * - parsing uses `response.clone()` so the original response body remains untouched.
113
+ */
114
+ const makeJsonEffect = (response, context) => {
115
+ let cached;
116
+ return Effect.tryPromise({
117
+ try: () => {
118
+ cached = cached ?? response.clone().json();
119
+ return cached;
120
+ },
121
+ catch: (cause) => new NetworkResponseError({
122
+ method: context.method,
123
+ url: context.url,
124
+ message: formatMessage(cause, "Unable to parse response JSON"),
125
+ }),
126
+ });
127
+ };
128
+ const toNetworkResponse = (response, context) => ({
129
+ status: response.status,
130
+ statusText: response.statusText,
131
+ statusMessage: response.statusText,
132
+ headers: headersToRecord(response.headers),
133
+ json: makeJsonEffect(response, context),
134
+ });
135
+ /**
136
+ * Execute a fetch request using the injected {@link NetworkFetch} service.
137
+ *
138
+ * Invariants:
139
+ * - method is always normalized to upper-case before dispatch.
140
+ * - JSON payload (if present) is serialized before request execution.
141
+ * - caller headers override payload-derived headers when keys overlap.
142
+ * - the returned `NetworkResponse.json` remains lazy.
143
+ */
144
+ export const fetchNetwork = (url, method, payload, options) => Effect.gen(function* () {
145
+ const requestUrl = String(url);
146
+ const context = { method, url: requestUrl };
147
+ const fetchImpl = yield* NetworkFetch;
148
+ const serialized = yield* serializePayload(method, payload);
149
+ const providedHeaders = options?.headers
150
+ ? headersToRecord(normalizeHeaders(options.headers))
151
+ : {};
152
+ const requestHeaders = mergeHeaders(serialized?.headers ?? {}, providedHeaders);
153
+ const hasHeaders = Object.keys(requestHeaders).length > 0;
154
+ const response = yield* Effect.tryPromise({
155
+ try: () => fetchImpl(requestUrl, {
156
+ method: method.toUpperCase(),
157
+ ...(hasHeaders ? { headers: requestHeaders } : {}),
158
+ ...(serialized
159
+ ? {
160
+ body: serialized.body,
161
+ }
162
+ : {}),
163
+ }),
164
+ catch: (cause) => new NetworkRequestError({
165
+ method,
166
+ url: requestUrl,
167
+ message: formatMessage(cause, "Network request failed"),
168
+ }),
169
+ });
170
+ return toNetworkResponse(response, context);
171
+ });
172
+ //# sourceMappingURL=network.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network.js","sourceRoot":"","sources":["../src/network.ts"],"names":[],"mappings":"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","sourcesContent":["import { Context, Data, Effect, Layer } from \"effect\"\n\n/**\n * Supported HTTP methods accepted by {@link fetchNetwork}.\n */\nexport type NetworkMethod = \"get\" | \"post\" | \"delete\" | \"patch\"\n\n/**\n * Lightweight response model used by this package.\n *\n * Invariants:\n * - `json` is lazy: parsing only happens when the effect is run.\n * - `json` is memoized per response wrapper, so repeated evaluation does not\n * parse the same payload multiple times.\n */\nexport interface NetworkResponse {\n readonly status: number\n readonly statusText: string\n readonly statusMessage: string\n readonly headers: Readonly<Record<string, string>>\n readonly json: Effect.Effect<unknown, NetworkResponseError>\n}\n\n/**\n * Accepted request header input formats.\n */\nexport type NetworkHeaders =\n | Headers\n | Readonly<Record<string, string>>\n | Array<[string, string]>\n\n/**\n * Optional request options for {@link fetchNetwork}.\n */\nexport interface FetchNetworkOptions {\n readonly headers?: NetworkHeaders\n}\n\n/**\n * Effect service tag for the fetch implementation.\n *\n * Supply this service with `Effect.provide` / layers to swap fetch behavior\n * in tests or alternate runtimes.\n */\nexport class NetworkFetch extends Context.Tag(\"@passlock/node/network/Fetch\")<\n NetworkFetch,\n typeof fetch\n>() {}\n\n/**\n * Default live fetch layer backed by `globalThis.fetch`.\n */\nexport const NetworkFetchLive: Layer.Layer<NetworkFetch> = Layer.succeed(\n NetworkFetch,\n globalThis.fetch\n)\n\n/**\n * HTTP status buckets used by {@link matchStatus}.\n */\nexport type NetworkResponseStatusCase = \"2xx\" | \"3xx\" | \"4xx\" | \"5xx\"\n\ntype MatchStatusHandler<\n Resp extends NetworkResponse = NetworkResponse,\n A = unknown,\n E = unknown,\n> = (response: Resp) => Effect.Effect<A, E, never>\n\ntype HandlerEffect<\n Cases extends MatchStatusCases<Resp>,\n Resp extends NetworkResponse,\n Case extends NetworkResponseStatusCase | \"orElse\",\n> = Case extends keyof Cases\n ? NonNullable<Cases[Case]> extends MatchStatusHandler<Resp>\n ? ReturnType<NonNullable<Cases[Case]>>\n : never\n : never\n\ntype MatchStatusEffectUnion<\n Cases extends MatchStatusCases<Resp>,\n Resp extends NetworkResponse,\n> =\n | HandlerEffect<Cases, Resp, \"2xx\">\n | HandlerEffect<Cases, Resp, \"3xx\">\n | HandlerEffect<Cases, Resp, \"4xx\">\n | HandlerEffect<Cases, Resp, \"5xx\">\n | HandlerEffect<Cases, Resp, \"orElse\">\n\ntype MatchStatusResolvedHandler<\n Cases extends MatchStatusCases<Resp>,\n Resp extends NetworkResponse,\n> = NonNullable<\n Cases[\"2xx\"] | Cases[\"3xx\"] | Cases[\"4xx\"] | Cases[\"5xx\"] | Cases[\"orElse\"]\n>\n\ntype EffectSuccess<T> =\n T extends Effect.Effect<infer A, unknown, unknown> ? A : never\n\ntype EffectError<T> =\n T extends Effect.Effect<unknown, infer E, unknown> ? E : never\n\ntype EffectContext<T> =\n T extends Effect.Effect<unknown, unknown, infer R> ? R : never\n\n/**\n * Handlers used by {@link matchStatus}.\n *\n * Invariants:\n * - `orElse` is always required.\n * - Specific status family handlers are optional and fall back to `orElse`\n * when missing.\n */\nexport interface MatchStatusCases<\n Resp extends NetworkResponse = NetworkResponse,\n> {\n readonly \"2xx\"?: MatchStatusHandler<Resp>\n readonly \"3xx\"?: MatchStatusHandler<Resp>\n readonly \"4xx\"?: MatchStatusHandler<Resp>\n readonly \"5xx\"?: MatchStatusHandler<Resp>\n readonly orElse: MatchStatusHandler<Resp>\n}\n\ntype RequestContext = {\n readonly method: NetworkMethod\n readonly url: string\n}\n\n/**\n * Raised when the underlying fetch call fails before a response is received.\n */\nexport class NetworkRequestError extends Data.TaggedError(\n \"@error/NetworkRequest\"\n)<{\n readonly method: NetworkMethod\n readonly url: string\n readonly message: string\n}> {}\n\n/**\n * Raised when request payload serialization fails.\n */\nexport class NetworkPayloadError extends Data.TaggedError(\n \"@error/NetworkPayload\"\n)<{\n readonly method: NetworkMethod\n readonly message: string\n}> {}\n\n/**\n * Raised when response body parsing fails.\n */\nexport class NetworkResponseError extends Data.TaggedError(\n \"@error/NetworkResponse\"\n)<{\n readonly method: NetworkMethod\n readonly url: string\n readonly message: string\n}> {}\n\nconst formatMessage = (cause: unknown, fallback: string): string =>\n cause instanceof Error ? cause.message : fallback\n\n/**\n * Convert an HTTP status code into its status family bucket.\n *\n * Returns `undefined` for codes outside the 2xx-5xx families.\n */\nexport const statusToCase = (\n status: number\n): NetworkResponseStatusCase | undefined => {\n if (status >= 200 && status <= 299) return \"2xx\"\n if (status >= 300 && status <= 399) return \"3xx\"\n if (status >= 400 && status <= 499) return \"4xx\"\n if (status >= 500 && status <= 599) return \"5xx\"\n\n return undefined\n}\n\nconst resolveStatusHandler = <\n Resp extends NetworkResponse,\n Cases extends MatchStatusCases<Resp>,\n>(\n response: Resp,\n cases: Cases\n): MatchStatusResolvedHandler<Cases, Resp> => {\n const statusCase = statusToCase(response.status)\n if (!statusCase)\n return cases.orElse as MatchStatusResolvedHandler<Cases, Resp>\n\n const handler = cases[statusCase]\n return (handler ?? cases.orElse) as MatchStatusResolvedHandler<Cases, Resp>\n}\n\n/**\n * Route a {@link NetworkResponse} to the first matching status-family handler.\n *\n * Invariants:\n * - `2xx`/`3xx`/`4xx`/`5xx` handlers are matched by status family.\n * - `orElse` is always used as a fallback when no specific family handler exists.\n * - The returned effect type is inferred as the union of all handler effects.\n */\nexport const matchStatus = <\n Resp extends NetworkResponse,\n Cases extends MatchStatusCases<Resp>,\n>(\n response: Resp,\n cases: Cases\n): Effect.Effect<\n EffectSuccess<MatchStatusEffectUnion<Cases, Resp>>,\n EffectError<MatchStatusEffectUnion<Cases, Resp>>,\n EffectContext<MatchStatusEffectUnion<Cases, Resp>>\n> =>\n Effect.suspend(() => {\n const handler = resolveStatusHandler(response, cases)\n return handler(response)\n }) as Effect.Effect<\n EffectSuccess<MatchStatusEffectUnion<Cases, Resp>>,\n EffectError<MatchStatusEffectUnion<Cases, Resp>>,\n EffectContext<MatchStatusEffectUnion<Cases, Resp>>\n >\n\n/**\n * Serialize an optional payload into a JSON request body.\n *\n * Invariants:\n * - `GET` requests cannot carry a payload and fail with `NetworkPayloadError`.\n * - when a payload exists, `content-type: application/json` is emitted.\n */\nconst serializePayload = (\n method: NetworkMethod,\n payload?: unknown\n): Effect.Effect<\n | {\n readonly body: string\n readonly headers: Readonly<Record<string, string>>\n }\n | undefined,\n NetworkPayloadError\n> => {\n if (payload === undefined) {\n return Effect.succeed(undefined)\n }\n\n if (method === \"get\") {\n return Effect.fail(\n new NetworkPayloadError({\n method,\n message: \"GET requests do not support a request body\",\n })\n )\n }\n\n return Effect.try({\n try: () => ({\n body: JSON.stringify(payload),\n headers: { \"content-type\": \"application/json\" },\n }),\n catch: (cause) =>\n new NetworkPayloadError({\n method,\n message: formatMessage(cause, \"Unable to serialize payload to JSON\"),\n }),\n })\n}\n\n/**\n * Convert `Headers` into a readonly plain record.\n */\nexport const headersToRecord = (\n headers: Headers\n): Readonly<Record<string, string>> => Object.fromEntries(headers.entries())\n\nconst normalizeHeaders = (headers: NetworkHeaders): Headers => {\n if (headers instanceof Headers) {\n return new Headers(headers)\n }\n\n if (Array.isArray(headers)) {\n return new Headers(headers)\n }\n\n return new Headers(headers)\n}\n\nconst mergeHeaders = (\n ...headers: ReadonlyArray<Readonly<Record<string, string>>>\n): Readonly<Record<string, string>> => Object.assign({}, ...headers)\n\n/**\n * Build a lazy, memoized JSON parser effect from a response.\n *\n * Invariants:\n * - parsing happens on effect execution, not during response construction.\n * - parsing uses `response.clone()` so the original response body remains untouched.\n */\nconst makeJsonEffect = (\n response: Response,\n context: RequestContext\n): Effect.Effect<unknown, NetworkResponseError> => {\n let cached: Promise<unknown> | undefined\n\n return Effect.tryPromise({\n try: () => {\n cached = cached ?? response.clone().json()\n return cached\n },\n catch: (cause) =>\n new NetworkResponseError({\n method: context.method,\n url: context.url,\n message: formatMessage(cause, \"Unable to parse response JSON\"),\n }),\n })\n}\n\nconst toNetworkResponse = (\n response: Response,\n context: RequestContext\n): NetworkResponse => ({\n status: response.status,\n statusText: response.statusText,\n statusMessage: response.statusText,\n headers: headersToRecord(response.headers),\n json: makeJsonEffect(response, context),\n})\n\n/**\n * Execute a fetch request using the injected {@link NetworkFetch} service.\n *\n * Invariants:\n * - method is always normalized to upper-case before dispatch.\n * - JSON payload (if present) is serialized before request execution.\n * - caller headers override payload-derived headers when keys overlap.\n * - the returned `NetworkResponse.json` remains lazy.\n */\nexport const fetchNetwork = (\n url: string | URL,\n method: NetworkMethod,\n payload?: unknown,\n options?: FetchNetworkOptions\n): Effect.Effect<\n NetworkResponse,\n NetworkRequestError | NetworkPayloadError,\n NetworkFetch\n> =>\n Effect.gen(function* () {\n const requestUrl = String(url)\n const context: RequestContext = { method, url: requestUrl }\n const fetchImpl = yield* NetworkFetch\n const serialized = yield* serializePayload(method, payload)\n\n const providedHeaders = options?.headers\n ? headersToRecord(normalizeHeaders(options.headers))\n : {}\n\n const requestHeaders = mergeHeaders(\n serialized?.headers ?? {},\n providedHeaders\n )\n const hasHeaders = Object.keys(requestHeaders).length > 0\n\n const response = yield* Effect.tryPromise({\n try: () =>\n fetchImpl(requestUrl, {\n method: method.toUpperCase(),\n ...(hasHeaders ? { headers: requestHeaders } : {}),\n ...(serialized\n ? {\n body: serialized.body,\n }\n : {}),\n }),\n catch: (cause) =>\n new NetworkRequestError({\n method,\n url: requestUrl,\n message: formatMessage(cause, \"Network request failed\"),\n }),\n })\n\n return toNetworkResponse(response, context)\n })\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@passlock/cli",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
4
4
  "description": "CLI tooling support for the Passlock authentication framework",
5
5
  "keywords": [
6
6
  "passkey",
@@ -15,7 +15,7 @@
15
15
  "repository": {
16
16
  "type": "git",
17
17
  "url": "git+https://github.com/passlock-dev/passlock.git",
18
- "directory": "packages/client"
18
+ "directory": "packages/cli"
19
19
  },
20
20
  "license": "MIT",
21
21
  "author": {
@@ -25,16 +25,16 @@
25
25
  "type": "module",
26
26
  "exports": {
27
27
  ".": {
28
- "types": "./dist/index.d.ts",
29
- "import": "./dist/index.js",
30
- "default": "./dist/index.js"
28
+ "types": "./dist/cli.d.ts",
29
+ "import": "./dist/cli.js",
30
+ "default": "./dist/cli.js"
31
31
  }
32
32
  },
33
- "main": "./dist/index.js",
34
- "module": "./dist/index.js",
35
- "types": "./dist/index.d.ts",
33
+ "main": "./dist/cli.js",
34
+ "module": "./dist/cli.js",
35
+ "types": "./dist/cli.d.ts",
36
36
  "bin": {
37
- "passlock": "./dist/index.js"
37
+ "passlock": "./dist/cli.js"
38
38
  },
39
39
  "files": [
40
40
  "dist",
@@ -42,37 +42,40 @@
42
42
  "!dist/**/*.spec.*"
43
43
  ],
44
44
  "dependencies": {
45
- "@clack/prompts": "^1.0.0",
46
- "@effect/cli": "^0.73.1",
47
- "@effect/cluster": "^0.56.1",
48
- "@effect/platform": "^0.94.2",
49
- "@effect/platform-node": "^0.104.1",
50
- "effect": "3.19.15",
45
+ "@clack/prompts": "^1.0.1",
46
+ "effect": "3.19.19",
51
47
  "kleur": "^4.1.5"
52
48
  },
53
49
  "devDependencies": {
54
- "@biomejs/biome": "^2.3.13",
55
- "@types/node": "25.1.0",
56
- "globals": "^17.2.0",
57
- "npm-check-updates": "^19.3.2",
58
- "publint": "0.3.17",
59
- "rimraf": "^6.1.2",
50
+ "@biomejs/biome": "^2.4.4",
51
+ "@effect/vitest": "^0.27.0",
52
+ "@types/node": "25.3.3",
53
+ "globals": "^17.4.0",
54
+ "npm-check-updates": "^19.6.3",
55
+ "publint": "0.3.18",
56
+ "rimraf": "^6.1.3",
60
57
  "tsx": "4.21.0",
61
- "typescript": "^5.9.3"
58
+ "typescript": "^5.9.3",
59
+ "vite-tsconfig-paths": "^6.1.1",
60
+ "vitest": "^3.2.4"
62
61
  },
63
62
  "engines": {
64
63
  "node": ">=22"
65
64
  },
66
65
  "scripts": {
67
- "build": "tsc --build",
66
+ "build": "tsc -p tsconfig.build.json",
68
67
  "build:clean": "$npm_execpath run clean:full && $npm_execpath run build",
69
68
  "build:production": "$npm_execpath run build:clean && $npm_execpath run build:readme && $npm_execpath run replaceTokens && echo '' && publint",
70
- "build:readme": "LATEST=${npm_package_version} tsx ../../scripts/replace-readme-tokens.ts ./packages/cli",
71
- "clean": "tsc --build --clean",
72
- "clean:full": "rimraf dist tsconfig.tsbuildinfo",
73
- "replaceTokens": "LATEST=${npm_package_version} tsx ../../scripts/replace-tokens.ts ./packages/cli",
74
- "test:unit": "vitest",
75
- "typecheck": "tsc --noEmit",
69
+ "build:readme": "VERSION=${npm_package_version} tsx ../../scripts/replace-readme-tokens.ts ./packages/cli",
70
+ "typedoc": "typedoc",
71
+ "clean": "tsc -p tsconfig.build.json --clean",
72
+ "clean:full": "rimraf dist tsconfig.build.tsbuildinfo",
73
+ "replaceTokens": "VERSION=${npm_package_version} tsx ../../scripts/replace-tokens.ts ./packages/cli",
74
+ "test:unit": "vitest --project unit run",
75
+ "test:unit:watch": "vitest --project unit",
76
+ "test:integration": "vitest --project integration run",
77
+ "test:all": "vitest --project unit --project integration run",
78
+ "typecheck": "tsc -p tsconfig.test.json --noEmit",
76
79
  "lint": "biome check .",
77
80
  "lint:fix": "biome check --fix .",
78
81
  "lint:ci": "biome ci .",
package/dist/index.d.ts DELETED
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
3
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js DELETED
@@ -1,23 +0,0 @@
1
- #!/usr/bin/env node
2
- import { Command, Options } from "@effect/cli";
3
- import { HttpClient, HttpClientRequest } from "@effect/platform";
4
- import { NodeContext, NodeHttpClient, NodeRuntime } from "@effect/platform-node";
5
- import { Console, Effect, Layer, pipe } from "effect";
6
- import { init } from "./init.js";
7
- // prepend the correct endpoint
8
- const mapClient = (endpoint) => pipe(HttpClient.HttpClient, Effect.map(HttpClient.mapRequest(HttpClientRequest.prependUrl(endpoint))), Layer.effect(HttpClient.HttpClient));
9
- const endpoint = Options.text("endpoint")
10
- .pipe(Options.withAlias("e"))
11
- .pipe(Options.withDescription("Passlock API endpoint"))
12
- .pipe(Options.withDefault("https://api.passlock.dev"));
13
- const initCmd = pipe(Command.make("init", { endpoint }, ({ endpoint }) => pipe(init, Effect.provide(mapClient(endpoint)))), Command.withDescription("Setup a new Passlock cloud instance"));
14
- const mainCmd = pipe(Command.make("passlock", {}, () => Console.log("Passlock CLI tools\nRun with --help for commands and options")), Command.withDescription("Passlock CLI tools"));
15
- const command = pipe(mainCmd, Command.withSubcommands([initCmd]));
16
- // Set up the CLI application
17
- const cli = Command.run(command, {
18
- name: "Passlock CLI tools",
19
- version: "v2.0.0.alpha.1",
20
- });
21
- // Prepare and run the CLI application
22
- pipe(cli(process.argv), Effect.provide(NodeHttpClient.layer), Effect.provide(NodeContext.layer), NodeRuntime.runMain);
23
- //# sourceMappingURL=index.js.map
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAA;AAC9C,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAChE,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAA;AAChF,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,+BAA+B;AAC/B,MAAM,SAAS,GAAG,CAAC,QAAgB,EAAE,EAAE,CACrC,IAAI,CACF,UAAU,CAAC,UAAU,EACrB,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,UAAU,CAAC,iBAAiB,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,CAAC,EACzE,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,CACpC,CAAA;AAEH,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC;KACtC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;KAC5B,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,uBAAuB,CAAC,CAAC;KACtD,IAAI,CAAC,OAAO,CAAC,WAAW,CAAC,0BAA0B,CAAC,CAAC,CAAA;AAExD,MAAM,OAAO,GAAG,IAAI,CAClB,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,EAAE,QAAQ,EAAE,EAAE,EAAE,CAClD,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAChD,EACD,OAAO,CAAC,eAAe,CAAC,qCAAqC,CAAC,CAC/D,CAAA;AAED,MAAM,OAAO,GAAG,IAAI,CAClB,OAAO,CAAC,IAAI,CAAC,UAAU,EAAE,EAAE,EAAE,GAAG,EAAE,CAChC,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAC5E,EACD,OAAO,CAAC,eAAe,CAAC,oBAAoB,CAAC,CAC9C,CAAA;AAED,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;AAEjE,6BAA6B;AAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE;IAC/B,IAAI,EAAE,oBAAoB;IAC1B,OAAO,EAAE,gBAAgB;CAC1B,CAAC,CAAA;AAEF,sCAAsC;AACtC,IAAI,CACF,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EACjB,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,KAAK,CAAC,EACpC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC,EACjC,WAAW,CAAC,OAAO,CACpB,CAAA","sourcesContent":["#!/usr/bin/env node\n\nimport { Command, Options } from \"@effect/cli\"\nimport { HttpClient, HttpClientRequest } from \"@effect/platform\"\nimport { NodeContext, NodeHttpClient, NodeRuntime } from \"@effect/platform-node\"\nimport { Console, Effect, Layer, pipe } from \"effect\"\nimport { init } from \"./init.js\"\n\n// prepend the correct endpoint\nconst mapClient = (endpoint: string) =>\n pipe(\n HttpClient.HttpClient,\n Effect.map(HttpClient.mapRequest(HttpClientRequest.prependUrl(endpoint))),\n Layer.effect(HttpClient.HttpClient)\n )\n\nconst endpoint = Options.text(\"endpoint\")\n .pipe(Options.withAlias(\"e\"))\n .pipe(Options.withDescription(\"Passlock API endpoint\"))\n .pipe(Options.withDefault(\"https://api.passlock.dev\"))\n\nconst initCmd = pipe(\n Command.make(\"init\", { endpoint }, ({ endpoint }) =>\n pipe(init, Effect.provide(mapClient(endpoint)))\n ),\n Command.withDescription(\"Setup a new Passlock cloud instance\")\n)\n\nconst mainCmd = pipe(\n Command.make(\"passlock\", {}, () =>\n Console.log(\"Passlock CLI tools\\nRun with --help for commands and options\")\n ),\n Command.withDescription(\"Passlock CLI tools\")\n)\n\nconst command = pipe(mainCmd, Command.withSubcommands([initCmd]))\n\n// Set up the CLI application\nconst cli = Command.run(command, {\n name: \"Passlock CLI tools\",\n version: \"v2.0.0.alpha.1\",\n})\n\n// Prepare and run the CLI application\npipe(\n cli(process.argv),\n Effect.provide(NodeHttpClient.layer),\n Effect.provide(NodeContext.layer),\n NodeRuntime.runMain\n)\n"]}