@elastic/synthetics 1.0.0-beta.33 → 1.0.0-beta.34

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/src/push/index.ts CHANGED
@@ -23,8 +23,6 @@
23
23
  *
24
24
  */
25
25
 
26
- import { join } from 'path';
27
- import { existsSync } from 'fs';
28
26
  import { readFile, writeFile } from 'fs/promises';
29
27
  import { prompt } from 'enquirer';
30
28
  import { bold, yellow } from 'kleur/colors';
@@ -36,20 +34,19 @@ import {
36
34
  formatStaleMonitors,
37
35
  } from './request';
38
36
  import { buildMonitorSchema, createMonitors, MonitorSchema } from './monitor';
39
- import { ProjectSettings } from '../generator';
40
37
  import { Monitor } from '../dsl/monitor';
41
38
  import {
42
39
  progress,
43
40
  apiProgress,
44
41
  write,
45
42
  error,
46
- SYNTHETICS_PATH,
47
43
  aborted,
48
44
  indent,
49
45
  safeNDJSONParse,
50
46
  done,
51
47
  } from '../helpers';
52
- import type { PushOptions } from '../common_types';
48
+ import type { PushOptions, ProjectSettings } from '../common_types';
49
+ import { findSyntheticsConfig, readConfig } from '../config';
53
50
 
