create-trokky 0.1.4 → 0.1.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/cli.js CHANGED
@@ -86,6 +86,8 @@ async function main() {
86
86
  console.log(` # ${secret.name}= (${secret.optional ? 'optional — ' : ''}${secret.why})`);
87
87
  }
88
88
  }
89
+ if (config.target === 'workers')
90
+ console.log(' echo TROKKY_ENV=development >> .dev.vars');
89
91
  console.log(' npm install');
90
92
  console.log(config.target === 'workers' ? ' npm run build && npm run preview' : ' npm run dev');
91
93
  }
package/dist/emit.d.ts CHANGED
@@ -11,7 +11,8 @@ export declare function astroConfig(config: ProjectConfig): string;
11
11
  * takes its bindings from `cloudflare:workers`, a server is handed the core through Astro locals.
12
12
  */
13
13
  export declare function pageHelper(config: ProjectConfig): string;
14
- export declare function wranglerConfig(config: ProjectConfig): string;
14
+ /** `seedFiles`: the project ships public/seed/, which the sample-content seed reads through ASSETS. */
15
+ export declare function wranglerConfig(config: ProjectConfig, seedFiles?: boolean): string;
15
16
  /** The Worker's Trokky wiring: which adapters are imported is the composition, literally. */
16
17
  export declare function workersCore(config: ProjectConfig): string;
17
18
  export declare function workersEntry(config: ProjectConfig): string;
package/dist/emit.js CHANGED
@@ -56,7 +56,8 @@ export function packageJson(config) {
56
56
  else {
57
57
  scripts.dev = 'tsx watch src/server.ts';
58
58
  scripts.build = 'tsc -p tsconfig.json';
59
- scripts.start = 'node dist/server.js';
59
+ // rootDir is the project, so tsc mirrors src/ under dist/
60
+ scripts.start = 'node dist/src/server.js';
60
61
  }
61
62
  }
