@meith/cli 0.26.0 → 0.27.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.
@@ -11,7 +11,7 @@ const workspaceRoot = process.cwd()
11
11
  const materializedDir = join(workspaceRoot, '.meith', 'cli')
12
12
 
13
13
  function fail(message) {
14
- console.error(`community: ${message}`)
14
+ console.error(`meith: ${message}`)
15
15
  process.exit(1)
16
16
  }
17
17
 
@@ -26,7 +26,7 @@ function materialize() {
26
26
 
27
27
  if (!existsSync(boardConfig)) {
28
28
  fail(
29
- `no meith.config.ts in ${workspaceRoot}. Run community from a board's own ` +
29
+ `no meith.config.ts in ${workspaceRoot}. Run meith from a board's own ` +
30
30
  'directory — the one create-meith scaffolded, or one shaped like it.',
31
31
  )
32
32
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meith/cli",
3
- "version": "0.26.0",
4
- "description": "The operator CLI: migrations, backup and restore, imports, users and settings — and the community bin that runs it against an external board workspace.",
3
+ "version": "0.27.0",
4
+ "description": "The operator CLI: migrations, backup and restore, imports, users and settings — and the meith bin that runs it against an external board workspace.",
5
5
  "license": "MIT",
6
6
  "repository": {
7
7
  "type": "git",
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "type": "module",
12
12
  "bin": {
13
- "community": "./bin/community.mjs"
13
+ "meith": "./bin/meith.mjs"
14
14
  },
15
15
  "files": [
16
16
  "bin",
@@ -23,18 +23,18 @@
23
23
  },
24
24
  "dependencies": {
25
25
  "tsx": "^4.23.12",
26
- "@meith/accounts": "0.26.0",
27
- "@meith/core": "0.26.0",
28
- "@meith/db": "0.26.0",
29
- "@meith/demo": "0.26.0",
30
- "@meith/drivers": "0.26.0",
31
- "@meith/forums": "0.26.0",
32
- "@meith/plugin-kit": "0.26.0",
33
- "@meith/profile-fields": "0.26.0",
34
- "@meith/runtime": "0.26.0",
35
- "@meith/settings": "0.26.0",
36
- "@meith/tasks": "0.26.0",
37
- "create-meith": "0.26.0"
26
+ "@meith/accounts": "0.27.0",
27
+ "@meith/core": "0.27.0",
28
+ "@meith/db": "0.27.0",
29
+ "@meith/demo": "0.27.0",
30
+ "@meith/drivers": "0.27.0",
31
+ "@meith/forums": "0.27.0",
32
+ "@meith/plugin-kit": "0.27.0",
33
+ "@meith/profile-fields": "0.27.0",
34
+ "@meith/runtime": "0.27.0",
35
+ "@meith/settings": "0.27.0",
36
+ "@meith/tasks": "0.27.0",
37
+ "create-meith": "0.27.0"
38
38
  },
39
39
  "devDependencies": {
40
40
  "esbuild": "^0.28.2"
package/src/backup.ts CHANGED
@@ -674,7 +674,7 @@ async function pushUploadsToStore(
674
674
  }
675
675
 
676
676
  const RESTORE_USAGE =
677
- 'Usage: RESTORE_DATABASE_URL=<postgres://…> community restore <bundle.tar.gz> ' +
677
+ 'Usage: RESTORE_DATABASE_URL=<postgres://…> meith restore <bundle.tar.gz> ' +
678
678
  '[--uploads-dir <dir>] [--skip-uploads]'
679
679
 
680
680
  export function restoreDatabaseUrl(
@@ -101,7 +101,7 @@ async function readManifest(): Promise<Manifest> {
101
101
  if ((error as NodeJS.ErrnoException).code === 'ENOENT') {
102
102
  throw new ValidationError(
103
103
  `board:eject could not find this build's plugin manifest at ${path}. This command ` +
104
- 'runs inside the official image (docker compose run --rm web community board:eject ' +
104
+ 'runs inside the official image (docker compose run --rm web meith board:eject ' +
105
105
  '<dir>), where it is baked in — or, in this repository, against boards/stock. It is ' +
106
106
  'not meant to run against a workspace board:eject already produced.',
107
107
  )
@@ -179,7 +179,7 @@ export async function boardEject(args: readonly string[]): Promise<number> {
179
179
  const [dir] = positional
180
180
 
181
181
  if (dir === undefined || positional.length > 1) {
182
- throw new ValidationError('Usage: community board:eject <dir>')
182
+ throw new ValidationError('Usage: meith board:eject <dir>')
183
183
  }
184
184
 
185
185
  const target = resolve(process.cwd(), dir)
@@ -237,7 +237,12 @@ export async function boardEject(args: readonly string[]): Promise<number> {
237
237
  console.log(' git init && git add -A && git commit -m "Graduate from the stock image"')
238
238
  console.log(' # push it to a new GitHub repository')
239
239
  console.log(' # .github/workflows/build.yml builds and pushes the image on every push to main —')
240
- console.log(' # point Coolify at this repository and set MEITH_IMAGE to the pushed image')
240
+ console.log(
241
+ ' # point Coolify at this repository, on docker-compose.prebuilt.yaml, and set MEITH_IMAGE',
242
+ )
243
+ console.log(
244
+ ' # to the pushed image (or docker-compose.yaml instead, which builds on the server)',
245
+ )
241
246
  console.log(' # redeploy — same database, same uploads, same secrets, new image source')
242
247
  console.log('')
243
248
  console.log(
package/src/commands.ts CHANGED
@@ -17,7 +17,7 @@ async function readPassword(flags: Flags): Promise<string> {
17
17
  if (inline !== undefined) {
18
18
  console.warn(
19
19
  'warning: --password is visible in shell history and to `ps`. ' +
20
- 'Prefer: echo "secret" | community user:create --username u --email e@x.com',
20
+ 'Prefer: echo "secret" | meith user:create --username u --email e@x.com',
21
21
  )
22
22
  return inline
23
23
  }
@@ -25,7 +25,7 @@ async function readPassword(flags: Flags): Promise<string> {
25
25
  if (process.stdin.isTTY) {
26
26
  throw new ValidationError(
27
27
  'No password supplied. Pipe one in:\n' +
28
- ' echo "correct horse battery staple" | community user:create --username u --email u@example.com',
28
+ ' echo "correct horse battery staple" | meith user:create --username u --email u@example.com',
29
29
  )
30
30
  }
31
31
 
@@ -159,7 +159,7 @@ export function settingDisplayValue(definition: SettingDefinition, value: unknow
159
159
  export async function settingsGet(args: readonly string[]): Promise<number> {
160
160
  const { positional } = parseFlags(args)
161
161
  const key = positional[0]
162
- if (key === undefined) throw new ValidationError('Usage: community settings:get <key>')
162
+ if (key === undefined) throw new ValidationError('Usage: meith settings:get <key>')
163
163
 
164
164
  const definition = SETTING_DEFINITION_BY_KEY.get(key)
165
165
  if (!definition) throw new ValidationError(`Unknown setting "${key}".`)
@@ -212,9 +212,9 @@ export async function settingsSet(args: readonly string[]): Promise<number> {
212
212
  const [key, positionalValue, ...extra] = positional
213
213
  if (key === undefined || extra.length > 0) {
214
214
  throw new ValidationError(
215
- 'Usage: community settings:set <key> <value>\n' +
216
- ' community settings:set <secret-key> --from-env <name>\n' +
217
- ' printf %s "$SECRET" | community settings:set <secret-key>',
215
+ 'Usage: meith settings:set <key> <value>\n' +
216
+ ' meith settings:set <secret-key> --from-env <name>\n' +
217
+ ' printf %s "$SECRET" | meith settings:set <secret-key>',
218
218
  )
219
219
  }
220
220
 
@@ -234,7 +234,7 @@ export async function settingsSet(args: readonly string[]): Promise<number> {
234
234
  throw new ValidationError('--from-env is only available for secret settings.')
235
235
  }
236
236
  if (positionalValue === undefined) {
237
- throw new ValidationError('Usage: community settings:set <key> <value>')
237
+ throw new ValidationError('Usage: meith settings:set <key> <value>')
238
238
  }
239
239
  raw = positionalValue
240
240
  }
package/src/context.ts CHANGED
@@ -30,7 +30,7 @@ export function requirePostgres(): void {
30
30
  if (env.DATA_SOURCE !== 'postgres') {
31
31
  throw new ConfigurationError(
32
32
  'This command needs a database: DATA_SOURCE is "fixture".\n' +
33
- 'Set DATABASE_URL (see .env.example) and run `community migrate` first.',
33
+ 'Set DATABASE_URL (see .env.example) and run `meith migrate` first.',
34
34
  )
35
35
  }
36
36
  }
@@ -39,7 +39,7 @@ export async function defaultMemberGroupId(admin: PostgresAdminRepository): Prom
39
39
  const id = await admin.registeredGroupId()
40
40
  if (id === null) {
41
41
  throw new ConfigurationError(
42
- 'No "registered" usergroup found. Run `community migrate` to seed the group ladder.',
42
+ 'No "registered" usergroup found. Run `meith migrate` to seed the group ladder.',
43
43
  )
44
44
  }
45
45
  return id
package/src/import.ts CHANGED
@@ -125,7 +125,7 @@ function print(report: ImportReport, copiedFiles: boolean): void {
125
125
  console.log('')
126
126
  if (report.finished) {
127
127
  console.log(
128
- 'Import complete. Run `community task:run counters.reconcile` before opening the board.',
128
+ 'Import complete. Run `meith task:run counters.reconcile` before opening the board.',
129
129
  )
130
130
  if (!copiedFiles) {
131
131
  console.log(
package/src/index.ts CHANGED
@@ -32,9 +32,9 @@ function usage(commands: readonly Command[]): string {
32
32
  const width = Math.max(...commands.map((c) => c.name.length))
33
33
  const lines = commands.map((c) => ` ${c.name.padEnd(width)} ${c.summary}`)
34
34
  return [
35
- 'community — operator CLI',
35
+ 'meith — operator CLI',
36
36
  '',
37
- 'Usage: community <command> [options]',
37
+ 'Usage: meith <command> [options]',
38
38
  '',
39
39
  'Commands:',
40
40
  ...lines,
@@ -85,7 +85,7 @@ const commands: Command[] = [
85
85
  name: 'migrate',
86
86
  summary: 'Apply pending database migrations.',
87
87
  usage: [
88
- 'community migrate',
88
+ 'meith migrate',
89
89
  '',
90
90
  'Applies every migration this release has that the board has not, then exits.',
91
91
  'Safe to run concurrently: the runner holds a Postgres advisory lock for the',
@@ -143,7 +143,7 @@ const commands: Command[] = [
143
143
  {
144
144
  name: 'upgrade',
145
145
  summary: 'Apply core and plugin migrations, then record the version.',
146
- usage: 'community upgrade [--dry-run]',
146
+ usage: 'meith upgrade [--dry-run]',
147
147
  async run(args: readonly string[]) {
148
148
  const { assertEnv } = await import('@meith/core')
149
149
  const env = assertEnv()
@@ -166,7 +166,7 @@ const commands: Command[] = [
166
166
  {
167
167
  name: 'backup',
168
168
  summary: 'Dump the database and the uploads into one restorable bundle.',
169
- usage: 'community backup [--out <path>] [--uploads include|skip]',
169
+ usage: 'meith backup [--out <path>] [--uploads include|skip]',
170
170
  run: backupCommand,
171
171
  },
172
172
 
@@ -174,7 +174,7 @@ const commands: Command[] = [
174
174
  name: 'restore',
175
175
  summary: 'Restore a backup bundle into a new, empty database.',
176
176
  usage:
177
- 'RESTORE_DATABASE_URL=<postgres://…> community restore <bundle.tar.gz> ' +
177
+ 'RESTORE_DATABASE_URL=<postgres://…> meith restore <bundle.tar.gz> ' +
178
178
  '[--uploads-dir <dir>] [--skip-uploads]',
179
179
  run: restoreCommand,
180
180
  },
@@ -182,7 +182,7 @@ const commands: Command[] = [
182
182
  {
183
183
  name: 'plugin:purge',
184
184
  summary: 'Run a plugin’s onUninstall and remove its data. Do this before removing the code.',
185
- usage: 'community plugin:purge <key> [--yes]',
185
+ usage: 'meith plugin:purge <key> [--yes]',
186
186
  async run(args: readonly string[]) {
187
187
  const { assertEnv } = await import('@meith/core')
188
188
  const env = assertEnv()
@@ -194,7 +194,7 @@ const commands: Command[] = [
194
194
 
195
195
  const key = args.find((arg) => !arg.startsWith('--'))
196
196
  if (key === undefined) {
197
- console.error('Usage: community plugin:purge <key> [--yes]')
197
+ console.error('Usage: meith plugin:purge <key> [--yes]')
198
198
  return 1
199
199
  }
200
200
 
@@ -212,7 +212,7 @@ const commands: Command[] = [
212
212
  {
213
213
  name: 'plugin:add',
214
214
  summary: 'Add a package to board.plugins.json and regenerate meith.plugins.ts.',
215
- usage: 'community plugin:add <package> [--key <key>] [--disabled]',
215
+ usage: 'meith plugin:add <package> [--key <key>] [--disabled]',
216
216
  async run(args: readonly string[]) {
217
217
  const { pluginAdd } = await import('./plugin-manifest')
218
218
  return pluginAdd(args)
@@ -222,7 +222,7 @@ const commands: Command[] = [
222
222
  {
223
223
  name: 'plugin:remove',
224
224
  summary: 'Remove a plugin from board.plugins.json and regenerate meith.plugins.ts.',
225
- usage: 'community plugin:remove <key>',
225
+ usage: 'meith plugin:remove <key>',
226
226
  async run(args: readonly string[]) {
227
227
  const { pluginRemove } = await import('./plugin-manifest')
228
228
  return pluginRemove(args)
@@ -233,7 +233,7 @@ const commands: Command[] = [
233
233
  name: 'board:eject',
234
234
  summary:
235
235
  'Write this build as a standalone workspace — the first step of graduating off the stock image.',
236
- usage: 'community board:eject <dir>',
236
+ usage: 'meith board:eject <dir>',
237
237
  async run(args: readonly string[]) {
238
238
  const { boardEject } = await import('./board-eject')
239
239
  return boardEject(args)
@@ -264,22 +264,21 @@ const commands: Command[] = [
264
264
  {
265
265
  name: 'user:create',
266
266
  summary: 'Create a user account. Pipe the password in on stdin.',
267
- usage:
268
- 'echo "<password>" | community user:create --username <name> --email <addr> [--group <key>]',
267
+ usage: 'echo "<password>" | meith user:create --username <name> --email <addr> [--group <key>]',
269
268
  run: userCreate,
270
269
  },
271
270
 
272
271
  {
273
272
  name: 'user:promote',
274
273
  summary: "Change a user's primary group.",
275
- usage: 'community user:promote --user <id|username> --group <key|id>',
274
+ usage: 'meith user:promote --user <id|username> --group <key|id>',
276
275
  run: userPromote,
277
276
  },
278
277
 
279
278
  {
280
279
  name: 'user:2fa-clear',
281
280
  summary: "Clear a user's second factor when they have lost it, and sign them out.",
282
- usage: 'community user:2fa-clear --user <id|username>',
281
+ usage: 'meith user:2fa-clear --user <id|username>',
283
282
  run: userClearSecondFactor,
284
283
  },
285
284
 
@@ -287,7 +286,7 @@ const commands: Command[] = [
287
286
  name: 'forum:create',
288
287
  summary: 'Create a category, forum or link.',
289
288
  usage:
290
- 'community forum:create --title <title> --slug <slug> [--parent <id>] ' +
289
+ 'meith forum:create --title <title> --slug <slug> [--parent <id>] ' +
291
290
  '[--type category|forum|link] [--description <text>] [--link-url <url>]',
292
291
  run: forumCreate,
293
292
  },
@@ -295,7 +294,7 @@ const commands: Command[] = [
295
294
  {
296
295
  name: 'settings:get',
297
296
  summary: 'Print one resolved setting value.',
298
- usage: 'community settings:get <key>',
297
+ usage: 'meith settings:get <key>',
299
298
  run: settingsGet,
300
299
  },
301
300
 
@@ -303,9 +302,9 @@ const commands: Command[] = [
303
302
  name: 'settings:set',
304
303
  summary: 'Set one setting, validated by the registry.',
305
304
  usage:
306
- 'community settings:set <key> <value>\n' +
307
- 'community settings:set <secret-key> --from-env <name>\n' +
308
- 'printf %s "$SECRET" | community settings:set <secret-key>',
305
+ 'meith settings:set <key> <value>\n' +
306
+ 'meith settings:set <secret-key> --from-env <name>\n' +
307
+ 'printf %s "$SECRET" | meith settings:set <secret-key>',
309
308
  run: settingsSet,
310
309
  },
311
310
 
@@ -319,7 +318,7 @@ const commands: Command[] = [
319
318
  name: 'profile-field:add',
320
319
  summary: 'Define a custom profile field.',
321
320
  usage:
322
- 'community profile-field:add --key <key> --label <label> ' +
321
+ 'meith profile-field:add --key <key> --label <label> ' +
323
322
  '--type text|textarea|select|checkbox|url|number ' +
324
323
  '[--options a,b,c] [--required] [--postbit] [--order <n>]',
325
324
  run: profileFieldAdd,
@@ -328,14 +327,14 @@ const commands: Command[] = [
328
327
  {
329
328
  name: 'profile-field:remove',
330
329
  summary: "Delete a custom profile field and every member's answer to it.",
331
- usage: 'community profile-field:remove <key>',
330
+ usage: 'meith profile-field:remove <key>',
332
331
  run: profileFieldRemove,
333
332
  },
334
333
 
335
334
  {
336
335
  name: 'push:keys',
337
336
  summary: 'Generate a VAPID key pair for web push. --save writes it to the board.',
338
- usage: 'community push:keys [--save]',
337
+ usage: 'meith push:keys [--save]',
339
338
  run: pushKeys,
340
339
  },
341
340
 
@@ -348,7 +347,7 @@ const commands: Command[] = [
348
347
  {
349
348
  name: 'task:run',
350
349
  summary: 'Run every task that is due now, or one named task if it is due.',
351
- usage: 'community task:run [<task-id>]',
350
+ usage: 'meith task:run [<task-id>]',
352
351
  run: taskRun,
353
352
  },
354
353
 
@@ -367,7 +366,7 @@ const commands: Command[] = [
367
366
  {
368
367
  name: 'demo:reset',
369
368
  summary: 'Drop everything and rebuild the demo board. Needs DEMO_MODE.',
370
- usage: 'community demo:reset --yes',
369
+ usage: 'meith demo:reset --yes',
371
370
  run: demoReset,
372
371
  },
373
372
  ]
@@ -392,7 +391,7 @@ async function main(): Promise<number> {
392
391
  }
393
392
 
394
393
  if (rest.includes('--help')) {
395
- console.log(command.usage ?? `community ${command.name}`)
394
+ console.log(command.usage ?? `meith ${command.name}`)
396
395
  return 0
397
396
  }
398
397
 
@@ -113,13 +113,13 @@ export async function pluginAdd(args: readonly string[]): Promise<number> {
113
113
  const [packageName, ...extraPositional] = positional
114
114
 
115
115
  if (packageName === undefined || extraPositional.length > 0) {
116
- throw new ValidationError('Usage: community plugin:add <package> [--key <key>] [--disabled]')
116
+ throw new ValidationError('Usage: meith plugin:add <package> [--key <key>] [--disabled]')
117
117
  }
118
118
 
119
119
  const configFlags = [...flags.keys()].filter((name) => !ADD_FLAGS.has(name))
120
120
  if (configFlags.length > 0) {
121
121
  throw new ValidationError(
122
- `community plugin:add does not take plugin configuration (--${configFlags[0]}). The ` +
122
+ `meith plugin:add does not take plugin configuration (--${configFlags[0]}). The ` +
123
123
  "manifest has no field for it — a plugin's own settings are the only place its " +
124
124
  "configuration lives now, the way MEI-74 moved plugins/dues's plans there. Export a " +
125
125
  'zero-argument plugin and add it with just its package name.',
@@ -173,7 +173,7 @@ export async function pluginRemove(args: readonly string[]): Promise<number> {
173
173
  const [key, ...extraPositional] = positional
174
174
 
175
175
  if (key === undefined || extraPositional.length > 0) {
176
- throw new ValidationError('Usage: community plugin:remove <key>')
176
+ throw new ValidationError('Usage: meith plugin:remove <key>')
177
177
  }
178
178
 
179
179
  const originals = await Promise.all(BOARDS.map((board) => readManifestFor(board)))
@@ -25,7 +25,7 @@ export async function profileFieldList(): Promise<number> {
25
25
  if (fields.length === 0) {
26
26
  console.log(
27
27
  'No custom profile fields.\n' +
28
- 'Add one: community profile-field:add --key pronouns --label Pronouns --type text',
28
+ 'Add one: meith profile-field:add --key pronouns --label Pronouns --type text',
29
29
  )
30
30
  return 0
31
31
  }
@@ -90,7 +90,7 @@ export async function profileFieldRemove(args: readonly string[]): Promise<numbe
90
90
  const { positional } = parseFlags(args)
91
91
  const key = positional[0]
92
92
  if (key === undefined) {
93
- throw new ValidationError('Usage: community profile-field:remove <key>')
93
+ throw new ValidationError('Usage: meith profile-field:remove <key>')
94
94
  }
95
95
 
96
96
  const removed = await service().remove(key)
package/src/tasks.ts CHANGED
@@ -31,9 +31,7 @@ export async function taskRun(args: readonly string[]): Promise<number> {
31
31
  const { repository, tasks, onTaskFailure } = scheduler()
32
32
  const selected = only === undefined ? tasks : tasks.filter((t) => t.id === only)
33
33
  if (only !== undefined && selected.length === 0) {
34
- console.error(
35
- `No such task: ${only}\n` + `Run \`community task:list\` to see what is registered.`,
36
- )
34
+ console.error(`No such task: ${only}\n` + `Run \`meith task:list\` to see what is registered.`)
37
35
  return 1
38
36
  }
39
37
 
package/src/upgrade.ts CHANGED
@@ -11,7 +11,7 @@ import { type PluginDefinition, pluginNavigationPlacements } from '@meith/plugin
11
11
  import { runPluginLifecycle } from '@meith/runtime'
12
12
  import { type PluginUpgrade, planUpgrade, upgradeNotice } from '@meith/upgrade'
13
13
 
14
- export const CODE_VERSION = '0.26.0'
14
+ export const CODE_VERSION = '0.27.0'
15
15
 
16
16
  export function pluginUpgrades(plugins: readonly PluginDefinition[]): readonly PluginUpgrade[] {
17
17
  return plugins.map((plugin) => ({