@postman-enricher/core 1.0.0 → 1.1.0

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.
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Organize enricher - Reorganizes collection by REST resource hierarchy
3
+ */
4
+ import type { PostmanCollection, OrganizeConfig } from '@postman-enricher/shared';
5
+ export declare function organizeByResources(collection: PostmanCollection, config: OrganizeConfig): PostmanCollection;
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Organize enricher - Reorganizes collection by REST resource hierarchy
3
+ */
4
+ import { getUrlPath, isRequest } from '@postman-enricher/shared';
5
+ export function organizeByResources(collection, config) {
6
+ if (!config?.enabled || config.strategy !== 'resources') {
7
+ return collection;
8
+ }
9
+ const excludePathParams = config.excludePathParams ?? true;
10
+ const maxDepth = config.nestingLevel || Infinity;
11
+ const organized = buildResourceHierarchy(collection.item, excludePathParams, maxDepth);
12
+ return {
13
+ ...collection,
14
+ item: organized.length > 0 ? organized : collection.item,
15
+ };
16
+ }
17
+ function buildResourceHierarchy(items, excludePathParams, maxDepth) {
18
+ const folderMap = new Map();
19
+ items.forEach((item) => {
20
+ if (!isRequest(item) || !item.request?.url)
21
+ return;
22
+ const path = getUrlPath(item.request.url);
23
+ const segments = extractSegments(path, excludePathParams).slice(0, maxDepth);
24
+ if (segments.length === 0)
25
+ return;
26
+ // Create/get folders for the path hierarchy
27
+ let folderPath = '';
28
+ let parentFolder = null;
29
+ segments.forEach((segment, index) => {
30
+ folderPath = folderPath ? `${folderPath}/${segment}` : segment;
31
+ if (!folderMap.has(folderPath)) {
32
+ const folder = { name: segment, item: [] };
33
+ folderMap.set(folderPath, folder);
34
+ if (parentFolder) {
35
+ parentFolder.item.push(folder);
36
+ }
37
+ }
38
+ parentFolder = folderMap.get(folderPath);
39
+ // Add item to deepest folder
40
+ if (index === segments.length - 1) {
41
+ parentFolder.item.push(item);
42
+ }
43
+ });
44
+ });
45
+ // Return only top-level folders
46
+ return Array.from(folderMap.values()).filter((folder) => !folder.name.includes('/'));
47
+ }
48
+ function extractSegments(path, excludePathParams) {
49
+ return path
50
+ .split('/')
51
+ .filter((seg) => seg && !seg.endsWith(':'))
52
+ .filter((seg) => !excludePathParams || (!seg.startsWith(':') && !seg.startsWith('{')));
53
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Path Variables enricher - Ensures path parameters reference collection/environment variables
3
+ */
4
+ import type { PostmanCollection, PathVariablesConfig } from '@postman-enricher/shared';
5
+ export declare function setupPathVariables(collection: PostmanCollection, config: PathVariablesConfig): PostmanCollection;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Path Variables enricher - Ensures path parameters reference collection/environment variables
3
+ */
4
+ import { walkCollection, isRequest } from '@postman-enricher/shared';
5
+ export function setupPathVariables(collection, config) {
6
+ if (!config?.enabled) {
7
+ return collection;
8
+ }
9
+ walkCollection(collection.item, (item) => {
10
+ if (!isRequest(item) || !item.request?.url)
11
+ return;
12
+ const url = item.request.url;
13
+ if (typeof url === 'string' || !url.variable)
14
+ return;
15
+ // Update path variables with mappings
16
+ url.variable = url.variable.map((variable) => {
17
+ const mapping = config.mapping?.[variable.key];
18
+ if (mapping) {
19
+ return {
20
+ ...variable,
21
+ value: mapping.reference,
22
+ description: mapping.description || variable.description,
23
+ };
24
+ }
25
+ return variable;
26
+ });
27
+ });
28
+ return collection;
29
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * ID Preservation - Maintains IDs across collection regenerations
3
+ */
4
+ import type { PostmanCollection } from '@postman-enricher/shared';
5
+ export declare function preserveIds(collection: PostmanCollection, existingPath?: string): PostmanCollection;
@@ -0,0 +1,47 @@
1
+ /**
2
+ * ID Preservation - Maintains IDs across collection regenerations
3
+ */
4
+ import { walkCollection, isRequest, getRequestMethod, } from '@postman-enricher/shared';
5
+ import { readFileSync, existsSync } from 'fs';
6
+ export function preserveIds(collection, existingPath) {
7
+ if (!existingPath || !existsSync(existingPath)) {
8
+ return collection;
9
+ }
10
+ try {
11
+ const existing = JSON.parse(readFileSync(existingPath, 'utf8'));
12
+ const idMap = buildIdMap(existing);
13
+ // Restore collection ID
14
+ if (existing.info?._postman_id) {
15
+ collection.info._postman_id = existing.info._postman_id;
16
+ }
17
+ // Restore item IDs
18
+ walkCollection(collection.item, (item) => {
19
+ const key = getItemKey(item);
20
+ const existingId = idMap.get(key);
21
+ if (existingId) {
22
+ item.id = existingId;
23
+ }
24
+ });
25
+ return collection;
26
+ }
27
+ catch {
28
+ return collection; // Silently fail if existing collection is invalid
29
+ }
30
+ }
31
+ function buildIdMap(collection) {
32
+ const map = new Map();
33
+ walkCollection(collection.item, (item) => {
34
+ if (item.id) {
35
+ const key = getItemKey(item);
36
+ map.set(key, item.id);
37
+ }
38
+ });
39
+ return map;
40
+ }
41
+ function getItemKey(item) {
42
+ if (isRequest(item)) {
43
+ const method = getRequestMethod(item);
44
+ return `${method}_${item.name}`;
45
+ }
46
+ return `folder_${item.name}`;
47
+ }
package/dist/index.d.ts CHANGED
@@ -8,13 +8,17 @@ import { addDescriptions } from './enrichers/descriptions.js';
8
8
  import { addExamples } from './enrichers/examples.js';
9
9
  import { setupVariables } from './enrichers/variables.js';
10
10
  import { addTests } from './enrichers/tests.js';
11
+ import { organizeByResources } from './enrichers/organize.js';
12
+ import { setupPathVariables } from './enrichers/pathVariables.js';
13
+ import { preserveIds } from './enrichers/preserveIds.js';
11
14
  /**
12
15
  * Enrich a Postman collection with additional metadata and functionality
13
16
  * @param collection - Postman collection to enrich
14
17
  * @param config - Enrichment configuration (object or path to YAML file)
18
+ * @param existingCollectionPath - Optional path to existing collection for ID preservation
15
19
  * @returns Enriched Postman collection
16
20
  */
17
- export declare function enrichCollection(collection: PostmanCollection, config?: EnrichmentConfig | string): PostmanCollection;
21
+ export declare function enrichCollection(collection: PostmanCollection, config?: EnrichmentConfig | string, existingCollectionPath?: string): PostmanCollection;
18
22
  /**
19
23
  * Load enrichment configuration from a YAML file
20
24
  * @param filePath - Path to YAML configuration file
@@ -24,4 +28,4 @@ export declare function loadConfigFromYaml(filePath: string): EnrichmentConfig;
24
28
  /**
25
29
  * Export individual enrichers for advanced usage
26
30
  */
27
- export { filterEndpoints, addDescriptions, addExamples, setupVariables, addTests, };
31
+ export { filterEndpoints, addDescriptions, addExamples, setupVariables, addTests, organizeByResources, setupPathVariables, preserveIds, };
package/dist/index.js CHANGED
@@ -9,34 +9,49 @@ import { addDescriptions } from './enrichers/descriptions.js';
9
9
  import { addExamples } from './enrichers/examples.js';
10
10
  import { setupVariables } from './enrichers/variables.js';
11
11
  import { addTests } from './enrichers/tests.js';
12
+ import { organizeByResources } from './enrichers/organize.js';
13
+ import { setupPathVariables } from './enrichers/pathVariables.js';
14
+ import { preserveIds } from './enrichers/preserveIds.js';
12
15
  /**
13
16
  * Enrich a Postman collection with additional metadata and functionality
14
17
  * @param collection - Postman collection to enrich
15
18
  * @param config - Enrichment configuration (object or path to YAML file)
19
+ * @param existingCollectionPath - Optional path to existing collection for ID preservation
16
20
  * @returns Enriched Postman collection
17
21
  */
18
- export function enrichCollection(collection, config = {}) {
22
+ export function enrichCollection(collection, config = {}, existingCollectionPath) {
19
23
  // Load config from YAML file if string path provided
20
24
  const enrichmentConfig = typeof config === 'string' ? loadConfigFromYaml(config) : config;
21
25
  let enriched = { ...collection };
22
- // Apply enrichments in order
26
+ // 0. Preserve IDs from existing collection (if provided)
27
+ if (existingCollectionPath) {
28
+ enriched = preserveIds(enriched, existingCollectionPath);
29
+ }
23
30
  // 1. Filter endpoints first (reduce what we're working with)
24
31
  if (enrichmentConfig.filter) {
25
32
  enriched = filterEndpoints(enriched, enrichmentConfig.filter);
26
33
  }
27
- // 2. Add descriptions (collection, folders, requests)
34
+ // 2. Organize by resource hierarchy
35
+ if (enrichmentConfig.organize) {
36
+ enriched = organizeByResources(enriched, enrichmentConfig.organize);
37
+ }
38
+ // 3. Add descriptions (collection, folders, requests)
28
39
  if (enrichmentConfig.descriptions) {
29
40
  enriched = addDescriptions(enriched, enrichmentConfig.descriptions);
30
41
  }
31
- // 3. Add examples (request bodies and responses)
42
+ // 4. Add examples (request bodies and responses)
32
43
  if (enrichmentConfig.examples) {
33
44
  enriched = addExamples(enriched, enrichmentConfig.examples);
34
45
  }
35
- // 4. Setup variables (path variables, environment variables)
46
+ // 5. Setup variables (path variables, environment variables)
36
47
  if (enrichmentConfig.variables) {
37
48
  enriched = setupVariables(enriched, enrichmentConfig.variables);
38
49
  }
39
- // 5. Add test scripts
50
+ // 6. Setup path variables
51
+ if (enrichmentConfig.pathVariables) {
52
+ enriched = setupPathVariables(enriched, enrichmentConfig.pathVariables);
53
+ }
54
+ // 7. Add test scripts
40
55
  if (enrichmentConfig.tests) {
41
56
  enriched = addTests(enriched, enrichmentConfig.tests);
42
57
  }
@@ -59,4 +74,4 @@ export function loadConfigFromYaml(filePath) {
59
74
  /**
60
75
  * Export individual enrichers for advanced usage
61
76
  */
62
- export { filterEndpoints, addDescriptions, addExamples, setupVariables, addTests, };
77
+ export { filterEndpoints, addDescriptions, addExamples, setupVariables, addTests, organizeByResources, setupPathVariables, preserveIds, };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@postman-enricher/core",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Core enrichment logic for Postman Enricher",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -16,7 +16,7 @@
16
16
  ],
17
17
  "dependencies": {
18
18
  "yaml": "^2.8.1",
19
- "@postman-enricher/shared": "1.0.0"
19
+ "@postman-enricher/shared": "1.1.0"
20
20
  },
21
21
  "devDependencies": {
22
22
  "@anolilab/semantic-release-pnpm": "^3.0.0",