synqauth 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -19,7 +19,7 @@ It asks Synq for a development sign-in: an org of your own with one app, on `htt
19
19
  - writes the app's keys to `.env.local` (`SYNQ_ISSUER`, `SYNQ_CLIENT_ID`, `SYNQ_CLIENT_SECRET`, `SYNQ_APP_URL`, `SYNQ_SESSION_SECRET` and `SYNQ_CLAIM_TOKEN`), and makes sure git ignores it: it adds `.env*.local` to your app's `.gitignore` only where git doesn't ignore the file already (outside a git repo, where `.gitignore` doesn't say so)
20
20
  - adds `@synqauth/nextjs` with your package manager
21
21
  - adds `synq.config.ts`, `lib/synq.ts`, the route mount at `app/api/auth/[...synq]/route.ts`, and a page at `/synq` that signs you in and shows who
22
- - makes your `dev` script serve https (`next dev --experimental-https`), which Synq's development redirect URIs need
22
+ - makes your `dev` script serve https (`next dev --experimental-https`), which Synq's development redirect URIs need, and makes sure git ignores the local key and certificate Next.js makes for it in `certificates/`: it adds `/certificates/` to your app's `.gitignore` only where git doesn't ignore them already. Next.js adds that line itself only to a `.gitignore` your app's folder has, which an app in a workspace often lacks
23
23
 
24
24
  It never overwrites a file you have, and stops before making anything when `.env.local` already has Synq's values (`--force` makes another).
25
25
 
package/dist/bin.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { t as main } from "./cli-C7dDFb81.js";
2
+ import { n as main } from "./cli-sOLw5xeI.js";
3
3
  //#region src/bin.ts
4
4
  process.exitCode = await main(process.argv.slice(2));
5
5
  //#endregion
@@ -146,6 +146,13 @@ const HOST_MAP = [
146
146
  staging: null,
147
147
  preview: "https://preview.burnandclaim.com"
148
148
  },
149
+ {
150
+ product: "mollyverse",
151
+ surface: "api",
152
+ production: ["https://api.mollyverse.art"],
153
+ staging: null,
154
+ preview: "https://preview-api.mollyverse.art"
155
+ },
149
156
  {
150
157
  product: "mollyverse",
151
158
  surface: "website",
@@ -441,6 +448,42 @@ function withEnvLocalLine(gitignore) {
441
448
  const head = gitignore === "" || gitignore.endsWith("\n") ? gitignore : `${gitignore}\n`;
442
449
  return `${head}${head === "" ? "" : "\n"}# Local secrets, such as Synq's (npx synqauth init)\n.env*.local\n`;
443
450
  }
451
+ /** Where `next dev --experimental-https` keeps the key mkcert made it, in the app's folder. */
452
+ const CERTIFICATES_KEY = "certificates/localhost-key.pem";
453
+ /**
454
+ * Whether a `.gitignore`'s text keeps `certificates/` out of git. Next adds
455
+ * `certificates` itself, but only to a `.gitignore` in the app's own folder
456
+ * that exists already (AERO-2745).
457
+ */
458
+ function ignoresCertificates(gitignore) {
459
+ let ignored = false;
460
+ for (const line of gitignore.split(/\r?\n/).map((line) => line.trim())) {
461
+ if (line.startsWith("!")) ignored = false;
462
+ if ([
463
+ "certificates",
464
+ "certificates/",
465
+ "certificates/*",
466
+ "certificates/**",
467
+ "/certificates",
468
+ "/certificates/",
469
+ "/certificates/*",
470
+ "/certificates/**",
471
+ "**/certificates",
472
+ "**/certificates/",
473
+ "*.pem"
474
+ ].includes(line)) ignored = true;
475
+ }
476
+ return ignored;
477
+ }
478
+ /** `.gitignore`'s text with `/certificates/` added, when it doesn't ignore `certificates/` yet. */
479
+ function withCertificatesIgnored(gitignore) {
480
+ return ignoresCertificates(gitignore) ? void 0 : withCertificatesLine(gitignore);
481
+ }
482
+ /** `.gitignore`'s text with `/certificates/` added under a comment, keeping every byte it had. */
483
+ function withCertificatesLine(gitignore) {
484
+ const head = gitignore === "" || gitignore.endsWith("\n") ? gitignore : `${gitignore}\n`;
485
+ return `${head}${head === "" ? "" : "\n"}# The local HTTPS key and certificate of next dev --experimental-https\n/certificates/\n`;
486
+ }
444
487
  //#endregion
