create-newt-app 0.31.4 → 0.31.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -23,6 +23,7 @@ type Options = {
23
23
  nestDiOnly: boolean;
24
24
  includeExample: boolean;
25
25
  extras: readonly Extra[];
26
+ explicitFlags: readonly string[];
26
27
  };
27
28
  declare function doInit(options: Options): Promise<void>;
28
29
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":[],"sources":["../src/templates/types.ts","../src/index.ts"],"mappings":";KAgCY;;;cCdN;cACA;cACA;cACA;KAGD,kBAAkB;KAClB,mBAAmB;KACnB,iBAAiB;KACjB,qBAAqB;KAcrB;EACH;EACA;EACA;EACA;EACA;EACA,SAAS;EACT,UAAU;EACV,QAAQ;EACR,YAAY;EACZ;EACA;EACA,iBAAiB;;iBAWG,OAAO,SAAS,UAAO"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../src/templates/types.ts","../src/index.ts"],"mappings":";KAgCY;;;cCbN;cACA;cACA;cACA;KAGD,kBAAkB;KAClB,mBAAmB;KACnB,iBAAiB;KACjB,qBAAqB;KAcrB;EACH;EACA;EACA;EACA;EACA;EACA,SAAS;EACT,UAAU;EACV,QAAQ;EACR,YAAY;EACZ;EACA;EACA,iBAAiB;EACjB;;iBAWoB,OAAO,SAAS,UAAO"}
package/dist/index.js CHANGED
@@ -9,8 +9,12 @@ import { execa } from "execa";
9
9
  import ejs from "ejs";
10
10
  import { existsSync, promises } from "fs";
11
11
  import path from "path";
12
+ import { homedir } from "node:os";
13
+ import { promises as promises$1 } from "node:fs";
14
+ import https from "node:https";
15
+ import path$1 from "node:path";
12
16
  //#region package.json
13
- var version = "0.31.4";
17
+ var version = "0.31.6";
14
18
  var engines = { "node": ">=24.0.0" };
15
19
  //#endregion
16
20
  //#region src/templates/root/index.ts
@@ -10836,8 +10840,9 @@ CMD ["pnpm", "db:migrate"]`
10836
10840
  # Better Auth trusts this origin; without it every deployment falls back to
10837
10841
  # localhost:3000 and rejects requests from the real one.
10838
10842
  BETTER_AUTH_URL: \${BETTER_AUTH_URL:-http://localhost:3000}
10839
- DATABASE_URL: postgresql://postgres:\${POSTGRES_PASSWORD:-postgres}@db:5432/postgres
10840
-
10843
+ <% if (database === 'postgres') { %> DATABASE_URL: postgresql://postgres:\${POSTGRES_PASSWORD:-postgres}@db:5432/postgres
10844
+ <% } else { %> DATABASE_URL: /data/app.db
10845
+ <% } %>
10841
10846
  services:
10842
10847
  web:
10843
10848
  build:
@@ -10849,6 +10854,9 @@ services:
10849
10854
  - "3000:3000"
10850
10855
  environment:
10851
10856
  <<: *app-env
10857
+ <% if (database === 'sqlite') { %> volumes:
10858
+ - db_data:/data
10859
+ <% } -%>
10852
10860
  depends_on:
10853
10861
  - api
10854
10862
 
@@ -10858,9 +10866,12 @@ services:
10858
10866
  target: migrate
10859
10867
  environment:
10860
10868
  <<: *app-env
10861
- depends_on:
10869
+ <% if (database === 'postgres') { %> depends_on:
10862
10870
  db:
10863
10871
  condition: service_healthy
10872
+ <% } else { %> volumes:
10873
+ - db_data:/data
10874
+ <% } -%>
10864
10875
  restart: "no"
10865
10876
 
10866
10877
  api:
@@ -10871,13 +10882,17 @@ services:
10871
10882
  - "3001:3001"
10872
10883
  environment:
10873
10884
  <<: *app-env
10885
+ <% if (database === 'sqlite') { %> volumes:
10886
+ - db_data:/data
10887
+ <% } -%>
10874
10888
  depends_on:
10875
- db:
10889
+ <% if (database === 'postgres') { %> db:
10876
10890
  condition: service_healthy
10891
+ <% } -%>
10877
10892
  migrate:
10878
10893
  condition: service_completed_successfully
10879
10894
 
10880
- db:
10895
+ <% if (database === 'postgres') { %> db:
10881
10896
  image: postgres:17-alpine
10882
10897
  ports:
10883
10898
  - "5432:5432"
@@ -10891,6 +10906,7 @@ services:
10891
10906
  timeout: 5s
10892
10907
  retries: 5
10893
10908
 
10909
+ <% } -%>
10894
10910
  volumes:
10895
10911
  db_data:`
