@forumone/create-throughline 1.0.1 → 1.0.2-next-0ecb757
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/CHANGELOG.md +6 -0
- package/dist/post-install.d.ts.map +1 -1
- package/dist/post-install.js +5 -2
- package/dist/post-install.js.map +1 -1
- package/dist/templates/base/README.md +4 -3
- package/dist/templates/base/apps/web/src/payload.config.ts.template +22 -1
- package/dist/versions.json +2 -2
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# @forumone/create-throughline
|
|
2
2
|
|
|
3
|
+
## 1.0.2-next-0ecb757
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 0ecb757: A scaffolded project puts its env file where `next dev` reads it, and does not make every account an administrator. The instructions copy `.env.example` to `apps/web/.env.local` rather than the root, which `next dev` in `apps/web` never read. New users default to `editor`; the first account, made at `/admin/create-first-user`, is the admin; and only an admin may set a role or a group.
|
|
8
|
+
|
|
3
9
|
## 1.0.1
|
|
4
10
|
|
|
5
11
|
## 1.0.0
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post-install.d.ts","sourceRoot":"","sources":["../src/post-install.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAE3C;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"post-install.d.ts","sourceRoot":"","sources":["../src/post-install.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA;AAE3C;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA+FrD"}
|
package/dist/post-install.js
CHANGED
|
@@ -14,7 +14,10 @@ export function printNextSteps(answers) {
|
|
|
14
14
|
if (!answers.installDeps) {
|
|
15
15
|
lines.push(formatStep(step++, pc.bold('pnpm install')));
|
|
16
16
|
}
|
|
17
|
-
lines.push(formatStep(step++,
|
|
17
|
+
lines.push(formatStep(step++,
|
|
18
|
+
// apps/web, not the root: `next dev` reads env files from its own
|
|
19
|
+
// directory, and the Payload CLI looks there before walking up.
|
|
20
|
+
`Copy ${pc.bold('.env.example')} to ${pc.bold('apps/web/.env.local')} and fill in values`));
|
|
18
21
|
if (answers.databasePlatform === 'neon') {
|
|
19
22
|
lines.push(` ${pc.dim('- Create a Neon project; use its connection string for DATABASE_URI')}`);
|
|
20
23
|
}
|
|
@@ -43,7 +46,7 @@ export function printNextSteps(answers) {
|
|
|
43
46
|
lines.push(` ${pc.dim('pnpm --dir apps/web generate:importmap')}`);
|
|
44
47
|
lines.push(formatStep(step++, `${pc.bold('pnpm dev')} to run locally`));
|
|
45
48
|
lines.push(formatStep(step++, 'Open http://localhost:3000/admin and create your first admin user'));
|
|
46
|
-
lines.push(formatStep(step++, 'In the admin, create one key under MCP →
|
|
49
|
+
lines.push(formatStep(step++, 'In the admin, create one key under MCP → API Keys'));
|
|
47
50
|
lines.push(formatStep(step, 'Give that key to Claude (or your MCP client) for /api/mcp — see the generated README.md'));
|
|
48
51
|
// eslint-disable-next-line no-console
|
|
49
52
|
console.log();
|
package/dist/post-install.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"post-install.js","sourceRoot":"","sources":["../src/post-install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AACpC,OAAO,EAAE,MAAM,YAAY,CAAA;AAG3B;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,IAAI,IAAI,GAAG,CAAC,CAAA;IAEZ,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;IAC3C,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,OAAO,EAAE,CAAC,CAAC,CAAA;IAE7D,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAA;IACzD,CAAC;IAED,KAAK,CAAC,IAAI,CACR,UAAU,CACR,IAAI,EAAE,
|
|
1
|
+
{"version":3,"file":"post-install.js","sourceRoot":"","sources":["../src/post-install.ts"],"names":[],"mappings":"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"}
|
|
@@ -19,12 +19,12 @@ This is a Throughline project: a Payload CMS application wired with the Throughl
|
|
|
19
19
|
pnpm install
|
|
20
20
|
|
|
21
21
|
# 2. Copy the env template
|
|
22
|
-
cp .env.example
|
|
22
|
+
cp .env.example apps/web/.env.local # apps/web: `next dev` reads env files from there
|
|
23
23
|
|
|
24
24
|
# 3. Generate secrets (run each three times for the three secret slots)
|
|
25
25
|
openssl rand -base64 48
|
|
26
26
|
|
|
27
|
-
# 4. Edit
|
|
27
|
+
# 4. Edit apps/web/.env.local and fill in:
|
|
28
28
|
# - DATABASE_URI — your Postgres connection string
|
|
29
29
|
# - PAYLOAD_SECRET — generated above
|
|
30
30
|
# - APPROVAL_TOKEN_SECRET — generated above
|
|
@@ -50,7 +50,8 @@ pnpm --dir apps/web generate:importmap
|
|
|
50
50
|
# 7. Start the dev server
|
|
51
51
|
pnpm dev
|
|
52
52
|
|
|
53
|
-
# 8. Visit http://localhost:3000/admin and create your first user.
|
|
53
|
+
# 8. Visit http://localhost:3000/admin and create your first user. It is the admin;
|
|
54
|
+
# every account after it starts as an editor, and an admin grants more.
|
|
54
55
|
```
|
|
55
56
|
|
|
56
57
|
## After admin signup
|
|
@@ -140,25 +140,46 @@ const isAdmin: Access = ({ req: { user } }) =>
|
|
|
140
140
|
Array.isArray(user.roles) &&
|
|
141
141
|
(user.roles as unknown[]).includes('admin')
|
|
142
142
|
|
|
143
|
+
// Only an admin may set a role or a group, so nobody can grant themselves one.
|
|
144
|
+
const adminOnlyField = ({ req: { user } }: { req: { user?: unknown } }) =>
|
|
145
|
+
Array.isArray((user as { roles?: unknown } | undefined)?.roles) &&
|
|
146
|
+
((user as { roles: unknown[] }).roles).includes('admin')
|
|
147
|
+
|
|
143
148
|
// Users collection — extend with your own fields and SSO/auth provider.
|
|
144
149
|
const Users: CollectionConfig = {
|
|
145
150
|
slug: 'users',
|
|
146
151
|
auth: true,
|
|
147
152
|
admin: { useAsTitle: 'email' },
|
|
153
|
+
hooks: {
|
|
154
|
+
beforeChange: [
|
|
155
|
+
// The first account is the admin: /admin/create-first-user is how one
|
|
156
|
+
// exists at all. Every account after it starts as an editor, and an admin
|
|
157
|
+
// grants anything more.
|
|
158
|
+
async ({ data, operation, req }) => {
|
|
159
|
+
if (operation !== 'create') return data
|
|
160
|
+
const { totalDocs } = await req.payload.count({ collection: 'users', req })
|
|
161
|
+
return totalDocs === 0 ? { ...data, roles: ['admin'] } : data
|
|
162
|
+
},
|
|
163
|
+
],
|
|
164
|
+
},
|
|
148
165
|
fields: [
|
|
149
166
|
{ name: 'name', type: 'text' },
|
|
150
167
|
{
|
|
151
168
|
name: 'roles',
|
|
152
169
|
type: 'select',
|
|
153
170
|
hasMany: true,
|
|
154
|
-
|
|
171
|
+
// Least privilege: an editor authors content. The scaffold used to make
|
|
172
|
+
// every new account an administrator.
|
|
173
|
+
defaultValue: ['editor'],
|
|
155
174
|
options: ['admin', 'editor', 'approver'],
|
|
175
|
+
access: { create: adminOnlyField, update: adminOnlyField },
|
|
156
176
|
},
|
|
157
177
|
{
|
|
158
178
|
name: 'groups',
|
|
159
179
|
type: 'select',
|
|
160
180
|
hasMany: true,
|
|
161
181
|
options: ['editorial', 'legal', 'communications', 'senior'],
|
|
182
|
+
access: { create: adminOnlyField, update: adminOnlyField },
|
|
162
183
|
},
|
|
163
184
|
],
|
|
164
185
|
}
|
package/dist/versions.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@forumone/create-throughline",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2-next-0ecb757",
|
|
4
4
|
"description": "Scaffolder for new Throughline projects (Payload CMS + MCP servers + Inngest workflows).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -50,8 +50,8 @@
|
|
|
50
50
|
"tsx": "^4.21.0",
|
|
51
51
|
"typescript": "^5.6.0",
|
|
52
52
|
"vitest": "^4.1.10",
|
|
53
|
-
"@forumone/throughline-
|
|
54
|
-
"@forumone/throughline-
|
|
53
|
+
"@forumone/throughline-eslint-config": "0.0.1",
|
|
54
|
+
"@forumone/throughline-tsconfig": "0.0.1"
|
|
55
55
|
},
|
|
56
56
|
"engines": {
|
|
57
57
|
"node": ">=20.9.0"
|