445
488
  //#region src/nextjs.ts
446
489
  /**
@@ -717,7 +760,7 @@ async function init(options) {
717
760
  const envPath = join(project.dir, ".env.local");
718
761
  const envText = existsSync(envPath) ? readFileSync(envPath, "utf8") : "";
719
762
  const present = synqNamesIn(envText);
720
- if (present.length > 0 && !options.force) throw new InitError(`This project has Synq already: .env.local sets ${present.join(", ")}. Run ${CLI_NAME} init --force to make another development sign-in.`, "has_synq");
763
+ if (present.length > 0 && !options.force) throw new InitError(`This project has Synq already: .env.local sets ${present.join(", ")}. Run ${options.rerun ?? `synqauth init`} --force to make another development sign-in.`, "has_synq");
721
764
  const made = await createClaimableOrg(apiOriginFor("synq", options.stage, options.env), {
722
765
  name: project.name,
723
766
  appType: "web",
@@ -753,16 +796,28 @@ async function init(options) {
753
796
  }
754
797
  const written = [".env.local"];
755
798
  const run = options.run ?? runIn;
756
- const gitSays = await run([
757
- "git",
758
- "check-ignore",
759
- "-q",
760
- ".env.local"
761
- ], project.dir, { quiet: true });
762
799
  const gitignorePath = join(project.dir, ".gitignore");
763
800
  const gitignore = existsSync(gitignorePath) ? readFileSync(gitignorePath, "utf8") : "";
764
- const ignored = gitSays === 0 ? void 0 : gitSays === 1 ? withEnvLocalLine(gitignore) : withEnvLocalIgnored(gitignore);
765
- if (ignored !== void 0) {
801
+ let ignored = gitignore;
802
+ for (const [path, line, unlessIgnored] of [[
803
+ ".env.local",
804
+ withEnvLocalLine,
805
+ withEnvLocalIgnored
806
+ ], [
807
+ CERTIFICATES_KEY,
808
+ withCertificatesLine,
809
+ withCertificatesIgnored
810
+ ]]) {
811
+ const gitSays = await run([
812
+ "git",
813
+ "check-ignore",
814
+ "-q",
815
+ path
816
+ ], project.dir, { quiet: true });
817
+ if (gitSays === 0) continue;
818
+ ignored = gitSays === 1 ? line(ignored) : unlessIgnored(ignored) ?? ignored;
819
+ }
820
+ if (ignored !== gitignore) {
766
821
  writeFileSync(gitignorePath, ignored);
767
822
  written.push(".gitignore");
768
823
  }
@@ -842,8 +897,23 @@ function runIn(command, cwd, { quiet = false } = {}) {
842
897
  }
843
898
  //#endregion
844
899
  //#region src/cli.ts
845
- const VERSION = "0.3.0";
846
- const HELP = `Usage: npx ${CLI_NAME} init [options]
900
+ const VERSION = "0.4.0";
901
+ /** How a person runs init again with an option, for each entry: `<this> --force`. */
902
+ const RERUN = {
903
+ synqauth: `${CLI_NAME} init`,
904
+ "create-synq": "npm create synq --"
905
+ };
906
+ const USAGE = {
907
+ synqauth: `Usage: npx ${CLI_NAME} init [options]`,
908
+ "create-synq": `Usage: npm create synq -- [options]
909
+ pnpm create synq [options]
910
+ yarn create synq [options]
911
+
912
+ With npm, options go after --, as in npm create synq -- --force.`
913
+ };
914
+ /** The help, in the words of the command that ran it. */
915
+ function help(entry = "synqauth") {
916
+ return `${USAGE[entry]}
847
917
 
848
918
  Gives your Next.js app a working Synq sign-in, with no account: a development
849
919
  sign-in you claim later by signing up.
@@ -854,12 +924,15 @@ Options:
854
924
  --stage <s> Which Synq: production (the default), preview, staging or local
855
925
  -h, --help Show this
856
926
  -v, --version Show the version`;
927
+ }
857
928
  const console_ = {
858
929
  out: (line) => process.stdout.write(`${line}\n`),
859
930
  err: (line) => process.stderr.write(`${line}\n`)
860
931
  };