10896
10912
  },
@@ -11269,8 +11285,9 @@ CMD ["pnpm", "db:migrate"]`
11269
11285
  # Better Auth trusts this origin; without it every deployment falls back to
11270
11286
  # localhost:3000 and rejects requests from the real one.
11271
11287
  BETTER_AUTH_URL: \${BETTER_AUTH_URL:-http://localhost:3000}
11272
- DATABASE_URL: postgresql://postgres:\${POSTGRES_PASSWORD:-postgres}@db:5432/postgres
11273
-
11288
+ <% if (database === 'postgres') { %> DATABASE_URL: postgresql://postgres:\${POSTGRES_PASSWORD:-postgres}@db:5432/postgres
11289
+ <% } else { %> DATABASE_URL: /data/app.db
11290
+ <% } %>
11274
11291
  services:
11275
11292
  web:
11276
11293
  build:
@@ -11280,9 +11297,13 @@ services:
11280
11297
  - "3000:3000"
11281
11298
  environment:
11282
11299
  <<: *app-env
11300
+ <% if (database === 'sqlite') { %> volumes:
11301
+ - db_data:/data
11302
+ <% } -%>
11283
11303
  depends_on:
11284
- db:
11304
+ <% if (database === 'postgres') { %> db:
11285
11305
  condition: service_healthy
11306
+ <% } -%>
11286
11307
  migrate:
11287
11308
  condition: service_completed_successfully
11288
11309
 
@@ -11292,12 +11313,15 @@ services:
11292
11313
  target: migrate
11293
11314
  environment:
11294
11315
  <<: *app-env
11295
- depends_on:
11316
+ <% if (database === 'postgres') { %> depends_on:
11296
11317
  db:
11297
11318
  condition: service_healthy
11319
+ <% } else { %> volumes:
11320
+ - db_data:/data
11321
+ <% } -%>
11298
11322
  restart: "no"
11299
11323
 
11300
- db:
11324
+ <% if (database === 'postgres') { %> db:
11301
11325
  image: postgres:17-alpine
11302
11326
  ports:
11303
11327
  - "5432:5432"
@@ -11311,6 +11335,7 @@ services:
11311
11335
  timeout: 5s
11312
11336
  retries: 5
11313
11337
 
11338
+ <% } -%>
11314
11339
  volumes:
11315
11340
  db_data:`
11316
11341
  },
@@ -12582,6 +12607,135 @@ async function initGit(cwd) {
12582
12607
  ], { cwd });
12583
12608
  }
12584
12609
  //#endregion