54
51
  export async function push(monitors: Monitor[], options: PushOptions) {
55
52
  if (monitors.length === 0) {
@@ -148,34 +145,39 @@ export function formatDuplicateError(monitors: Set<Monitor>) {
148
145
  return outer;
149
146
  }
150
147
 
151
- const PROJECT_SETTINGS_PATH = join(SYNTHETICS_PATH, 'project.json');
152
148
  const INSTALLATION_HELP = `Run 'npx @elastic/synthetics init' to create project with default settings.`;
153
149
 
154
150
  export async function loadSettings() {
155
- if (!existsSync(PROJECT_SETTINGS_PATH)) {
156
- throw error(`Aborted. Synthetics project not set up.
151
+ try {
152
+ const config = await readConfig('asd');
153
+ // Missing config file, fake throw to capture as missing file
154
+ if (Object.keys(config).length === 0) {
155
+ throw '';
156
+ }
157
+ return config.project || ({} as ProjectSettings);
158
+ } catch (e) {
159
+ throw error(`Aborted (missing synthetics config file), Project not set up corrrectly.
157
160
 
158
161
  ${INSTALLATION_HELP}`);
159
162
  }
160
-
161
- const contents = await readFile(PROJECT_SETTINGS_PATH, 'utf-8');
162
- return JSON.parse(contents) as ProjectSettings;
163
163
  }
164
164
 
165
165
  export function validateSettings(opts: PushOptions) {
166
166
  const INVALID = 'Aborted. Invalid synthetics project settings.';
167
167
 
168
168
  let reason = '';
169
- if (!opts.project) {
170
- reason = 'Set project id via CLI as `--project <id>`';
169
+ if (!opts.id) {
170
+ reason = `Set project id via
171
+ - CLI '--id <id>'
172
+ - Config file 'project.id' field`;
171
173
  } else if (!opts.locations && !opts.privateLocations) {
172
174
  reason = `Set default location for all monitors via
173
- - CLI as '--locations <values...> or --privateLocations <values...>'
174
- - Synthetics config file 'monitors.locations' | 'monitors.privateLocations' field`;
175
+ - CLI '--locations <values...> or --privateLocations <values...>'
176
+ - Config file 'monitors.locations' | 'monitors.privateLocations' field`;
175
177
  } else if (!opts.schedule) {
176
178
  reason = `Set default schedule in minutes for all monitors via
177
- - CLI as '--schedule <mins>'
178
- - Synthetics config file 'monitors.schedule' field`;
179
+ - CLI '--schedule <mins>'
180
+ - Config file 'monitors.schedule' field`;
179
181
  }
180
182
 
181
183
  if (!reason) return;
@@ -187,24 +189,27 @@ ${reason}
187
189
  ${INSTALLATION_HELP}`);
188
190
  }
189
191
 
190
- async function overrideSettings(project: string) {
191
- const settings = JSON.parse(await readFile(PROJECT_SETTINGS_PATH, 'utf-8'));
192
- settings.project = project;
193
-
194
- await writeFile(
195
- PROJECT_SETTINGS_PATH,
196
- JSON.stringify(settings, null, 2),
197
- 'utf-8'
192
+ async function overrideSettings(oldValue: string, newValue: string) {
193
+ const cwd = process.cwd();
194
+ const configPath = await findSyntheticsConfig(cwd, cwd);
195
+ if (!configPath) {
196
+ throw aborted(`Unable to find synthetics config file: ${configPath}`);
197
+ }
198
+ const config = await readFile(configPath, 'utf-8');
199
+ const updatedConfig = config.replace(
200
+ `id: '${oldValue}'`,
201
+ `id: '${newValue}'`
198
202
  );
203
+ await writeFile(configPath, updatedConfig, 'utf-8');
199
204
  }
200
205
 
201
206
  export async function catchIncorrectSettings(
202
207
  settings: ProjectSettings,
203
208
  options: PushOptions
204
209
  ) {
205
- let override = !settings.project;
206
- if (settings.project && settings.project !== options.project) {
207
- if (typeof process.env.TEST_OVERRIDE != null) {
210
+ let override = !settings.id;
211
+ if (settings.id && settings.id !== options.id) {
212
+ if (process.env.TEST_OVERRIDE != null) {
208
213
  override = Boolean(process.env.TEST_OVERRIDE);
209
214
  } else {
210
215
  // Add an extra line to make it easier to read the prompt
@@ -212,7 +217,7 @@ export async function catchIncorrectSettings(
212
217
  ({ override } = await prompt<{ override: boolean }>({
213
218
  type: 'confirm',
214
219
  name: 'override',
215
- message: `Monitors were pushed under the '${settings.project}' project. Are you sure you want to push them under the new '${options.project}' (note that this will duplicate the monitors, the old ones being orphaned)`,
220
+ message: `Monitors were pushed under the '${settings.id}' project. Are you sure you want to push them under the new '${options.id}' (note that this will duplicate the monitors, the old ones being orphaned)`,
216
221
  initial: false,
217
222
  }));
218
223
  }
@@ -221,6 +226,6 @@ export async function catchIncorrectSettings(
221
226
  }
222
227
  }
223
228
  if (override) {
224
- await overrideSettings(options.project);
229
+ await overrideSettings(settings.id, options.id);
225
230
  }
226
231
  }
@@ -81,7 +81,7 @@ export async function createMonitors(
81
81
  keepStale: boolean
82
82
  ) {
83
83
  const schema: APISchema = {
84
- project: options.project,
84
+ project: options.id,
85
85
  keep_stale: keepStale,
86
86
  monitors,
87
87
  };
@@ -23,14 +23,17 @@
23
23
  *
24
24
  */
25
25
 
26
- import path from 'path';
26
+ import { isAbsolute, dirname, extname, join } from 'path';
27
27
  import fs from 'fs/promises';
28
28
  import * as esbuild from 'esbuild';
29
29
 
30
+ const SOURCE_DIR = join(__dirname, '..', '..');
31
+ const SOURCE_NODE_MODULES = join(SOURCE_DIR, 'node_modules');
32
+
30
33
  export function commonOptions(): esbuild.BuildOptions {
31
34
  return {
32
35
  bundle: true,
33
- external: ['node_modules', '@elastic/synthetics'],
36
+ external: ['@elastic/synthetics'],
34
37
  minify: false,
35
38
  platform: 'node',
36
39
  logLevel: 'silent',
@@ -55,27 +58,49 @@ export function MultiAssetPlugin(callback: PluginCallback): esbuild.Plugin {
55
58
  // Note that we use `isAbsolute` to handle UNC/windows style paths like C:\path\to\thing
56
59
  // This is not necessary for relative directories since `.\file` is not supported as an import
57
60
  // nor is `~/path/to/file`.
58
- if (path.isAbsolute(str) || str.startsWith('./') || str.startsWith('../')) {
61
+ if (isAbsolute(str) || str.startsWith('./') || str.startsWith('../')) {
59
62
  return true;
60
63
  }
61
64
  return false;
62
65
  };
63
66
 
67
+ // If we're importing the @elastic/synthetics package
68
+ // directly from source instead of using the fully
69
+ // qualified name, we must skip it too. That's just
70
+ // so it doesn't get bundled on tests or when we locally
71
+ // refer to the package itself.
72
+ const isLocalSynthetics = (entryPath: string) => {
73
+ return entryPath.startsWith(SOURCE_DIR);
74
+ };
75
+
76
+ // When importing the local synthetics module directly
77
+ // it may import its own local dependencies, so we must
78
+ // make sure those will be resolved using Node's resolution
79
+ // algorithm, as they're still "node_modules" that we must bundle
80
+ const isLocalSyntheticsModule = (str: string) => {
81
+ return str.startsWith(SOURCE_NODE_MODULES);
82
+ };
83
+
64
84
  return {
65
85
  name: 'esbuild-multiasset-plugin',
66
86
  setup(build) {
67
87
  build.onResolve({ filter: /.*?/ }, async args => {
68
88
  // External and other packages need be marked external to
69
89
  // be removed from the bundle
70
- if (
71
- build.initialOptions.external?.includes(args.path) ||
72
- !isBare(args.path)
73
- ) {
90
+ if (build.initialOptions.external?.includes(args.path)) {
74
91
  return {
75
92
  external: true,
76
93
  };
77
94
  }
78
95
 
96
+ if (
97
+ !isBare(args.path) ||
98
+ args.importer.includes('/node_modules/') ||
99
+ isLocalSyntheticsModule(args.importer)
100
+ ) {
101
+ return;
102
+ }
103
+
79
104
  if (args.kind === 'entry-point') {
80
105
  return {
81
106
  path: args.path,
@@ -86,8 +111,12 @@ export function MultiAssetPlugin(callback: PluginCallback): esbuild.Plugin {
86
111
  // If the modules are resolved locally, then
87
112
  // use the imported path to get full path
88
113
  const entryPath =
89
- path.join(path.dirname(args.importer), args.path) +
90
- path.extname(args.importer);
114
+ join(dirname(args.importer), args.path) + extname(args.importer);
115
+
116
+ if (isLocalSynthetics(entryPath)) {
117
+ return { external: true };
118
+ }
119
+
91
120
  // Spin off another build to copy over the imported modules without bundling
92
121
  const result = await esbuild.build({
93
122
  ...commonOptions(),
@@ -16,6 +16,14 @@ export default env => {
16
16
  locations: ['{{locations}}'],
17
17
  privateLocations: ['{{privateLocations}}'],
18
18
  },
19
+ /**
20
+ * Project monitors settings
21
+ */
22
+ project: {
23
+ id: '{{id}}',
24
+ url: '{{url}}',
25
+ space: '{{space}}',
26
+ },
19
27
  };
20
28
  if (env !== 'development') {
21
29
  /**