@wirechunk/cli 0.0.5 → 0.0.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wirechunk/cli",
3
- "version": "0.0.5",
3
+ "version": "0.0.7",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "scripts": {
@@ -10,6 +10,7 @@
10
10
  "format:check": "prettier --check .",
11
11
  "typecheck": "tsc",
12
12
  "typecheck-src": "tsc --skipLibCheck",
13
+ "typecheck-src:tsgo": "tsgo --skipLibCheck",
13
14
  "test": "echo 'no tests yet'",
14
15
  "build": "npm run build:clean && npm run build:cli",
15
16
  "build:clean": "rm -rf build",
@@ -23,21 +24,21 @@
23
24
  "#api": "./src/core-api/api.ts"
24
25
  },
25
26
  "dependencies": {
26
- "argon2": "^0.41.1"
27
+ "argon2": "^0.44.0"
27
28
  },
28
29
  "devDependencies": {
29
- "@commander-js/extra-typings": "^13.0.0",
30
+ "@commander-js/extra-typings": "^14.0.0",
30
31
  "@graphql-typed-document-node/core": "^3.2.0",
31
32
  "@types/archiver": "^6.0.3",
32
33
  "@wirechunk/backend-lib": "0.0.0",
33
34
  "@wirechunk/lib": "0.0.0",
34
35
  "archiver": "^7.0.1",
35
- "chalk": "^5.3.0",
36
- "commander": "^13.0.0",
36
+ "chalk": "^5.6.2",
37
+ "commander": "^14.0.2",
37
38
  "graphql-request": "^7.1.2",
38
- "slonik": "^46.3.0",
39
- "slonik-interceptor-query-logging": "^46.3.0",
40
- "zod": "^3.24.1"
39
+ "slonik": "^48.8.7",
40
+ "slonik-interceptor-query-logging": "^48.8.7",
41
+ "zod": "^4.1.13"
41
42
  },
