@nitwel/sandbox 1.0.5 → 1.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/dist/cli.js CHANGED
@@ -5,6 +5,7 @@ program
5
5
  .option('-b, --build', 'Rebuild directus from source')
6
6
  .option('-d, --dev', 'Start directus in developer mode. Not compatible with build')
7
7
  .option('-w, --watch', 'Restart the api when changes are made')
8
+ .option('-a, --app [port]', 'Spin up the app in dev mode')
8
9
  .option('--inspect', 'Start the api with debugger', true)
9
10
  .option('-p, --port <port>', 'Port to start the api on')
10
11
  .option('-v, --version <version>', 'Which version of the database to use')
package/dist/config.d.ts CHANGED
@@ -31,8 +31,9 @@ declare const maildev: {
31
31
  };
32
32
  declare const baseConfig: {
33
33
  readonly maria: {
34
- readonly TZ: "0" | "UTC";
34
+ readonly TZ: "UTC";
35
35
  readonly ADMIN_EMAIL: "admin@example.com";
36
+ readonly PROJECT_OWNER: "admin@example.com";
36
37
  readonly ADMIN_PASSWORD: "pw";
37
38
  readonly ADMIN_TOKEN: "admin";
38
39
  readonly SECRET: "directus-test";
@@ -65,8 +66,9 @@ declare const baseConfig: {
65
66
  readonly DB_VERSION: "11";
66
67
  };
67
68
  readonly postgres: {
68
- readonly TZ: "0" | "UTC";
69
+ readonly TZ: "UTC";
69
70
  readonly ADMIN_EMAIL: "admin@example.com";
71
+ readonly PROJECT_OWNER: "admin@example.com";
70
72
  readonly ADMIN_PASSWORD: "pw";
71
73
  readonly ADMIN_TOKEN: "admin";
72
74
  readonly SECRET: "directus-test";
@@ -99,8 +101,9 @@ declare const baseConfig: {
99
101
  readonly DB_VERSION: "18-3.6-alpine";
100
102
  };
101
103
  readonly sqlite: {
102
- readonly TZ: "0" | "UTC";
104
+ readonly TZ: "UTC";
103
105
  readonly ADMIN_EMAIL: "admin@example.com";
106
+ readonly PROJECT_OWNER: "admin@example.com";
104
107
  readonly ADMIN_PASSWORD: "pw";
105
108
  readonly ADMIN_TOKEN: "admin";
106
109
  readonly SECRET: "directus-test";
@@ -128,8 +131,9 @@ declare const baseConfig: {
128
131
  readonly DB_FILENAME: "./test.db";
129
132
  };
130
133
  readonly cockroachdb: {
131
- readonly TZ: "0" | "UTC";
134
+ readonly TZ: "UTC";
132
135
  readonly ADMIN_EMAIL: "admin@example.com";
136
+ readonly PROJECT_OWNER: "admin@example.com";
133
137
  readonly ADMIN_PASSWORD: "pw";
134
138
  readonly ADMIN_TOKEN: "admin";
135
139
  readonly SECRET: "directus-test";
@@ -163,8 +167,9 @@ declare const baseConfig: {
163
167
  readonly COCKROACH_UI: "$PORT";
164
168
  };
165
169
  readonly mssql: {
166
- readonly TZ: "0" | "UTC";
170
+ readonly TZ: "UTC";
167
171
  readonly ADMIN_EMAIL: "admin@example.com";
172
+ readonly PROJECT_OWNER: "admin@example.com";
168
173
  readonly ADMIN_PASSWORD: "pw";
169
174
  readonly ADMIN_TOKEN: "admin";
170
175
  readonly SECRET: "directus-test";
@@ -197,8 +202,9 @@ declare const baseConfig: {
197
202
  readonly DB_VERSION: "2022-latest";
198
203
  };
199
204
  readonly mysql: {
200
- readonly TZ: "0" | "UTC";
205
+ readonly TZ: "UTC";
201
206
  readonly ADMIN_EMAIL: "admin@example.com";
207
+ readonly PROJECT_OWNER: "admin@example.com";
202
208
  readonly ADMIN_PASSWORD: "pw";
203
209
  readonly ADMIN_TOKEN: "admin";
204
210
  readonly SECRET: "directus-test";
@@ -231,8 +237,9 @@ declare const baseConfig: {
231
237
  readonly DB_VERSION: "8.4";
232
238
  };
233
239
  readonly oracle: {
234
- readonly TZ: "0" | "UTC";
240
+ readonly TZ: "UTC";
235
241
  readonly ADMIN_EMAIL: "admin@example.com";
242
+ readonly PROJECT_OWNER: "admin@example.com";
236
243
  readonly ADMIN_PASSWORD: "pw";
237
244
  readonly ADMIN_TOKEN: "admin";
238
245
  readonly SECRET: "directus-test";
package/dist/config.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import { join } from 'path';
2
2
  import { directusFolder } from './find-directus.js';
3
- const isWindows = ['win32', 'win64'].includes(process.platform);
4
3
  const directusConfig = {
5
- TZ: isWindows ? '0' : 'UTC',
4
+ TZ: 'UTC',
6
5
  ADMIN_EMAIL: 'admin@example.com',
6
+ PROJECT_OWNER: 'admin@example.com',
7
7
  ADMIN_PASSWORD: 'pw',
8
8
  ADMIN_TOKEN: 'admin',
9
9
  SECRET: 'directus-test',
package/dist/sandbox.d.ts CHANGED
@@ -13,6 +13,8 @@ export type Options = {
13
13
  watch: boolean;
14
14
  /** Port to start the api on */
15
15
  port: Port;
16
+ /** Spin up the app in dev mode */
17
+ app: boolean | number;
16
18
  /** Which version of the database to use */
17
19
  version: string | undefined;
18
20
  /** Configure the behavior of the spun up docker container */
@@ -70,6 +72,7 @@ export type Sandbox = {
70
72
  logger: Logger;
71
73
  };
72
74
  export declare const apiFolder: string;
75
+ export declare const appFolder: string;
73
76
  export declare const databases: Database[];
74
77
  export type SandboxesOptions = {
75
78
  database: Database;
package/dist/sandbox.js CHANGED
@@ -1,12 +1,13 @@
1
1
  import {} from 'child_process';
2
- import { merge } from 'lodash-es';
3
2
  import { join } from 'path';
4
- import { getEnv } from './config.js';
5
- import { createLogger } from './logger.js';
6
- import { buildDirectus, bootstrap, dockerDown, dockerUp, loadSchema, saveSchema, startDirectus, } from './steps/index.js';
7
3
  import chalk from 'chalk';
8
4
  import getPort from 'get-port';
5
+ import { merge } from 'lodash-es';
6
+ import { getEnv } from './config.js';
9
7
  import { directusFolder } from './find-directus.js';
8
+ import { createLogger } from './logger.js';
9
+ import { startApp } from './steps/app.js';
10
+ import { bootstrap, buildApi, dockerDown, dockerUp, loadSchema, saveSchema, startApi } from './steps/index.js';
10
11
  async function getOptions(options) {
11
12
  if (options?.schema === true)
12
13
  options.schema = 'snapshot.json';
@@ -16,6 +17,7 @@ async function getOptions(options) {
16
17
  dev: false,
17
18
  watch: false,
18
19
  port,
20
+ app: false,
19
21
  version: undefined,
20
22
  docker: {
21
23
  keep: false,
@@ -40,6 +42,7 @@ async function getOptions(options) {
40
42
  }, options);
41
43
  }
42
44
  export const apiFolder = join(directusFolder, 'api');
45
+ export const appFolder = join(directusFolder, 'app');
43
46
  export const databases = [
44
47
  'maria',
45
48
  'cockroachdb',
@@ -60,7 +63,7 @@ export async function sandboxes(sandboxes, options) {
60
63
  try {
61
64
  // Rebuild directus
62
65
  if (opts.build && !opts.dev) {
63
- build = await buildDirectus(opts, logger, restartApis);
66
+ build = await buildApi(opts, logger, restartApis);
64
67
  }
65
68
  await Promise.all(sandboxes.map(async ({ database, options }, index) => {
66
69
  const opts = await getOptions(options);
@@ -73,7 +76,7 @@ export async function sandboxes(sandboxes, options) {
73
76
  await bootstrap(env, logger);
74
77
  if (opts.schema)
75
78
  await loadSchema(opts.schema, env, logger);
76
- apis.push({ processes: await startDirectus(opts, env, logger), index, opts, env, logger });
79
+ apis.push({ processes: await startApi(opts, env, logger), index, opts, env, logger });
77
80
  }
78
81
  catch (e) {
79
82
  logger.error(String(e));
@@ -87,7 +90,7 @@ export async function sandboxes(sandboxes, options) {
87
90
  }
88
91
  async function restartApis() {
89
92
  apis.forEach((api) => api.processes.forEach((process) => process.kill()));
90
- apis = await Promise.all(apis.map(async (api) => ({ ...api, processes: await startDirectus(api.opts, api.env, api.logger) })));
93
+ apis = await Promise.all(apis.map(async (api) => ({ ...api, processes: await startApi(api.opts, api.env, api.logger) })));
91
94
  }
92
95
  async function stop() {
93
96
  build?.kill();
@@ -104,19 +107,22 @@ export async function sandbox(database, options) {
104
107
  const env = await getEnv(database, opts);
105
108
  const logger = opts.prefix ? createLogger(env, opts, opts.prefix) : createLogger(env, opts);
106
109
  let apis = [];
110
+ let app;
107
111
  let project;
108
112
  let build;
109
113
  let interval;
110
114
  try {
111
115
  // Rebuild directus
112
116
  if (opts.build && !opts.dev) {
113
- build = await buildDirectus(opts, logger, restartApi);
117
+ build = await buildApi(opts, logger, restartApi);
114
118
  }
115
119
  project = await dockerUp(database, opts, env, logger);
116
120
  await bootstrap(env, logger);
117
121
  if (opts.schema)
118
122
  await loadSchema(opts.schema, env, logger);
119
- apis = await startDirectus(opts, env, logger);
123
+ apis = await startApi(opts, env, logger);
124
+ if (opts.app !== false)
125
+ app = await startApp(opts, env, logger);
120
126
  if (opts.export)
121
127
  interval = await saveSchema(env);
122
128
  }
@@ -127,7 +133,7 @@ export async function sandbox(database, options) {
127
133
  }
128
134
  async function restartApi() {
129
135
  apis.forEach((api) => api.kill());
130
- apis = await startDirectus(opts, env, logger);
136
+ apis = await startApi(opts, env, logger);
131
137
  }
132
138
  async function stop() {
133
139
  const start = performance.now();
@@ -135,6 +141,7 @@ export async function sandbox(database, options) {
135
141
  clearInterval(interval);
136
142
  build?.kill();
137
143
  apis.forEach((api) => api.kill());
144
+ app?.kill();
138
145
  if (project && !opts.docker.keep)
139
146
  await dockerDown(project, env, logger);
140
147
  const time = chalk.gray(`(${Math.round(performance.now() - start)}ms)`);
@@ -1,6 +1,6 @@
1
1
  import { type Env } from '../config.js';
2
2
  import { type Logger } from '../logger.js';
3
3
  import { type Options } from '../sandbox.js';
4
- export declare function buildDirectus(opts: Options, logger: Logger, onRebuild: () => void): Promise<import("child_process").ChildProcessWithoutNullStreams | undefined>;
4
+ export declare function buildApi(opts: Options, logger: Logger, onRebuild: () => void): Promise<import("child_process").ChildProcessWithoutNullStreams | undefined>;
5
5
  export declare function bootstrap(env: Env, logger: Logger): Promise<void>;
6
- export declare function startDirectus(opts: Options, env: Env, logger: Logger): Promise<import("child_process").ChildProcessWithoutNullStreams[]>;
6
+ export declare function startApi(opts: Options, env: Env, logger: Logger): Promise<import("child_process").ChildProcessWithoutNullStreams[]>;
package/dist/steps/api.js CHANGED
@@ -1,11 +1,11 @@
1
1
  import { spawn } from 'child_process';
2
2
  import { join } from 'path';
3
+ import chalk from 'chalk';
4
+ import { detect } from 'detect-port';
3
5
  import {} from '../config.js';
4
6
  import {} from '../logger.js';
5
7
  import { apiFolder } from '../sandbox.js';
6
- import chalk from 'chalk';
7
- import { detect } from 'detect-port';
8
- export async function buildDirectus(opts, logger, onRebuild) {
8
+ export async function buildApi(opts, logger, onRebuild) {
9
9
  const start = performance.now();
10
10
  logger.info('Rebuilding Directus');
11
11
  let timeout;
@@ -66,7 +66,7 @@ export async function bootstrap(env, logger) {
66
66
  const time = chalk.gray(`(${Math.round(performance.now() - start)}ms)`);
67
67
  logger.info(`Completed Bootstraping Database ${time}`);
68
68
  }
69
- export async function startDirectus(opts, env, logger) {
69
+ export async function startApi(opts, env, logger) {
70
70
  const apiCount = Math.max(1, Number(opts.instances));
71
71
  const apiPorts = [...Array(apiCount).keys()].flatMap((i) => Number(env.PORT) + i * (opts.inspect ? 2 : 1));
72
72
  const allPorts = apiPorts.flatMap((port) => (opts.inspect ? [port, port + 1] : [port]));
@@ -78,12 +78,12 @@ export async function startDirectus(opts, env, logger) {
78
78
  }
79
79
  return await Promise.all(apiPorts.map((port) => {
80
80
  const newLogger = apiCount > 1 ? logger.addGroup(`API ${port}`) : logger;
81
- return startDirectusInstance(opts, { ...env, PORT: String(port) }, newLogger);
81
+ return startApiInstance(opts, { ...env, PORT: String(port) }, newLogger);
82
82
  }));
83
83
  }
84
- async function startDirectusInstance(opts, env, logger) {
84
+ async function startApiInstance(opts, env, logger) {
85
85
  const start = performance.now();
86
- logger.info('Starting Directus');
86
+ logger.info('Starting Server');
87
87
  const debuggerPort = Number(env.PORT) + 1;
88
88
  let api;
89
89
  let timeout;
@@ -0,0 +1,3 @@
1
+ import type { Logger } from '../logger.js';
2
+ import { type Env, type Options } from '../sandbox.js';
3
+ export declare function startApp(opts: Options, env: Env, logger: Logger): Promise<import("child_process").ChildProcessWithoutNullStreams>;
@@ -0,0 +1,44 @@
1
+ import { spawn } from 'child_process';
2
+ import chalk from 'chalk';
3
+ import { appFolder } from '../sandbox.js';
4
+ export async function startApp(opts, env, logger) {
5
+ const start = performance.now();
6
+ logger.info('Starting App');
7
+ let timeout;
8
+ const port = typeof opts.app !== 'boolean' ? opts.app : 8080;
9
+ const app = spawn('pnpm', ['vite', '--host', '--clearScreen false', `--port ${port}`], {
10
+ cwd: appFolder,
11
+ shell: true,
12
+ });
13
+ logger.pipe(app.stdout, 'debug');
14
+ app.on('error', (err) => {
15
+ logger.error(err.toString());
16
+ });
17
+ app.on('close', (code) => {
18
+ if (code === null || code === 0)
19
+ return;
20
+ const error = new Error(`Api stopped with error code ${code}`);
21
+ clearTimeout(timeout);
22
+ logger.error(error.toString());
23
+ throw error;
24
+ });
25
+ logger.pipe(app.stderr, 'error');
26
+ await new Promise((resolve, reject) => {
27
+ app.stdout.on('data', (data) => {
28
+ const msg = String(data);
29
+ if (msg.includes(`ready in`)) {
30
+ resolve(undefined);
31
+ }
32
+ else {
33
+ logger.debug(msg);
34
+ }
35
+ });
36
+ // In case the api takes too long to start
37
+ timeout = setTimeout(() => {
38
+ reject(new Error('timeout starting app'));
39
+ }, 60_000);
40
+ });
41
+ const time = chalk.gray(`(${Math.round(performance.now() - start)}ms)`);
42
+ logger.info(`App started at http://${env.HOST}:${port} ${time}`);
43
+ return app;
44
+ }
@@ -1,9 +1,9 @@
1
1
  import { spawn } from 'child_process';
2
2
  import { dirname, join } from 'path';
3
+ import { fileURLToPath } from 'url';
4
+ import chalk from 'chalk';
3
5
  import {} from '../config.js';
4
6
  import {} from '../logger.js';
5
- import chalk from 'chalk';
6
- import { fileURLToPath } from 'url';
7
7
  const fileName = fileURLToPath(import.meta.url);
8
8
  const folderName = dirname(fileName);
9
9
  export async function dockerUp(database, opts, env, logger) {
@@ -1,12 +1,12 @@
1
1
  import { spawn } from 'child_process';
2
2
  import { writeFile } from 'fs/promises';
3
- import { camelCase, upperFirst } from 'lodash-es';
4
3
  import { join, resolve } from 'path';
4
+ import chalk from 'chalk';
5
+ import { camelCase, upperFirst } from 'lodash-es';
5
6
  import {} from '../config.js';
6
7
  import {} from '../logger.js';
7
8
  import { getRelationInfo } from '../relation.js';
8
9
  import { apiFolder } from '../sandbox.js';
9
- import chalk from 'chalk';
10
10
  export async function loadSchema(schema_file, env, logger) {
11
11
  const start = performance.now();
12
12
  logger.info('Applying Schema');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nitwel/sandbox",
3
- "version": "1.0.5",
3
+ "version": "1.0.7",
4
4
  "description": "Toolkit for spinning up directus test environments",
5
5
  "homepage": "https://directus.io",
6
6
  "exports": {
@@ -25,25 +25,25 @@
25
25
  "@directus/utils": "13.0.9",
26
26
  "@types/lodash-es": "4.17.12",
27
27
  "@types/node": "22.13.14",
28
- "chalk": "5.4.1",
29
- "commander": "14.0.0",
28
+ "chalk": "5.6.2",
29
+ "commander": "14.0.2",
30
30
  "copyfiles": "2.4.1",
31
31
  "detect-port": "2.1.0",
32
32
  "get-port": "7.1.0",
33
33
  "lodash-es": "4.17.21",
34
- "tsdown": "0.14.2",
35
- "tsx": "4.20.3",
34
+ "tsdown": "0.15.11",
35
+ "tsx": "4.20.6",
36
36
  "typedoc": "0.28.12",
37
37
  "typedoc-plugin-markdown": "4.8.1",
38
- "typescript": "5.8.3",
39
- "@directus/types": "13.2.3"
38
+ "typescript": "5.9.3",
39
+ "@directus/types": "14.0.0"
40
40
  },
41
41
  "engines": {
42
42
  "node": ">=12.20.0"
43
43
  },
44
44
  "optionalDependencies": {
45
- "mysql2": "3.14.3",
46
- "oracledb": "6.9.0",
45
+ "mysql2": "3.15.3",
46
+ "oracledb": "6.10.0",
47
47
  "pg": "8.16.3",
48
48
  "sqlite3": "5.1.7",
49
49
  "tedious": "18.6.1"