apify-test-tools 0.9.1-beta.5 → 0.9.1-beta.6

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 (49) hide show
  1. package/.github/workflows/on_pull_request.yaml +1 -1
  2. package/CHANGELOG.md +4 -0
  3. package/bin/utils/config/load-config.ts +14 -132
  4. package/bin/utils/config/parser.ts +88 -0
  5. package/bin/utils/config/structures/base.ts +61 -0
  6. package/bin/utils/config/structures/legacy.ts +20 -0
  7. package/dist/bin/utils/config/load-config.d.ts +2 -33
  8. package/dist/bin/utils/config/load-config.d.ts.map +1 -1
  9. package/dist/bin/utils/config/load-config.js +13 -91
  10. package/dist/bin/utils/config/load-config.js.map +1 -1
  11. package/dist/bin/utils/config/parser.d.ts +19 -0
  12. package/dist/bin/utils/config/parser.d.ts.map +1 -0
  13. package/dist/bin/utils/config/parser.js +72 -0
  14. package/dist/bin/utils/config/parser.js.map +1 -0
  15. package/dist/bin/utils/config/structures/base.d.ts +35 -0
  16. package/dist/bin/utils/config/structures/base.d.ts.map +1 -0
  17. package/dist/bin/utils/config/structures/base.js +40 -0
  18. package/dist/bin/utils/config/structures/base.js.map +1 -0
  19. package/dist/bin/utils/config/structures/legacy.d.ts +6 -0
  20. package/dist/bin/utils/config/structures/legacy.d.ts.map +1 -0
  21. package/dist/bin/utils/config/structures/legacy.js +14 -0
  22. package/dist/bin/utils/config/structures/legacy.js.map +1 -0
  23. package/dist/test/unit/bin/utils/config/load-config.test.d.ts +2 -0
  24. package/dist/test/unit/bin/utils/config/load-config.test.d.ts.map +1 -0
  25. package/dist/test/unit/bin/utils/config/load-config.test.js +138 -0
  26. package/dist/test/unit/bin/utils/config/load-config.test.js.map +1 -0
  27. package/dist/test/unit/bin/utils/config/parser.test.d.ts +2 -0
  28. package/dist/test/unit/bin/utils/config/parser.test.d.ts.map +1 -0
  29. package/dist/test/unit/bin/utils/config/parser.test.js +111 -0
  30. package/dist/test/unit/bin/utils/config/parser.test.js.map +1 -0
  31. package/dist/test/unit/bin/utils/config/structures/base.test.d.ts +2 -0
  32. package/dist/test/unit/bin/utils/config/structures/base.test.d.ts.map +1 -0
  33. package/dist/test/unit/bin/utils/config/structures/base.test.js +74 -0
  34. package/dist/test/unit/bin/utils/config/structures/base.test.js.map +1 -0
  35. package/dist/test/unit/bin/utils/config/structures/legacy.test.d.ts +2 -0
  36. package/dist/test/unit/bin/utils/config/structures/legacy.test.d.ts.map +1 -0
  37. package/dist/test/unit/bin/utils/config/structures/legacy.test.js +63 -0
  38. package/dist/test/unit/bin/utils/config/structures/legacy.test.js.map +1 -0
  39. package/dist/tsconfig.tsbuildinfo +1 -1
  40. package/package.json +1 -1
  41. package/test/unit/bin/utils/config/load-config.test.ts +179 -0
  42. package/test/unit/bin/utils/config/parser.test.ts +137 -0
  43. package/test/unit/bin/utils/config/structures/base.test.ts +83 -0
  44. package/test/unit/bin/utils/config/structures/legacy.test.ts +78 -0
  45. package/dist/test/unit/bin/utils/actor-config.test.d.ts +0 -2
  46. package/dist/test/unit/bin/utils/actor-config.test.d.ts.map +0 -1
  47. package/dist/test/unit/bin/utils/actor-config.test.js +0 -396
  48. package/dist/test/unit/bin/utils/actor-config.test.js.map +0 -1
  49. package/test/unit/bin/utils/actor-config.test.ts +0 -481
@@ -12,7 +12,7 @@ jobs:
12
12
  name: PR title check
13
13
  runs-on: ubuntu-latest
14
14
  steps:
15
- - uses: apify/actions/pr-title-check@v1.3.0
15
+ - uses: apify/actions/pr-title-check@v1.6.1
16
16
 
17
17
  code_checks:
18
18
  name: Code checks
