@nitwel/sandbox 1.0.6 → 1.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/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,7 +31,7 @@ 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
36
  readonly PROJECT_OWNER: "admin@example.com";
37
37
  readonly ADMIN_PASSWORD: "pw";
@@ -66,7 +66,7 @@ declare const baseConfig: {
66
66
  readonly DB_VERSION: "11";
67
67
  };
68
68
  readonly postgres: {
69
- readonly TZ: "0" | "UTC";
69
+ readonly TZ: "UTC";
70
70
  readonly ADMIN_EMAIL: "admin@example.com";
71
71
  readonly PROJECT_OWNER: "admin@example.com";
72
72
  readonly ADMIN_PASSWORD: "pw";
@@ -101,7 +101,7 @@ declare const baseConfig: {
101
101
  readonly DB_VERSION: "18-3.6-alpine";
102
102
  };
103
103
  readonly sqlite: {
104
- readonly TZ: "0" | "UTC";
104
+ readonly TZ: "UTC";
105
105
  readonly ADMIN_EMAIL: "admin@example.com";
106
106
  readonly PROJECT_OWNER: "admin@example.com";
107
107
  readonly ADMIN_PASSWORD: "pw";
@@ -131,7 +131,7 @@ declare const baseConfig: {
131
131
  readonly DB_FILENAME: "./test.db";
132
132
  };
133
133
  readonly cockroachdb: {
134
- readonly TZ: "0" | "UTC";
134
+ readonly TZ: "UTC";
135
135
  readonly ADMIN_EMAIL: "admin@example.com";
136
136
  readonly PROJECT_OWNER: "admin@example.com";
137
137
  readonly ADMIN_PASSWORD: "pw";
@@ -167,7 +167,7 @@ declare const baseConfig: {
167
167
  readonly COCKROACH_UI: "$PORT";
168
168
  };
169
169
  readonly mssql: {
170
- readonly TZ: "0" | "UTC";
170
+ readonly TZ: "UTC";
171
171
  readonly ADMIN_EMAIL: "admin@example.com";
172
172
  readonly PROJECT_OWNER: "admin@example.com";
173
173
  readonly ADMIN_PASSWORD: "pw";
@@ -202,7 +202,7 @@ declare const baseConfig: {
202
202
  readonly DB_VERSION: "2022-latest";
203
203
  };
204
204
  readonly mysql: {
205
- readonly TZ: "0" | "UTC";
205
+ readonly TZ: "UTC";
206
206
  readonly ADMIN_EMAIL: "admin@example.com";
207
207
  readonly PROJECT_OWNER: "admin@example.com";
208
208
  readonly ADMIN_PASSWORD: "pw";
@@ -237,7 +237,7 @@ declare const baseConfig: {
237
237
  readonly DB_VERSION: "8.4";
238
238
  };
239
239
  readonly oracle: {
240
- readonly TZ: "0" | "UTC";
240
+ readonly TZ: "UTC";
241
241
  readonly ADMIN_EMAIL: "admin@example.com";
242
242
  readonly PROJECT_OWNER: "admin@example.com";
243
243
  readonly ADMIN_PASSWORD: "pw";
package/dist/config.js CHANGED
@@ -1,8 +1,7 @@
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',
7
6
  PROJECT_OWNER: 'admin@example.com',
8
7
  ADMIN_PASSWORD: 'pw',
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.6",
3
+ "version": "1.0.8",
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"