@c-time/frelio-dependency-map 1.0.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.
- package/README.md +101 -0
- package/dist/guards.d.ts +9 -0
- package/dist/guards.js +72 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +33 -0
- package/dist/schema.d.ts +22 -0
- package/dist/schema.js +31 -0
- package/dist/types.d.ts +66 -0
- package/dist/types.js +17 -0
- package/dist/utils.d.ts +36 -0
- package/dist/utils.js +99 -0
- package/package.json +41 -0
package/README.md
ADDED
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
# frelio-dependency-map
|
|
2
|
+
|
|
3
|
+
Type definitions and utilities for frelio dependency map files.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install frelio-dependency-map
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Basic Usage
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { DependencyMap, isDependencyMap } from 'frelio-dependency-map'
|
|
17
|
+
import fs from 'fs'
|
|
18
|
+
|
|
19
|
+
// Load a dependency map file
|
|
20
|
+
const data = JSON.parse(fs.readFileSync('_dependency-map.json', 'utf-8'))
|
|
21
|
+
|
|
22
|
+
// Validate the data
|
|
23
|
+
if (isDependencyMap(data)) {
|
|
24
|
+
// data is now typed as DependencyMap
|
|
25
|
+
console.log('Output paths:', Object.keys(data))
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Validation with Detailed Errors
|
|
30
|
+
|
|
31
|
+
```typescript
|
|
32
|
+
import { validateDependencyMap } from 'frelio-dependency-map'
|
|
33
|
+
|
|
34
|
+
const result = validateDependencyMap(data)
|
|
35
|
+
if (!result.valid) {
|
|
36
|
+
console.error('Validation errors:', result.errors)
|
|
37
|
+
}
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Finding Affected Outputs
|
|
41
|
+
|
|
42
|
+
```typescript
|
|
43
|
+
import { findAffectedOutputs, DependencyMap } from 'frelio-dependency-map'
|
|
44
|
+
|
|
45
|
+
const map: DependencyMap = {
|
|
46
|
+
'/articles/{slug}.json': ['content_types/article', 'contents/*/article/*'],
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Find which outputs need rebuilding when a file changes
|
|
50
|
+
const affected = findAffectedOutputs(
|
|
51
|
+
map,
|
|
52
|
+
'contents/published/article/my-post.json'
|
|
53
|
+
)
|
|
54
|
+
console.log(affected) // ['/articles/{slug}.json']
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### JSON Schema Validation
|
|
58
|
+
|
|
59
|
+
```typescript
|
|
60
|
+
import { dependencyMapSchema } from 'frelio-dependency-map/schema'
|
|
61
|
+
import Ajv from 'ajv'
|
|
62
|
+
|
|
63
|
+
const ajv = new Ajv()
|
|
64
|
+
const validate = ajv.compile(dependencyMapSchema)
|
|
65
|
+
|
|
66
|
+
if (!validate(data)) {
|
|
67
|
+
console.error(validate.errors)
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## API
|
|
72
|
+
|
|
73
|
+
### Types
|
|
74
|
+
|
|
75
|
+
- `DependencyMap` - Main type for dependency map objects
|
|
76
|
+
- `OutputPath` - Type alias for output path strings
|
|
77
|
+
- `DependencyPath` - Type alias for dependency path strings
|
|
78
|
+
- `ValidationResult` - Result of validation operations
|
|
79
|
+
- `ValidationError` - Individual validation error
|
|
80
|
+
|
|
81
|
+
### Functions
|
|
82
|
+
|
|
83
|
+
- `isDependencyMap(value)` - Type guard for DependencyMap
|
|
84
|
+
- `validateDependencyMap(value)` - Validates with detailed errors
|
|
85
|
+
- `getDependencyPaths(map, outputPath)` - Get dependencies for an output
|
|
86
|
+
- `getOutputPaths(map)` - Get all output paths
|
|
87
|
+
- `getAllDependencyPaths(map)` - Get all unique dependency paths
|
|
88
|
+
- `mergeDependencyMaps(...maps)` - Merge multiple maps
|
|
89
|
+
- `findAffectedOutputs(map, changedPath)` - Find outputs affected by a change
|
|
90
|
+
- `createDependencyMap()` - Create an empty dependency map
|
|
91
|
+
- `setDependencies(map, outputPath, deps)` - Set dependencies for an output
|
|
92
|
+
- `removeDependencies(map, outputPath)` - Remove an output from the map
|
|
93
|
+
|
|
94
|
+
### Constants
|
|
95
|
+
|
|
96
|
+
- `DEPENDENCY_PATH_PREFIXES` - Common path prefixes
|
|
97
|
+
- `dependencyMapSchema` - JSON Schema for validation
|
|
98
|
+
|
|
99
|
+
## License
|
|
100
|
+
|
|
101
|
+
MIT
|
package/dist/guards.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { DependencyMap, ValidationResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Type guard to check if a value is a valid DependencyMap
|
|
4
|
+
*/
|
|
5
|
+
export declare function isDependencyMap(value: unknown): value is DependencyMap;
|
|
6
|
+
/**
|
|
7
|
+
* Validates a value as a DependencyMap and returns detailed errors
|
|
8
|
+
*/
|
|
9
|
+
export declare function validateDependencyMap(value: unknown): ValidationResult;
|
package/dist/guards.js
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type guard to check if a value is a valid DependencyMap
|
|
3
|
+
*/
|
|
4
|
+
export function isDependencyMap(value) {
|
|
5
|
+
if (value === null || typeof value !== 'object') {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
const obj = value;
|
|
9
|
+
for (const [key, val] of Object.entries(obj)) {
|
|
10
|
+
// Key must be a non-empty string
|
|
11
|
+
if (typeof key !== 'string' || key.length === 0) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
// Value must be an array of strings
|
|
15
|
+
if (!Array.isArray(val)) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
for (const item of val) {
|
|
19
|
+
if (typeof item !== 'string') {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Validates a value as a DependencyMap and returns detailed errors
|
|
28
|
+
*/
|
|
29
|
+
export function validateDependencyMap(value) {
|
|
30
|
+
const errors = [];
|
|
31
|
+
if (value === null) {
|
|
32
|
+
errors.push({ path: '', message: 'Value is null' });
|
|
33
|
+
return { valid: false, errors };
|
|
34
|
+
}
|
|
35
|
+
if (typeof value !== 'object') {
|
|
36
|
+
errors.push({ path: '', message: `Expected object, got ${typeof value}` });
|
|
37
|
+
return { valid: false, errors };
|
|
38
|
+
}
|
|
39
|
+
const obj = value;
|
|
40
|
+
for (const [key, val] of Object.entries(obj)) {
|
|
41
|
+
if (typeof key !== 'string' || key.length === 0) {
|
|
42
|
+
errors.push({
|
|
43
|
+
path: key,
|
|
44
|
+
message: 'Output path must be a non-empty string',
|
|
45
|
+
});
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
if (!Array.isArray(val)) {
|
|
49
|
+
errors.push({
|
|
50
|
+
path: key,
|
|
51
|
+
message: `Expected array of dependencies, got ${typeof val}`,
|
|
52
|
+
});
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
for (let i = 0; i < val.length; i++) {
|
|
56
|
+
const item = val[i];
|
|
57
|
+
if (typeof item !== 'string') {
|
|
58
|
+
errors.push({
|
|
59
|
+
path: `${key}[${i}]`,
|
|
60
|
+
message: `Expected string dependency path, got ${typeof item}`,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
else if (item.length === 0) {
|
|
64
|
+
errors.push({
|
|
65
|
+
path: `${key}[${i}]`,
|
|
66
|
+
message: 'Dependency path cannot be empty',
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return { valid: errors.length === 0, errors };
|
|
72
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* frelio-dependency-map
|
|
3
|
+
*
|
|
4
|
+
* Type definitions and utilities for frelio dependency map files.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import {
|
|
9
|
+
* DependencyMap,
|
|
10
|
+
* isDependencyMap,
|
|
11
|
+
* validateDependencyMap,
|
|
12
|
+
* findAffectedOutputs
|
|
13
|
+
* } from 'frelio-dependency-map'
|
|
14
|
+
*
|
|
15
|
+
* // Load and validate a dependency map
|
|
16
|
+
* const data = JSON.parse(fs.readFileSync('_dependency-map.json', 'utf-8'))
|
|
17
|
+
*
|
|
18
|
+
* if (isDependencyMap(data)) {
|
|
19
|
+
* // Type-safe access
|
|
20
|
+
* const affected = findAffectedOutputs(data, 'contents/published/article/my-post.json')
|
|
21
|
+
* console.log('Affected outputs:', affected)
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @packageDocumentation
|
|
26
|
+
*/
|
|
27
|
+
export type { DependencyMap, OutputPath, DependencyPath, DependencyPathPrefix, ValidationResult, ValidationError, } from './types.js';
|
|
28
|
+
export { DEPENDENCY_PATH_PREFIXES } from './types.js';
|
|
29
|
+
export { dependencyMapSchema } from './schema.js';
|
|
30
|
+
export type { DependencyMapSchema } from './schema.js';
|
|
31
|
+
export { isDependencyMap, validateDependencyMap } from './guards.js';
|
|
32
|
+
export { getDependencyPaths, getOutputPaths, getAllDependencyPaths, mergeDependencyMaps, findAffectedOutputs, createDependencyMap, setDependencies, removeDependencies, } from './utils.js';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* frelio-dependency-map
|
|
3
|
+
*
|
|
4
|
+
* Type definitions and utilities for frelio dependency map files.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import {
|
|
9
|
+
* DependencyMap,
|
|
10
|
+
* isDependencyMap,
|
|
11
|
+
* validateDependencyMap,
|
|
12
|
+
* findAffectedOutputs
|
|
13
|
+
* } from 'frelio-dependency-map'
|
|
14
|
+
*
|
|
15
|
+
* // Load and validate a dependency map
|
|
16
|
+
* const data = JSON.parse(fs.readFileSync('_dependency-map.json', 'utf-8'))
|
|
17
|
+
*
|
|
18
|
+
* if (isDependencyMap(data)) {
|
|
19
|
+
* // Type-safe access
|
|
20
|
+
* const affected = findAffectedOutputs(data, 'contents/published/article/my-post.json')
|
|
21
|
+
* console.log('Affected outputs:', affected)
|
|
22
|
+
* }
|
|
23
|
+
* ```
|
|
24
|
+
*
|
|
25
|
+
* @packageDocumentation
|
|
26
|
+
*/
|
|
27
|
+
export { DEPENDENCY_PATH_PREFIXES } from './types.js';
|
|
28
|
+
// Schema
|
|
29
|
+
export { dependencyMapSchema } from './schema.js';
|
|
30
|
+
// Type guards & validation
|
|
31
|
+
export { isDependencyMap, validateDependencyMap } from './guards.js';
|
|
32
|
+
// Utilities
|
|
33
|
+
export { getDependencyPaths, getOutputPaths, getAllDependencyPaths, mergeDependencyMaps, findAffectedOutputs, createDependencyMap, setDependencies, removeDependencies, } from './utils.js';
|
package/dist/schema.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Schema for DependencyMap validation
|
|
3
|
+
*/
|
|
4
|
+
export declare const dependencyMapSchema: {
|
|
5
|
+
readonly $schema: "http://json-schema.org/draft-07/schema#";
|
|
6
|
+
readonly title: "DependencyMap";
|
|
7
|
+
readonly description: "Maps output file paths to arrays of dependency paths for incremental builds";
|
|
8
|
+
readonly type: "object";
|
|
9
|
+
readonly additionalProperties: {
|
|
10
|
+
readonly type: "array";
|
|
11
|
+
readonly items: {
|
|
12
|
+
readonly type: "string";
|
|
13
|
+
readonly minLength: 1;
|
|
14
|
+
};
|
|
15
|
+
readonly description: "Array of dependency paths (glob patterns allowed)";
|
|
16
|
+
};
|
|
17
|
+
readonly examples: readonly [{
|
|
18
|
+
readonly '/articles/{slug}.json': readonly ["content_types/article", "templates/article/detail.html", "contents/*/article/*"];
|
|
19
|
+
readonly '/articles/index.json': readonly ["content_types/article", "templates/article/list.html", "contents/*/article/*"];
|
|
20
|
+
}];
|
|
21
|
+
};
|
|
22
|
+
export type DependencyMapSchema = typeof dependencyMapSchema;
|
package/dist/schema.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON Schema for DependencyMap validation
|
|
3
|
+
*/
|
|
4
|
+
export const dependencyMapSchema = {
|
|
5
|
+
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
6
|
+
title: 'DependencyMap',
|
|
7
|
+
description: 'Maps output file paths to arrays of dependency paths for incremental builds',
|
|
8
|
+
type: 'object',
|
|
9
|
+
additionalProperties: {
|
|
10
|
+
type: 'array',
|
|
11
|
+
items: {
|
|
12
|
+
type: 'string',
|
|
13
|
+
minLength: 1,
|
|
14
|
+
},
|
|
15
|
+
description: 'Array of dependency paths (glob patterns allowed)',
|
|
16
|
+
},
|
|
17
|
+
examples: [
|
|
18
|
+
{
|
|
19
|
+
'/articles/{slug}.json': [
|
|
20
|
+
'content_types/article',
|
|
21
|
+
'templates/article/detail.html',
|
|
22
|
+
'contents/*/article/*',
|
|
23
|
+
],
|
|
24
|
+
'/articles/index.json': [
|
|
25
|
+
'content_types/article',
|
|
26
|
+
'templates/article/list.html',
|
|
27
|
+
'contents/*/article/*',
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
};
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency Map type definitions
|
|
3
|
+
*
|
|
4
|
+
* A dependency map tracks which source files affect each output file,
|
|
5
|
+
* enabling incremental/differential builds.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Output path pattern (e.g., "/articles/{slug}.json", "/articles/index.json")
|
|
9
|
+
* Can include template variables like {slug}, {page}, etc.
|
|
10
|
+
*/
|
|
11
|
+
export type OutputPath = string;
|
|
12
|
+
/**
|
|
13
|
+
* Dependency path pattern
|
|
14
|
+
* Examples: "contents/*/article/*", "templates/article/detail.html"
|
|
15
|
+
* Can include glob patterns for matching multiple files.
|
|
16
|
+
*
|
|
17
|
+
* Common prefixes:
|
|
18
|
+
* - content_types/ - Content type definitions
|
|
19
|
+
* - templates/ - Template files
|
|
20
|
+
* - contents/ - Content data files (often with glob patterns)
|
|
21
|
+
*/
|
|
22
|
+
export type DependencyPath = string;
|
|
23
|
+
/**
|
|
24
|
+
* Dependency Map
|
|
25
|
+
*
|
|
26
|
+
* Maps output file paths to arrays of dependency paths.
|
|
27
|
+
* Used by the builder for incremental builds - when any dependency changes,
|
|
28
|
+
* the corresponding output files need to be regenerated.
|
|
29
|
+
*
|
|
30
|
+
* Example:
|
|
31
|
+
* ```
|
|
32
|
+
* {
|
|
33
|
+
* "/articles/{slug}.json": [
|
|
34
|
+
* "content_types/article",
|
|
35
|
+
* "templates/article/detail.html",
|
|
36
|
+
* "contents/*/article/*"
|
|
37
|
+
* ]
|
|
38
|
+
* }
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
export type DependencyMap = {
|
|
42
|
+
[outputPath: OutputPath]: DependencyPath[];
|
|
43
|
+
};
|
|
44
|
+
/**
|
|
45
|
+
* Common dependency path prefixes used in frelio projects
|
|
46
|
+
*/
|
|
47
|
+
export declare const DEPENDENCY_PATH_PREFIXES: {
|
|
48
|
+
/** Content type schema definitions */
|
|
49
|
+
readonly CONTENT_TYPES: "content_types/";
|
|
50
|
+
/** Template files */
|
|
51
|
+
readonly TEMPLATES: "templates/";
|
|
52
|
+
/** Content data files */
|
|
53
|
+
readonly CONTENTS: "contents/";
|
|
54
|
+
};
|
|
55
|
+
export type DependencyPathPrefix = (typeof DEPENDENCY_PATH_PREFIXES)[keyof typeof DEPENDENCY_PATH_PREFIXES];
|
|
56
|
+
/**
|
|
57
|
+
* Result of validation operations
|
|
58
|
+
*/
|
|
59
|
+
export type ValidationResult = {
|
|
60
|
+
valid: boolean;
|
|
61
|
+
errors: ValidationError[];
|
|
62
|
+
};
|
|
63
|
+
export type ValidationError = {
|
|
64
|
+
path: string;
|
|
65
|
+
message: string;
|
|
66
|
+
};
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dependency Map type definitions
|
|
3
|
+
*
|
|
4
|
+
* A dependency map tracks which source files affect each output file,
|
|
5
|
+
* enabling incremental/differential builds.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Common dependency path prefixes used in frelio projects
|
|
9
|
+
*/
|
|
10
|
+
export const DEPENDENCY_PATH_PREFIXES = {
|
|
11
|
+
/** Content type schema definitions */
|
|
12
|
+
CONTENT_TYPES: 'content_types/',
|
|
13
|
+
/** Template files */
|
|
14
|
+
TEMPLATES: 'templates/',
|
|
15
|
+
/** Content data files */
|
|
16
|
+
CONTENTS: 'contents/',
|
|
17
|
+
};
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import type { DependencyMap, DependencyPath, OutputPath } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Gets the dependency paths for a specific output path
|
|
4
|
+
* Returns an empty array if the output path is not found
|
|
5
|
+
*/
|
|
6
|
+
export declare function getDependencyPaths(map: DependencyMap, outputPath: OutputPath): DependencyPath[];
|
|
7
|
+
/**
|
|
8
|
+
* Gets all output paths defined in the dependency map
|
|
9
|
+
*/
|
|
10
|
+
export declare function getOutputPaths(map: DependencyMap): OutputPath[];
|
|
11
|
+
/**
|
|
12
|
+
* Gets all unique dependency paths across all outputs
|
|
13
|
+
*/
|
|
14
|
+
export declare function getAllDependencyPaths(map: DependencyMap): DependencyPath[];
|
|
15
|
+
/**
|
|
16
|
+
* Merges multiple dependency maps into one
|
|
17
|
+
* Later maps override earlier ones for the same output path
|
|
18
|
+
*/
|
|
19
|
+
export declare function mergeDependencyMaps(...maps: DependencyMap[]): DependencyMap;
|
|
20
|
+
/**
|
|
21
|
+
* Finds all output paths that depend on a given dependency path
|
|
22
|
+
* Supports exact match and simple glob pattern matching
|
|
23
|
+
*/
|
|
24
|
+
export declare function findAffectedOutputs(map: DependencyMap, changedPath: DependencyPath): OutputPath[];
|
|
25
|
+
/**
|
|
26
|
+
* Creates an empty dependency map
|
|
27
|
+
*/
|
|
28
|
+
export declare function createDependencyMap(): DependencyMap;
|
|
29
|
+
/**
|
|
30
|
+
* Adds or updates dependencies for an output path
|
|
31
|
+
*/
|
|
32
|
+
export declare function setDependencies(map: DependencyMap, outputPath: OutputPath, dependencies: DependencyPath[]): DependencyMap;
|
|
33
|
+
/**
|
|
34
|
+
* Removes an output path from the dependency map
|
|
35
|
+
*/
|
|
36
|
+
export declare function removeDependencies(map: DependencyMap, outputPath: OutputPath): DependencyMap;
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gets the dependency paths for a specific output path
|
|
3
|
+
* Returns an empty array if the output path is not found
|
|
4
|
+
*/
|
|
5
|
+
export function getDependencyPaths(map, outputPath) {
|
|
6
|
+
return map[outputPath] ?? [];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Gets all output paths defined in the dependency map
|
|
10
|
+
*/
|
|
11
|
+
export function getOutputPaths(map) {
|
|
12
|
+
return Object.keys(map);
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Gets all unique dependency paths across all outputs
|
|
16
|
+
*/
|
|
17
|
+
export function getAllDependencyPaths(map) {
|
|
18
|
+
const allPaths = new Set();
|
|
19
|
+
for (const paths of Object.values(map)) {
|
|
20
|
+
for (const path of paths) {
|
|
21
|
+
allPaths.add(path);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return Array.from(allPaths).sort();
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Merges multiple dependency maps into one
|
|
28
|
+
* Later maps override earlier ones for the same output path
|
|
29
|
+
*/
|
|
30
|
+
export function mergeDependencyMaps(...maps) {
|
|
31
|
+
const result = {};
|
|
32
|
+
for (const map of maps) {
|
|
33
|
+
for (const [outputPath, deps] of Object.entries(map)) {
|
|
34
|
+
result[outputPath] = [...deps];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return result;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Finds all output paths that depend on a given dependency path
|
|
41
|
+
* Supports exact match and simple glob pattern matching
|
|
42
|
+
*/
|
|
43
|
+
export function findAffectedOutputs(map, changedPath) {
|
|
44
|
+
const affected = [];
|
|
45
|
+
for (const [outputPath, deps] of Object.entries(map)) {
|
|
46
|
+
for (const dep of deps) {
|
|
47
|
+
if (matchesDependencyPath(dep, changedPath)) {
|
|
48
|
+
affected.push(outputPath);
|
|
49
|
+
break;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return affected;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Checks if a dependency pattern matches a given path
|
|
57
|
+
* Supports * as a wildcard for any single path segment
|
|
58
|
+
*/
|
|
59
|
+
function matchesDependencyPath(pattern, path) {
|
|
60
|
+
// Exact match
|
|
61
|
+
if (pattern === path) {
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
// Convert glob pattern to regex
|
|
65
|
+
// * matches any characters except /
|
|
66
|
+
const regexPattern = pattern
|
|
67
|
+
.replace(/[.+?^${}()|[\]\\]/g, '\\$&') // Escape special regex chars
|
|
68
|
+
.replace(/\*/g, '[^/]*'); // * matches any segment
|
|
69
|
+
try {
|
|
70
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
71
|
+
return regex.test(path);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
// If regex compilation fails, fall back to exact match
|
|
75
|
+
return pattern === path;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Creates an empty dependency map
|
|
80
|
+
*/
|
|
81
|
+
export function createDependencyMap() {
|
|
82
|
+
return {};
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Adds or updates dependencies for an output path
|
|
86
|
+
*/
|
|
87
|
+
export function setDependencies(map, outputPath, dependencies) {
|
|
88
|
+
return {
|
|
89
|
+
...map,
|
|
90
|
+
[outputPath]: [...dependencies],
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Removes an output path from the dependency map
|
|
95
|
+
*/
|
|
96
|
+
export function removeDependencies(map, outputPath) {
|
|
97
|
+
const { [outputPath]: _, ...rest } = map;
|
|
98
|
+
return rest;
|
|
99
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@c-time/frelio-dependency-map",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Type definitions and utilities for frelio dependency map files",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./schema": {
|
|
14
|
+
"types": "./dist/schema.d.ts",
|
|
15
|
+
"import": "./dist/schema.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"files": [
|
|
19
|
+
"dist",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"scripts": {
|
|
23
|
+
"build": "tsc -p tsconfig.build.json",
|
|
24
|
+
"dev": "tsc -p tsconfig.build.json --watch",
|
|
25
|
+
"prepublishOnly": "npm run build"
|
|
26
|
+
},
|
|
27
|
+
"keywords": [
|
|
28
|
+
"frelio",
|
|
29
|
+
"dependency-map",
|
|
30
|
+
"typescript",
|
|
31
|
+
"types",
|
|
32
|
+
"cms"
|
|
33
|
+
],
|
|
34
|
+
"license": "MIT",
|
|
35
|
+
"devDependencies": {
|
|
36
|
+
"typescript": "^5.7.0"
|
|
37
|
+
},
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=18"
|
|
40
|
+
}
|
|
41
|
+
}
|