@elastic/synthetics 1.0.0-beta.35 → 1.0.0-beta.36

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.
Files changed (44) hide show
  1. package/dist/cli.js +4 -1
  2. package/dist/cli.js.map +1 -1
  3. package/dist/common_types.d.ts +1 -1
  4. package/dist/common_types.d.ts.map +1 -1
  5. package/dist/core/browser-service.d.ts +1 -1
  6. package/dist/core/browser-service.d.ts.map +1 -1
  7. package/dist/dsl/journey.d.ts.map +1 -1
  8. package/dist/dsl/journey.js +1 -0
  9. package/dist/dsl/journey.js.map +1 -1
  10. package/dist/dsl/monitor.d.ts +2 -0
  11. package/dist/dsl/monitor.d.ts.map +1 -1
  12. package/dist/dsl/monitor.js +3 -0
  13. package/dist/dsl/monitor.js.map +1 -1
  14. package/dist/formatter/javascript.d.ts +1 -1
  15. package/dist/formatter/javascript.d.ts.map +1 -1
  16. package/dist/formatter/javascript.js +1 -1
  17. package/dist/formatter/javascript.js.map +1 -1
  18. package/dist/helpers.d.ts +1 -1
  19. package/dist/helpers.d.ts.map +1 -1
  20. package/dist/helpers.js +3 -3
  21. package/dist/helpers.js.map +1 -1
  22. package/dist/plugins/network.js +3 -3
  23. package/dist/plugins/network.js.map +1 -1
  24. package/dist/push/index.js +3 -3
  25. package/dist/push/index.js.map +1 -1
  26. package/dist/push/monitor.d.ts +5 -2
  27. package/dist/push/monitor.d.ts.map +1 -1
  28. package/dist/push/monitor.js +108 -8
  29. package/dist/push/monitor.js.map +1 -1
  30. package/dist/push/plugin.d.ts.map +1 -1
  31. package/dist/push/plugin.js +6 -2
  32. package/dist/push/plugin.js.map +1 -1
  33. package/dist/tsconfig.tsbuildinfo +1 -1
  34. package/package.json +23 -22
  35. package/src/cli.ts +4 -1
  36. package/src/common_types.ts +1 -1
  37. package/src/dsl/journey.ts +1 -0
  38. package/src/dsl/monitor.ts +5 -0
  39. package/src/formatter/javascript.ts +1 -1
  40. package/src/helpers.ts +1 -1
  41. package/src/plugins/network.ts +3 -3
  42. package/src/push/index.ts +4 -4
  43. package/src/push/monitor.ts +132 -11
  44. package/src/push/plugin.ts +6 -2
package/src/push/index.ts CHANGED
@@ -40,7 +40,7 @@ import {
40
40
  apiProgress,
41
41
  write,
42
42
  error,
43
- aborted,
43
+ warn,
44
44
  indent,
45
45
  safeNDJSONParse,
46
46
  done,
@@ -79,7 +79,7 @@ export async function push(monitors: Monitor[], options: PushOptions) {
79
79
  initial: false,
80
80
  });
81
81
  if (!deleteAll) {
82
- throw aborted('Push command Aborted');
82
+ throw warn('Push command Aborted');
83
83
  }
84
84
  }
85
85
  progress(`deleting all stale monitors`);
@@ -207,7 +207,7 @@ async function overrideSettings(oldValue: string, newValue: string) {
207
207
  const cwd = process.cwd();
208
208
  const configPath = await findSyntheticsConfig(cwd, cwd);
209
209
  if (!configPath) {
210
- throw aborted(`Unable to find synthetics config file: ${configPath}`);
210
+ throw warn(`Unable to find synthetics config file: ${configPath}`);
211
211
  }
212
212
  const config = await readFile(configPath, 'utf-8');
213
213
  const updatedConfig = config.replace(
@@ -239,7 +239,7 @@ export async function catchIncorrectSettings(
239
239
  initial: false,
240
240
  }));
241
241
  if (!override) {
242
- throw aborted('Push command Aborted');
242
+ throw warn('Push command Aborted');
243
243
  }
244
244
  }