package/CHANGELOG.md CHANGED
@@ -5,6 +5,10 @@ All notable changes to this project will be documented in this file.
5
5
  <!-- git-cliff-unreleased-start -->
6
6
  ## 0.9.1 - **not yet released**
7
7
 
8
+ ### 🚀 Features
9
+
10
+ - **config/modes:** Lay groundwork for multiple configuration structures ([#142](https://github.com/apify/apify-test-tools/pull/142)) ([7e18638](https://github.com/apify/apify-test-tools/commit/7e18638a8d3523154dbe819312c2b16b54c548ff)) by [@JuanGalilea](https://github.com/JuanGalilea)
11
+
8
12
  ### 🐛 Bug Fixes
9
13
 
10
14
  - Apply default actor timeout to runs ([#134](https://github.com/apify/apify-test-tools/pull/134)) ([82f5f7d](https://github.com/apify/apify-test-tools/commit/82f5f7d4de990db7ad8edf940c19ffd6b20bad13)) by [@Patai5](https://github.com/Patai5)
@@ -1,61 +1,23 @@
1
1
  import path from 'node:path';
2
2
 
3
- import { z } from 'zod';
4
-
5
3
  import { selectActors } from '../../actor-filtering.js';
6
4
  import { isPathWithinScope } from '../../path-utils.js';
7
5
  import type { ActorConfig } from '../../types.js';
8
6
  import { safeReadJsonObjectFile } from '../json-file.js';
7
+ import { parseConfigFile } from './parser.js';
8
+ import type { ResolvedActorConfig } from './structures/base.js';
9
9
 
10
10
  export const CONFIG_FILE_NAME = 'apify-test-tools.config.json';
11
11
 
12
- // Reading the config happens in four stages, each one swappable on its own:
12
+ // Reading the config happens in three stages, each one swappable on its own:
13
13
  //
14
14
  // 1. file -> plain object (safeReadJsonObjectFile)
15
- // 2. plain object -> ActorConfigFile (parseConfigFile — the schema, swap point for new flavours)
16
- // 3. ActorConfigFile -> ResolvedActorConfig[] (resolveRawConfig — one normalized shape for everyone)
17
- // 4. ResolvedActorConfig -> ActorConfig (loadActorConfig — merges in .actor/actor.json)
18
- //
19
- // Stages 1-3 are the "what did the user write" half and stage 4 the "what does the repo look like"
20
- // half. A differently shaped config file only has to reach stage 3's output to work with the rest
21
- // of the tool.
22
-
23
- // #region schema (soon to be moved)
24
-
25
- const ACTOR_ENTRY_SCHEMA = z.object({
26
- folder: z.string(),
27
- // "owner/name", with neither half empty — deliberately permissive about what characters those
28
- // halves may contain, the platform is the authority on that.
29
- actorFullName: z.string().regex(/^[^/]+\/[^/]+$/),
30
- tokenEnvVar: z.string(),
31
- overrideActorContext: z.array(z.string()).optional(),
32
- });
33
-
34
- const CONFIG_FILE_SCHEMA = z.object({
35
- actors: z.array(ACTOR_ENTRY_SCHEMA),
36
- });
37
-
38
- export type ActorConfigFile = z.infer<typeof CONFIG_FILE_SCHEMA>;
39
-
40
- /**
41
- * The single shape stage 4 understands: an actor entry whose paths have been normalized, with no
42
- * trace left of which config flavour produced it. Whatever replaces or extends
43
- * {@link parseConfigFile} and {@link resolveRawConfig} only has to produce this.
44
- */
45
- export interface ResolvedActorConfig {
46
- actorFullName: string;
47
- folder: string;
48
- tokenEnvVar: string;
49
- overrideActorContext?: string[];
50
- }
51
-
52
- // #endregion
15
+ // 2. plain object -> ResolvedActorConfig[] (parseConfigFile — picks a strategy, validates
16
+ // and normalizes; see ./parser.ts)
17
+ // 3. ResolvedActorConfig -> ActorConfig (loadActorConfig — merges in .actor/actor.json)
53
18
 
54
19
  // #region utils
55
20
 
56
- // Strips a trailing slash so config-declared paths ("actors/shopify/" vs "actors/shopify") compare equal.
57
- const stripTrailingSlash = (pathValue: string): string => pathValue.replace(/\/+$/, '');
58
-
59
21
  const findOverlappingContextPaths = (contextPaths: string[]): [string, string] | undefined => {
60
22
  for (let i = 0; i < contextPaths.length; i++) {
61
23
  for (let j = i + 1; j < contextPaths.length; j++) {
@@ -70,41 +32,9 @@ const findOverlappingContextPaths = (contextPaths: string[]): [string, string] |
70
32
  return undefined;
71
33
  };
72
34
 
73
- type ConfigParsingIssue = z.ZodError<ActorConfigFile>['issues'][number];
74
-
75
- // Restates a schema violation in the wording this config file has always used, so error output
76
- // stays recognizable now that the hand-rolled checks are gone.
77
- const describeIssue = (issue: ConfigParsingIssue, rawActors: unknown[]): string => {
78
- const [, index, field] = issue.path;
79
-
80
- if (typeof index !== 'number') {
81
- return `Config file "${CONFIG_FILE_NAME}" must have an "actors" array at the top level.`;
82
- }
83
-
84
- const folder = (rawActors[index] as { folder?: unknown } | undefined)?.folder;
85
-
86
- switch (field) {
87
- case 'folder':
88
- return (
89
- `Invalid "folder" for actor entry at index ${index} in "${CONFIG_FILE_NAME}". ` +
90
- `Must be a string (use "." for a single-actor repo).`
91
- );
92
- case 'actorFullName':
93
- return (
94
- `Invalid "actorFullName" for folder "${folder}" in "${CONFIG_FILE_NAME}". ` +
95
- `Must be in "owner/name" format (e.g. "apify/web-scraper").`
96
- );
97
- case 'tokenEnvVar':
98
- return `Invalid "tokenEnvVar" for folder "${folder}" in "${CONFIG_FILE_NAME}". Must be a string.`;
99
- case 'overrideActorContext':
100
- return (
101
- `Invalid "overrideActorContext" for folder "${folder}" in "${CONFIG_FILE_NAME}". ` +
102
- `Must be an array of strings.`
103
- );
104
- default:
105
- return `Invalid actor entry at index ${index} in "${CONFIG_FILE_NAME}": ${issue.message}`;
106
- }
107
- };
35
+ // The repo root is spelled "" internally but "." in a config file, so report it the way a reader
36
+ // would have written it.
37
+ const displayFolder = (folder: string): string => folder || '.';
108
38
 
109
39
  // #endregion
110
40
 
@@ -133,52 +63,7 @@ const readConfigFileContents = async (): Promise<Record<string, unknown>> => {
133
63
  };
134
64
 
135
65
  /**
136
- * Stage 2validates the file's shape. Every problem is reported at once rather than only the
137
- * first one to fail.
138
- */
139
- export const parseConfigFile = (contents: Record<string, unknown>): ActorConfigFile => {
140
- const parsed = CONFIG_FILE_SCHEMA.safeParse(contents);
141
- if (parsed.success) {
142
- return parsed.data;
143
- }
144
-
145
- const rawActors = Array.isArray(contents.actors) ? contents.actors : [];
146
- const messages = new Set(parsed.error.issues.map((issue) => describeIssue(issue, rawActors)));
147
- throw new Error([...messages].join('\n'));
148
- };
149
-
150
- /**
151
- * Stage 3 — normalizes the paths the user wrote and rejects entries that collide once normalized.
152
- * The repo root is "" from here on, however it was spelled in the file.
153
- */
154
- export const resolveRawConfig = (config: ActorConfigFile): ResolvedActorConfig[] => {
155
- const seenFolders = new Set<string>();
156
-
157
- return config.actors.map((entry) => {
158
- const folder = entry.folder === '.' ? '' : stripTrailingSlash(entry.folder);
159
-
160
- if (seenFolders.has(folder)) {
161
- throw new Error(
162
- `Duplicate folder "${entry.folder}" in "${CONFIG_FILE_NAME}". Each actor must have a unique folder.`,
163
- );
164
- }
165
- seenFolders.add(folder);
166
-
167
- return {
168
- actorFullName: entry.actorFullName,
169
- folder,
170
- tokenEnvVar: entry.tokenEnvVar,
171
- overrideActorContext: entry.overrideActorContext?.map(stripTrailingSlash),
172
- };
173
- });
174
- };
175
-
176
- // The repo root is spelled "" internally but "." in a config file, so report it the way a reader
177
- // would have written it.
178
- const displayFolder = (folder: string): string => folder || '.';
179
-
180
- /**
181
- * Stage 4 — resolves one normalized entry against the repo, reading the actor's `.actor/actor.json`
66
+ * Stage 3resolves one normalized entry against the repo, reading the actor's `.actor/actor.json`
182
67
  * for its `dockerContextDir` and deciding which paths count as the actor's context.
183
68
  */
184
69
  export const loadActorConfig = (entry: ResolvedActorConfig): ActorConfig => {
@@ -235,16 +120,13 @@ export const loadActorConfig = (entry: ResolvedActorConfig): ActorConfig => {
235
120
  // #endregion
236
121
 
237
122
  export const readConfigFile = async (selection: { actors: string[]; ignore: string[] }): Promise<ActorConfig[]> => {
238
- const rawConfig = await readConfigFileContents();
239
-
240
- // replace this when enabling different file structures
241
- // some kind of strategy pattern seems appropriate here
242
- const resolvedConfigs = resolveRawConfig(parseConfigFile(rawConfig));
123
+ const rawFileContents = await readConfigFileContents();
124
+ const parsedConfigs = parseConfigFile(rawFileContents);
243
125
 
244
126
  const actorConfigs: ActorConfig[] = [];
245
- for (const resolved of resolvedConfigs) {
127
+ for (const parsed of parsedConfigs) {
246
128
  // Sequential on purpose: the first actor with a problem should be the one reported.
247
- actorConfigs.push(loadActorConfig(resolved));
129
+ actorConfigs.push(loadActorConfig(parsed));
248
130
  }
249
131
 
250
132
  return selectActors(selection, actorConfigs);
@@ -0,0 +1,88 @@
1
+ import z from 'zod';
2
+
3
+ import { CONFIG_FILE_STRATEGY, type ResolvedActorConfig, type StrategyParser } from './structures/base.js';
4
+ import { LEGACY_PARSER } from './structures/legacy.js';
5
+
6
+ const CONFIG_FILE_STRATEGIES: {
7
+ // instead of Record, we do this to ensure that the modes match
8
+ [key in CONFIG_FILE_STRATEGY]: StrategyParser & { mode: key };
9
+ } = {
10
+ [CONFIG_FILE_STRATEGY.LEGACY]: LEGACY_PARSER,
11
+ } as const;
12
+
13
+ const ModeSelectionSchema = z.enum(CONFIG_FILE_STRATEGY).default(CONFIG_FILE_STRATEGY.LEGACY);
14
+
15
+ function selectStrategy(mode: unknown): StrategyParser {
16
+ const parsed = ModeSelectionSchema.safeParse(mode);
17
+ if (!parsed.success) {
18
+ throw new Error(z.prettifyError(parsed.error));
19
+ }
20
+
21
+ return CONFIG_FILE_STRATEGIES[parsed.data];
22
+ }
23
+
24
+ // Strips a trailing slash so config-declared paths ("actors/shopify/" vs "actors/shopify") compare equal.
25
+ const stripTrailingSlash = (pathValue: string): string => pathValue.replace(/\/+$/, '');
26
+
27
+ // The repo root may be written as ".", "./", "/" or ""; everything downstream spells it "".
28
+ const normalizeFolder = (folder: string): string => {
29
+ const stripped = stripTrailingSlash(folder);
30
+ return stripped === '.' ? '' : stripped;
31
+ };
32
+
33
+ /**
34
+ * Normalizes the paths the user wrote and checks the cross-entry invariants a per-entry schema
35
+ * cannot: that no two actors claim the same folder once normalized, nor the same actor on the
36
+ * platform. Collects every violation before throwing, so one run reports all of them rather than
37
+ * only the first.
38
+ *
39
+ * @returns the actors it vouched for, with their paths normalized.
40
+ * @throws Error listing every problem found.
41
+ */
42
+ function verifyConfiguration(body: ResolvedActorConfig[]): ResolvedActorConfig[] {
43
+ const seenFolders = new Set<string>();
44
+ const seenActorFullNames = new Set<string>();
45
+ const errors: string[] = [];
46
+
47
+ const normalized = body.map((entry) => ({
48
+ ...entry,
49
+ folder: normalizeFolder(entry.folder),
50
+ overrideActorContext: entry.overrideActorContext?.map(stripTrailingSlash),
51
+ }));
52
+
53
+ for (const [index, entry] of normalized.entries()) {
54
+ // TODO: drop folder uniqueness (this requires several changes on other places)
55
+ if (seenFolders.has(entry.folder)) {
56
+ errors.push(`Duplicate folder "${body[index].folder}". Each actor must have a unique folder.`);
57
+ } else {
58
+ seenFolders.add(entry.folder);
59
+ }
60
+
61
+ if (seenActorFullNames.has(entry.actorFullName)) {
62
+ errors.push(`Duplicate actor "${entry.actorFullName}". Each entry must point at a different actor.`);
63
+ } else {
64
+ seenActorFullNames.add(entry.actorFullName);
65
+ }
66
+ }
67
+
68
+ if (errors.length > 0) {
69
+ throw new Error(errors.join('\n'));
70
+ }
71
+
72
+ return normalized;
73
+ }
74
+
75
+ // eslint-disable-next-line no-underscore-dangle
76
+ export const _privates = {
77
+ selectStrategy,
78
+ verifyConfiguration,
79
+ };
80
+
81
+ export function parseConfigFile(body: Record<string, unknown>): ResolvedActorConfig[] {
82
+ const { mode, ...rest } = body;
83
+ const strategy = selectStrategy(mode);
84
+
85
+ const resolved = strategy.parse(rest);
86
+ const validated = verifyConfiguration(resolved);
87
+ return validated;
88
+ }
@@ -0,0 +1,61 @@
1
+ import { prettifyError, type ZodType } from 'zod';
2
+
3
+ import { ACTOR_NAME, USERNAME } from '@apify/consts';
4
+
5
+ function stripRegexAnchor(regex: string): string {
6
+ return regex.replace(/^\^/, '').replace(/\$$/, '');
7
+ }
8
+
9
+ export const ACTOR_FULL_NAME_REGEX = new RegExp(
10
+ `^${stripRegexAnchor(USERNAME.REGEX.source)}/${stripRegexAnchor(ACTOR_NAME.REGEX.source)}$`,
11
+ USERNAME.REGEX.flags + ACTOR_NAME.REGEX.flags,
12
+ );
13
+
14
+ export interface ResolvedActorConfig {
15
+ actorFullName: string;
16
+ folder: string;
17
+ tokenEnvVar: string;
18
+ overrideActorContext?: string[];
19
+ }
20
+
21
+ export enum CONFIG_FILE_STRATEGY {
22
+ LEGACY = 'legacy',
23
+ }
24
+
25
+ export type StrategyParser = {
26
+ mode: CONFIG_FILE_STRATEGY;
27
+ parse: (body: Record<string, unknown>) => ResolvedActorConfig[];
28
+ };
29
+
30
+ export function defineStrategy<T extends Record<string, unknown>, Mode extends CONFIG_FILE_STRATEGY>(
31
+ // mode is transparent so it can be validated with & { mode: Mode }
32
+ mode: Mode,
33
+ schema: ZodType<T>,
34
+ resolve: (body: T) => ResolvedActorConfig[],
35
+ ) {
36
+ return {
37
+ mode,
38
+ /**
39
+ *
40
+ * @param body raw config file to be read
41
+ * @returns ResolvedActorConfig[] if the config file is valid, otherwise throws an error with a description of the issues.
42
+ * @throws Error if the config file is invalid.
43
+ * @example
44
+ * ```ts
45
+ * const strategy = defineStrategy(CONFIG_FILE_STRATEGY.LEGACY, schema, resolve);
46
+ * const resolvedActors = strategy.parse(configFileContents);
47
+ * ```
48
+ *
49
+ * This function is used to parse the config file according to the strategy defined by the user.
50
+ * It uses the schema defined in the strategy to validate the config file and resolve it into a list of ResolvedActorConfig.
51
+ * If the config file is invalid, it throws an error with a description of the issues.
52
+ */
53
+ parse: (body: Record<string, unknown>) => {
54
+ const parsed = schema.safeParse(body);
55
+ if (parsed.success) {
56
+ return resolve(parsed.data);
57
+ }
58
+ throw new Error(prettifyError(parsed.error));
59
+ },
60
+ };
61
+ }
@@ -0,0 +1,20 @@
1
+ import z from 'zod';
2
+
3
+ import { ACTOR_FULL_NAME_REGEX, CONFIG_FILE_STRATEGY, defineStrategy } from './base.js';
4
+
5
+ const schema = z.object({
6
+ actors: z
7
+ .array(
8
+ z.object({
9
+ folder: z.string(),
10
+ actorFullName: z.string().regex(ACTOR_FULL_NAME_REGEX),
11
+ tokenEnvVar: z.string(),
12
+ overrideActorContext: z.array(z.string()).optional(),
13
+ }),
14
+ )
15
+ .min(1),
16
+ });
17
+
18
+ type LegacyConfig = z.infer<typeof schema>;
19
+
20
+ export const LEGACY_PARSER = defineStrategy(CONFIG_FILE_STRATEGY.LEGACY, schema, (body: LegacyConfig) => body.actors);
@@ -1,38 +1,8 @@
1
- import { z } from 'zod';
2
1
  import type { ActorConfig } from '../../types.js';
2
+ import type { ResolvedActorConfig } from './structures/base.js';
3
3
  export declare const CONFIG_FILE_NAME = "apify-test-tools.config.json";
4
- declare const CONFIG_FILE_SCHEMA: z.ZodObject<{
5
- actors: z.ZodArray<z.ZodObject<{
6
- folder: z.ZodString;
7
- actorFullName: z.ZodString;
8
- tokenEnvVar: z.ZodString;
9
- overrideActorContext: z.ZodOptional<z.ZodArray<z.ZodString>>;
10
- }, z.core.$strip>>;
11
- }, z.core.$strip>;
12
- export type ActorConfigFile = z.infer<typeof CONFIG_FILE_SCHEMA>;
13
4
  /**
14
- * The single shape stage 4 understands: an actor entry whose paths have been normalized, with no
15
- * trace left of which config flavour produced it. Whatever replaces or extends
16
- * {@link parseConfigFile} and {@link resolveRawConfig} only has to produce this.
17
- */
18
- export interface ResolvedActorConfig {
19
- actorFullName: string;
20
- folder: string;
21
- tokenEnvVar: string;
22
- overrideActorContext?: string[];
23
- }
24
- /**
25
- * Stage 2 — validates the file's shape. Every problem is reported at once rather than only the
26
- * first one to fail.
27
- */
28
- export declare const parseConfigFile: (contents: Record<string, unknown>) => ActorConfigFile;
29
- /**
30
- * Stage 3 — normalizes the paths the user wrote and rejects entries that collide once normalized.
31
- * The repo root is "" from here on, however it was spelled in the file.
32
- */
33
- export declare const resolveRawConfig: (config: ActorConfigFile) => ResolvedActorConfig[];
34
- /**
35
- * Stage 4 — resolves one normalized entry against the repo, reading the actor's `.actor/actor.json`
5
+ * Stage 3 resolves one normalized entry against the repo, reading the actor's `.actor/actor.json`
36
6
  * for its `dockerContextDir` and deciding which paths count as the actor's context.
37
7
  */
38
8
  export declare const loadActorConfig: (entry: ResolvedActorConfig) => ActorConfig;
@@ -40,5 +10,4 @@ export declare const readConfigFile: (selection: {
40
10
  actors: string[];
41
11
  ignore: string[];
42
12
  }) => Promise<ActorConfig[]>;
43
- export {};
44
13
  //# sourceMappingURL=load-config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"load-config.d.ts","sourceRoot":"","sources":["../../../../bin/utils/config/load-config.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlD,eAAO,MAAM,gBAAgB,iCAAiC,CAAC;AAwB/D,QAAA,MAAM,kBAAkB;;;;;;;iBAEtB,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAEjE;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;IACpB,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;CACnC;AAqFD;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,eASnE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,QAAQ,eAAe,KAAG,mBAAmB,EAoB7E,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,mBAAmB,KAAG,WAiD5D,CAAC;AAIF,eAAO,MAAM,cAAc,GAAU,WAAW;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,KAAG,OAAO,CAAC,WAAW,EAAE,CAc7G,CAAC"}
1
+ {"version":3,"file":"load-config.d.ts","sourceRoot":"","sources":["../../../../bin/utils/config/load-config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAEhE,eAAO,MAAM,gBAAgB,iCAAiC,CAAC;AAuD/D;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAI,OAAO,mBAAmB,KAAG,WAiD5D,CAAC;AAIF,eAAO,MAAM,cAAc,GAAU,WAAW;IAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,KAAG,OAAO,CAAC,WAAW,EAAE,CAW7G,CAAC"}
@@ -1,35 +1,16 @@
1
1
  import path from 'node:path';
2
- import { z } from 'zod';
3
2
  import { selectActors } from '../../actor-filtering.js';
4
3
  import { isPathWithinScope } from '../../path-utils.js';
5
4
  import { safeReadJsonObjectFile } from '../json-file.js';
5
+ import { parseConfigFile } from './parser.js';
6
6
  export const CONFIG_FILE_NAME = 'apify-test-tools.config.json';
7
- // Reading the config happens in four stages, each one swappable on its own:
7
+ // Reading the config happens in three stages, each one swappable on its own:
8
8
  //
9
9
  // 1. file -> plain object (safeReadJsonObjectFile)
10
- // 2. plain object -> ActorConfigFile (parseConfigFile — the schema, swap point for new flavours)
11
- // 3. ActorConfigFile -> ResolvedActorConfig[] (resolveRawConfig — one normalized shape for everyone)
12
- // 4. ResolvedActorConfig -> ActorConfig (loadActorConfig — merges in .actor/actor.json)
13
- //
14
- // Stages 1-3 are the "what did the user write" half and stage 4 the "what does the repo look like"
15
- // half. A differently shaped config file only has to reach stage 3's output to work with the rest
16
- // of the tool.
17
- // #region schema (soon to be moved)
18
- const ACTOR_ENTRY_SCHEMA = z.object({
19
- folder: z.string(),
20
- // "owner/name", with neither half empty — deliberately permissive about what characters those
21
- // halves may contain, the platform is the authority on that.
22
- actorFullName: z.string().regex(/^[^/]+\/[^/]+$/),
23
- tokenEnvVar: z.string(),
24
- overrideActorContext: z.array(z.string()).optional(),
25
- });
26
- const CONFIG_FILE_SCHEMA = z.object({
27
- actors: z.array(ACTOR_ENTRY_SCHEMA),
28
- });
29
- // #endregion
10
+ // 2. plain object -> ResolvedActorConfig[] (parseConfigFile — picks a strategy, validates
11
+ // and normalizes; see ./parser.ts)
12
+ // 3. ResolvedActorConfig -> ActorConfig (loadActorConfig — merges in .actor/actor.json)
30
13
  // #region utils
31
- // Strips a trailing slash so config-declared paths ("actors/shopify/" vs "actors/shopify") compare equal.
32
- const stripTrailingSlash = (pathValue) => pathValue.replace(/\/+$/, '');
33
14
  const findOverlappingContextPaths = (contextPaths) => {
34
15
  for (let i = 0; i < contextPaths.length; i++) {
35
16
  for (let j = i + 1; j < contextPaths.length; j++) {
@@ -41,30 +22,9 @@ const findOverlappingContextPaths = (contextPaths) => {
41
22
  }
42
23
  return undefined;
43
24
  };
44
- // Restates a schema violation in the wording this config file has always used, so error output
45
- // stays recognizable now that the hand-rolled checks are gone.
46
- const describeIssue = (issue, rawActors) => {
47
- const [, index, field] = issue.path;
48
- if (typeof index !== 'number') {
49
- return `Config file "${CONFIG_FILE_NAME}" must have an "actors" array at the top level.`;
50
- }
51
- const folder = rawActors[index]?.folder;
52
- switch (field) {
53
- case 'folder':
54
- return (`Invalid "folder" for actor entry at index ${index} in "${CONFIG_FILE_NAME}". ` +
55
- `Must be a string (use "." for a single-actor repo).`);
56
- case 'actorFullName':
57
- return (`Invalid "actorFullName" for folder "${folder}" in "${CONFIG_FILE_NAME}". ` +
58
- `Must be in "owner/name" format (e.g. "apify/web-scraper").`);
59
- case 'tokenEnvVar':
60
- return `Invalid "tokenEnvVar" for folder "${folder}" in "${CONFIG_FILE_NAME}". Must be a string.`;
61
- case 'overrideActorContext':
62
- return (`Invalid "overrideActorContext" for folder "${folder}" in "${CONFIG_FILE_NAME}". ` +
63
- `Must be an array of strings.`);
64
- default:
65
- return `Invalid actor entry at index ${index} in "${CONFIG_FILE_NAME}": ${issue.message}`;
66
- }
67
- };
25
+ // The repo root is spelled "" internally but "." in a config file, so report it the way a reader
26
+ // would have written it.
27
+ const displayFolder = (folder) => folder || '.';
68
28
  // #endregion
69
29
  // #region stages
70
30
  /** Stage 1 — the config file as a plain object, or a failure phrased for whoever wrote it. */
@@ -86,43 +46,7 @@ const readConfigFileContents = async () => {
86
46
  }
87
47
  };
88
48
  /**
89
- * Stage 2validates the file's shape. Every problem is reported at once rather than only the
90
- * first one to fail.
91
- */
92
- export const parseConfigFile = (contents) => {
93
- const parsed = CONFIG_FILE_SCHEMA.safeParse(contents);
94
- if (parsed.success) {
95
- return parsed.data;
96
- }
97
- const rawActors = Array.isArray(contents.actors) ? contents.actors : [];
98
- const messages = new Set(parsed.error.issues.map((issue) => describeIssue(issue, rawActors)));
99
- throw new Error([...messages].join('\n'));
100
- };
101
- /**
102
- * Stage 3 — normalizes the paths the user wrote and rejects entries that collide once normalized.
103
- * The repo root is "" from here on, however it was spelled in the file.
104
- */
105
- export const resolveRawConfig = (config) => {
106
- const seenFolders = new Set();
107
- return config.actors.map((entry) => {
108
- const folder = entry.folder === '.' ? '' : stripTrailingSlash(entry.folder);
109
- if (seenFolders.has(folder)) {
110
- throw new Error(`Duplicate folder "${entry.folder}" in "${CONFIG_FILE_NAME}". Each actor must have a unique folder.`);
111
- }
112
- seenFolders.add(folder);
113
- return {
114
- actorFullName: entry.actorFullName,
115
- folder,
116
- tokenEnvVar: entry.tokenEnvVar,
117
- overrideActorContext: entry.overrideActorContext?.map(stripTrailingSlash),
118
- };
119
- });
120
- };
121
- // The repo root is spelled "" internally but "." in a config file, so report it the way a reader
122
- // would have written it.
123
- const displayFolder = (folder) => folder || '.';
124
- /**
125
- * Stage 4 — resolves one normalized entry against the repo, reading the actor's `.actor/actor.json`
49
+ * Stage 3resolves one normalized entry against the repo, reading the actor's `.actor/actor.json`
126
50
  * for its `dockerContextDir` and deciding which paths count as the actor's context.
127
51
  */
128
52
  export const loadActorConfig = (entry) => {
@@ -163,14 +87,12 @@ export const loadActorConfig = (entry) => {
163
87
  };
164
88
  // #endregion
165
89
  export const readConfigFile = async (selection) => {
166
- const rawConfig = await readConfigFileContents();
167
- // replace this when enabling different file structures
168
- // some kind of strategy pattern seems appropriate here
169
- const resolvedConfigs = resolveRawConfig(parseConfigFile(rawConfig));
90
+ const rawFileContents = await readConfigFileContents();
91
+ const parsedConfigs = parseConfigFile(rawFileContents);
170
92
  const actorConfigs = [];
171
- for (const resolved of resolvedConfigs) {
93
+ for (const parsed of parsedConfigs) {
172
94
  // Sequential on purpose: the first actor with a problem should be the one reported.
173
- actorConfigs.push(loadActorConfig(resolved));
95
+ actorConfigs.push(loadActorConfig(parsed));
174
96
  }
175
97
  return selectActors(selection, actorConfigs);
176
98
  };
@@ -1 +1 @@
1
- {"version":3,"file":"load-config.js","sourceRoot":"","sources":["../../../../bin/utils/config/load-config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"load-config.js","sourceRoot":"","sources":["../../../../bin/utils/config/load-config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ import { type ResolvedActorConfig, type StrategyParser } from './structures/base.js';
2
+ declare function selectStrategy(mode: unknown): StrategyParser;
3
+ /**
4
+ * Normalizes the paths the user wrote and checks the cross-entry invariants a per-entry schema
5
+ * cannot: that no two actors claim the same folder once normalized, nor the same actor on the
6
+ * platform. Collects every violation before throwing, so one run reports all of them rather than
7
+ * only the first.
8
+ *
9
+ * @returns the actors it vouched for, with their paths normalized.
10
+ * @throws Error listing every problem found.
11
+ */
12
+ declare function verifyConfiguration(body: ResolvedActorConfig[]): ResolvedActorConfig[];
13
+ export declare const _privates: {
14
+ selectStrategy: typeof selectStrategy;
15
+ verifyConfiguration: typeof verifyConfiguration;
16
+ };
17
+ export declare function parseConfigFile(body: Record<string, unknown>): ResolvedActorConfig[];
18
+ export {};
19
+ //# sourceMappingURL=parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parser.d.ts","sourceRoot":"","sources":["../../../../bin/utils/config/parser.ts"],"names":[],"mappings":"AAEA,OAAO,EAAwB,KAAK,mBAAmB,EAAE,KAAK,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAY3G,iBAAS,cAAc,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,CAOrD;AAWD;;;;;;;;GAQG;AACH,iBAAS,mBAAmB,CAAC,IAAI,EAAE,mBAAmB,EAAE,GAAG,mBAAmB,EAAE,CA+B/E;AAGD,eAAO,MAAM,SAAS;;;CAGrB,CAAC;AAEF,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,mBAAmB,EAAE,CAOpF"}