@wirechunk/cli 0.0.6 → 0.0.8
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/build/main.js +27191 -22361
- package/package.json +14 -8
- package/src/commands/bootstrap.ts +0 -85
- package/src/commands/create-extension-version.ts +0 -184
- package/src/commands/create-extension.ts +0 -14
- package/src/commands/create-user.ts +0 -211
- package/src/commands/edit-admin.ts +0 -139
- package/src/commands/ext-dev/get-db-url.ts +0 -36
- package/src/commands/ext-dev/init-db.ts +0 -228
- package/src/core-api/api.ts +0 -4807
- package/src/core-api/mutations/create-extension-version.generated.ts +0 -96
- package/src/core-api/mutations/create-extension-version.graphql +0 -14
- package/src/core-api/operations.ts +0 -23
- package/src/env.ts +0 -85
- package/src/errors.ts +0 -30
- package/src/global-options.ts +0 -6
- package/src/main.ts +0 -136
- package/src/users/permissions.ts +0 -41
- package/src/util.ts +0 -81
- package/tsconfig.build.json +0 -10
- package/tsconfig.json +0 -26
- package/vite.config.ts +0 -18
|
@@ -1,96 +0,0 @@
|
|
|
1
|
-
import type { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
|
|
2
|
-
import type * as Types from '#api';
|
|
3
|
-
|
|
4
|
-
export type CreateExtensionVersionMutationVariables = Types.Exact<{
|
|
5
|
-
input: Types.CreateExtensionVersionInput;
|
|
6
|
-
}>;
|
|
7
|
-
|
|
8
|
-
export type CreateExtensionVersionMutation = {
|
|
9
|
-
createExtensionVersion:
|
|
10
|
-
| { __typename: 'AuthorizationError'; message: string }
|
|
11
|
-
| {
|
|
12
|
-
__typename: 'CreateExtensionVersionSuccessResult';
|
|
13
|
-
signedUrl: string;
|
|
14
|
-
extensionVersion: { __typename: 'ExtensionVersion'; id: string };
|
|
15
|
-
}
|
|
16
|
-
| { __typename: 'InternalError'; message: string }
|
|
17
|
-
| { __typename: 'UserError'; message: string };
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export const CreateExtensionVersionDocument = {
|
|
21
|
-
kind: 'Document',
|
|
22
|
-
definitions: [
|
|
23
|
-
{
|
|
24
|
-
kind: 'OperationDefinition',
|
|
25
|
-
operation: 'mutation',
|
|
26
|
-
name: { kind: 'Name', value: 'CreateExtensionVersion' },
|
|
27
|
-
variableDefinitions: [
|
|
28
|
-
{
|
|
29
|
-
kind: 'VariableDefinition',
|
|
30
|
-
variable: { kind: 'Variable', name: { kind: 'Name', value: 'input' } },
|
|
31
|
-
type: {
|
|
32
|
-
kind: 'NonNullType',
|
|
33
|
-
type: {
|
|
34
|
-
kind: 'NamedType',
|
|
35
|
-
name: { kind: 'Name', value: 'CreateExtensionVersionInput' },
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
},
|
|
39
|
-
],
|
|
40
|
-
selectionSet: {
|
|
41
|
-
kind: 'SelectionSet',
|
|
42
|
-
selections: [
|
|
43
|
-
{
|
|
44
|
-
kind: 'Field',
|
|
45
|
-
name: { kind: 'Name', value: 'createExtensionVersion' },
|
|
46
|
-
arguments: [
|
|
47
|
-
{
|
|
48
|
-
kind: 'Argument',
|
|
49
|
-
name: { kind: 'Name', value: 'input' },
|
|
50
|
-
value: { kind: 'Variable', name: { kind: 'Name', value: 'input' } },
|
|
51
|
-
},
|
|
52
|
-
],
|
|
53
|
-
selectionSet: {
|
|
54
|
-
kind: 'SelectionSet',
|
|
55
|
-
selections: [
|
|
56
|
-
{ kind: 'Field', name: { kind: 'Name', value: '__typename' } },
|
|
57
|
-
{
|
|
58
|
-
kind: 'InlineFragment',
|
|
59
|
-
typeCondition: {
|
|
60
|
-
kind: 'NamedType',
|
|
61
|
-
name: { kind: 'Name', value: 'CreateExtensionVersionSuccessResult' },
|
|
62
|
-
},
|
|
63
|
-
selectionSet: {
|
|
64
|
-
kind: 'SelectionSet',
|
|
65
|
-
selections: [
|
|
66
|
-
{
|
|
67
|
-
kind: 'Field',
|
|
68
|
-
name: { kind: 'Name', value: 'extensionVersion' },
|
|
69
|
-
selectionSet: {
|
|
70
|
-
kind: 'SelectionSet',
|
|
71
|
-
selections: [{ kind: 'Field', name: { kind: 'Name', value: 'id' } }],
|
|
72
|
-
},
|
|
73
|
-
},
|
|
74
|
-
{ kind: 'Field', name: { kind: 'Name', value: 'signedUrl' } },
|
|
75
|
-
],
|
|
76
|
-
},
|
|
77
|
-
},
|
|
78
|
-
{
|
|
79
|
-
kind: 'InlineFragment',
|
|
80
|
-
typeCondition: { kind: 'NamedType', name: { kind: 'Name', value: 'Error' } },
|
|
81
|
-
selectionSet: {
|
|
82
|
-
kind: 'SelectionSet',
|
|
83
|
-
selections: [{ kind: 'Field', name: { kind: 'Name', value: 'message' } }],
|
|
84
|
-
},
|
|
85
|
-
},
|
|
86
|
-
],
|
|
87
|
-
},
|
|
88
|
-
},
|
|
89
|
-
],
|
|
90
|
-
},
|
|
91
|
-
},
|
|
92
|
-
],
|
|
93
|
-
} as unknown as DocumentNode<
|
|
94
|
-
CreateExtensionVersionMutation,
|
|
95
|
-
CreateExtensionVersionMutationVariables
|
|
96
|
-
>;
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
mutation CreateExtensionVersion($input: CreateExtensionVersionInput!) {
|
|
2
|
-
createExtensionVersion(input: $input) {
|
|
3
|
-
__typename
|
|
4
|
-
... on CreateExtensionVersionSuccessResult {
|
|
5
|
-
extensionVersion {
|
|
6
|
-
id
|
|
7
|
-
}
|
|
8
|
-
signedUrl
|
|
9
|
-
}
|
|
10
|
-
... on Error {
|
|
11
|
-
message
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { GraphQLClient } from 'graphql-request';
|
|
2
|
-
import type {
|
|
3
|
-
CreateExtensionVersionMutation,
|
|
4
|
-
CreateExtensionVersionMutationVariables,
|
|
5
|
-
} from './mutations/create-extension-version.generated.ts';
|
|
6
|
-
import { CreateExtensionVersionDocument } from './mutations/create-extension-version.generated.ts';
|
|
7
|
-
|
|
8
|
-
export const createExtensionVersion = ({
|
|
9
|
-
client,
|
|
10
|
-
variables,
|
|
11
|
-
sessionAuthToken,
|
|
12
|
-
}: {
|
|
13
|
-
client: GraphQLClient;
|
|
14
|
-
variables: CreateExtensionVersionMutationVariables;
|
|
15
|
-
sessionAuthToken: string;
|
|
16
|
-
}): Promise<CreateExtensionVersionMutation> =>
|
|
17
|
-
client.request({
|
|
18
|
-
document: CreateExtensionVersionDocument,
|
|
19
|
-
variables,
|
|
20
|
-
requestHeaders: {
|
|
21
|
-
Authorization: `Bearer ${sessionAuthToken}`,
|
|
22
|
-
},
|
|
23
|
-
});
|
package/src/env.ts
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs';
|
|
2
|
-
import { readFile } from 'node:fs/promises';
|
|
3
|
-
import process from 'node:process';
|
|
4
|
-
import { parseEnv as parseEnvContents } from 'node:util';
|
|
5
|
-
import { isLocalhost } from '@wirechunk/lib/localhost.ts';
|
|
6
|
-
|
|
7
|
-
export type Env = Record<string, string> & {
|
|
8
|
-
CORE_DATABASE_URL?: string;
|
|
9
|
-
// A URL to the server root, like https://wirechunk.com or http://localhost:8080
|
|
10
|
-
CORE_SERVER_URL: string;
|
|
11
|
-
WIRECHUNK_API_TOKEN?: string;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
// A .env file is required only if the required environment variables are not already set.
|
|
15
|
-
const envFilePath = '.env';
|
|
16
|
-
const envLocalFilePath = '.env.local';
|
|
17
|
-
|
|
18
|
-
const hasEnvFile = existsSync(envFilePath);
|
|
19
|
-
|
|
20
|
-
export const requireApiToken = (env: Env): string => {
|
|
21
|
-
if (!env.WIRECHUNK_API_TOKEN) {
|
|
22
|
-
console.error(
|
|
23
|
-
'Missing API token for authentication. Provide a WIRECHUNK_API_TOKEN environment variable.',
|
|
24
|
-
);
|
|
25
|
-
process.exit(1);
|
|
26
|
-
}
|
|
27
|
-
return env.WIRECHUNK_API_TOKEN;
|
|
28
|
-
};
|
|
29
|
-
|
|
30
|
-
export const requireCoreDbUrl = (env: Env): string => {
|
|
31
|
-
if (!env.CORE_DATABASE_URL) {
|
|
32
|
-
if (hasEnvFile) {
|
|
33
|
-
console.error('Missing CORE_DATABASE_URL in environment');
|
|
34
|
-
} else {
|
|
35
|
-
console.error(`Missing CORE_DATABASE_URL in environment, no ${envFilePath} file found`);
|
|
36
|
-
}
|
|
37
|
-
process.exit(1);
|
|
38
|
-
}
|
|
39
|
-
return env.CORE_DATABASE_URL;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
const coreServerUrlFromEnv = (env: Record<string, string>): string => {
|
|
43
|
-
const url = env.CORE_SERVER_URL;
|
|
44
|
-
if (url) {
|
|
45
|
-
return url.endsWith('/api') ? url.substring(0, url.length - 4) : url;
|
|
46
|
-
}
|
|
47
|
-
const adminDomain = env.ADMIN_DOMAIN;
|
|
48
|
-
if (adminDomain) {
|
|
49
|
-
return isLocalhost(adminDomain) ? `http://${adminDomain}` : `https://${adminDomain}`;
|
|
50
|
-
}
|
|
51
|
-
return 'https://wirechunk.com';
|
|
52
|
-
};
|
|
53
|
-
|
|
54
|
-
export const parseEnv = async (envMode: string | undefined): Promise<Env> => {
|
|
55
|
-
const env: Record<string, string> = {};
|
|
56
|
-
|
|
57
|
-
if (hasEnvFile) {
|
|
58
|
-
const envFileRaw = await readFile(envFilePath, 'utf8');
|
|
59
|
-
Object.assign(env, parseEnvContents(envFileRaw));
|
|
60
|
-
}
|
|
61
|
-
if (envMode) {
|
|
62
|
-
const modeFilePath = `.env.${envMode}`;
|
|
63
|
-
if (existsSync(modeFilePath)) {
|
|
64
|
-
const modeFileRaw = await readFile(modeFilePath, 'utf8');
|
|
65
|
-
Object.assign(env, parseEnvContents(modeFileRaw));
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
if (existsSync(envLocalFilePath)) {
|
|
69
|
-
const envLocalFileRaw = await readFile(envLocalFilePath, 'utf8');
|
|
70
|
-
Object.assign(env, parseEnvContents(envLocalFileRaw));
|
|
71
|
-
}
|
|
72
|
-
if (envMode) {
|
|
73
|
-
const modeLocalFilePath = `.env.${envMode}.local`;
|
|
74
|
-
if (existsSync(modeLocalFilePath)) {
|
|
75
|
-
const modeLocalFileRaw = await readFile(modeLocalFilePath, 'utf8');
|
|
76
|
-
Object.assign(env, parseEnvContents(modeLocalFileRaw));
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
Object.assign(env, process.env);
|
|
80
|
-
|
|
81
|
-
return {
|
|
82
|
-
...env,
|
|
83
|
-
CORE_SERVER_URL: coreServerUrlFromEnv(env),
|
|
84
|
-
};
|
|
85
|
-
};
|
package/src/errors.ts
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import type { UniqueIntegrityConstraintViolationError } from 'slonik';
|
|
2
|
-
|
|
3
|
-
export const detailedUniqueIntegrityConstraintViolationError = (
|
|
4
|
-
error: UniqueIntegrityConstraintViolationError,
|
|
5
|
-
): string => {
|
|
6
|
-
// The default error message is not very helpful, so we provide a more specific one.
|
|
7
|
-
const message =
|
|
8
|
-
error.message === 'Query violates a unique integrity constraint.'
|
|
9
|
-
? `A database uniqueness constraint was violated when inserting or updating`
|
|
10
|
-
: error.message;
|
|
11
|
-
const details: string[] = [];
|
|
12
|
-
if (error.table) {
|
|
13
|
-
details.push(`table "${error.table}"`);
|
|
14
|
-
}
|
|
15
|
-
if (error.column) {
|
|
16
|
-
details.push(`column "${error.column}"`);
|
|
17
|
-
}
|
|
18
|
-
if (error.constraint) {
|
|
19
|
-
details.push(`constraint "${error.constraint}"`);
|
|
20
|
-
}
|
|
21
|
-
if (details.length) {
|
|
22
|
-
return `${message} (${details.join(', ')})`;
|
|
23
|
-
}
|
|
24
|
-
return message;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
// Returns true if error is an object with a code property that signifies there is a duplicate database.
|
|
28
|
-
// Note the expected shape comes from the 'pg' library.
|
|
29
|
-
export const isDuplicateDatabaseError = (error: unknown): boolean =>
|
|
30
|
-
!!error && typeof error === 'object' && 'code' in error && error.code === '42P04';
|
package/src/global-options.ts
DELETED
package/src/main.ts
DELETED
|
@@ -1,136 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
import type { OptionValues } from '@commander-js/extra-typings';
|
|
4
|
-
import { Command } from '@commander-js/extra-typings';
|
|
5
|
-
import chalk from 'chalk';
|
|
6
|
-
import { bootstrap } from './commands/bootstrap.ts';
|
|
7
|
-
import { createExtensionVersion } from './commands/create-extension-version.ts';
|
|
8
|
-
import { createUser } from './commands/create-user.ts';
|
|
9
|
-
import { editAdmin } from './commands/edit-admin.ts';
|
|
10
|
-
import { getDbUrl } from './commands/ext-dev/get-db-url.ts';
|
|
11
|
-
import { initDb } from './commands/ext-dev/init-db.ts';
|
|
12
|
-
import type { Env } from './env.ts';
|
|
13
|
-
import { parseEnv } from './env.ts';
|
|
14
|
-
import type { WithGlobalOptions } from './global-options.ts';
|
|
15
|
-
|
|
16
|
-
const program = new Command()
|
|
17
|
-
.name('wirechunk')
|
|
18
|
-
.option('--verbose', 'output debug logging')
|
|
19
|
-
.option(
|
|
20
|
-
'--env-mode <mode>',
|
|
21
|
-
'the mode to use for finding .env files to load environment variables, such as "test" to load .env, .env.test, .env.local, and .env.test.local; also for finding config files to include when creating an extension or extension version, such as config.production.json',
|
|
22
|
-
).description(`The official Wirechunk CLI
|
|
23
|
-
|
|
24
|
-
By default, environment variables are loaded from the .env file in the current working directory,
|
|
25
|
-
then the .env.local file, and then from the environment. Variables from the environment have the
|
|
26
|
-
highest precedence.
|
|
27
|
-
|
|
28
|
-
Environment variables used by some commands:
|
|
29
|
-
CORE_SERVER_URL (the core admin server URL for commands using the API)
|
|
30
|
-
CORE_DATABASE_URL (the core database URL for commands requiring direct database access)`);
|
|
31
|
-
|
|
32
|
-
const withOptionsAndEnv =
|
|
33
|
-
<Args extends string[], Options extends OptionValues>(
|
|
34
|
-
action: (options: WithGlobalOptions<Options>, env: Env) => Promise<void> | void,
|
|
35
|
-
) =>
|
|
36
|
-
async (options: Options, cmd: Command<Args, Options>) => {
|
|
37
|
-
const mergedOptions = { ...program.opts(), ...options };
|
|
38
|
-
if (mergedOptions.verbose) {
|
|
39
|
-
console.log(`Running ${chalk.green.bold(cmd.name())}`);
|
|
40
|
-
}
|
|
41
|
-
const env = await parseEnv(mergedOptions.envMode);
|
|
42
|
-
return action(mergedOptions, env);
|
|
43
|
-
};
|
|
44
|
-
|
|
45
|
-
program
|
|
46
|
-
.command('bootstrap')
|
|
47
|
-
.description('create a platform')
|
|
48
|
-
.requiredOption('--name <string>', 'the name of the platform')
|
|
49
|
-
.option('--handle <string>', 'the handle of the platform (used by the admin site)')
|
|
50
|
-
.requiredOption(
|
|
51
|
-
'--admin-site-domain <string>',
|
|
52
|
-
'the domain of the platform admin site (dashboard)',
|
|
53
|
-
)
|
|
54
|
-
.option(
|
|
55
|
-
'--email-send-from <string>',
|
|
56
|
-
'the email address from which to send emails, defaults to "site@<admin-site-domain>',
|
|
57
|
-
)
|
|
58
|
-
.action(withOptionsAndEnv(bootstrap));
|
|
59
|
-
|
|
60
|
-
program
|
|
61
|
-
.command('create-extension-version')
|
|
62
|
-
.description('create an extension version')
|
|
63
|
-
.option(
|
|
64
|
-
'--extension-id <string>',
|
|
65
|
-
'the ID of the extension, can be set with an EXTENSION_ID environment variable instead',
|
|
66
|
-
)
|
|
67
|
-
.requiredOption('--version-name <string>', 'the name of the version')
|
|
68
|
-
.option(
|
|
69
|
-
'--config-file <string>',
|
|
70
|
-
'the path to a file to use when creating the extension version, containing environment-style key-value pairs',
|
|
71
|
-
)
|
|
72
|
-
.action(withOptionsAndEnv(createExtensionVersion));
|
|
73
|
-
|
|
74
|
-
program
|
|
75
|
-
.command('create-user')
|
|
76
|
-
.description('create a user')
|
|
77
|
-
.requiredOption('--email <string>', 'the email address of the user')
|
|
78
|
-
.requiredOption('--password <string>', 'the password of the user')
|
|
79
|
-
.requiredOption('--first-name <string>', 'the first name of the user')
|
|
80
|
-
.requiredOption('--last-name <string>', 'the last name of the user')
|
|
81
|
-
.option(
|
|
82
|
-
'--org-id <string>',
|
|
83
|
-
'the ID of the org to which the user belongs, defaults to creating a new org if not specified',
|
|
84
|
-
)
|
|
85
|
-
.option(
|
|
86
|
-
'--platform-id <string>',
|
|
87
|
-
'the ID of the platform ID to which the users will be added, used only if org ID is not specified',
|
|
88
|
-
)
|
|
89
|
-
.option(
|
|
90
|
-
'--role <string>',
|
|
91
|
-
'the role the user will have (defaults to the default role set on the platform, if defined, or an empty string)',
|
|
92
|
-
)
|
|
93
|
-
.option('--email-verified', 'mark the email address as already verified by the user', false)
|
|
94
|
-
.option('--pending', 'create the user in a pending state', false)
|
|
95
|
-
.action(withOptionsAndEnv(createUser));
|
|
96
|
-
|
|
97
|
-
// TODO: create-admin
|
|
98
|
-
|
|
99
|
-
const extDev = program.command('ext-dev').description('extension development commands');
|
|
100
|
-
|
|
101
|
-
extDev
|
|
102
|
-
.command('get-db-url')
|
|
103
|
-
.description(
|
|
104
|
-
'write the connection info for the extension database to a .env.local or .env.<env-mode>.local file',
|
|
105
|
-
)
|
|
106
|
-
.option(
|
|
107
|
-
'--extension-id <string>',
|
|
108
|
-
'the ID of the extension, can be set with an EXTENSION_ID environment variable instead',
|
|
109
|
-
)
|
|
110
|
-
.action(withOptionsAndEnv(getDbUrl));
|
|
111
|
-
|
|
112
|
-
extDev
|
|
113
|
-
.command('init-db')
|
|
114
|
-
.description(
|
|
115
|
-
'initialize a development database for an extension, useful for testing, assumes the extension role exists',
|
|
116
|
-
)
|
|
117
|
-
.option(
|
|
118
|
-
'--extension-id <string>',
|
|
119
|
-
'the ID of the extension, can be set with an EXTENSION_ID environment variable instead',
|
|
120
|
-
)
|
|
121
|
-
.option('--db-name <string>', 'a custom name for the database, applicable only for testing')
|
|
122
|
-
.action(withOptionsAndEnv(initDb));
|
|
123
|
-
|
|
124
|
-
program
|
|
125
|
-
.command('edit-admin')
|
|
126
|
-
.description('edit a platform admin user or make a user a platform admin')
|
|
127
|
-
.requiredOption('--platform-id <string>', 'the ID of the platform to edit')
|
|
128
|
-
.requiredOption('--user-id <string>', 'the ID of the admin user to edit')
|
|
129
|
-
.option('--owner', 'grants the user full permission to manage everything on the platform')
|
|
130
|
-
.option('--no-owner', 'removes owner privileges on the platform')
|
|
131
|
-
.option('--active', 'activates or deactivates the user’s admin access on the platform')
|
|
132
|
-
.option('--no-active', 'deactivates the user’s admin access on the platform')
|
|
133
|
-
.option('--revoke-all-permissions', 'revokes all permission of the user on their platform')
|
|
134
|
-
.action(withOptionsAndEnv(editAdmin));
|
|
135
|
-
|
|
136
|
-
await program.parseAsync();
|
package/src/users/permissions.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { cleanSmallId } from '@wirechunk/lib/clean-small-id.ts';
|
|
2
|
-
import { allPermissions } from '@wirechunk/lib/permissions.ts';
|
|
3
|
-
import type { CommonQueryMethods } from 'slonik';
|
|
4
|
-
import { sql } from 'slonik';
|
|
5
|
-
import { voidSelectSchema } from '../util.ts';
|
|
6
|
-
|
|
7
|
-
export const revokeAllUserPlatformPermissions = async (
|
|
8
|
-
{
|
|
9
|
-
platformAdminId,
|
|
10
|
-
}: {
|
|
11
|
-
platformAdminId: string;
|
|
12
|
-
},
|
|
13
|
-
db: CommonQueryMethods,
|
|
14
|
-
): Promise<void> => {
|
|
15
|
-
await db.query(
|
|
16
|
-
sql.type(
|
|
17
|
-
voidSelectSchema,
|
|
18
|
-
)`delete from "Permissions" where "platformAdminId" = ${platformAdminId}`,
|
|
19
|
-
);
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export const grantAllUserPlatformPermissions = async (
|
|
23
|
-
{
|
|
24
|
-
platformAdminId,
|
|
25
|
-
}: {
|
|
26
|
-
platformAdminId: string;
|
|
27
|
-
},
|
|
28
|
-
db: CommonQueryMethods,
|
|
29
|
-
): Promise<void> => {
|
|
30
|
-
await db.query(
|
|
31
|
-
sql.type(
|
|
32
|
-
voidSelectSchema,
|
|
33
|
-
)`insert into "Permissions" ("id", "platformAdminId", "object", "action") values ${sql.join(
|
|
34
|
-
allPermissions.map(
|
|
35
|
-
(permission) =>
|
|
36
|
-
sql.fragment`(${cleanSmallId()}, ${platformAdminId}, ${permission.object}, ${permission.action})`,
|
|
37
|
-
),
|
|
38
|
-
sql.fragment`,`,
|
|
39
|
-
)} on conflict ("platformAdminId", "object", "action") do nothing`,
|
|
40
|
-
);
|
|
41
|
-
};
|
package/src/util.ts
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import type { ClientConfigurationInput } from 'slonik/src/types.js';
|
|
2
|
-
import { createQueryLoggingInterceptor } from 'slonik-interceptor-query-logging';
|
|
3
|
-
import { z } from 'zod';
|
|
4
|
-
import type { Env } from './env.ts';
|
|
5
|
-
import { requireCoreDbUrl } from './env.ts';
|
|
6
|
-
import type { GlobalOptions } from './global-options.ts';
|
|
7
|
-
|
|
8
|
-
// Returns the name to use for an extension's database in development mode.
|
|
9
|
-
export const extensionDbName = (id: string): string => `ext_${id}`;
|
|
10
|
-
|
|
11
|
-
export const voidSelectSchema = z.object({});
|
|
12
|
-
|
|
13
|
-
export const requireExtensionIdOptionOrEnvVar = (
|
|
14
|
-
options: { extensionId?: string },
|
|
15
|
-
env: Env,
|
|
16
|
-
): string => {
|
|
17
|
-
const extensionId = options.extensionId || env.EXTENSION_ID;
|
|
18
|
-
if (!extensionId) {
|
|
19
|
-
console.error(
|
|
20
|
-
'Missing an extension ID, must be specified either as the --extension-id argument or the EXTENSION_ID environment variable',
|
|
21
|
-
);
|
|
22
|
-
process.exit(1);
|
|
23
|
-
}
|
|
24
|
-
return extensionId;
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
// Returns the value for the interceptors property to use on a Slonik ClientConfigurationInput.
|
|
28
|
-
// Note that you still need to set a ROARR_LOG=true environment variable to enable logging.
|
|
29
|
-
export const dbPoolOptions = (opts: GlobalOptions): ClientConfigurationInput =>
|
|
30
|
-
opts.verbose ? { interceptors: [createQueryLoggingInterceptor({ logValues: true })] } : {};
|
|
31
|
-
|
|
32
|
-
// Replace instances of a variable, or add a variable if needed, preserving other lines.
|
|
33
|
-
export const replaceEnvVar = (lines: string[], name: string, value: string): string[] => {
|
|
34
|
-
const newLines: string[] = [];
|
|
35
|
-
let hasName = false;
|
|
36
|
-
const namePattern = new RegExp(String.raw`^\s*${name}\s*=\s*`);
|
|
37
|
-
for (const line of lines) {
|
|
38
|
-
if (namePattern.test(line)) {
|
|
39
|
-
if (!hasName) {
|
|
40
|
-
newLines.push(`${name}=${value}`);
|
|
41
|
-
hasName = true;
|
|
42
|
-
}
|
|
43
|
-
} else {
|
|
44
|
-
newLines.push(line);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
if (!hasName) {
|
|
48
|
-
newLines.push(`${name}=${value}`);
|
|
49
|
-
}
|
|
50
|
-
return newLines;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
export const replaceDbName = (url: URL, dbName: string): URL => {
|
|
54
|
-
const urlObj = new URL(url.toString());
|
|
55
|
-
urlObj.pathname = `/${dbName}`;
|
|
56
|
-
return urlObj;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
export type DbConnectInfo = {
|
|
60
|
-
url: URL;
|
|
61
|
-
dbName: string;
|
|
62
|
-
};
|
|
63
|
-
|
|
64
|
-
export const getExtensionDbConnectInfo = (
|
|
65
|
-
opts: {
|
|
66
|
-
extensionId?: string;
|
|
67
|
-
dbName?: string;
|
|
68
|
-
},
|
|
69
|
-
env: Env,
|
|
70
|
-
): DbConnectInfo => {
|
|
71
|
-
const extensionId = requireExtensionIdOptionOrEnvVar(opts, env);
|
|
72
|
-
const dbName = opts.dbName || extensionDbName(extensionId);
|
|
73
|
-
const url = replaceDbName(new URL(requireCoreDbUrl(env)), dbName);
|
|
74
|
-
url.username = `ext_${extensionId}`;
|
|
75
|
-
url.password = '';
|
|
76
|
-
|
|
77
|
-
return {
|
|
78
|
-
url,
|
|
79
|
-
dbName,
|
|
80
|
-
};
|
|
81
|
-
};
|
package/tsconfig.build.json
DELETED
package/tsconfig.json
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2023",
|
|
4
|
-
"lib": ["ES2024", "ESNext.Promise"],
|
|
5
|
-
"module": "NodeNext",
|
|
6
|
-
"moduleResolution": "NodeNext",
|
|
7
|
-
"allowImportingTsExtensions": true,
|
|
8
|
-
"resolveJsonModule": true,
|
|
9
|
-
"allowJs": false,
|
|
10
|
-
"sourceMap": true,
|
|
11
|
-
"esModuleInterop": true,
|
|
12
|
-
"isolatedModules": true,
|
|
13
|
-
"forceConsistentCasingInFileNames": true,
|
|
14
|
-
"noFallthroughCasesInSwitch": true,
|
|
15
|
-
"strict": true,
|
|
16
|
-
"strictNullChecks": true,
|
|
17
|
-
"noImplicitReturns": true,
|
|
18
|
-
"noUncheckedIndexedAccess": true,
|
|
19
|
-
"noUnusedLocals": true,
|
|
20
|
-
"skipLibCheck": false,
|
|
21
|
-
"noEmit": true,
|
|
22
|
-
"paths": {
|
|
23
|
-
"#api": ["./src/core-api/api.ts"]
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
package/vite.config.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { resolve } from 'node:path';
|
|
2
|
-
import { defineConfig } from 'vite';
|
|
3
|
-
|
|
4
|
-
export default defineConfig({
|
|
5
|
-
ssr: {
|
|
6
|
-
// Every dependency except for built-in node dependencies are inlined.
|
|
7
|
-
noExternal: [/^(?!node:).*/],
|
|
8
|
-
external: ['argon2'],
|
|
9
|
-
},
|
|
10
|
-
build: {
|
|
11
|
-
ssr: true,
|
|
12
|
-
target: 'node22',
|
|
13
|
-
rollupOptions: {
|
|
14
|
-
input: resolve(import.meta.dirname, 'src/main.ts'),
|
|
15
|
-
},
|
|
16
|
-
outDir: 'build',
|
|
17
|
-
},
|
|
18
|
-
});
|