12610
+ //#region src/telemetry.ts
12611
+ const ENDPOINT = "https://newt-telemetry.newt-app.workers.dev";
12612
+ const SEND_TIMEOUT_MS = 2e3;
12613
+ const UNREACHABLE_BACKOFF_MS = 2592e6;
12614
+ const CI_PROVIDERS = [
12615
+ ["GITHUB_ACTIONS", "github-actions"],
12616
+ ["GITLAB_CI", "gitlab-ci"],
12617
+ ["CIRCLECI", "circleci"],
12618
+ ["TRAVIS", "travis"],
12619
+ ["BUILDKITE", "buildkite"],
12620
+ ["JENKINS_URL", "jenkins"],
12621
+ ["TEAMCITY_VERSION", "teamcity"],
12622
+ ["CODEBUILD_BUILD_ID", "codebuild"],
12623
+ ["VERCEL", "vercel"],
12624
+ ["NETLIFY", "netlify"]
12625
+ ];
12626
+ function detectCi(env = process.env) {
12627
+ const named = CI_PROVIDERS.find(([key]) => env[key]);
12628
+ if (named) return named[1];
12629
+ return env.CI ? "unknown" : "none";
12630
+ }
12631
+ function isOptedOut(env = process.env) {
12632
+ if (env.DO_NOT_TRACK === "1" || env.DO_NOT_TRACK?.toLowerCase() === "true") return true;
12633
+ if (env.NEWT_TELEMETRY_DISABLED === "1") return true;
12634
+ if (env.NEWT_TELEMETRY !== void 0) return env.NEWT_TELEMETRY !== "1";
12635
+ return false;
12636
+ }
12637
+ function isEnabled(env = process.env) {
12638
+ return Boolean(ENDPOINT) && !isOptedOut(env);
12639
+ }
12640
+ function statePath() {
12641
+ const base = process.env.XDG_STATE_HOME ?? path$1.join(homedir(), ".local", "state");
12642
+ return path$1.join(base, "create-newt-app", "telemetry.json");
12643
+ }
12644
+ async function readState() {
12645
+ try {
12646
+ return JSON.parse(await promises$1.readFile(statePath(), "utf8"));
12647
+ } catch {
12648
+ return {};
12649
+ }
12650
+ }
12651
+ async function writeState(next) {
12652
+ try {
12653
+ const file = statePath();
12654
+ await promises$1.mkdir(path$1.dirname(file), { recursive: true });
12655
+ await promises$1.writeFile(file, JSON.stringify(next), "utf8");
12656
+ } catch {}
12657
+ }
12658
+ function nodeMajor(version = process.version) {
12659
+ const match = /^v?(\d+)/.exec(version);
12660
+ return match ? `v${match[1]}` : "other";
12661
+ }
12662
+ function buildPayload(report) {
12663
+ const { selection } = report;
12664
+ return {
12665
+ cliVersion: version,
12666
+ nodeMajor: nodeMajor(),
12667
+ platform: process.platform,
12668
+ mode: report.mode,
12669
+ ci: detectCi(),
12670
+ explicitFlags: [...report.explicitFlags].sort().join(","),
12671
+ shadcn: selection.shadcn,
12672
+ testing: selection.testing,
12673
+ database: selection.database,
12674
+ linter: selection.linter,
12675
+ deployment: selection.deployment,
12676
+ nestDiOnly: selection.nestDiOnly,
12677
+ todoExample: selection.todoExample,
12678
+ antiSlop: selection.extras.includes("anti-slop")
12679
+ };
12680
+ }
12681
+ function post(body) {
12682
+ return new Promise((resolve) => {
12683
+ try {
12684
+ const req = https.request(ENDPOINT, {
12685
+ method: "POST",
12686
+ headers: {
12687
+ "content-type": "application/json",
12688
+ "content-length": Buffer.byteLength(body)
12689
+ },
12690
+ timeout: SEND_TIMEOUT_MS
12691
+ });
12692
+ req.on("response", (res) => {
12693
+ res.resume();
12694
+ const status = res.statusCode ?? 0;
12695
+ res.on("end", () => resolve(status >= 200 && status < 300));
12696
+ });
12697
+ req.on("timeout", () => {
12698
+ req.destroy();
12699
+ resolve(false);
12700
+ });
12701
+ req.on("error", () => resolve(false));
12702
+ req.end(body);
12703
+ } catch {
12704
+ resolve(false);
12705
+ }
12706
+ });
12707
+ }
12708
+ const NOTICE = [
12709
+ "create-newt-app sends one anonymous event per scaffold: the options you chose,",
12710
+ "the CLI and Node major versions, your platform, whether prompts or flags were",
12711
+ "used, and whether this is CI. No project name, no paths, no file contents, and",
12712
+ "no identifier of any kind.",
12713
+ "Opt out with DO_NOT_TRACK=1 or NEWT_TELEMETRY_DISABLED=1."
12714
+ ].join("\n");
12715
+ async function reportRun(report) {
12716
+ if (!isEnabled()) return;
12717
+ const state = await readState();
12718
+ if (state.unreachableUntil && state.unreachableUntil > Date.now()) return;
12719
+ if (!state.notifiedAt) {
12720
+ console.log();
12721
+ console.log(NOTICE);
12722
+ console.log();
12723
+ await writeState({
12724
+ ...state,
12725
+ notifiedAt: Date.now()
12726
+ });
12727
+ }
12728
+ if (!await post(JSON.stringify(buildPayload(report)))) await writeState({
12729
+ ...state,
12730
+ notifiedAt: state.notifiedAt ?? Date.now(),
12731
+ unreachableUntil: Date.now() + UNREACHABLE_BACKOFF_MS
12732
+ });
12733
+ else if (state.unreachableUntil) await writeState({
12734
+ ...state,
12735
+ unreachableUntil: void 0
12736
+ });
12737
+ }
12738
+ //#endregion
12585
12739
  //#region src/index.ts