42
43
  "publishConfig": {
43
44
  "access": "public"
@@ -23,8 +23,6 @@ const bytesFormat = Intl.NumberFormat('en', {
23
23
  const ignoreGlobs = [
24
24
  '**/.git/**/*',
25
25
  '.git/**/*',
26
- 'eslint.config.js',
27
- '**/eslint.config.js',
28
26
  'node_modules/**/*',
29
27
  '**/node_modules/**/*',
30
28
  'yalc.lock',
@@ -9,17 +9,24 @@ import { detailedUniqueIntegrityConstraintViolationError } from '../errors.ts';
9
9
  import type { WithGlobalOptions } from '../global-options.ts';
10
10
  import { voidSelectSchema } from '../util.ts';
11
11
 
12
- const insertUserResult = z.object({
13
- id: z.string(),
14
- });
15
-
16
12
  const findOrgResult = z.object({
17
13
  platformId: z.string(),
18
14
  });
19
15
 
16
+ // Copied from backend-lib/roles.ts for now because different zod versions.
17
+ const roleSchema = z.object({
18
+ id: z.string(),
19
+ name: z.string(),
20
+ default: z.boolean().optional().default(false),
21
+ });
22
+
23
+ // The schema for the platform roles configuration.
24
+ const rolesSchema = z.array(roleSchema);
25
+
20
26
  const findPlatformResult = z.object({
21
27
  id: z.string(),
22
28
  name: z.string(),
29
+ roles: rolesSchema.nullable(),
23
30
  });
24
31
 
25
32
  type CreateUserOptions = {
@@ -29,7 +36,7 @@ type CreateUserOptions = {
29
36
  lastName: string;
30
37
  orgId?: string;
31
38
  platformId?: string;
32
- role: string;
39
+ role?: string;
33
40
  emailVerified: boolean;
34
41
  pending: boolean;
35
42
  };
@@ -52,7 +59,7 @@ export const createUser = async (
52
59
  process.exit(1);
53
60
  }
54
61
  const password = await hashPassword(opts.password);
55
- const { role } = opts;
62
+ const inputRole = opts.role || '';
56
63
  const status = opts.pending ? 'Pending' : 'Active';
57
64
  const firstName = opts.firstName.trim();
58
65
  if (!firstName.length) {
@@ -70,7 +77,8 @@ export const createUser = async (
70
77
  let orgPrimary = false;
71
78
 
72
79
  try {
73
- const user = await db.transaction(async (db) => {
80
+ const userId = cleanSmallId();
81
+ await db.transaction(async (db) => {
74
82
  if (!platformId) {
75
83
  if (!orgId) {
76
84
  throw new Error('Either --org-id or --platform-id must be specified');
@@ -93,17 +101,61 @@ export const createUser = async (
93
101
  throw new Error(`Org ID ${orgId} does not belong to platform ID ${platformId}`);
94
102
  }
95
103
  }
104
+
96
105
  const platform = await db.maybeOne(
97
106
  sql.type(
98
107
  findPlatformResult,
99
- )`select "id", "name" from "Platforms" where "id" = ${platformId}`,
108
+ )`select "id", "name", "roles" from "Platforms" where "id" = ${platformId}`,
100
109
  );
110
+
101
111
  if (!platform) {
102
112
  throw new Error(`No platform found with ID ${platformId}`);
103
113
  }
104
114
  if (opts.verbose) {
105
115
  console.log(`Found platform ${platform.name} (ID ${platform.id})`);
106
116
  }
117
+
118
+ // Determine the role to use.
119
+ let roleToUse = '';
120
+ if (platform.roles && platform.roles.length) {
121
+ if (inputRole) {
122
+ const roleExists = platform.roles.some((r) => r.name === inputRole);
123
+ if (roleExists) {
124
+ roleToUse = inputRole;
125
+ } else {
126
+ const validRoles = platform.roles.map((r) => r.name).join(', ');
127
+ console.error(
128
+ `Error: Invalid role "${inputRole}". Valid roles for this platform are: ${validRoles}`,
129
+ );
130
+ process.exit(1);
131
+ }
132
+ } else {
133
+ const defaultRole = platform.roles.find((r) => r.default);
134
+ if (defaultRole) {
135
+ roleToUse = defaultRole.name;
136
+ if (opts.verbose) {
137
+ console.log(`No role provided. Using default role: ${roleToUse}`);
138
+ }
139
+ } else {
140
+ // No default role exists and no role was provided.
141
+ if (opts.verbose) {
142
+ console.log(
143
+ 'No default role exists and no role was provided. Using empty string for the role.',
144
+ );
145
+ }
146
+ }
147
+ }
148
+ } else {
149
+ // No roles defined for this platform.
150
+ if (inputRole) {
151
+ console.error('Error: A role was specified but no roles are defined for this platform.');
152
+ process.exit(1);
153
+ }
154
+ if (opts.verbose) {
155
+ console.log('No roles defined for this platform. Using empty string for the role.');
156
+ }
157
+ }
158
+
107
159
  if (!orgId) {
108
160
  orgId = cleanSmallId();
109
161
  await db.maybeOne(
@@ -117,23 +169,46 @@ export const createUser = async (
117
169
  orgPrimary = true;
118
170
  }
119
171
 
120
- const user = await db.one(
121
- sql.type(
122
- insertUserResult,
123
- )`insert into "Users" ("platformId", "email", "emailVerified", "password", "passwordStatus", "orgId", "role", "status", "firstName", "lastName") values (${platformId}, ${email}, ${opts.emailVerified}, ${password}, 'Ok', ${orgId}, ${role}, ${status}, ${firstName}, ${lastName}) returning "id"`,
172
+ const user = await db.maybeOne(
173
+ sql.type(voidSelectSchema)`insert into "Users" (
174
+ "id",
175
+ "platformId",
176
+ "email",
177
+ "emailVerified",
178
+ "password",
179
+ "passwordStatus",
180
+ "orgId",
181
+ "role",
182
+ "status",
183
+ "firstName",
184
+ "lastName"
185
+ )
186
+ values (
187
+ ${userId},
188
+ ${platformId},
189
+ ${email},
190
+ ${opts.emailVerified},
191
+ ${password},
192
+ 'Ok',
193
+ ${orgId},
194
+ ${roleToUse},
195
+ ${status},
196
+ ${firstName},
197
+ ${lastName}
198
+ )`,
124
199
  );
125
200
 
126
201
  if (orgPrimary) {
127
202
  await db.maybeOne(
128
203
  sql.type(
129
204
  voidSelectSchema,
130
- )`update "Orgs" set "primaryUserId" = ${user.id} where "id" = ${orgId}`,
205
+ )`update "Orgs" set "primaryUserId" = ${userId} where "id" = ${orgId}`,
131
206
  );
132
207
  }
133
208
 
134
209
  return user;
135
210
  });
136
- console.log(`Created user (ID ${user.id})`);
211
+ console.log(`Created user (ID ${userId})`);
137
212
  } catch (e) {
138
213
  if (e instanceof UniqueIntegrityConstraintViolationError) {
139
214
  console.error(detailedUniqueIntegrityConstraintViolationError(e));
@@ -37,13 +37,14 @@ const initExtDb = async ({
37
37
 
38
38
  const extRoleIdent = sql.identifier([extensionRoleName]);
39
39
 
40
+ // Note the password_required 'false' option is needed for local development environments without passwords.
40
41
  await db.query(sql.unsafe`
41
42
  create user mapping if not exists for ${extRoleIdent} server wirechunk
42
43
  options (user ${sql.literalValue(extensionRoleName)}, password_required 'false')
43
44
  `);
44
45
  await db.query(sql.unsafe`
45
46
  create foreign table if not exists "Users" (
46
- "id" uuid not null,
47
+ "id" text not null,
47
48
  "firstName" text not null,
48
49
  "lastName" text not null,
49
50
  "email" text not null,
@@ -59,7 +60,7 @@ const initExtDb = async ({
59
60
  create foreign table if not exists "Orgs" (
60
61
  "id" text not null,
61
62
  "name" text,
62
- "primaryUserId" uuid,
63
+ "primaryUserId" text,
63
64
  "createdAt" timestamptz not null
64
65
  ) server wirechunk options (schema_name 'public', table_name 'Orgs')
65
66
  `);
@@ -217,11 +218,11 @@ export const initDb = async (
217
218
  db,
218
219
  });
219
220
 
220
- const extDbSuper = new URL(extDb.url);
221
- extDbSuper.username = coreDbUrlObject.username;
221
+ const superExtDb = new URL(extDb.url);
222
+ superExtDb.username = coreDbUrlObject.username;
222
223
 
223
224
  await initExtDb({
224
- db: await createPool(extDbSuper.toString(), dbPoolOptions(opts)),
225
+ db: await createPool(superExtDb.toString(), dbPoolOptions(opts)),
225
226
  extensionRoleName: extRole,
226
227
  coreDbUrl: coreDbUrlObject,
227
228
  });