861
932
  async function main(argv, context = {}) {
862
933
  const output = context.output ?? console_;
934
+ const entry = context.entry ?? "synqauth";
935
+ const HELP = help(entry);
863
936
  let parsed;
864
937
  try {
865
938
  parsed = parse(argv);
@@ -872,16 +945,22 @@ async function main(argv, context = {}) {
872
945
  output.out(VERSION);
873
946
  return 0;
874
947
  }
875
- const [command] = parsed.positionals;
948
+ const [command, ...extra] = entry === "create-synq" ? ["init", ...parsed.positionals] : parsed.positionals;
876
949
  if (parsed.values.help || command === void 0) {
877
950
  output.out(HELP);
878
951
  return command === void 0 && !parsed.values.help ? 2 : 0;
879
952
  }
880
- if (command !== "init" || parsed.positionals.length > 1) {
953
+ if (command !== "init") {
881
954
  output.err(`${CLI_NAME} has no command "${command}".`);
882
955
  output.err(HELP);
883
956
  return 2;
884
957
  }
958
+ if (extra.length > 0) {
959
+ const ran = entry === "create-synq" ? "npm create synq" : `${CLI_NAME} init`;
960
+ output.err(`${ran} takes options only, not "${extra.join(" ")}": run it in your Next.js app's folder.`);
961
+ output.err(HELP);
962
+ return 2;
963
+ }
885
964
  const stage = parsed.values.stage;
886
965
  if (!STAGES.includes(stage)) {
887
966
  output.err(`--stage must be one of ${STAGES.join(", ")}.`);
@@ -896,7 +975,8 @@ async function main(argv, context = {}) {
896
975
  install: parsed.values["no-install"] !== true,
897
976
  version: VERSION,
898
977
  fetch: context.fetch,
899
- run: context.run
978
+ run: context.run,
979
+ rerun: RERUN[entry]
900
980
  });
901
981
  for (const line of summary(result)) output.out(line);
902
982
  return result.installed === false ? 1 : 0;
@@ -947,4 +1027,4 @@ function summary(result) {
947
1027
  return lines;
948
1028
  }
949
1029
  //#endregion
950
- export { init as a, InitError as i, summary as n, SynqApiError as o, CLI_NAME as r, main as t };
1030
+ export { InitError as a, CLI_NAME as i, main as n, init as o, summary as r, SynqApiError as s, help as t };
package/dist/index.d.ts CHANGED
@@ -77,6 +77,11 @@ type InitOptions = {
77
77
  run?: (command: readonly string[], cwd: string, options?: {
78
78
  quiet?: boolean;
79
79
  }) => Promise<number>;
80
+ /**
81
+ * The command that runs init again, which a hint follows with an option:
82
+ * `synqauth init` (the default), or `npm create synq --` when create-synq ran it.
83
+ */
84
+ rerun?: string;
80
85
  now?: () => Date;
81
86
  };
82
87
  type InitResult = {
@@ -105,6 +110,10 @@ export declare class InitError extends Error {
105
110
  export declare function init(options: InitOptions): Promise<InitResult>;
106
111
  //#endregion
107
112
  //#region src/cli.d.ts
113
+ /** Which command ran it: `npx synqauth init`, or `npm create synq` (the create-synq package). */
114
+ type Entry = 'synqauth' | 'create-synq';
115
+ /** The help, in the words of the command that ran it. */
116
+ export declare function help(entry?: Entry): string;
108
117
  type Output = {
109
118
  out: (line: string) => void;
110
119
  err: (line: string) => void;
@@ -115,8 +124,10 @@ export declare function main(argv: readonly string[], context?: {
115
124
  output?: Output;
116
125
  run?: Parameters<typeof init>[0]['run'];
117
126
  fetch?: typeof fetch;
127
+ /** `create-synq`: argv is init's options alone, and the help names `npm create synq`. */
128
+ entry?: Entry;
118
129
  }): Promise<number>;
119
130
  /** What init did, and what to do next, in the order a developer reads it. */
120
131
  export declare function summary(result: InitResult): string[];
121
132
  //#endregion
122
- export type { InitOptions, InitResult, Stage };
133
+ export type { Entry, InitOptions, InitResult, Stage };
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import { a as init, i as InitError, n as summary, o as SynqApiError, r as CLI_NAME, t as main } from "./cli-C7dDFb81.js";
2
- export { CLI_NAME, InitError, SynqApiError, init, main, summary };
1
+ import { a as InitError, i as CLI_NAME, n as main, o as init, r as summary, s as SynqApiError, t as help } from "./cli-sOLw5xeI.js";
2
+ export { CLI_NAME, InitError, SynqApiError, help, init, main, summary };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "synqauth",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "Synq's command line: npx synqauth init gives your Next.js app a working sign-in, with no account until you claim it.",
5
5
  "license": "MIT",
6
6
  "repository": {