245
245
  if (override) {
@@ -23,19 +23,27 @@
23
23
  *
24
24
  */
25
25
 
26
- import { mkdir, rm } from 'fs/promises';
26
+ import { mkdir, rm, readFile } from 'fs/promises';
27
27
  import { join } from 'path';
28
+ import { LineCounter, parseDocument, YAMLSeq, YAMLMap } from 'yaml';
29
+ import { bold, red } from 'kleur/colors';
28
30
  import { Bundler } from './bundler';
29
31
  import { sendRequest } from './request';
30
- import { removeTrailingSlash, SYNTHETICS_PATH } from '../helpers';
32
+ import {
33
+ removeTrailingSlash,
34
+ SYNTHETICS_PATH,
35
+ totalist,
36
+ indent,
37
+ warn,
38
+ } from '../helpers';
31
39
  import { LocationsMap } from '../locations/public-locations';
32
40
  import { Monitor, MonitorConfig } from '../dsl/monitor';
33
41
  import { PushOptions } from '../common_types';
34
42
 
35
43
  export type MonitorSchema = Omit<MonitorConfig, 'locations'> & {
36
- content: string;
37
44
  locations: string[];
38
- filter: Monitor['filter'];
45
+ content?: string;
46
+ filter?: Monitor['filter'];
39
47
  };
40
48
 
41
49
  export type APISchema = {
@@ -60,21 +68,134 @@ export async function buildMonitorSchema(monitors: Monitor[]) {
60
68
  const schemas: MonitorSchema[] = [];
61
69
 
62
70
  for (const monitor of monitors) {
63
- const { source, config, filter } = monitor;
64
- const outPath = join(bundlePath, config.name + '.zip');
65
- const content = await bundler.build(source.file, outPath);
66
- schemas.push({
71
+ const { source, config, filter, type } = monitor;
72
+ const schema = {
67
73
  ...config,
68
- content,
69
74
  locations: translateLocation(config.locations),
70
- filter: filter,
71
- });
75
+ };
76
+ if (type === 'browser') {
77
+ const outPath = join(bundlePath, config.name + '.zip');
78
+ const content = await bundler.build(source.file, outPath);
79
+ Object.assign(schema, { content, filter });
80
+ }
81
+ schemas.push(schema);
72
82
  }
73
83
 
74
84
  await rm(bundlePath, { recursive: true });
75
85
  return schemas;
76
86
  }
77
87
 
88
+ export async function createLightweightMonitors(
89
+ workDir: string,
90
+ options: PushOptions
91
+ ) {
92
+ const lwFiles = new Set<string>();
93
+ await totalist(workDir, (rel, abs) => {
94
+ if (/.(yml|yaml)$/.test(rel)) {
95
+ lwFiles.add(abs);
96
+ }
97
+ });
98
+ // Warn users about schedule that are less than 60 seconds
99
+ if (lwFiles.size > 0) {
100
+ warn(
101
+ 'lightweight monitors schedule < 1 minute resolution are not supported, will get reset to their nearest minute interval.'
102
+ );
103
+ }
104
+
105
+ const monitors: Monitor[] = [];
106
+ for (const file of lwFiles.values()) {
107
+ const content = await readFile(file, 'utf-8');
108
+ const lineCounter = new LineCounter();
109
+ const parsedDoc = parseDocument(content, {
110
+ lineCounter,
111
+ keepSourceTokens: true,
112
+ });
113
+ // Skip other yml files that are not relevant
114
+ const monitorSeq = parsedDoc.get('heartbeat.monitors') as YAMLSeq<YAMLMap>;
115
+ if (!monitorSeq) {
116
+ continue;
117
+ }
118
+
119
+ for (const monNode of monitorSeq.items) {
120
+ // Skip browser monitors and disabled monitors from pushing
121
+ if (
122
+ monNode.get('type') === 'browser' ||
123
+ monNode.get('enabled') === false
124
+ ) {
125
+ continue;
126
+ }
127
+ const config = monNode.toJSON();
128
+ const { line, col } = lineCounter.linePos(monNode.srcToken.offset);
129
+ try {
130
+ const mon = buildMonitorFromYaml(config, options);
131
+ mon.setSource({ file, line, column: col });
132
+ monitors.push(mon);
133
+ } catch (e) {
134
+ let outer = bold(`Aborted: ${e}\n`);
135
+ outer += indent(
136
+ `* ${config.id || config.name} - ${file}:${line}:${col}\n`
137
+ );
138
+ throw red(outer);
139
+ }
140
+ }
141
+ }
142
+ return monitors;
143
+ }
144
+
145
+ const REQUIRED_MONITOR_FIELDS = ['id', 'name'];
146
+ export function buildMonitorFromYaml(
147
+ config: MonitorConfig,
148
+ options: PushOptions
149
+ ) {
150
+ // Validate required fields
151
+ for (const field of REQUIRED_MONITOR_FIELDS) {
152
+ if (!config[field]) {
153
+ throw `Monitor ${field} is required`;
154
+ }
155
+ }
156
+ const schedule = config.schedule && parseSchedule(String(config.schedule));
157
+ const privateLocations =
158
+ config['private_locations'] || options.privateLocations;
159
+ delete config['private_locations'];
160
+
161
+ return new Monitor({
162
+ locations: options.locations,
163
+ ...config,
164
+ privateLocations,
165
+ schedule: schedule || options.schedule,
166
+ });
167
+ }
168
+
169
+ export function parseSchedule(schedule: string) {
170
+ const EVERY_SYNTAX = '@every';
171
+ if (!(schedule + '').startsWith(EVERY_SYNTAX)) {
172
+ throw `Monitor schedule format(${schedule}) not supported: use '@every' syntax instead`;
173
+ }
174
+
175
+ const duration = schedule.substring(EVERY_SYNTAX.length + 1);
176
+ // split between non-digit (\D) and a digit (\d)
177
+ const durations = duration.split(/(?<=\D)(?=\d)/g);
178
+ let minutes = 0;
179
+ for (const dur of durations) {
180
+ // split between a digit and non-digit
181
+ const [value, format] = dur.split(/(?<=\d)(?=\D)/g);
182
+ // Calculate based on the duration symbol
183
+ const scheduleValue = parseInt(value, 10);
184
+ switch (format) {
185
+ case 's':
186
+ minutes += Math.ceil(scheduleValue / 60);
187
+ break;
188
+ case 'm':
189
+ minutes += scheduleValue;
190
+ break;
191
+ case 'h':
192
+ minutes += scheduleValue * 60;
193
+ break;
194
+ }
195
+ }
196
+ return minutes;
197
+ }
198
+
78
199
  export async function createMonitors(
79
200
  monitors: MonitorSchema[],
80
201
  options: PushOptions,
@@ -27,8 +27,12 @@ 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');
30
+ // ROOT directory of the Package - /
31
+ const ROOT_DIR = join(__dirname, '..', '..');
32
+ // Source of the package - /src, /dist, etc.
33
+ const SOURCE_DIR = join(__dirname, '..');
34
+ // Node modules directory of the package - /node_modules
35
+ const SOURCE_NODE_MODULES = join(ROOT_DIR, 'node_modules');
32
36
 
33
37
  export function commonOptions(): esbuild.BuildOptions {
34
38
  return {