12586
12740
  const TESTING_CHOICES = ["jest", "vitest"];
12587
12741
  const DATABASE_CHOICES = ["sqlite", "postgres"];
@@ -12766,6 +12920,12 @@ async function doInit(options) {
12766
12920
  console.log(chalk.blue(` cd ${name}`));
12767
12921
  console.log(chalk.blue(` pnpm dev`));
12768
12922
  console.log();
12923
+ await reportRun({
12924
+ mode: options.nonInteractive ? "flags" : "interactive",
12925
+ explicitFlags: options.explicitFlags,
12926
+ selection
12927
+ });
12928
+ process.exit(0);
12769
12929
  } catch (error) {
12770
12930
  console.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
12771
12931
  process.exit(1);
@@ -12774,16 +12934,17 @@ async function doInit(options) {
12774
12934
  const program = new Command();
12775
12935
  program.name("create-newt-app").version(version).description("Create a new newt-app monorepo").argument("[name]").option("-ni, --no-install", "Skip pnpm install", true).option("-ng, --no-git", "Skip git initialization", true).option("--shadcn", "Include shadcn/ui", false).option("--testing <framework>", "Testing framework: vitest or jest", "jest").option("--database <database>", "Database: sqlite or postgres", "sqlite").option("--linter <linter>", "Linter: eslint or oxc", "eslint").option("--deployment <strategy>", "Deployment: none, standalone, or spa", "none").option("--nest-di-only", "Use NestJS for dependency injection only", false).option("--include-example", "Include the todo example", false).option("--extras <list>", "Extras, comma-separated: anti-slop", "").action(async (name, options, command) => {
12776
12936
  intro(`Create a ${chalk.blue("newt")} app.`);
12777
- const nonInteractive = [
12778
- "shadcn",
12779
- "testing",
12780
- "database",
12781
- "linter",
12782
- "deployment",
12783
- "nestDiOnly",
12784
- "includeExample",
12785
- "extras"
12786
- ].some((flag) => command.getOptionValueSource(flag) === "cli");
12937
+ const explicitFlags = Object.entries({
12938
+ shadcn: "--shadcn",
12939
+ testing: "--testing",
12940
+ database: "--database",
12941
+ linter: "--linter",
12942
+ deployment: "--deployment",
12943
+ nestDiOnly: "--nest-di-only",
12944
+ includeExample: "--include-example",
12945
+ extras: "--extras"
12946
+ }).filter(([option]) => command.getOptionValueSource(option) === "cli").map(([, flag]) => flag);
12947
+ const nonInteractive = explicitFlags.length > 0;
12787
12948
  const extras = options.extras.split(",").map((extra) => extra.trim()).filter(Boolean);
12788
12949
  const invalid = [
12789
12950
  {
@@ -12828,7 +12989,8 @@ program.name("create-newt-app").version(version).description("Create a new newt-
12828
12989
  deployment: options.deployment,
12829
12990
  nestDiOnly: options.nestDiOnly,
12830
12991
  includeExample: options.includeExample,
12831
- extras
12992
+ extras,
12993
+ explicitFlags
12832
12994
  });
12833
12995
  });
12834
12996
  program.parse();