@codama/fragments 0.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.
- package/LICENSE +23 -0
- package/README.md +542 -0
- package/dist/index.browser.cjs +208 -0
- package/dist/index.browser.cjs.map +1 -0
- package/dist/index.browser.mjs +176 -0
- package/dist/index.browser.mjs.map +1 -0
- package/dist/index.node.cjs +195 -0
- package/dist/index.node.cjs.map +1 -0
- package/dist/index.node.mjs +163 -0
- package/dist/index.node.mjs.map +1 -0
- package/dist/index.react-native.mjs +176 -0
- package/dist/index.react-native.mjs.map +1 -0
- package/dist/javascript.browser.cjs +403 -0
- package/dist/javascript.browser.cjs.map +1 -0
- package/dist/javascript.browser.mjs +353 -0
- package/dist/javascript.browser.mjs.map +1 -0
- package/dist/javascript.node.cjs +390 -0
- package/dist/javascript.node.cjs.map +1 -0
- package/dist/javascript.node.mjs +340 -0
- package/dist/javascript.node.mjs.map +1 -0
- package/dist/javascript.react-native.mjs +353 -0
- package/dist/javascript.react-native.mjs.map +1 -0
- package/dist/rust.browser.cjs +371 -0
- package/dist/rust.browser.cjs.map +1 -0
- package/dist/rust.browser.mjs +322 -0
- package/dist/rust.browser.mjs.map +1 -0
- package/dist/rust.node.cjs +358 -0
- package/dist/rust.node.cjs.map +1 -0
- package/dist/rust.node.mjs +309 -0
- package/dist/rust.node.mjs.map +1 -0
- package/dist/rust.react-native.mjs +322 -0
- package/dist/rust.react-native.mjs.map +1 -0
- package/dist/types/core/BaseFragment.d.ts +21 -0
- package/dist/types/core/BaseFragment.d.ts.map +1 -0
- package/dist/types/core/casing.d.ts +52 -0
- package/dist/types/core/casing.d.ts.map +1 -0
- package/dist/types/core/createFragmentTemplate.d.ts +38 -0
- package/dist/types/core/createFragmentTemplate.d.ts.map +1 -0
- package/dist/types/core/fs.d.ts +28 -0
- package/dist/types/core/fs.d.ts.map +1 -0
- package/dist/types/core/index.d.ts +9 -0
- package/dist/types/core/index.d.ts.map +1 -0
- package/dist/types/core/mapFragmentContent.d.ts +43 -0
- package/dist/types/core/mapFragmentContent.d.ts.map +1 -0
- package/dist/types/core/path.d.ts +43 -0
- package/dist/types/core/path.d.ts.map +1 -0
- package/dist/types/core/renderMap.d.ts +61 -0
- package/dist/types/core/renderMap.d.ts.map +1 -0
- package/dist/types/core/setFragmentContent.d.ts +23 -0
- package/dist/types/core/setFragmentContent.d.ts.map +1 -0
- package/dist/types/index.d.ts +17 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/javascript/ImportMap.d.ts +61 -0
- package/dist/types/javascript/ImportMap.d.ts.map +1 -0
- package/dist/types/javascript/addToImportMap.d.ts +25 -0
- package/dist/types/javascript/addToImportMap.d.ts.map +1 -0
- package/dist/types/javascript/fragment.d.ts +135 -0
- package/dist/types/javascript/fragment.d.ts.map +1 -0
- package/dist/types/javascript/getDocblockFragment.d.ts +53 -0
- package/dist/types/javascript/getDocblockFragment.d.ts.map +1 -0
- package/dist/types/javascript/getExportAllFragment.d.ts +21 -0
- package/dist/types/javascript/getExportAllFragment.d.ts.map +1 -0
- package/dist/types/javascript/getExternalDependencies.d.ts +29 -0
- package/dist/types/javascript/getExternalDependencies.d.ts.map +1 -0
- package/dist/types/javascript/importMapToString.d.ts +40 -0
- package/dist/types/javascript/importMapToString.d.ts.map +1 -0
- package/dist/types/javascript/index.d.ts +23 -0
- package/dist/types/javascript/index.d.ts.map +1 -0
- package/dist/types/javascript/mergeImportMaps.d.ts +34 -0
- package/dist/types/javascript/mergeImportMaps.d.ts.map +1 -0
- package/dist/types/javascript/removeFromImportMap.d.ts +21 -0
- package/dist/types/javascript/removeFromImportMap.d.ts.map +1 -0
- package/dist/types/javascript/resolveImportMap.d.ts +33 -0
- package/dist/types/javascript/resolveImportMap.d.ts.map +1 -0
- package/dist/types/rust/ImportMap.d.ts +52 -0
- package/dist/types/rust/ImportMap.d.ts.map +1 -0
- package/dist/types/rust/addAliasToImportMap.d.ts +24 -0
- package/dist/types/rust/addAliasToImportMap.d.ts.map +1 -0
- package/dist/types/rust/addToImportMap.d.ts +27 -0
- package/dist/types/rust/addToImportMap.d.ts.map +1 -0
- package/dist/types/rust/fragment.d.ts +118 -0
- package/dist/types/rust/fragment.d.ts.map +1 -0
- package/dist/types/rust/getDocblockFragment.d.ts +53 -0
- package/dist/types/rust/getDocblockFragment.d.ts.map +1 -0
- package/dist/types/rust/getExternalDependencies.d.ts +30 -0
- package/dist/types/rust/getExternalDependencies.d.ts.map +1 -0
- package/dist/types/rust/importMapToString.d.ts +30 -0
- package/dist/types/rust/importMapToString.d.ts.map +1 -0
- package/dist/types/rust/index.d.ts +23 -0
- package/dist/types/rust/index.d.ts.map +1 -0
- package/dist/types/rust/mergeImportMaps.d.ts +23 -0
- package/dist/types/rust/mergeImportMaps.d.ts.map +1 -0
- package/dist/types/rust/removeFromImportMap.d.ts +20 -0
- package/dist/types/rust/removeFromImportMap.d.ts.map +1 -0
- package/dist/types/rust/resolveImportMap.d.ts +32 -0
- package/dist/types/rust/resolveImportMap.d.ts.map +1 -0
- package/package.json +106 -0
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
require('fs');
|
|
4
|
+
var errors = require('@codama/errors');
|
|
5
|
+
require('path');
|
|
6
|
+
|
|
7
|
+
// src/core/casing.ts
|
|
8
|
+
function capitalize(str) {
|
|
9
|
+
if (str.length === 0) return str;
|
|
10
|
+
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
|
|
11
|
+
}
|
|
12
|
+
function titleCase(str) {
|
|
13
|
+
return str.replace(/([A-Z])/g, " $1").split(/[^a-zA-Z0-9]+/).filter((word) => word.length > 0).map(capitalize).join(" ");
|
|
14
|
+
}
|
|
15
|
+
function pascalCase(str) {
|
|
16
|
+
return titleCase(str).split(" ").join("");
|
|
17
|
+
}
|
|
18
|
+
function camelCase(str) {
|
|
19
|
+
if (str.length === 0) return str;
|
|
20
|
+
const pascalStr = pascalCase(str);
|
|
21
|
+
return pascalStr.charAt(0).toLowerCase() + pascalStr.slice(1);
|
|
22
|
+
}
|
|
23
|
+
function kebabCase(str) {
|
|
24
|
+
return titleCase(str).split(" ").join("-").toLowerCase();
|
|
25
|
+
}
|
|
26
|
+
function snakeCase(str) {
|
|
27
|
+
return titleCase(str).split(" ").join("_").toLowerCase();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/core/createFragmentTemplate.ts
|
|
31
|
+
function createFragmentTemplate(template, items, isFragment, mergeFragments) {
|
|
32
|
+
const fragments = items.filter(isFragment);
|
|
33
|
+
const zippedItems = items.map((item, i) => {
|
|
34
|
+
const itemPrefix = template[i];
|
|
35
|
+
if (typeof item === "undefined") return itemPrefix;
|
|
36
|
+
if (isFragment(item)) return itemPrefix + item.content;
|
|
37
|
+
return itemPrefix + String(item);
|
|
38
|
+
});
|
|
39
|
+
return mergeFragments(fragments, () => zippedItems.join("") + template[template.length - 1]);
|
|
40
|
+
}
|
|
41
|
+
function joinPath(...paths) {
|
|
42
|
+
{
|
|
43
|
+
return paths.join("/").replace(/\/+/g, "/");
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
function pathDirectory(path) {
|
|
47
|
+
{
|
|
48
|
+
return path.substring(0, path.lastIndexOf("/"));
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function pathBasename(path) {
|
|
52
|
+
{
|
|
53
|
+
const slash = path.lastIndexOf("/");
|
|
54
|
+
return slash >= 0 ? path.substring(slash + 1) : path;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
function relativePath(from, to) {
|
|
58
|
+
{
|
|
59
|
+
throw new errors.CodamaError(errors.CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: "relative" });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// src/core/fs.ts
|
|
64
|
+
function createDirectory(path) {
|
|
65
|
+
{
|
|
66
|
+
throw new errors.CodamaError(errors.CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: "mkdirSync" });
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function deleteDirectory(path) {
|
|
70
|
+
{
|
|
71
|
+
throw new errors.CodamaError(errors.CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: "rmSync" });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function writeFile(path, content) {
|
|
75
|
+
{
|
|
76
|
+
throw new errors.CodamaError(errors.CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: "writeFileSync" });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function fileExists(path) {
|
|
80
|
+
{
|
|
81
|
+
throw new errors.CodamaError(errors.CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: "existsSync" });
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function readFile(path) {
|
|
85
|
+
{
|
|
86
|
+
throw new errors.CodamaError(errors.CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: "readFileSync" });
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function readJson(path) {
|
|
90
|
+
return JSON.parse(readFile());
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/core/setFragmentContent.ts
|
|
94
|
+
function setFragmentContent(fragment, content) {
|
|
95
|
+
return Object.freeze({ ...fragment, content });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// src/core/mapFragmentContent.ts
|
|
99
|
+
function mapFragmentContent(fragment, mapContent) {
|
|
100
|
+
return setFragmentContent(fragment, mapContent(fragment.content));
|
|
101
|
+
}
|
|
102
|
+
async function mapFragmentContentAsync(fragment, mapContent) {
|
|
103
|
+
return setFragmentContent(fragment, await mapContent(fragment.content));
|
|
104
|
+
}
|
|
105
|
+
function createRenderMap(pathOrEntries, content) {
|
|
106
|
+
let entries = [];
|
|
107
|
+
if (typeof pathOrEntries === "string" && content !== void 0) {
|
|
108
|
+
entries = [[pathOrEntries, content]];
|
|
109
|
+
} else if (typeof pathOrEntries === "object" && pathOrEntries !== null) {
|
|
110
|
+
entries = Object.entries(pathOrEntries).flatMap(
|
|
111
|
+
([key, value]) => value === void 0 ? [] : [[key, value]]
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
return Object.freeze(new Map(entries));
|
|
115
|
+
}
|
|
116
|
+
function addToRenderMap(renderMap, path, content) {
|
|
117
|
+
return mergeRenderMaps([renderMap, createRenderMap(path, content)]);
|
|
118
|
+
}
|
|
119
|
+
function removeFromRenderMap(renderMap, path) {
|
|
120
|
+
const newMap = new Map(renderMap);
|
|
121
|
+
newMap.delete(path);
|
|
122
|
+
return Object.freeze(newMap);
|
|
123
|
+
}
|
|
124
|
+
function mergeRenderMaps(renderMaps) {
|
|
125
|
+
if (renderMaps.length === 0) return createRenderMap();
|
|
126
|
+
if (renderMaps.length === 1) return renderMaps[0];
|
|
127
|
+
const merged = new Map(renderMaps[0]);
|
|
128
|
+
for (const map of renderMaps.slice(1)) {
|
|
129
|
+
for (const [key, value] of map) {
|
|
130
|
+
merged.set(key, value);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return Object.freeze(merged);
|
|
134
|
+
}
|
|
135
|
+
function mapRenderMapFragment(renderMap, fn) {
|
|
136
|
+
return Object.freeze(new Map([...[...renderMap.entries()].map(([key, value]) => [key, fn(value, key)])]));
|
|
137
|
+
}
|
|
138
|
+
async function mapRenderMapFragmentAsync(renderMap, fn) {
|
|
139
|
+
return Object.freeze(
|
|
140
|
+
new Map(
|
|
141
|
+
await Promise.all([
|
|
142
|
+
...[...renderMap.entries()].map(async ([key, value]) => [key, await fn(value, key)])
|
|
143
|
+
])
|
|
144
|
+
)
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
function mapRenderMapContent(renderMap, fn) {
|
|
148
|
+
return mapRenderMapFragment(
|
|
149
|
+
renderMap,
|
|
150
|
+
(fragment, path) => mapFragmentContent(fragment, (content) => fn(content, path))
|
|
151
|
+
);
|
|
152
|
+
}
|
|
153
|
+
async function mapRenderMapContentAsync(renderMap, fn) {
|
|
154
|
+
return await mapRenderMapFragmentAsync(
|
|
155
|
+
renderMap,
|
|
156
|
+
(fragment, path) => mapFragmentContentAsync(fragment, (content) => fn(content, path))
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
function getFromRenderMap(renderMap, path) {
|
|
160
|
+
const value = renderMap.get(path);
|
|
161
|
+
if (value === void 0) {
|
|
162
|
+
throw new errors.CodamaError(errors.CODAMA_ERROR__VISITORS__RENDER_MAP_KEY_NOT_FOUND, { key: path });
|
|
163
|
+
}
|
|
164
|
+
return value;
|
|
165
|
+
}
|
|
166
|
+
function renderMapContains(renderMap, path, value) {
|
|
167
|
+
const { content } = getFromRenderMap(renderMap, path);
|
|
168
|
+
return typeof value === "string" ? content.includes(value) : value.test(content);
|
|
169
|
+
}
|
|
170
|
+
function writeRenderMap(renderMap, basePath) {
|
|
171
|
+
renderMap.forEach(({ content }, relativePath2) => {
|
|
172
|
+
writeFile(joinPath(basePath, relativePath2));
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
exports.addToRenderMap = addToRenderMap;
|
|
177
|
+
exports.camelCase = camelCase;
|
|
178
|
+
exports.capitalize = capitalize;
|
|
179
|
+
exports.createDirectory = createDirectory;
|
|
180
|
+
exports.createFragmentTemplate = createFragmentTemplate;
|
|
181
|
+
exports.createRenderMap = createRenderMap;
|
|
182
|
+
exports.deleteDirectory = deleteDirectory;
|
|
183
|
+
exports.fileExists = fileExists;
|
|
184
|
+
exports.getFromRenderMap = getFromRenderMap;
|
|
185
|
+
exports.joinPath = joinPath;
|
|
186
|
+
exports.kebabCase = kebabCase;
|
|
187
|
+
exports.mapFragmentContent = mapFragmentContent;
|
|
188
|
+
exports.mapFragmentContentAsync = mapFragmentContentAsync;
|
|
189
|
+
exports.mapRenderMapContent = mapRenderMapContent;
|
|
190
|
+
exports.mapRenderMapContentAsync = mapRenderMapContentAsync;
|
|
191
|
+
exports.mapRenderMapFragment = mapRenderMapFragment;
|
|
192
|
+
exports.mapRenderMapFragmentAsync = mapRenderMapFragmentAsync;
|
|
193
|
+
exports.mergeRenderMaps = mergeRenderMaps;
|
|
194
|
+
exports.pascalCase = pascalCase;
|
|
195
|
+
exports.pathBasename = pathBasename;
|
|
196
|
+
exports.pathDirectory = pathDirectory;
|
|
197
|
+
exports.readFile = readFile;
|
|
198
|
+
exports.readJson = readJson;
|
|
199
|
+
exports.relativePath = relativePath;
|
|
200
|
+
exports.removeFromRenderMap = removeFromRenderMap;
|
|
201
|
+
exports.renderMapContains = renderMapContains;
|
|
202
|
+
exports.setFragmentContent = setFragmentContent;
|
|
203
|
+
exports.snakeCase = snakeCase;
|
|
204
|
+
exports.titleCase = titleCase;
|
|
205
|
+
exports.writeFile = writeFile;
|
|
206
|
+
exports.writeRenderMap = writeRenderMap;
|
|
207
|
+
//# sourceMappingURL=index.browser.cjs.map
|
|
208
|
+
//# sourceMappingURL=index.browser.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/casing.ts","../src/core/createFragmentTemplate.ts","../src/core/path.ts","../src/core/fs.ts","../src/core/setFragmentContent.ts","../src/core/mapFragmentContent.ts","../src/core/renderMap.ts"],"names":["CodamaError","CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE","CODAMA_ERROR__VISITORS__RENDER_MAP_KEY_NOT_FOUND","relativePath"],"mappings":"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","file":"index.browser.cjs","sourcesContent":["/**\n * String-casing helpers used by code generators when emitting\n * identifiers. They normalise an arbitrary input string into a\n * conventional shape (camelCase, PascalCase, kebab-case, snake_case,\n * Title Case) by inserting word boundaries before uppercase letters and\n * splitting on any sequence of non-alphanumeric characters.\n *\n * Returned values are plain `string`. This package deliberately does\n * not depend on `@codama/node-types`, so the branded `CamelCaseString`\n * / `PascalCaseString` / … types are not applied here. Consumers that\n * want the brand (e.g. `@codama/nodes`) can wrap these helpers and\n * apply the cast at their own boundary.\n *\n * The implementations all run through {@link titleCase} as a common\n * intermediate form, so a single deterministic word-splitting policy\n * is shared across every output shape.\n */\n\n/**\n * Uppercase the first character and lowercase the rest. Returns the\n * input unchanged when it is empty.\n */\nexport function capitalize(str: string): string {\n if (str.length === 0) return str;\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\n}\n\n/**\n * Normalise an arbitrary string into Title Case — a space-separated\n * sequence of {@link capitalize}d words. Inserts a space before each\n * uppercase letter, then splits on any run of non-alphanumeric\n * characters and re-joins with single spaces.\n */\nexport function titleCase(str: string): string {\n return str\n .replace(/([A-Z])/g, ' $1')\n .split(/[^a-zA-Z0-9]+/)\n .filter(word => word.length > 0)\n .map(capitalize)\n .join(' ');\n}\n\n/**\n * Normalise an arbitrary string into PascalCase by stripping the\n * spaces from its {@link titleCase} form.\n */\nexport function pascalCase(str: string): string {\n return titleCase(str).split(' ').join('');\n}\n\n/**\n * Normalise an arbitrary string into camelCase by lowercasing the\n * first character of its {@link pascalCase} form.\n */\nexport function camelCase(str: string): string {\n if (str.length === 0) return str;\n const pascalStr = pascalCase(str);\n return pascalStr.charAt(0).toLowerCase() + pascalStr.slice(1);\n}\n\n/**\n * Normalise an arbitrary string into kebab-case — lowercase words\n * joined with `-` — by replacing the spaces in its {@link titleCase}\n * form.\n */\nexport function kebabCase(str: string): string {\n return titleCase(str).split(' ').join('-').toLowerCase();\n}\n\n/**\n * Normalise an arbitrary string into snake_case — lowercase words\n * joined with `_` — by replacing the spaces in its {@link titleCase}\n * form.\n */\nexport function snakeCase(str: string): string {\n return titleCase(str).split(' ').join('_').toLowerCase();\n}\n","import type { BaseFragment } from './BaseFragment';\n\n/**\n * Generic template-tag implementation used by every flavor's `fragment`\n * tagged template.\n *\n * Walks the template/items pair, interpolating fragments verbatim and\n * coercing other values to strings, then defers to the caller-provided\n * `mergeFragments` for combining the surviving sub-fragments. This keeps the\n * fragment shape (imports, features, etc.) opaque to the core layer; each\n * flavor plugs in its own merge logic.\n *\n * Most consumers never call this directly — they use the `fragment` tag\n * exported by `@codama/fragments/javascript` or `@codama/fragments/rust`,\n * which both wrap this helper.\n *\n * @typeParam TFragment - The concrete fragment type. Must extend {@link BaseFragment}.\n * @param template - The template-strings array supplied by the tag call site.\n * @param items - The interpolated values, in order. May be fragments,\n * strings, numbers, booleans, `undefined`, or anything coercible to a string.\n * @param isFragment - A predicate that identifies values of the concrete\n * fragment type so they can be inlined and forwarded to the merger.\n * @param mergeFragments - The flavor-specific merger that knows how to\n * combine fragments' non-content fields (e.g. imports, features). Receives\n * only the sub-fragments found in the template, plus a callback that\n * produces the final merged content string from each sub-fragment's content.\n * @return The fragment produced by `mergeFragments`.\n *\n * @example\n * ```ts\n * import { createFragmentTemplate } from '@codama/fragments';\n *\n * function fragment(template: TemplateStringsArray, ...items: unknown[]) {\n * return createFragmentTemplate(template, items, isFragment, mergeFragments);\n * }\n * ```\n */\nexport function createFragmentTemplate<TFragment extends BaseFragment>(\n template: TemplateStringsArray,\n items: unknown[],\n isFragment: (value: unknown) => value is TFragment,\n mergeFragments: (fragments: TFragment[], mergeContent: (contents: string[]) => string) => TFragment,\n): TFragment {\n const fragments = items.filter(isFragment);\n const zippedItems = items.map((item, i) => {\n const itemPrefix = template[i];\n if (typeof item === 'undefined') return itemPrefix;\n if (isFragment(item)) return itemPrefix + item.content;\n return itemPrefix + String(item as string);\n });\n return mergeFragments(fragments, () => zippedItems.join('') + template[template.length - 1]);\n}\n","/**\n * Path manipulation helpers used by code generators to assemble output\n * file paths.\n *\n * The {@link Path} type is a thin documentation alias for `string` —\n * any place a generator stores or threads a filesystem-relative path,\n * use this name to communicate intent. The {@link joinPath} and\n * {@link pathDirectory} helpers delegate to `node:path` on Node and\n * fall back to lightweight string manipulation on non-Node platforms.\n */\n\nimport { basename, dirname, join, posix } from 'node:path';\n\nimport { CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, CodamaError } from '@codama/errors';\n\n/** A filesystem path inside the generator's output tree. */\nexport type Path = string;\n\n/**\n * Join two or more path segments together. Uses `node:path`'s\n * platform-aware {@link join} on Node; on other platforms (browser,\n * react-native) falls back to a `/`-joined form with consecutive\n * slashes collapsed.\n */\nexport function joinPath(...paths: Path[]): string {\n if (!__NODEJS__) {\n return paths.join('/').replace(/\\/+/g, '/');\n }\n\n return join(...paths);\n}\n\n/**\n * Return the directory portion of a path (i.e. everything up to the\n * last `/` segment). Uses `node:path`'s {@link dirname} on Node and a\n * plain `lastIndexOf` fallback on other platforms.\n */\nexport function pathDirectory(path: Path): Path {\n if (!__NODEJS__) {\n return path.substring(0, path.lastIndexOf('/'));\n }\n\n return dirname(path);\n}\n\n/**\n * Return the trailing segment of a path (everything after the last\n * `/`). Uses `node:path`'s {@link basename} on Node and a plain\n * `lastIndexOf` fallback on other platforms.\n */\nexport function pathBasename(path: Path): Path {\n if (!__NODEJS__) {\n const slash = path.lastIndexOf('/');\n return slash >= 0 ? path.substring(slash + 1) : path;\n }\n\n return basename(path);\n}\n\n/**\n * Compute the POSIX-style relative path from `from` to `to`. Both\n * arguments are treated as `/`-separated logical paths regardless of\n * platform, so the result is consistent across operating systems —\n * suitable for emitting into source code as an import specifier.\n *\n * Node only: non-Node platforms throw {@link CodamaError} because\n * implementing a correct POSIX relative-path algorithm without\n * `node:path` is non-trivial and no current consumer needs it.\n */\nexport function relativePath(from: Path, to: Path): string {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'relative' });\n }\n\n return posix.relative(from, to);\n}\n","/**\n * Node-only filesystem helpers used by code generators to write their\n * output to disk. Each function checks the `__NODEJS__` build flag and\n * throws a structured {@link CodamaError} on non-Node platforms so\n * accidental calls from a browser bundle fail loudly rather than\n * silently no-oping.\n */\n\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';\n\nimport { CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, CodamaError } from '@codama/errors';\n\nimport { Path, pathDirectory } from './path';\n\n/** Create a directory (and any missing parents) at the given path. */\nexport function createDirectory(path: Path): void {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'mkdirSync' });\n }\n\n mkdirSync(path, { recursive: true });\n}\n\n/** Recursively delete the directory at the given path, if it exists. */\nexport function deleteDirectory(path: Path): void {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'rmSync' });\n }\n\n if (existsSync(path)) {\n rmSync(path, { recursive: true });\n }\n}\n\n/**\n * Write `content` to a file at `path`, creating intermediate\n * directories as needed.\n */\nexport function writeFile(path: Path, content: string): void {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'writeFileSync' });\n }\n\n const directory = pathDirectory(path);\n if (!existsSync(directory)) {\n createDirectory(directory);\n }\n writeFileSync(path, content);\n}\n\n/** Check whether a file or directory exists at the given path. */\nexport function fileExists(path: Path): boolean {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'existsSync' });\n }\n\n return existsSync(path);\n}\n\n/** Read the file at the given path as a UTF-8 string. */\nexport function readFile(path: Path): string {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'readFileSync' });\n }\n\n return readFileSync(path, 'utf-8');\n}\n\n/**\n * Read the file at the given path as a UTF-8 string and parse it as\n * JSON. The result is typed as the caller-supplied `T`; no runtime\n * validation is performed.\n */\nexport function readJson<T>(path: Path): T {\n return JSON.parse(readFile(path)) as T;\n}\n","import type { BaseFragment } from './BaseFragment';\n\n/**\n * Return a new frozen fragment whose `content` field has been replaced with\n * `content`, preserving every other field of the input fragment.\n *\n * The output keeps the input's exact concrete type (`TFragment`) so callers\n * never lose any extra fields a flavored fragment may carry (imports,\n * features, etc.).\n *\n * @typeParam TFragment - The concrete fragment type. Must extend {@link BaseFragment}.\n * @param fragment - The source fragment to copy.\n * @param content - The new code string.\n * @return A frozen fragment of the same shape as `fragment` with `content` replaced.\n *\n * @example\n * ```ts\n * import { setFragmentContent } from '@codama/fragments';\n *\n * const next = setFragmentContent(prev, prev.content.toUpperCase());\n * ```\n */\nexport function setFragmentContent<TFragment extends BaseFragment>(fragment: TFragment, content: string): TFragment {\n return Object.freeze({ ...fragment, content });\n}\n","import type { BaseFragment } from './BaseFragment';\nimport { setFragmentContent } from './setFragmentContent';\n\n/**\n * Apply a synchronous transformation to a fragment's `content`, returning a\n * new fragment with every other field preserved.\n *\n * @typeParam TFragment - The concrete fragment type. Must extend {@link BaseFragment}.\n * @param fragment - The source fragment.\n * @param mapContent - A function that receives the current content and\n * returns the new content.\n * @return A frozen fragment with the transformed content.\n *\n * @example\n * ```ts\n * import { mapFragmentContent } from '@codama/fragments';\n *\n * const trimmed = mapFragmentContent(fragment, c => c.trimEnd());\n * ```\n *\n * @see {@link mapFragmentContentAsync} for the async variant.\n */\nexport function mapFragmentContent<TFragment extends BaseFragment>(\n fragment: TFragment,\n mapContent: (content: string) => string,\n): TFragment {\n return setFragmentContent(fragment, mapContent(fragment.content));\n}\n\n/**\n * Async variant of {@link mapFragmentContent}: apply an async transformation\n * to a fragment's `content`.\n *\n * @typeParam TFragment - The concrete fragment type. Must extend {@link BaseFragment}.\n * @param fragment - The source fragment.\n * @param mapContent - An async function that receives the current content\n * and returns a promise resolving to the new content.\n * @return A promise that resolves to a frozen fragment with the transformed\n * content.\n *\n * @example\n * ```ts\n * import { mapFragmentContentAsync } from '@codama/fragments';\n *\n * const formatted = await mapFragmentContentAsync(fragment, formatWithPrettier);\n * ```\n *\n * @see {@link mapFragmentContent} for the sync variant.\n */\nexport async function mapFragmentContentAsync<TFragment extends BaseFragment>(\n fragment: TFragment,\n mapContent: (content: string) => Promise<string>,\n): Promise<TFragment> {\n return setFragmentContent(fragment, await mapContent(fragment.content));\n}\n","/**\n * A `RenderMap` is the in-memory data structure a code generator builds\n * up before writing anything to disk: a frozen `ReadonlyMap` keyed by\n * output path, with a `BaseFragment` (or a concrete subtype carrying\n * imports / features / …) as the value. The helpers in this module are\n * pure data operations — they construct, merge, transform, and query\n * render maps without touching the filesystem.\n *\n * {@link writeRenderMap} is the single filesystem-touching entry point\n * here: it walks a finished map and writes every entry. Renderers that\n * tie a render map to a `Visitor` (see `@codama/renderers-core`) layer\n * that on top.\n */\n\nimport { CODAMA_ERROR__VISITORS__RENDER_MAP_KEY_NOT_FOUND, CodamaError } from '@codama/errors';\n\nimport type { BaseFragment } from './BaseFragment';\nimport { writeFile } from './fs';\nimport { mapFragmentContent, mapFragmentContentAsync } from './mapFragmentContent';\nimport { joinPath, type Path } from './path';\n\n/**\n * A frozen map keyed by output {@link Path}, with each entry holding a\n * fragment that will be written to that path. `TFragment` defaults to\n * {@link BaseFragment} but generators typically pass a richer flavor\n * (e.g. `Fragment` from `@codama/fragments/javascript`) to carry\n * imports and other per-file metadata.\n */\nexport type RenderMap<TFragment extends BaseFragment> = ReadonlyMap<Path, TFragment>;\n\nexport function createRenderMap<TFragment extends BaseFragment = BaseFragment>(): RenderMap<TFragment>;\nexport function createRenderMap<TFragment extends BaseFragment>(path: Path, content: TFragment): RenderMap<TFragment>;\nexport function createRenderMap<TFragment extends BaseFragment>(\n entries: Record<Path, TFragment | undefined>,\n): RenderMap<TFragment>;\nexport function createRenderMap<TFragment extends BaseFragment>(\n pathOrEntries?: Path | Record<Path, TFragment | undefined>,\n content?: TFragment,\n): RenderMap<TFragment> {\n let entries: [Path, TFragment][] = [];\n if (typeof pathOrEntries === 'string' && content !== undefined) {\n entries = [[pathOrEntries, content]];\n } else if (typeof pathOrEntries === 'object' && pathOrEntries !== null) {\n entries = Object.entries(pathOrEntries).flatMap(([key, value]) =>\n value === undefined ? [] : ([[key, value]] as const),\n );\n }\n return Object.freeze(new Map(entries));\n}\n\n/** Add or overwrite a single `(path, fragment)` entry. */\nexport function addToRenderMap<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n path: Path,\n content: TFragment,\n): RenderMap<TFragment> {\n return mergeRenderMaps([renderMap, createRenderMap(path, content)]);\n}\n\n/** Remove the entry at `path`, returning a new frozen map. */\nexport function removeFromRenderMap<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n path: Path,\n): RenderMap<TFragment> {\n const newMap = new Map(renderMap);\n newMap.delete(path);\n return Object.freeze(newMap);\n}\n\n/**\n * Combine multiple render maps into one. Later maps overwrite earlier\n * entries at the same path.\n */\nexport function mergeRenderMaps<TFragment extends BaseFragment>(\n renderMaps: RenderMap<TFragment>[],\n): RenderMap<TFragment> {\n if (renderMaps.length === 0) return createRenderMap();\n if (renderMaps.length === 1) return renderMaps[0];\n const merged = new Map(renderMaps[0]);\n for (const map of renderMaps.slice(1)) {\n for (const [key, value] of map) {\n merged.set(key, value);\n }\n }\n return Object.freeze(merged);\n}\n\n/** Transform every fragment in the map, preserving the keys. */\nexport function mapRenderMapFragment<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n fn: (fragment: TFragment, path: Path) => TFragment,\n): RenderMap<TFragment> {\n return Object.freeze(new Map([...[...renderMap.entries()].map(([key, value]) => [key, fn(value, key)] as const)]));\n}\n\n/** Async variant of {@link mapRenderMapFragment}. */\nexport async function mapRenderMapFragmentAsync<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n fn: (fragment: TFragment, path: Path) => Promise<TFragment>,\n): Promise<RenderMap<TFragment>> {\n return Object.freeze(\n new Map(\n await Promise.all([\n ...[...renderMap.entries()].map(async ([key, value]) => [key, await fn(value, key)] as const),\n ]),\n ),\n );\n}\n\n/** Transform the `content` of every fragment in the map. */\nexport function mapRenderMapContent<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n fn: (content: string, path: Path) => string,\n): RenderMap<TFragment> {\n return mapRenderMapFragment(renderMap, (fragment, path) =>\n mapFragmentContent(fragment, content => fn(content, path)),\n );\n}\n\n/** Async variant of {@link mapRenderMapContent}. */\nexport async function mapRenderMapContentAsync<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n fn: (content: string, path: Path) => Promise<string>,\n): Promise<RenderMap<TFragment>> {\n return await mapRenderMapFragmentAsync(renderMap, (fragment, path) =>\n mapFragmentContentAsync(fragment, content => fn(content, path)),\n );\n}\n\n/**\n * Look up the fragment at `path`, throwing a structured\n * {@link CodamaError} when the key is missing.\n */\nexport function getFromRenderMap<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n path: Path,\n): TFragment {\n const value = renderMap.get(path);\n if (value === undefined) {\n throw new CodamaError(CODAMA_ERROR__VISITORS__RENDER_MAP_KEY_NOT_FOUND, { key: path });\n }\n return value;\n}\n\n/**\n * Test whether the fragment at `path` contains `value`. Accepts either\n * a plain substring or a regular expression.\n */\nexport function renderMapContains<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n path: Path,\n value: RegExp | string,\n): boolean {\n const { content } = getFromRenderMap(renderMap, path);\n return typeof value === 'string' ? content.includes(value) : value.test(content);\n}\n\n/**\n * Walk the render map and write every entry to disk, rooted at\n * `basePath`. Each path is joined with `basePath` via {@link joinPath}\n * and written via {@link writeFile}; the directory structure is\n * created on demand.\n */\nexport function writeRenderMap<TFragment extends BaseFragment>(renderMap: RenderMap<TFragment>, basePath: Path): void {\n renderMap.forEach(({ content }, relativePath) => {\n writeFile(joinPath(basePath, relativePath), content);\n });\n}\n"]}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import 'fs';
|
|
2
|
+
import { CodamaError, CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, CODAMA_ERROR__VISITORS__RENDER_MAP_KEY_NOT_FOUND } from '@codama/errors';
|
|
3
|
+
import 'path';
|
|
4
|
+
|
|
5
|
+
// src/core/casing.ts
|
|
6
|
+
function capitalize(str) {
|
|
7
|
+
if (str.length === 0) return str;
|
|
8
|
+
return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();
|
|
9
|
+
}
|
|
10
|
+
function titleCase(str) {
|
|
11
|
+
return str.replace(/([A-Z])/g, " $1").split(/[^a-zA-Z0-9]+/).filter((word) => word.length > 0).map(capitalize).join(" ");
|
|
12
|
+
}
|
|
13
|
+
function pascalCase(str) {
|
|
14
|
+
return titleCase(str).split(" ").join("");
|
|
15
|
+
}
|
|
16
|
+
function camelCase(str) {
|
|
17
|
+
if (str.length === 0) return str;
|
|
18
|
+
const pascalStr = pascalCase(str);
|
|
19
|
+
return pascalStr.charAt(0).toLowerCase() + pascalStr.slice(1);
|
|
20
|
+
}
|
|
21
|
+
function kebabCase(str) {
|
|
22
|
+
return titleCase(str).split(" ").join("-").toLowerCase();
|
|
23
|
+
}
|
|
24
|
+
function snakeCase(str) {
|
|
25
|
+
return titleCase(str).split(" ").join("_").toLowerCase();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/core/createFragmentTemplate.ts
|
|
29
|
+
function createFragmentTemplate(template, items, isFragment, mergeFragments) {
|
|
30
|
+
const fragments = items.filter(isFragment);
|
|
31
|
+
const zippedItems = items.map((item, i) => {
|
|
32
|
+
const itemPrefix = template[i];
|
|
33
|
+
if (typeof item === "undefined") return itemPrefix;
|
|
34
|
+
if (isFragment(item)) return itemPrefix + item.content;
|
|
35
|
+
return itemPrefix + String(item);
|
|
36
|
+
});
|
|
37
|
+
return mergeFragments(fragments, () => zippedItems.join("") + template[template.length - 1]);
|
|
38
|
+
}
|
|
39
|
+
function joinPath(...paths) {
|
|
40
|
+
{
|
|
41
|
+
return paths.join("/").replace(/\/+/g, "/");
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function pathDirectory(path) {
|
|
45
|
+
{
|
|
46
|
+
return path.substring(0, path.lastIndexOf("/"));
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function pathBasename(path) {
|
|
50
|
+
{
|
|
51
|
+
const slash = path.lastIndexOf("/");
|
|
52
|
+
return slash >= 0 ? path.substring(slash + 1) : path;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function relativePath(from, to) {
|
|
56
|
+
{
|
|
57
|
+
throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: "relative" });
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// src/core/fs.ts
|
|
62
|
+
function createDirectory(path) {
|
|
63
|
+
{
|
|
64
|
+
throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: "mkdirSync" });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
function deleteDirectory(path) {
|
|
68
|
+
{
|
|
69
|
+
throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: "rmSync" });
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function writeFile(path, content) {
|
|
73
|
+
{
|
|
74
|
+
throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: "writeFileSync" });
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
function fileExists(path) {
|
|
78
|
+
{
|
|
79
|
+
throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: "existsSync" });
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function readFile(path) {
|
|
83
|
+
{
|
|
84
|
+
throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: "readFileSync" });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
function readJson(path) {
|
|
88
|
+
return JSON.parse(readFile());
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// src/core/setFragmentContent.ts
|
|
92
|
+
function setFragmentContent(fragment, content) {
|
|
93
|
+
return Object.freeze({ ...fragment, content });
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// src/core/mapFragmentContent.ts
|
|
97
|
+
function mapFragmentContent(fragment, mapContent) {
|
|
98
|
+
return setFragmentContent(fragment, mapContent(fragment.content));
|
|
99
|
+
}
|
|
100
|
+
async function mapFragmentContentAsync(fragment, mapContent) {
|
|
101
|
+
return setFragmentContent(fragment, await mapContent(fragment.content));
|
|
102
|
+
}
|
|
103
|
+
function createRenderMap(pathOrEntries, content) {
|
|
104
|
+
let entries = [];
|
|
105
|
+
if (typeof pathOrEntries === "string" && content !== void 0) {
|
|
106
|
+
entries = [[pathOrEntries, content]];
|
|
107
|
+
} else if (typeof pathOrEntries === "object" && pathOrEntries !== null) {
|
|
108
|
+
entries = Object.entries(pathOrEntries).flatMap(
|
|
109
|
+
([key, value]) => value === void 0 ? [] : [[key, value]]
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
return Object.freeze(new Map(entries));
|
|
113
|
+
}
|
|
114
|
+
function addToRenderMap(renderMap, path, content) {
|
|
115
|
+
return mergeRenderMaps([renderMap, createRenderMap(path, content)]);
|
|
116
|
+
}
|
|
117
|
+
function removeFromRenderMap(renderMap, path) {
|
|
118
|
+
const newMap = new Map(renderMap);
|
|
119
|
+
newMap.delete(path);
|
|
120
|
+
return Object.freeze(newMap);
|
|
121
|
+
}
|
|
122
|
+
function mergeRenderMaps(renderMaps) {
|
|
123
|
+
if (renderMaps.length === 0) return createRenderMap();
|
|
124
|
+
if (renderMaps.length === 1) return renderMaps[0];
|
|
125
|
+
const merged = new Map(renderMaps[0]);
|
|
126
|
+
for (const map of renderMaps.slice(1)) {
|
|
127
|
+
for (const [key, value] of map) {
|
|
128
|
+
merged.set(key, value);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return Object.freeze(merged);
|
|
132
|
+
}
|
|
133
|
+
function mapRenderMapFragment(renderMap, fn) {
|
|
134
|
+
return Object.freeze(new Map([...[...renderMap.entries()].map(([key, value]) => [key, fn(value, key)])]));
|
|
135
|
+
}
|
|
136
|
+
async function mapRenderMapFragmentAsync(renderMap, fn) {
|
|
137
|
+
return Object.freeze(
|
|
138
|
+
new Map(
|
|
139
|
+
await Promise.all([
|
|
140
|
+
...[...renderMap.entries()].map(async ([key, value]) => [key, await fn(value, key)])
|
|
141
|
+
])
|
|
142
|
+
)
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
function mapRenderMapContent(renderMap, fn) {
|
|
146
|
+
return mapRenderMapFragment(
|
|
147
|
+
renderMap,
|
|
148
|
+
(fragment, path) => mapFragmentContent(fragment, (content) => fn(content, path))
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
async function mapRenderMapContentAsync(renderMap, fn) {
|
|
152
|
+
return await mapRenderMapFragmentAsync(
|
|
153
|
+
renderMap,
|
|
154
|
+
(fragment, path) => mapFragmentContentAsync(fragment, (content) => fn(content, path))
|
|
155
|
+
);
|
|
156
|
+
}
|
|
157
|
+
function getFromRenderMap(renderMap, path) {
|
|
158
|
+
const value = renderMap.get(path);
|
|
159
|
+
if (value === void 0) {
|
|
160
|
+
throw new CodamaError(CODAMA_ERROR__VISITORS__RENDER_MAP_KEY_NOT_FOUND, { key: path });
|
|
161
|
+
}
|
|
162
|
+
return value;
|
|
163
|
+
}
|
|
164
|
+
function renderMapContains(renderMap, path, value) {
|
|
165
|
+
const { content } = getFromRenderMap(renderMap, path);
|
|
166
|
+
return typeof value === "string" ? content.includes(value) : value.test(content);
|
|
167
|
+
}
|
|
168
|
+
function writeRenderMap(renderMap, basePath) {
|
|
169
|
+
renderMap.forEach(({ content }, relativePath2) => {
|
|
170
|
+
writeFile(joinPath(basePath, relativePath2));
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export { addToRenderMap, camelCase, capitalize, createDirectory, createFragmentTemplate, createRenderMap, deleteDirectory, fileExists, getFromRenderMap, joinPath, kebabCase, mapFragmentContent, mapFragmentContentAsync, mapRenderMapContent, mapRenderMapContentAsync, mapRenderMapFragment, mapRenderMapFragmentAsync, mergeRenderMaps, pascalCase, pathBasename, pathDirectory, readFile, readJson, relativePath, removeFromRenderMap, renderMapContains, setFragmentContent, snakeCase, titleCase, writeFile, writeRenderMap };
|
|
175
|
+
//# sourceMappingURL=index.browser.mjs.map
|
|
176
|
+
//# sourceMappingURL=index.browser.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/casing.ts","../src/core/createFragmentTemplate.ts","../src/core/path.ts","../src/core/fs.ts","../src/core/setFragmentContent.ts","../src/core/mapFragmentContent.ts","../src/core/renderMap.ts"],"names":["CodamaError","CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE","relativePath"],"mappings":"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","file":"index.browser.mjs","sourcesContent":["/**\n * String-casing helpers used by code generators when emitting\n * identifiers. They normalise an arbitrary input string into a\n * conventional shape (camelCase, PascalCase, kebab-case, snake_case,\n * Title Case) by inserting word boundaries before uppercase letters and\n * splitting on any sequence of non-alphanumeric characters.\n *\n * Returned values are plain `string`. This package deliberately does\n * not depend on `@codama/node-types`, so the branded `CamelCaseString`\n * / `PascalCaseString` / … types are not applied here. Consumers that\n * want the brand (e.g. `@codama/nodes`) can wrap these helpers and\n * apply the cast at their own boundary.\n *\n * The implementations all run through {@link titleCase} as a common\n * intermediate form, so a single deterministic word-splitting policy\n * is shared across every output shape.\n */\n\n/**\n * Uppercase the first character and lowercase the rest. Returns the\n * input unchanged when it is empty.\n */\nexport function capitalize(str: string): string {\n if (str.length === 0) return str;\n return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase();\n}\n\n/**\n * Normalise an arbitrary string into Title Case — a space-separated\n * sequence of {@link capitalize}d words. Inserts a space before each\n * uppercase letter, then splits on any run of non-alphanumeric\n * characters and re-joins with single spaces.\n */\nexport function titleCase(str: string): string {\n return str\n .replace(/([A-Z])/g, ' $1')\n .split(/[^a-zA-Z0-9]+/)\n .filter(word => word.length > 0)\n .map(capitalize)\n .join(' ');\n}\n\n/**\n * Normalise an arbitrary string into PascalCase by stripping the\n * spaces from its {@link titleCase} form.\n */\nexport function pascalCase(str: string): string {\n return titleCase(str).split(' ').join('');\n}\n\n/**\n * Normalise an arbitrary string into camelCase by lowercasing the\n * first character of its {@link pascalCase} form.\n */\nexport function camelCase(str: string): string {\n if (str.length === 0) return str;\n const pascalStr = pascalCase(str);\n return pascalStr.charAt(0).toLowerCase() + pascalStr.slice(1);\n}\n\n/**\n * Normalise an arbitrary string into kebab-case — lowercase words\n * joined with `-` — by replacing the spaces in its {@link titleCase}\n * form.\n */\nexport function kebabCase(str: string): string {\n return titleCase(str).split(' ').join('-').toLowerCase();\n}\n\n/**\n * Normalise an arbitrary string into snake_case — lowercase words\n * joined with `_` — by replacing the spaces in its {@link titleCase}\n * form.\n */\nexport function snakeCase(str: string): string {\n return titleCase(str).split(' ').join('_').toLowerCase();\n}\n","import type { BaseFragment } from './BaseFragment';\n\n/**\n * Generic template-tag implementation used by every flavor's `fragment`\n * tagged template.\n *\n * Walks the template/items pair, interpolating fragments verbatim and\n * coercing other values to strings, then defers to the caller-provided\n * `mergeFragments` for combining the surviving sub-fragments. This keeps the\n * fragment shape (imports, features, etc.) opaque to the core layer; each\n * flavor plugs in its own merge logic.\n *\n * Most consumers never call this directly — they use the `fragment` tag\n * exported by `@codama/fragments/javascript` or `@codama/fragments/rust`,\n * which both wrap this helper.\n *\n * @typeParam TFragment - The concrete fragment type. Must extend {@link BaseFragment}.\n * @param template - The template-strings array supplied by the tag call site.\n * @param items - The interpolated values, in order. May be fragments,\n * strings, numbers, booleans, `undefined`, or anything coercible to a string.\n * @param isFragment - A predicate that identifies values of the concrete\n * fragment type so they can be inlined and forwarded to the merger.\n * @param mergeFragments - The flavor-specific merger that knows how to\n * combine fragments' non-content fields (e.g. imports, features). Receives\n * only the sub-fragments found in the template, plus a callback that\n * produces the final merged content string from each sub-fragment's content.\n * @return The fragment produced by `mergeFragments`.\n *\n * @example\n * ```ts\n * import { createFragmentTemplate } from '@codama/fragments';\n *\n * function fragment(template: TemplateStringsArray, ...items: unknown[]) {\n * return createFragmentTemplate(template, items, isFragment, mergeFragments);\n * }\n * ```\n */\nexport function createFragmentTemplate<TFragment extends BaseFragment>(\n template: TemplateStringsArray,\n items: unknown[],\n isFragment: (value: unknown) => value is TFragment,\n mergeFragments: (fragments: TFragment[], mergeContent: (contents: string[]) => string) => TFragment,\n): TFragment {\n const fragments = items.filter(isFragment);\n const zippedItems = items.map((item, i) => {\n const itemPrefix = template[i];\n if (typeof item === 'undefined') return itemPrefix;\n if (isFragment(item)) return itemPrefix + item.content;\n return itemPrefix + String(item as string);\n });\n return mergeFragments(fragments, () => zippedItems.join('') + template[template.length - 1]);\n}\n","/**\n * Path manipulation helpers used by code generators to assemble output\n * file paths.\n *\n * The {@link Path} type is a thin documentation alias for `string` —\n * any place a generator stores or threads a filesystem-relative path,\n * use this name to communicate intent. The {@link joinPath} and\n * {@link pathDirectory} helpers delegate to `node:path` on Node and\n * fall back to lightweight string manipulation on non-Node platforms.\n */\n\nimport { basename, dirname, join, posix } from 'node:path';\n\nimport { CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, CodamaError } from '@codama/errors';\n\n/** A filesystem path inside the generator's output tree. */\nexport type Path = string;\n\n/**\n * Join two or more path segments together. Uses `node:path`'s\n * platform-aware {@link join} on Node; on other platforms (browser,\n * react-native) falls back to a `/`-joined form with consecutive\n * slashes collapsed.\n */\nexport function joinPath(...paths: Path[]): string {\n if (!__NODEJS__) {\n return paths.join('/').replace(/\\/+/g, '/');\n }\n\n return join(...paths);\n}\n\n/**\n * Return the directory portion of a path (i.e. everything up to the\n * last `/` segment). Uses `node:path`'s {@link dirname} on Node and a\n * plain `lastIndexOf` fallback on other platforms.\n */\nexport function pathDirectory(path: Path): Path {\n if (!__NODEJS__) {\n return path.substring(0, path.lastIndexOf('/'));\n }\n\n return dirname(path);\n}\n\n/**\n * Return the trailing segment of a path (everything after the last\n * `/`). Uses `node:path`'s {@link basename} on Node and a plain\n * `lastIndexOf` fallback on other platforms.\n */\nexport function pathBasename(path: Path): Path {\n if (!__NODEJS__) {\n const slash = path.lastIndexOf('/');\n return slash >= 0 ? path.substring(slash + 1) : path;\n }\n\n return basename(path);\n}\n\n/**\n * Compute the POSIX-style relative path from `from` to `to`. Both\n * arguments are treated as `/`-separated logical paths regardless of\n * platform, so the result is consistent across operating systems —\n * suitable for emitting into source code as an import specifier.\n *\n * Node only: non-Node platforms throw {@link CodamaError} because\n * implementing a correct POSIX relative-path algorithm without\n * `node:path` is non-trivial and no current consumer needs it.\n */\nexport function relativePath(from: Path, to: Path): string {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'relative' });\n }\n\n return posix.relative(from, to);\n}\n","/**\n * Node-only filesystem helpers used by code generators to write their\n * output to disk. Each function checks the `__NODEJS__` build flag and\n * throws a structured {@link CodamaError} on non-Node platforms so\n * accidental calls from a browser bundle fail loudly rather than\n * silently no-oping.\n */\n\nimport { existsSync, mkdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';\n\nimport { CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, CodamaError } from '@codama/errors';\n\nimport { Path, pathDirectory } from './path';\n\n/** Create a directory (and any missing parents) at the given path. */\nexport function createDirectory(path: Path): void {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'mkdirSync' });\n }\n\n mkdirSync(path, { recursive: true });\n}\n\n/** Recursively delete the directory at the given path, if it exists. */\nexport function deleteDirectory(path: Path): void {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'rmSync' });\n }\n\n if (existsSync(path)) {\n rmSync(path, { recursive: true });\n }\n}\n\n/**\n * Write `content` to a file at `path`, creating intermediate\n * directories as needed.\n */\nexport function writeFile(path: Path, content: string): void {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'writeFileSync' });\n }\n\n const directory = pathDirectory(path);\n if (!existsSync(directory)) {\n createDirectory(directory);\n }\n writeFileSync(path, content);\n}\n\n/** Check whether a file or directory exists at the given path. */\nexport function fileExists(path: Path): boolean {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'existsSync' });\n }\n\n return existsSync(path);\n}\n\n/** Read the file at the given path as a UTF-8 string. */\nexport function readFile(path: Path): string {\n if (!__NODEJS__) {\n throw new CodamaError(CODAMA_ERROR__NODE_FILESYSTEM_FUNCTION_UNAVAILABLE, { fsFunction: 'readFileSync' });\n }\n\n return readFileSync(path, 'utf-8');\n}\n\n/**\n * Read the file at the given path as a UTF-8 string and parse it as\n * JSON. The result is typed as the caller-supplied `T`; no runtime\n * validation is performed.\n */\nexport function readJson<T>(path: Path): T {\n return JSON.parse(readFile(path)) as T;\n}\n","import type { BaseFragment } from './BaseFragment';\n\n/**\n * Return a new frozen fragment whose `content` field has been replaced with\n * `content`, preserving every other field of the input fragment.\n *\n * The output keeps the input's exact concrete type (`TFragment`) so callers\n * never lose any extra fields a flavored fragment may carry (imports,\n * features, etc.).\n *\n * @typeParam TFragment - The concrete fragment type. Must extend {@link BaseFragment}.\n * @param fragment - The source fragment to copy.\n * @param content - The new code string.\n * @return A frozen fragment of the same shape as `fragment` with `content` replaced.\n *\n * @example\n * ```ts\n * import { setFragmentContent } from '@codama/fragments';\n *\n * const next = setFragmentContent(prev, prev.content.toUpperCase());\n * ```\n */\nexport function setFragmentContent<TFragment extends BaseFragment>(fragment: TFragment, content: string): TFragment {\n return Object.freeze({ ...fragment, content });\n}\n","import type { BaseFragment } from './BaseFragment';\nimport { setFragmentContent } from './setFragmentContent';\n\n/**\n * Apply a synchronous transformation to a fragment's `content`, returning a\n * new fragment with every other field preserved.\n *\n * @typeParam TFragment - The concrete fragment type. Must extend {@link BaseFragment}.\n * @param fragment - The source fragment.\n * @param mapContent - A function that receives the current content and\n * returns the new content.\n * @return A frozen fragment with the transformed content.\n *\n * @example\n * ```ts\n * import { mapFragmentContent } from '@codama/fragments';\n *\n * const trimmed = mapFragmentContent(fragment, c => c.trimEnd());\n * ```\n *\n * @see {@link mapFragmentContentAsync} for the async variant.\n */\nexport function mapFragmentContent<TFragment extends BaseFragment>(\n fragment: TFragment,\n mapContent: (content: string) => string,\n): TFragment {\n return setFragmentContent(fragment, mapContent(fragment.content));\n}\n\n/**\n * Async variant of {@link mapFragmentContent}: apply an async transformation\n * to a fragment's `content`.\n *\n * @typeParam TFragment - The concrete fragment type. Must extend {@link BaseFragment}.\n * @param fragment - The source fragment.\n * @param mapContent - An async function that receives the current content\n * and returns a promise resolving to the new content.\n * @return A promise that resolves to a frozen fragment with the transformed\n * content.\n *\n * @example\n * ```ts\n * import { mapFragmentContentAsync } from '@codama/fragments';\n *\n * const formatted = await mapFragmentContentAsync(fragment, formatWithPrettier);\n * ```\n *\n * @see {@link mapFragmentContent} for the sync variant.\n */\nexport async function mapFragmentContentAsync<TFragment extends BaseFragment>(\n fragment: TFragment,\n mapContent: (content: string) => Promise<string>,\n): Promise<TFragment> {\n return setFragmentContent(fragment, await mapContent(fragment.content));\n}\n","/**\n * A `RenderMap` is the in-memory data structure a code generator builds\n * up before writing anything to disk: a frozen `ReadonlyMap` keyed by\n * output path, with a `BaseFragment` (or a concrete subtype carrying\n * imports / features / …) as the value. The helpers in this module are\n * pure data operations — they construct, merge, transform, and query\n * render maps without touching the filesystem.\n *\n * {@link writeRenderMap} is the single filesystem-touching entry point\n * here: it walks a finished map and writes every entry. Renderers that\n * tie a render map to a `Visitor` (see `@codama/renderers-core`) layer\n * that on top.\n */\n\nimport { CODAMA_ERROR__VISITORS__RENDER_MAP_KEY_NOT_FOUND, CodamaError } from '@codama/errors';\n\nimport type { BaseFragment } from './BaseFragment';\nimport { writeFile } from './fs';\nimport { mapFragmentContent, mapFragmentContentAsync } from './mapFragmentContent';\nimport { joinPath, type Path } from './path';\n\n/**\n * A frozen map keyed by output {@link Path}, with each entry holding a\n * fragment that will be written to that path. `TFragment` defaults to\n * {@link BaseFragment} but generators typically pass a richer flavor\n * (e.g. `Fragment` from `@codama/fragments/javascript`) to carry\n * imports and other per-file metadata.\n */\nexport type RenderMap<TFragment extends BaseFragment> = ReadonlyMap<Path, TFragment>;\n\nexport function createRenderMap<TFragment extends BaseFragment = BaseFragment>(): RenderMap<TFragment>;\nexport function createRenderMap<TFragment extends BaseFragment>(path: Path, content: TFragment): RenderMap<TFragment>;\nexport function createRenderMap<TFragment extends BaseFragment>(\n entries: Record<Path, TFragment | undefined>,\n): RenderMap<TFragment>;\nexport function createRenderMap<TFragment extends BaseFragment>(\n pathOrEntries?: Path | Record<Path, TFragment | undefined>,\n content?: TFragment,\n): RenderMap<TFragment> {\n let entries: [Path, TFragment][] = [];\n if (typeof pathOrEntries === 'string' && content !== undefined) {\n entries = [[pathOrEntries, content]];\n } else if (typeof pathOrEntries === 'object' && pathOrEntries !== null) {\n entries = Object.entries(pathOrEntries).flatMap(([key, value]) =>\n value === undefined ? [] : ([[key, value]] as const),\n );\n }\n return Object.freeze(new Map(entries));\n}\n\n/** Add or overwrite a single `(path, fragment)` entry. */\nexport function addToRenderMap<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n path: Path,\n content: TFragment,\n): RenderMap<TFragment> {\n return mergeRenderMaps([renderMap, createRenderMap(path, content)]);\n}\n\n/** Remove the entry at `path`, returning a new frozen map. */\nexport function removeFromRenderMap<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n path: Path,\n): RenderMap<TFragment> {\n const newMap = new Map(renderMap);\n newMap.delete(path);\n return Object.freeze(newMap);\n}\n\n/**\n * Combine multiple render maps into one. Later maps overwrite earlier\n * entries at the same path.\n */\nexport function mergeRenderMaps<TFragment extends BaseFragment>(\n renderMaps: RenderMap<TFragment>[],\n): RenderMap<TFragment> {\n if (renderMaps.length === 0) return createRenderMap();\n if (renderMaps.length === 1) return renderMaps[0];\n const merged = new Map(renderMaps[0]);\n for (const map of renderMaps.slice(1)) {\n for (const [key, value] of map) {\n merged.set(key, value);\n }\n }\n return Object.freeze(merged);\n}\n\n/** Transform every fragment in the map, preserving the keys. */\nexport function mapRenderMapFragment<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n fn: (fragment: TFragment, path: Path) => TFragment,\n): RenderMap<TFragment> {\n return Object.freeze(new Map([...[...renderMap.entries()].map(([key, value]) => [key, fn(value, key)] as const)]));\n}\n\n/** Async variant of {@link mapRenderMapFragment}. */\nexport async function mapRenderMapFragmentAsync<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n fn: (fragment: TFragment, path: Path) => Promise<TFragment>,\n): Promise<RenderMap<TFragment>> {\n return Object.freeze(\n new Map(\n await Promise.all([\n ...[...renderMap.entries()].map(async ([key, value]) => [key, await fn(value, key)] as const),\n ]),\n ),\n );\n}\n\n/** Transform the `content` of every fragment in the map. */\nexport function mapRenderMapContent<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n fn: (content: string, path: Path) => string,\n): RenderMap<TFragment> {\n return mapRenderMapFragment(renderMap, (fragment, path) =>\n mapFragmentContent(fragment, content => fn(content, path)),\n );\n}\n\n/** Async variant of {@link mapRenderMapContent}. */\nexport async function mapRenderMapContentAsync<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n fn: (content: string, path: Path) => Promise<string>,\n): Promise<RenderMap<TFragment>> {\n return await mapRenderMapFragmentAsync(renderMap, (fragment, path) =>\n mapFragmentContentAsync(fragment, content => fn(content, path)),\n );\n}\n\n/**\n * Look up the fragment at `path`, throwing a structured\n * {@link CodamaError} when the key is missing.\n */\nexport function getFromRenderMap<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n path: Path,\n): TFragment {\n const value = renderMap.get(path);\n if (value === undefined) {\n throw new CodamaError(CODAMA_ERROR__VISITORS__RENDER_MAP_KEY_NOT_FOUND, { key: path });\n }\n return value;\n}\n\n/**\n * Test whether the fragment at `path` contains `value`. Accepts either\n * a plain substring or a regular expression.\n */\nexport function renderMapContains<TFragment extends BaseFragment>(\n renderMap: RenderMap<TFragment>,\n path: Path,\n value: RegExp | string,\n): boolean {\n const { content } = getFromRenderMap(renderMap, path);\n return typeof value === 'string' ? content.includes(value) : value.test(content);\n}\n\n/**\n * Walk the render map and write every entry to disk, rooted at\n * `basePath`. Each path is joined with `basePath` via {@link joinPath}\n * and written via {@link writeFile}; the directory structure is\n * created on demand.\n */\nexport function writeRenderMap<TFragment extends BaseFragment>(renderMap: RenderMap<TFragment>, basePath: Path): void {\n renderMap.forEach(({ content }, relativePath) => {\n writeFile(joinPath(basePath, relativePath), content);\n });\n}\n"]}
|