-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathyarn.config.cjs
More file actions
156 lines (145 loc) · 5.56 KB
/
Copy pathyarn.config.cjs
File metadata and controls
156 lines (145 loc) · 5.56 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
// /** @type {import('@yarnpkg/types')} */
// const { defineConfig } = require('@yarnpkg/types');
const defineConfig = config => config;
module.exports = defineConfig({
async constraints({ Yarn }) {
const root = Yarn.workspace({ cwd: '.' });
for (const workspace of Yarn.workspaces()) {
if (workspace.cwd.startsWith('csr/')) continue; // skip csr workspaces for now, they have different requirements
const depsToWorkspace = Yarn.dependencies({ ident: workspace.ident });
if (!workspace.cwd.startsWith('packages/')) {
// workspace is not a published package (example or root)
// ...it should be private
workspace.set('private', true);
// ...there should be no dependencies to it
for (const dep of depsToWorkspace) {
dep.delete();
}
// done with this workspace
continue;
}
// workspace is a published package
// make sure all deps to this workspace use the correct version
for (const dep of depsToWorkspace) {
if (dep.workspace.cwd.startsWith('examples/')) {
// example apps should always use the workspace version
dep.update('workspace:*');
} else if (dep.type === 'peerDependencies') {
// peer dependencies should use a GT & LT range
// example: ">=0.1.4 <=0.3.x" where 0.3.x is the next breaking version
const [minVersion] = dep.range.match(/^>=\d+\.\d+\.\d+/) || [];
if (!minVersion) {
dep.error(`Expected peer dependency to use a min version`);
}
// TODO maybe automatically set the max version to the next breaking version
// dep.workspace.set(['peerDependencies', dep.ident], `${minVersion} <=${workspace.pkg.version}`);
// peer dependencies should also have a dev dependency to the workspace
dep.workspace.set(['devDependencies', dep.ident], 'workspace:*');
} else if (dep.type === 'devDependencies') {
dep.update('workspace:*');
} else if (dep.type === 'dependencies') {
// there should be no regular deps between packages.
dep.delete();
}
}
// package.json invariants
workspace.set('type', 'module');
if (workspace.cwd === 'packages/react') {
workspace.set('files', ['./index.*', './server.*', './patch-next-dev.cjs']);
workspace.set('scripts.prepack', 'yarn build && yarn bundle && cp dist/* .');
workspace.set('scripts.postpack', 'rm server.* & rm index.*');
workspace.set(
'exports',
buildExports({
'.': 'index',
'./server': 'server',
}),
);
workspace.set('publishConfig', {
registry: 'https://registry.npmjs.org/',
access: 'public',
main: 'index.cjs',
module: 'index.mjs',
types: 'index.d.ts',
exports: conditionalExports(
{
'.': 'index',
'./server': 'server',
},
'./',
),
});
} else {
workspace.set('files', ['dist/index.*']);
workspace.set('scripts.prepack', 'yarn build && yarn bundle');
workspace.set('exports', buildExports({ '.': 'index' }));
workspace.set('publishConfig', {
registry: 'https://registry.npmjs.org/',
access: 'public',
exports: distExports({ '.': 'index' }),
main: 'dist/index.cjs',
module: 'dist/index.mjs',
types: 'dist/index.d.ts',
});
}
if (workspace.cwd === 'packages/sdk') {
workspace.set('scripts.bundle', 'rollup -c && api-extractor run && ../../emit-dcts.sh');
} else {
workspace.set('scripts.bundle', 'rollup -c && ../../validate-api.sh && ../../emit-dcts.sh');
}
workspace.set('scripts.build', 'tsc');
workspace.set('scripts.clean', 'rm -rf {build,dist}');
workspace.unset('main');
workspace.unset('module');
workspace.unset('types');
// dev deps that should all share the same version (from root package.json)
for (const id of ['rollup', 'typescript']) {
workspace.set(['devDependencies', id], getRootVersion(id));
}
}
function getRootVersion(id) {
const version = root.pkg.dependencies.get(id)?.version;
if (!version) {
root.error(`Expected dependency on ${id}.`);
}
return version;
}
},
});
function buildExports(map) {
return Object.fromEntries(
Object.entries(map).map(([key, value]) => {
if (typeof value === 'string') {
value = {
import: `./build/${value}.js`,
types: `./build/${value}.d.ts`,
};
}
return [key, value];
}),
);
}
/**
* Build a conditional exports map for bundled output living under `prefix`.
*
* `types` is nested inside each condition rather than listed as a sibling: conditions are
* matched in order, so a top-level `types` after `import`/`require` is never reached. The
* require branch points at .d.cts (see emit-dcts.sh) so that CJS consumers on
* moduleResolution=node16 don't fall back to the ESM .d.ts.
*/
function conditionalExports(map, prefix) {
return Object.fromEntries(
Object.entries(map).map(([key, value]) => {
if (typeof value === 'string') {
value = {
import: { types: `${prefix}${value}.d.ts`, default: `${prefix}${value}.mjs` },
require: { types: `${prefix}${value}.d.cts`, default: `${prefix}${value}.cjs` },
};
}
return [key, value];
}),
);
}
function distExports(map) {
return conditionalExports(map, './dist/');
}