62
63
  return JSON.stringify({
@@ -133,10 +134,14 @@ export async function load(astro: AstroGlobal): Promise<Site> {
133
134
  }
134
135
  `;
135
136
  }
136
- export function wranglerConfig(config) {
137
+ /** `seedFiles`: the project ships public/seed/, which the sample-content seed reads through ASSETS. */
138
+ export function wranglerConfig(config, seedFiles = false) {
139
+ // An API-only project whose sample content ships files still binds ./public: the seed reads
140
+ // them through the binding, and run_worker_first keeps them from being served. One whose seed
141
+ // has no files has no public/ at all, and wrangler refuses a missing assets directory.
137
142
  const assets = hasFrontend(config)
138
143
  ? `"./dist/client"`
139
- : hasStudio(config)
144
+ : hasStudio(config) || seedFiles
140
145
  ? `"./public"`
141
146
  : null;
142
147
  const lines = [
@@ -149,7 +154,15 @@ export function wranglerConfig(config) {
149
154
  ' "compatibility_flags": ["nodejs_compat"],',
150
155
  ];
151
156
  if (assets) {
152
- lines.push(' "assets": {', ` "directory": ${assets},`, ' "binding": "ASSETS",', ' // Every request goes through the Worker: /studio needs its config injected, and /api', ' // is not a file. Static files are fetched through the binding by the handlers.', ' "run_worker_first": true,', ' "html_handling": "none",', ' "not_found_handling": "none"', ' },');
157
+ lines.push(' "assets": {', ` "directory": ${assets},`, ' "binding": "ASSETS",', ...(hasStudio(config)
158
+ ? [
159
+ ' // Every request goes through the Worker: /studio needs its config injected, and /api',
160
+ ' // is not a file. Static files are fetched through the binding by the handlers.',
161
+ ]
162
+ : [
163
+ ' // Only the sample-content seed reads these, through the binding. Every request goes',
164
+ ' // through the Worker, which serves nothing outside /api, so none of them is public.',
165
+ ]), ' "run_worker_first": true,', ' "html_handling": "none",', ' "not_found_handling": "none"', ' },');
153
166
  }
154
167
  lines.push(' "d1_databases": [', ` { "binding": "DB", "database_name": ${JSON.stringify(config.name)}, "database_id": "" }`, ' ],', ' "r2_buckets": [', ` { "binding": "MEDIA", "bucket_name": ${JSON.stringify(config.name + '-media')} }`, ' ],');
155
168
  if (config.images === 'cloudflare-images') {
@@ -457,7 +470,10 @@ export function envExample(config) {
457
470
  lines.push(...comment(secret.why), `${secret.name}=`, '');
458
471
  }
459
472
  if (edge) {
460
- lines.push(...comment('Local development only: keep this line in .dev.vars and never set it on the deployed'), ...comment('Worker, which must run with the production checks.'), 'TROKKY_ENV=development', '');
473
+ // TROKKY_ENV=development is not listed here: the deploy button offers every line of this
474
+ // file as a value to set on the deployed Worker, which must run with the production checks.
475
+ // The README adds it to the local .dev.vars instead.
476
+ lines.push(...comment('For local development, also add TROKKY_ENV=development to your .dev.vars (the'), ...comment('README shows how). Never set it on the deployed Worker.'), '');
461
477
  }
462
478
  if (config.data === 'postgres-data')
463
479
  lines.push('# Postgres connection string.', 'DATABASE_URL=', '');
package/dist/generate.js CHANGED
@@ -54,7 +54,8 @@ export function generate(config, source) {
54
54
  tree.set('src/trokky/page.ts', emit.pageHelper(config));
55
55
  }
56
56
  if (config.target === 'workers') {
57
- tree.set('wrangler.jsonc', emit.wranglerConfig(config));
57
+ const seedFiles = [...tree.keys()].some(k => k.startsWith('public/seed/'));
58
+ tree.set('wrangler.jsonc', emit.wranglerConfig(config, seedFiles));
58
59
  tree.set('src/worker.ts', emit.workersEntry(config));
59
60
  tree.set('src/trokky/core.ts', emit.workersCore(config));
60
61
  tree.set('.dev.vars.example', emit.envExample(config));
@@ -68,8 +69,9 @@ export function generate(config, source) {
68
69
  if (!hasStudio(config)) {
69
70
  tree.delete('scripts/copy-studio.mjs');
70
71
  }
71
- // Seed assets are only reachable when something serves static files.
72
- if (config.content === 'blank' || (config.target === 'workers' && !hasStudio(config) && !hasFrontend(config))) {
72
+ // Blank content has nothing to seed. Every other project reads its seed files: from disk on
73
+ // Node, through the assets binding on Workers (bound for API-only projects too).
74
+ if (config.content === 'blank') {
73
75
  for (const path of [...tree.keys()])
74
76
  if (path.startsWith('public/seed/'))
75
77
  tree.delete(path);
@@ -99,6 +101,7 @@ Generated with \`npm create trokky@latest\`.
99
101
 
100
102
  \`\`\`
101
103
  ${edge ? `cp .dev.vars.example .dev.vars # fill both secrets
104
+ echo TROKKY_ENV=development >> .dev.vars
102
105
  npm install
103
106
  npm run build && npm run preview` : `cp .env.example .env # fill both secrets
104
107
  npm install
@@ -109,16 +112,28 @@ ${edge ? `## Deploy
109
112
 
110
113
  \`\`\`
111
114
  npm run build && npm run deploy
115
+ npx wrangler secret put TROKKY_CLAIM_SECRET
116
+ npx wrangler secret put TROKKY_JWT_SECRET
112
117
  \`\`\`
113
118
 
119
+ \`.dev.vars\` is not uploaded, so the deployed Worker needs its own secrets; without
120
+ \`TROKKY_JWT_SECRET\` it answers with an error. Set the claim secret first: once the JWT secret
121
+ is in, the site answers, and an unset claim secret leaves the claim open.
122
+
114
123
  Wrangler provisions the D1 database and R2 bucket named in \`wrangler.jsonc\` on first deploy.
115
124
  \`database_id\` is intentionally empty: it is bound by name.
116
125
 
117
126
  ` : ''}## The first minute
118
127
 
119
- Open ${hasStudio(config) ? '`/studio`' : 'the API'}. Nobody owns this instance yet, so the first
120
- screen asks you to **claim** it: pick a username and password, and paste \`TROKKY_CLAIM_SECRET\`.
121
- ${config.content === 'blank' ? '' : 'Sample content appears a moment later — edit it or delete it.'}
128
+ ${hasStudio(config) ? `Open \`/studio\`. Nobody owns this instance yet, so the first screen asks you to **claim** it:
129
+ pick a username, an email and a password, and paste \`TROKKY_CLAIM_SECRET\`.` : `Nobody owns this instance yet. **Claim** it over HTTP (on a deployed site, use its URL instead of
130
+ localhost); the response signs you in:
131
+
132
+ \`\`\`
133
+ curl -X POST http://localhost:${edge ? '8787' : '3000'}/api/auth/claim -H 'Content-Type: application/json' \\
134
+ -d '{"username":"admin","email":"you@example.com","password":"<a strong password>","secret":"<TROKKY_CLAIM_SECRET>"}'
135
+ \`\`\``}
136
+ ${config.content === 'blank' ? '' : edge ? 'Sample content appears a moment after the claim — edit it or delete it.' : 'Sample content is written at the first start — edit it or delete it.'}
122
137
 
123
138
  Without a claim secret the claim is open to whoever reaches the URL first. That is fine for the
124
139
  minute between deploying and opening the link; it is not fine for an instance left sitting.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-trokky",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "Compose a Trokky project: pick the target, adapters and parts you want.",
5
5
  "type": "module",
6
6
  "license": "MIT",