@metreeca/rack 0.0.0-stage → 0.2.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 +201 -0
- package/README.md +37 -2
- package/dist/tool/cp.d.ts +30 -0
- package/dist/tool/cp.d.ts.map +1 -0
- package/dist/tool/cp.js +74 -0
- package/dist/tool/cp.js.map +1 -0
- package/dist/tool/index.core.d.ts +18 -0
- package/dist/tool/index.core.d.ts.map +1 -0
- package/dist/tool/index.core.js +66 -0
- package/dist/tool/index.core.js.map +1 -0
- package/dist/tool/index.d.ts +19 -0
- package/dist/tool/index.d.ts.map +1 -0
- package/dist/tool/index.js +17 -0
- package/dist/tool/index.js.map +1 -0
- package/dist/tool/ln.d.ts +47 -0
- package/dist/tool/ln.d.ts.map +1 -0
- package/dist/tool/ln.js +187 -0
- package/dist/tool/ln.js.map +1 -0
- package/dist/tool/rm.d.ts +25 -0
- package/dist/tool/rm.d.ts.map +1 -0
- package/dist/tool/rm.js +57 -0
- package/dist/tool/rm.js.map +1 -0
- package/dist/vite/index.d.ts +11 -0
- package/dist/vite/index.d.ts.map +1 -0
- package/dist/vite/index.js +26 -0
- package/dist/vite/index.js.map +1 -0
- package/dist/vite/symlinks.d.ts +48 -0
- package/dist/vite/symlinks.d.ts.map +1 -0
- package/dist/vite/symlinks.js +102 -0
- package/dist/vite/symlinks.js.map +1 -0
- package/package.json +67 -4
package/LICENSE
ADDED
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
10
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
11
|
+
|
|
12
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
13
|
+
the copyright owner that is granting the License.
|
|
14
|
+
|
|
15
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
16
|
+
other entities that control, are controlled by, or are under common
|
|
17
|
+
control with that entity. For the purposes of this definition,
|
|
18
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
19
|
+
direction or management of such entity, whether by contract or
|
|
20
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
21
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
22
|
+
|
|
23
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
24
|
+
exercising permissions granted by this License.
|
|
25
|
+
|
|
26
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
27
|
+
including but not limited to software source code, documentation
|
|
28
|
+
source, and configuration files.
|
|
29
|
+
|
|
30
|
+
"Object" form shall mean any form resulting from mechanical
|
|
31
|
+
transformation or translation of a Source form, including but
|
|
32
|
+
not limited to compiled object code, generated documentation,
|
|
33
|
+
and conversions to other media types.
|
|
34
|
+
|
|
35
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
36
|
+
Object form, made available under the License, as indicated by a
|
|
37
|
+
copyright notice that is included in or attached to the work
|
|
38
|
+
(an example is provided in the Appendix below).
|
|
39
|
+
|
|
40
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
41
|
+
form, that is based on (or derived from) the Work and for which the
|
|
42
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
43
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
44
|
+
of this License, Derivative Works shall not include works that remain
|
|
45
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
46
|
+
the Work and Derivative Works thereof.
|
|
47
|
+
|
|
48
|
+
"Contribution" shall mean any work of authorship, including
|
|
49
|
+
the original version of the Work and any modifications or additions
|
|
50
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
51
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
52
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
53
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
54
|
+
means any form of electronic, verbal, or written communication sent
|
|
55
|
+
to the Licensor or its representatives, including but not limited to
|
|
56
|
+
communication on electronic mailing lists, source code control systems,
|
|
57
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
58
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
59
|
+
excluding communication that is conspicuously marked or otherwise
|
|
60
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
61
|
+
|
|
62
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
63
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
64
|
+
subsequently incorporated within the Work.
|
|
65
|
+
|
|
66
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
67
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
68
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
69
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
70
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
71
|
+
Work and such Derivative Works in Source or Object form.
|
|
72
|
+
|
|
73
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
74
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
75
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
76
|
+
(except as stated in this section) patent license to make, have made,
|
|
77
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
78
|
+
where such license applies only to those patent claims licensable
|
|
79
|
+
by such Contributor that are necessarily infringed by their
|
|
80
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
81
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
82
|
+
institute patent litigation against any entity (including a
|
|
83
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
84
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
85
|
+
or contributory patent infringement, then any patent licenses
|
|
86
|
+
granted to You under this License for that Work shall terminate
|
|
87
|
+
as of the date such litigation is filed.
|
|
88
|
+
|
|
89
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
90
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
91
|
+
modifications, and in Source or Object form, provided that You
|
|
92
|
+
meet the following conditions:
|
|
93
|
+
|
|
94
|
+
(a) You must give any other recipients of the Work or
|
|
95
|
+
Derivative Works a copy of this License; and
|
|
96
|
+
|
|
97
|
+
(b) You must cause any modified files to carry prominent notices
|
|
98
|
+
stating that You changed the files; and
|
|
99
|
+
|
|
100
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
101
|
+
that You distribute, all copyright, patent, trademark, and
|
|
102
|
+
attribution notices from the Source form of the Work,
|
|
103
|
+
excluding those notices that do not pertain to any part of
|
|
104
|
+
the Derivative Works; and
|
|
105
|
+
|
|
106
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
107
|
+
distribution, then any Derivative Works that You distribute must
|
|
108
|
+
include a readable copy of the attribution notices contained
|
|
109
|
+
within such NOTICE file, excluding those notices that do not
|
|
110
|
+
pertain to any part of the Derivative Works, in at least one
|
|
111
|
+
of the following places: within a NOTICE text file distributed
|
|
112
|
+
as part of the Derivative Works; within the Source form or
|
|
113
|
+
documentation, if provided along with the Derivative Works; or,
|
|
114
|
+
within a display generated by the Derivative Works, if and
|
|
115
|
+
wherever such third-party notices normally appear. The contents
|
|
116
|
+
of the NOTICE file are for informational purposes only and
|
|
117
|
+
do not modify the License. You may add Your own attribution
|
|
118
|
+
notices within Derivative Works that You distribute, alongside
|
|
119
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
120
|
+
that such additional attribution notices cannot be construed
|
|
121
|
+
as modifying the License.
|
|
122
|
+
|
|
123
|
+
You may add Your own copyright statement to Your modifications and
|
|
124
|
+
may provide additional or different license terms and conditions
|
|
125
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
126
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
127
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
128
|
+
the conditions stated in this License.
|
|
129
|
+
|
|
130
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
131
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
132
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
133
|
+
this License, without any additional terms or conditions.
|
|
134
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
135
|
+
the terms of any separate license agreement you may have executed
|
|
136
|
+
with Licensor regarding such Contributions.
|
|
137
|
+
|
|
138
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
139
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
140
|
+
except as required for reasonable and customary use in describing the
|
|
141
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
142
|
+
|
|
143
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
144
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
145
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
146
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
147
|
+
implied, including, without limitation, any warranties or conditions
|
|
148
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
149
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
150
|
+
appropriateness of using or redistributing the Work and assume any
|
|
151
|
+
risks associated with Your exercise of permissions under this License.
|
|
152
|
+
|
|
153
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
154
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
155
|
+
unless required by applicable law (such as deliberate and grossly
|
|
156
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
157
|
+
liable to You for damages, including any direct, indirect, special,
|
|
158
|
+
incidental, or consequential damages of any character arising as a
|
|
159
|
+
result of this License or out of the use or inability to use the
|
|
160
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
161
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
162
|
+
other commercial damages or losses), even if such Contributor
|
|
163
|
+
has been advised of the possibility of such damages.
|
|
164
|
+
|
|
165
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
166
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
167
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
168
|
+
or other liability obligations and/or rights consistent with this
|
|
169
|
+
License. However, in accepting such obligations, You may act only
|
|
170
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
171
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
172
|
+
defend, and hold each Contributor harmless for any liability
|
|
173
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
174
|
+
of your accepting any such warranty or additional liability.
|
|
175
|
+
|
|
176
|
+
END OF TERMS AND CONDITIONS
|
|
177
|
+
|
|
178
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
179
|
+
|
|
180
|
+
To apply the Apache License to your work, attach the following
|
|
181
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
182
|
+
replaced with your own identifying information. (Don't include
|
|
183
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
184
|
+
comment syntax for the file format. We also recommend that a
|
|
185
|
+
file or class name and description of purpose be included on the
|
|
186
|
+
same "printed page" as the copyright notice for easier
|
|
187
|
+
identification within third-party archives.
|
|
188
|
+
|
|
189
|
+
Copyright [yyyy] [name of copyright owner]
|
|
190
|
+
|
|
191
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
192
|
+
you may not use this file except in compliance with the License.
|
|
193
|
+
You may obtain a copy of the License at
|
|
194
|
+
|
|
195
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
196
|
+
|
|
197
|
+
Unless required by applicable law or agreed to in writing, software
|
|
198
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
199
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
200
|
+
See the License for the specific language governing permissions and
|
|
201
|
+
limitations under the License.
|
package/README.md
CHANGED
|
@@ -1,3 +1,38 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @metreeca/rack
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[](https://www.npmjs.com/package/@metreeca/rack)
|
|
4
|
+
|
|
5
|
+
Everyday tooling for npm package development.
|
|
6
|
+
|
|
7
|
+
**@metreeca/rack** collects build, test and documentation tooling for recurring npm package development needs, so each
|
|
8
|
+
package consumes a single maintained copy instead of carrying its own. Tools are grouped by the toolchain they extend:
|
|
9
|
+
|
|
10
|
+
| Subpath | Contents |
|
|
11
|
+
|-----------------------------|--------------|
|
|
12
|
+
| [@metreeca/rack/tool][tool] | CLI tools |
|
|
13
|
+
| [@metreeca/rack/vite][vite] | Vite plugins |
|
|
14
|
+
|
|
15
|
+
[tool]: https://metreeca.github.io/rack/modules/tool.html
|
|
16
|
+
|
|
17
|
+
[vite]: https://metreeca.github.io/rack/modules/vite.html
|
|
18
|
+
|
|
19
|
+
# Installation
|
|
20
|
+
|
|
21
|
+
```shell
|
|
22
|
+
npm install --save-dev @metreeca/rack
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
> [!WARNING]
|
|
26
|
+
>
|
|
27
|
+
> TypeScript consumers must use `"moduleResolution": "nodenext"/"node16"/"bundler"` in `tsconfig.json`.
|
|
28
|
+
> The legacy `"node"` resolver is not supported.
|
|
29
|
+
|
|
30
|
+
# Support
|
|
31
|
+
|
|
32
|
+
- open an [issue](https://github.com/metreeca/rack/issues) to report a problem or to suggest a new feature
|
|
33
|
+
- start a [discussion](https://github.com/metreeca/rack/discussions) to ask a how-to question or to share an idea
|
|
34
|
+
|
|
35
|
+
# License
|
|
36
|
+
|
|
37
|
+
This project is licensed under the Apache 2.0 License –
|
|
38
|
+
see [LICENSE](https://github.com/metreeca/rack?tab=Apache-2.0-1-ov-file) file for details.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Copies the files matching a set of glob patterns into a target directory, keeping their relative layout.
|
|
4
|
+
*
|
|
5
|
+
* Each match lands under `target` at its path relative to the base of its pattern, that is the leading segments free
|
|
6
|
+
* of glob characters: `src/**\/*.css` copies `src/a/b.css` to `<target>/a/b.css`, and a plain file path copies the
|
|
7
|
+
* file to the top of `target`. Missing directories are created and existing files are overwritten.
|
|
8
|
+
*
|
|
9
|
+
* Directories matched by a pattern are skipped: only files are copied.
|
|
10
|
+
*
|
|
11
|
+
* Each copied file is printed on stdout, one per line, by its source path as the pattern matched it.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
*
|
|
15
|
+
* Shipping stylesheets next to the compiled modules, from an npm script:
|
|
16
|
+
*
|
|
17
|
+
* ```shell
|
|
18
|
+
* cp dist 'src/**\/*.css'
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Patterns are quoted so that they reach the tool unexpanded, as shells differ in their glob support.
|
|
22
|
+
*
|
|
23
|
+
* @param target The directory receiving the copies
|
|
24
|
+
* @param patterns The glob patterns selecting the files to copy
|
|
25
|
+
*
|
|
26
|
+
* @throws TypeError If `target` is empty or if no pattern is provided
|
|
27
|
+
* @throws Error If a pattern matches no file, in which case no file is copied for any of the patterns
|
|
28
|
+
*/
|
|
29
|
+
export declare function cp(target: string, ...patterns: readonly string[]): void;
|
|
30
|
+
//# sourceMappingURL=cp.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cp.d.ts","sourceRoot":"","sources":["../../src/tool/cp.ts"],"names":[],"mappings":";AA8BA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAiCvE"}
|
package/dist/tool/cp.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/*
|
|
3
|
+
* Copyright © 2026 Metreeca srl
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import { copyFileSync, globSync, mkdirSync, statSync } from "node:fs";
|
|
18
|
+
import { dirname, join, relative } from "node:path";
|
|
19
|
+
import { cli } from "./index.core.js";
|
|
20
|
+
if (import.meta.main) {
|
|
21
|
+
process.exitCode = cli(cp, "<target> <pattern>...");
|
|
22
|
+
}
|
|
23
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
24
|
+
/**
|
|
25
|
+
* Copies the files matching a set of glob patterns into a target directory, keeping their relative layout.
|
|
26
|
+
*
|
|
27
|
+
* Each match lands under `target` at its path relative to the base of its pattern, that is the leading segments free
|
|
28
|
+
* of glob characters: `src/**\/*.css` copies `src/a/b.css` to `<target>/a/b.css`, and a plain file path copies the
|
|
29
|
+
* file to the top of `target`. Missing directories are created and existing files are overwritten.
|
|
30
|
+
*
|
|
31
|
+
* Directories matched by a pattern are skipped: only files are copied.
|
|
32
|
+
*
|
|
33
|
+
* Each copied file is printed on stdout, one per line, by its source path as the pattern matched it.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
*
|
|
37
|
+
* Shipping stylesheets next to the compiled modules, from an npm script:
|
|
38
|
+
*
|
|
39
|
+
* ```shell
|
|
40
|
+
* cp dist 'src/**\/*.css'
|
|
41
|
+
* ```
|
|
42
|
+
*
|
|
43
|
+
* Patterns are quoted so that they reach the tool unexpanded, as shells differ in their glob support.
|
|
44
|
+
*
|
|
45
|
+
* @param target The directory receiving the copies
|
|
46
|
+
* @param patterns The glob patterns selecting the files to copy
|
|
47
|
+
*
|
|
48
|
+
* @throws TypeError If `target` is empty or if no pattern is provided
|
|
49
|
+
* @throws Error If a pattern matches no file, in which case no file is copied for any of the patterns
|
|
50
|
+
*/
|
|
51
|
+
export function cp(target, ...patterns) {
|
|
52
|
+
if (!target) {
|
|
53
|
+
throw new TypeError("missing target operand");
|
|
54
|
+
}
|
|
55
|
+
if (!patterns.length) {
|
|
56
|
+
throw new TypeError("missing pattern operand");
|
|
57
|
+
}
|
|
58
|
+
patterns.flatMap(copies).forEach(({ source, destination }) => {
|
|
59
|
+
mkdirSync(dirname(destination), { recursive: true });
|
|
60
|
+
copyFileSync(source, destination);
|
|
61
|
+
console.log(source);
|
|
62
|
+
});
|
|
63
|
+
function copies(pattern) {
|
|
64
|
+
const sources = globSync(pattern).filter(source => statSync(source).isFile());
|
|
65
|
+
if (!sources.length) {
|
|
66
|
+
throw new Error(`unmatched pattern <${pattern}>`);
|
|
67
|
+
}
|
|
68
|
+
const segments = pattern.split("/");
|
|
69
|
+
const wild = segments.findIndex(segment => /[*?[\]{}]/.test(segment));
|
|
70
|
+
const base = wild < 0 ? dirname(pattern) : segments.slice(0, wild).join("/") || ".";
|
|
71
|
+
return sources.map(source => ({ source, destination: join(target, relative(base, source)) }));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=cp.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cp.js","sourceRoot":"","sources":["../../src/tool/cp.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AACtE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAGtC,IAAK,MAAM,CAAC,IAAI,CAAC,IAAI,EAAG,CAAC;IACxB,OAAO,CAAC,QAAQ,GAAG,GAAG,CAAC,EAAE,EAAE,uBAAuB,CAAC,CAAC;AACrD,CAAC;AAGD,wHAAwH;AAExH;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,UAAU,EAAE,CAAC,MAAc,EAAE,GAAG,QAA2B;IAEhE,IAAK,CAAC,MAAM,EAAG,CAAC;QACf,MAAM,IAAI,SAAS,CAAC,wBAAwB,CAAC,CAAC;IAC/C,CAAC;IAED,IAAK,CAAC,QAAQ,CAAC,MAAM,EAAG,CAAC;QACxB,MAAM,IAAI,SAAS,CAAC,yBAAyB,CAAC,CAAC;IAChD,CAAC;IAED,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,EAAE;QAC5D,SAAS,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,YAAY,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACrB,CAAC,CAAC,CAAC;IAGH,SAAS,MAAM,CAAC,OAAe;QAE9B,MAAM,OAAO,GAAG,QAAQ,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QAE9E,IAAK,CAAC,OAAO,CAAC,MAAM,EAAG,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,sBAAsB,OAAO,GAAG,CAAC,CAAC;QACnD,CAAC;QAED,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACpC,MAAM,IAAI,GAAG,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QACtE,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC;QAEpF,OAAO,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,WAAW,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAE/F,CAAC;AAEF,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runs a tool on a command line, with GNU-style help and error messages.
|
|
3
|
+
*
|
|
4
|
+
* The tool receives the operands as its arguments, with `undefined` in place of a missing one, and throws a
|
|
5
|
+
* `TypeError` on a command line it cannot act on, so that the error message also points to the help.
|
|
6
|
+
*
|
|
7
|
+
* `--help` and `-h` print the usage line to stdout and skip the tool. Errors go to stderr prefixed with the tool name;
|
|
8
|
+
* usage errors, including unrecognized options, also point to `--help`. Operands starting with `-` follow `--`.
|
|
9
|
+
*
|
|
10
|
+
* @param tool The tool to run on the operands
|
|
11
|
+
* @param help The operand synopsis printed by `--help` after the tool name, such as `<target> <pattern>...`
|
|
12
|
+
* @param name The tool name prefixing messages; defaults to the script name without extension, else the `tool` name
|
|
13
|
+
* @param args The command line arguments after the script path; defaults to those the process was launched with
|
|
14
|
+
*
|
|
15
|
+
* @returns The process exit status: `0` on success, `1` on failure
|
|
16
|
+
*/
|
|
17
|
+
export declare function cli(tool: (...args: string[]) => void, help: string, name?: string, args?: readonly string[]): number;
|
|
18
|
+
//# sourceMappingURL=index.core.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.core.d.ts","sourceRoot":"","sources":["../../src/tool/index.core.ts"],"names":[],"mappings":"AAoBA;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,GAAG,CAClB,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,KAAK,IAAI,EACjC,IAAI,EAAE,MAAM,EACZ,IAAI,GAAE,MAAgF,EACtF,IAAI,GAAE,SAAS,MAAM,EAA0B,GAC7C,MAAM,CAoDR"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2026 Metreeca srl
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { parse } from "node:path";
|
|
17
|
+
import { parseArgs } from "node:util";
|
|
18
|
+
/**
|
|
19
|
+
* Runs a tool on a command line, with GNU-style help and error messages.
|
|
20
|
+
*
|
|
21
|
+
* The tool receives the operands as its arguments, with `undefined` in place of a missing one, and throws a
|
|
22
|
+
* `TypeError` on a command line it cannot act on, so that the error message also points to the help.
|
|
23
|
+
*
|
|
24
|
+
* `--help` and `-h` print the usage line to stdout and skip the tool. Errors go to stderr prefixed with the tool name;
|
|
25
|
+
* usage errors, including unrecognized options, also point to `--help`. Operands starting with `-` follow `--`.
|
|
26
|
+
*
|
|
27
|
+
* @param tool The tool to run on the operands
|
|
28
|
+
* @param help The operand synopsis printed by `--help` after the tool name, such as `<target> <pattern>...`
|
|
29
|
+
* @param name The tool name prefixing messages; defaults to the script name without extension, else the `tool` name
|
|
30
|
+
* @param args The command line arguments after the script path; defaults to those the process was launched with
|
|
31
|
+
*
|
|
32
|
+
* @returns The process exit status: `0` on success, `1` on failure
|
|
33
|
+
*/
|
|
34
|
+
export function cli(tool, help, name = process.argv[1] !== undefined ? parse(process.argv[1]).name : tool.name, args = process.argv.slice(2)) {
|
|
35
|
+
const { values, positionals, tokens } = parseArgs({
|
|
36
|
+
args: [...args],
|
|
37
|
+
options: { help: { type: "boolean", short: "h" } },
|
|
38
|
+
allowPositionals: true,
|
|
39
|
+
strict: false, // unknown options are rejected below, with a GNU-style message
|
|
40
|
+
tokens: true
|
|
41
|
+
});
|
|
42
|
+
const unknown = tokens.find(token => token.kind === "option" && token.name !== "help");
|
|
43
|
+
if (unknown?.kind === "option") {
|
|
44
|
+
return fail(`unrecognized option <${unknown.rawName}>`, true);
|
|
45
|
+
}
|
|
46
|
+
else if (values.help) {
|
|
47
|
+
console.log(`Usage: ${name} ${help}`);
|
|
48
|
+
return 0;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
try {
|
|
52
|
+
tool(...positionals);
|
|
53
|
+
return 0;
|
|
54
|
+
}
|
|
55
|
+
catch (error) {
|
|
56
|
+
return fail(error instanceof Error ? error.message : String(error), error instanceof TypeError);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function fail(message, usage) {
|
|
60
|
+
console.error(usage
|
|
61
|
+
? `${name}: ${message}\nTry '${name} --help' for more information.`
|
|
62
|
+
: `${name}: ${message}`);
|
|
63
|
+
return 1;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=index.core.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.core.js","sourceRoot":"","sources":["../../src/tool/index.core.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAGtC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,GAAG,CAClB,IAAiC,EACjC,IAAY,EACZ,OAAe,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EACtF,OAA0B,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAG/C,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;QACjD,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC;QACf,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAClD,gBAAgB,EAAE,IAAI;QACtB,MAAM,EAAE,KAAK,EAAE,+DAA+D;QAC9E,MAAM,EAAE,IAAI;KACZ,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CACnC,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,CAChD,CAAC;IAEF,IAAK,OAAO,EAAE,IAAI,KAAK,QAAQ,EAAG,CAAC;QAElC,OAAO,IAAI,CAAC,wBAAwB,OAAO,CAAC,OAAO,GAAG,EAAE,IAAI,CAAC,CAAC;IAE/D,CAAC;SAAM,IAAK,MAAM,CAAC,IAAI,EAAG,CAAC;QAE1B,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC;QAEtC,OAAO,CAAC,CAAC;IAEV,CAAC;SAAM,CAAC;QAEP,IAAI,CAAC;YAEJ,IAAI,CAAC,GAAG,WAAW,CAAC,CAAC;YAErB,OAAO,CAAC,CAAC;QAEV,CAAC;QAAC,OAAQ,KAAK,EAAG,CAAC;YAElB,OAAO,IAAI,CAAC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,YAAY,SAAS,CAAC,CAAC;QAEjG,CAAC;IAEF,CAAC;IAGD,SAAS,IAAI,CAAC,OAAe,EAAE,KAAc;QAE5C,OAAO,CAAC,KAAK,CAAC,KAAK;YAClB,CAAC,CAAC,GAAG,IAAI,KAAK,OAAO,UAAU,IAAI,gCAAgC;YACnE,CAAC,CAAC,GAAG,IAAI,KAAK,OAAO,EAAE,CACvB,CAAC;QAEF,OAAO,CAAC,CAAC;IAEV,CAAC;AAEF,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Unix-like command line tools for npm package scripts.
|
|
3
|
+
*
|
|
4
|
+
* Each tool is installed as a command alongside the package and behaves the same on every platform and shell. Inside
|
|
5
|
+
* npm scripts, these commands take precedence over system commands with the same name, such as the Unix `cp`.
|
|
6
|
+
*
|
|
7
|
+
* Every tool lists the paths it acts on to stdout, one per line, so that a script log shows what changed on disk. It
|
|
8
|
+
* prints its usage with `--help`, and exits with a non-zero status after printing an error message to stderr.
|
|
9
|
+
*
|
|
10
|
+
* | Tool | Purpose |
|
|
11
|
+
* |----------------------------|-----------------------------------------------------------------------------|
|
|
12
|
+
* | `cp <target> <pattern>...` | Copies files matching glob patterns into a directory, keeping their layout |
|
|
13
|
+
* | `ln [<deps>]...` | Links dependencies to their local checkouts instead of registry releases |
|
|
14
|
+
* | `rm <pattern>...` | Removes files and directories matching glob patterns, with their content |
|
|
15
|
+
*
|
|
16
|
+
* @module
|
|
17
|
+
*/
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tool/index.ts"],"names":[],"mappings":"AAgBA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2026 Metreeca srl
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tool/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Links the local checkouts of the dependencies of the current package into its `node_modules`.
|
|
4
|
+
*
|
|
5
|
+
* The current package, and in a monorepo each of its workspace members, then builds and runs against the working
|
|
6
|
+
* trees of its dependencies instead of their registry releases. Dependencies are matched to checkouts by package name.
|
|
7
|
+
*
|
|
8
|
+
* - **Deps**: each folder searched is either a package or a folder holding packages as direct children; a monorepo
|
|
9
|
+
* found there contributes its workspace members as well, wherever its `workspaces` patterns place them
|
|
10
|
+
* - **Selection**: links every package named in the `dependencies`, `devDependencies`, `peerDependencies` or
|
|
11
|
+
* `optionalDependencies` of the current package or its members. Each linked package then brings in the checkouts
|
|
12
|
+
* named in its own `dependencies`, `peerDependencies` or `optionalDependencies`. A package shared along the chain
|
|
13
|
+
* is thus loaded once from its working tree, never also as a registry copy with distinct classes and symbols
|
|
14
|
+
* - **Copies**: installed copies of a linked package are replaced with links at any depth, both in the current
|
|
15
|
+
* package and in linked checkouts, since a linked package resolves its own imports from its checkout
|
|
16
|
+
* - **Commands**: the `bin` commands of each linked package are linked into the `.bin` folder next to it and made
|
|
17
|
+
* executable, so that npm scripts run the working tree version of a command rather than its registry release
|
|
18
|
+
* - **Precedence**: where a name is found in more than one folder, the folder listed first wins
|
|
19
|
+
* - **Versions**: version ranges are ignored, as a working tree may carry a version that is not released yet
|
|
20
|
+
*
|
|
21
|
+
* Links replace whatever the current package has installed under the same name. Inside a linked checkout, they only
|
|
22
|
+
* replace installed copies and never add new packages. Missing folders are skipped, so the same command runs
|
|
23
|
+
* unchanged on every machine, including machines where some of the named folders hold no local checkouts at all.
|
|
24
|
+
*
|
|
25
|
+
* Each package link is printed on stdout, relative to the current package, such as `node_modules/@scope/name`; links
|
|
26
|
+
* to `bin` commands are created silently, since they follow from the package links already listed.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
*
|
|
30
|
+
* Linking the sibling checkouts of a package after a clean install, from an npm script:
|
|
31
|
+
*
|
|
32
|
+
* ```shell
|
|
33
|
+
* npm ci && ln
|
|
34
|
+
* ```
|
|
35
|
+
*
|
|
36
|
+
* Linking from a folder of local dependencies elsewhere:
|
|
37
|
+
*
|
|
38
|
+
* ```shell
|
|
39
|
+
* npm ci && ln ~/Metreeca/Packages
|
|
40
|
+
* ```
|
|
41
|
+
*
|
|
42
|
+
* @param deps The folders searched for local dependencies, in order of precedence; defaults to the parent folder (`..`)
|
|
43
|
+
*
|
|
44
|
+
* @throws Error If the current folder holds no `package.json`
|
|
45
|
+
*/
|
|
46
|
+
export declare function ln(...deps: readonly string[]): void;
|
|
47
|
+
//# sourceMappingURL=ln.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ln.d.ts","sourceRoot":"","sources":["../../src/tool/ln.ts"],"names":[],"mappings":";AA0CA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2CG;AACH,wBAAgB,EAAE,CAAC,GAAG,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAiLnD"}
|
package/dist/tool/ln.js
ADDED
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/*
|
|
3
|
+
* Copyright © 2026 Metreeca srl
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import { chmodSync, existsSync, globSync, lstatSync, mkdirSync, readdirSync, readFileSync, realpathSync, rmSync, statSync, symlinkSync } from "node:fs";
|
|
18
|
+
import { dirname, join, relative, resolve } from "node:path";
|
|
19
|
+
import { cli } from "./index.core.js";
|
|
20
|
+
if (import.meta.main) {
|
|
21
|
+
process.exitCode = cli(ln, "[<deps>]...");
|
|
22
|
+
}
|
|
23
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
24
|
+
/**
|
|
25
|
+
* Links the local checkouts of the dependencies of the current package into its `node_modules`.
|
|
26
|
+
*
|
|
27
|
+
* The current package, and in a monorepo each of its workspace members, then builds and runs against the working
|
|
28
|
+
* trees of its dependencies instead of their registry releases. Dependencies are matched to checkouts by package name.
|
|
29
|
+
*
|
|
30
|
+
* - **Deps**: each folder searched is either a package or a folder holding packages as direct children; a monorepo
|
|
31
|
+
* found there contributes its workspace members as well, wherever its `workspaces` patterns place them
|
|
32
|
+
* - **Selection**: links every package named in the `dependencies`, `devDependencies`, `peerDependencies` or
|
|
33
|
+
* `optionalDependencies` of the current package or its members. Each linked package then brings in the checkouts
|
|
34
|
+
* named in its own `dependencies`, `peerDependencies` or `optionalDependencies`. A package shared along the chain
|
|
35
|
+
* is thus loaded once from its working tree, never also as a registry copy with distinct classes and symbols
|
|
36
|
+
* - **Copies**: installed copies of a linked package are replaced with links at any depth, both in the current
|
|
37
|
+
* package and in linked checkouts, since a linked package resolves its own imports from its checkout
|
|
38
|
+
* - **Commands**: the `bin` commands of each linked package are linked into the `.bin` folder next to it and made
|
|
39
|
+
* executable, so that npm scripts run the working tree version of a command rather than its registry release
|
|
40
|
+
* - **Precedence**: where a name is found in more than one folder, the folder listed first wins
|
|
41
|
+
* - **Versions**: version ranges are ignored, as a working tree may carry a version that is not released yet
|
|
42
|
+
*
|
|
43
|
+
* Links replace whatever the current package has installed under the same name. Inside a linked checkout, they only
|
|
44
|
+
* replace installed copies and never add new packages. Missing folders are skipped, so the same command runs
|
|
45
|
+
* unchanged on every machine, including machines where some of the named folders hold no local checkouts at all.
|
|
46
|
+
*
|
|
47
|
+
* Each package link is printed on stdout, relative to the current package, such as `node_modules/@scope/name`; links
|
|
48
|
+
* to `bin` commands are created silently, since they follow from the package links already listed.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
*
|
|
52
|
+
* Linking the sibling checkouts of a package after a clean install, from an npm script:
|
|
53
|
+
*
|
|
54
|
+
* ```shell
|
|
55
|
+
* npm ci && ln
|
|
56
|
+
* ```
|
|
57
|
+
*
|
|
58
|
+
* Linking from a folder of local dependencies elsewhere:
|
|
59
|
+
*
|
|
60
|
+
* ```shell
|
|
61
|
+
* npm ci && ln ~/Metreeca/Packages
|
|
62
|
+
* ```
|
|
63
|
+
*
|
|
64
|
+
* @param deps The folders searched for local dependencies, in order of precedence; defaults to the parent folder (`..`)
|
|
65
|
+
*
|
|
66
|
+
* @throws Error If the current folder holds no `package.json`
|
|
67
|
+
*/
|
|
68
|
+
export function ln(...deps) {
|
|
69
|
+
const home = resolve(".");
|
|
70
|
+
const local = join(home, "package.json");
|
|
71
|
+
if (!existsSync(local)) {
|
|
72
|
+
throw new Error(`missing package manifest <${local}>`);
|
|
73
|
+
}
|
|
74
|
+
const own = packages(home);
|
|
75
|
+
const names = new Set(own.map(path => manifest(path).name));
|
|
76
|
+
const index = new Map((deps.length ? deps : [".."])
|
|
77
|
+
.map(dep => resolve(dep))
|
|
78
|
+
.flatMap(dep => existsSync(join(dep, "package.json"))
|
|
79
|
+
? [dep]
|
|
80
|
+
: children(dep).map(name => join(dep, name)).filter(folder))
|
|
81
|
+
.flatMap(packages)
|
|
82
|
+
.map((path) => [manifest(path).name, path])
|
|
83
|
+
.filter(([name]) => !names.has(name))
|
|
84
|
+
.reverse() // later entries override earlier ones, so that the folder listed first wins
|
|
85
|
+
);
|
|
86
|
+
const linked = closure(own.flatMap(path => dependencies(path, true)));
|
|
87
|
+
const roots = new Set([home, ...[...linked.values()].map(path => checkout(path))]);
|
|
88
|
+
linked.forEach((path, name) => link({ modules: join(home, "node_modules"), name, path }));
|
|
89
|
+
[...roots]
|
|
90
|
+
.flatMap(packages)
|
|
91
|
+
.flatMap(path => copies(join(path, "node_modules")))
|
|
92
|
+
.forEach(link);
|
|
93
|
+
function link({ modules, name, path }) {
|
|
94
|
+
const target = join(modules, name);
|
|
95
|
+
replace(target, path);
|
|
96
|
+
console.log(relative(home, target));
|
|
97
|
+
commands(path, name).forEach(([command, script]) => {
|
|
98
|
+
replace(join(modules, ".bin", command), join(target, script));
|
|
99
|
+
if (existsSync(join(path, script))) {
|
|
100
|
+
chmodSync(join(path, script), 0o755); // as npm does, since builds such as tsc emit scripts without the mode
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
function replace(link, target) {
|
|
105
|
+
rmSync(link, { recursive: true, force: true }); // removes links without following them
|
|
106
|
+
mkdirSync(dirname(link), { recursive: true });
|
|
107
|
+
symlinkSync(relative(dirname(link), target), link, "junction"); // type ignored outside Windows
|
|
108
|
+
}
|
|
109
|
+
function commands(path, name) {
|
|
110
|
+
const { bin } = manifest(path);
|
|
111
|
+
if (process.platform === "win32") {
|
|
112
|
+
return []; // npm exposes commands through generated shims rather than links
|
|
113
|
+
}
|
|
114
|
+
else if (typeof bin === "string") {
|
|
115
|
+
return [[name.replace(/^@[^/]+\//, ""), bin]];
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
return Object.entries(bin ?? {});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
function copies(modules) {
|
|
122
|
+
return children(modules)
|
|
123
|
+
.filter(name => !name.startsWith("."))
|
|
124
|
+
.flatMap(name => name.startsWith("@")
|
|
125
|
+
? children(join(modules, name)).map(member => `${name}/${member}`)
|
|
126
|
+
: [name])
|
|
127
|
+
.flatMap(name => {
|
|
128
|
+
const copy = join(modules, name);
|
|
129
|
+
const path = linked.get(name);
|
|
130
|
+
if (path !== undefined) {
|
|
131
|
+
return existsSync(copy) && realpathSync(copy) === realpathSync(path) ? [] : [{ modules, name, path }];
|
|
132
|
+
}
|
|
133
|
+
else if (lstatSync(copy).isSymbolicLink()) {
|
|
134
|
+
return []; // a link into another checkout, inspected as a root of its own when linked
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
return copies(join(copy, "node_modules"));
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
function packages(path) {
|
|
142
|
+
return existsSync(join(path, "package.json")) ? [path, ...(manifest(path).workspaces ?? [])
|
|
143
|
+
.flatMap(pattern => globSync(pattern, { cwd: path }))
|
|
144
|
+
.map(member => join(path, member))
|
|
145
|
+
.filter(member => existsSync(join(member, "package.json")))
|
|
146
|
+
] : [];
|
|
147
|
+
}
|
|
148
|
+
function checkout(path, parent = dirname(path)) {
|
|
149
|
+
if (parent === dirname(parent)) {
|
|
150
|
+
return path;
|
|
151
|
+
}
|
|
152
|
+
else if (existsSync(join(parent, "package.json"))) {
|
|
153
|
+
return packages(parent).includes(path) ? parent : path;
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
return checkout(path, dirname(parent));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function children(path) {
|
|
160
|
+
return folder(path) ? readdirSync(path) : [];
|
|
161
|
+
}
|
|
162
|
+
function folder(path) {
|
|
163
|
+
return statSync(path, { throwIfNoEntry: false })?.isDirectory() ?? false;
|
|
164
|
+
}
|
|
165
|
+
function closure(required, closed = new Map()) {
|
|
166
|
+
const fresh = new Map(required.flatMap((name) => {
|
|
167
|
+
const path = index.get(name);
|
|
168
|
+
return path !== undefined && !closed.has(name) ? [[name, path]] : [];
|
|
169
|
+
}));
|
|
170
|
+
return fresh.size
|
|
171
|
+
? closure([...fresh.values()].flatMap(path => dependencies(path)), new Map([...closed, ...fresh]))
|
|
172
|
+
: closed;
|
|
173
|
+
}
|
|
174
|
+
function dependencies(path, dev = false) {
|
|
175
|
+
const { dependencies, devDependencies, peerDependencies, optionalDependencies } = manifest(path);
|
|
176
|
+
return Object.keys({
|
|
177
|
+
...dependencies,
|
|
178
|
+
...(dev ? devDependencies : {}),
|
|
179
|
+
...peerDependencies,
|
|
180
|
+
...optionalDependencies
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
function manifest(path) {
|
|
184
|
+
return JSON.parse(readFileSync(join(path, "package.json"), "utf8")); // trusted local file, not validated
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=ln.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ln.js","sourceRoot":"","sources":["../../src/tool/ln.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Removes the files and directories matching a set of glob patterns, with their whole content.
|
|
4
|
+
*
|
|
5
|
+
* Patterns matching nothing are ignored, so that the same command can run again on an already clean tree.
|
|
6
|
+
*
|
|
7
|
+
* Each removed file or directory is printed on stdout once, relative to the current folder. Matches inside a removed
|
|
8
|
+
* directory are not listed, even where a pattern selects them explicitly, as they go along with their ancestor.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
*
|
|
12
|
+
* Removing build outputs, from an npm script:
|
|
13
|
+
*
|
|
14
|
+
* ```shell
|
|
15
|
+
* rm dist docs 'src/**\/*.tsbuildinfo'
|
|
16
|
+
* ```
|
|
17
|
+
*
|
|
18
|
+
* Patterns are quoted so that they reach the tool unexpanded, as shells differ in their glob support.
|
|
19
|
+
*
|
|
20
|
+
* @param patterns The glob patterns selecting the files and directories to remove
|
|
21
|
+
*
|
|
22
|
+
* @throws TypeError If no pattern is provided
|
|
23
|
+
*/
|
|
24
|
+
export declare function rm(...patterns: readonly string[]): void;
|
|
25
|
+
//# sourceMappingURL=rm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rm.d.ts","sourceRoot":"","sources":["../../src/tool/rm.ts"],"names":[],"mappings":";AA8BA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,EAAE,CAAC,GAAG,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAcvD"}
|
package/dist/tool/rm.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/*
|
|
3
|
+
* Copyright © 2026 Metreeca srl
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
import { globSync, rmSync } from "node:fs";
|
|
18
|
+
import { relative, resolve, sep } from "node:path";
|
|
19
|
+
import { cli } from "./index.core.js";
|
|
20
|
+
if (import.meta.main) {
|
|
21
|
+
process.exitCode = cli(rm, "<pattern>...");
|
|
22
|
+
}
|
|
23
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
24
|
+
/**
|
|
25
|
+
* Removes the files and directories matching a set of glob patterns, with their whole content.
|
|
26
|
+
*
|
|
27
|
+
* Patterns matching nothing are ignored, so that the same command can run again on an already clean tree.
|
|
28
|
+
*
|
|
29
|
+
* Each removed file or directory is printed on stdout once, relative to the current folder. Matches inside a removed
|
|
30
|
+
* directory are not listed, even where a pattern selects them explicitly, as they go along with their ancestor.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
*
|
|
34
|
+
* Removing build outputs, from an npm script:
|
|
35
|
+
*
|
|
36
|
+
* ```shell
|
|
37
|
+
* rm dist docs 'src/**\/*.tsbuildinfo'
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* Patterns are quoted so that they reach the tool unexpanded, as shells differ in their glob support.
|
|
41
|
+
*
|
|
42
|
+
* @param patterns The glob patterns selecting the files and directories to remove
|
|
43
|
+
*
|
|
44
|
+
* @throws TypeError If no pattern is provided
|
|
45
|
+
*/
|
|
46
|
+
export function rm(...patterns) {
|
|
47
|
+
if (!patterns.length) {
|
|
48
|
+
throw new TypeError("missing pattern operand");
|
|
49
|
+
}
|
|
50
|
+
const matches = [...new Set(patterns.flatMap(pattern => globSync(pattern)).map(path => resolve(path)))];
|
|
51
|
+
const paths = matches.filter(path => !matches.some(match => path.startsWith(match + sep))); // gone with ancestors
|
|
52
|
+
paths.forEach(path => {
|
|
53
|
+
rmSync(path, { recursive: true, force: true });
|
|
54
|
+
console.log(relative(".", path));
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=rm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rm.js","sourceRoot":"","sources":["../../src/tool/rm.ts"],"names":[],"mappings":";AAEA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,GAAG,EAAE,MAAM,iBAAiB,CAAC;AAGtC,IAAK,MAAM,CAAC,IAAI,CAAC,IAAI,EAAG,CAAC;IACxB,OAAO,CAAC,QAAQ,GAAG,GAAG,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC;AAC5C,CAAC;AAGD,wHAAwH;AAExH;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,EAAE,CAAC,GAAG,QAA2B;IAEhD,IAAK,CAAC,QAAQ,CAAC,MAAM,EAAG,CAAC;QACxB,MAAM,IAAI,SAAS,CAAC,yBAAyB,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,OAAO,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACxG,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB;IAElH,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;QACpB,MAAM,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC;IAClC,CAAC,CAAC,CAAC;AAEJ,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vite plugins for building and testing npm packages.
|
|
3
|
+
*
|
|
4
|
+
* | Plugin | Purpose |
|
|
5
|
+
* |------------------|---------------------------------------------------------------------------------|
|
|
6
|
+
* | {@link symlinks} | Runs tests against the live source of locally linked packages, with no rebuild |
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
export { symlinks } from "./symlinks.js";
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"AAgBA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2026 Metreeca srl
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Vite plugins for building and testing npm packages.
|
|
18
|
+
*
|
|
19
|
+
* | Plugin | Purpose |
|
|
20
|
+
* |------------------|---------------------------------------------------------------------------------|
|
|
21
|
+
* | {@link symlinks} | Runs tests against the live source of locally linked packages, with no rebuild |
|
|
22
|
+
*
|
|
23
|
+
* @module
|
|
24
|
+
*/
|
|
25
|
+
export { symlinks } from "./symlinks.js";
|
|
26
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/vite/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { Plugin } from "vite";
|
|
2
|
+
/**
|
|
3
|
+
* Creates a plugin running tests against the live source of locally linked packages, with no rebuild.
|
|
4
|
+
*
|
|
5
|
+
* Imports of workspace members and of sibling checkouts linked into `node_modules` resolve to their TypeScript source,
|
|
6
|
+
* so edits are picked up as they are saved. Packages installed from the registry keep resolving to their build.
|
|
7
|
+
*
|
|
8
|
+
* Packages are looked up as Node does, from the `node_modules` nearest to the importer up through its ancestors, so
|
|
9
|
+
* links hoisted to a workspace root are found from any member; imports with no importer start from the Vite root.
|
|
10
|
+
*
|
|
11
|
+
* The plugin replaces `resolve.conditions`, which breaks registry packages whose exports name a condition without
|
|
12
|
+
* publishing its target: Vite does not fall back to `default` when that target is missing from the installed files.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
*
|
|
16
|
+
* Linked packages map each exported subpath to its source under a custom condition, next to the build:
|
|
17
|
+
*
|
|
18
|
+
* ```json
|
|
19
|
+
* {
|
|
20
|
+
* "exports": {
|
|
21
|
+
* ".": { "source": "./src/index.ts", "default": "./dist/index.js" }
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*
|
|
26
|
+
* The consuming project registers the plugin with the same condition in its Vite or Vitest configuration:
|
|
27
|
+
*
|
|
28
|
+
* ```typescript
|
|
29
|
+
* import { symlinks } from "@metreeca/rack/vite";
|
|
30
|
+
* import { defineConfig } from "vitest/config";
|
|
31
|
+
*
|
|
32
|
+
* export default defineConfig({
|
|
33
|
+
* plugins: [symlinks({ conditions: "source" })]
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @param options The resolution settings
|
|
38
|
+
*
|
|
39
|
+
* @returns A plugin resolving linked imports to source and leaving all others to the default resolution
|
|
40
|
+
*/
|
|
41
|
+
export declare function symlinks({ conditions }: {
|
|
42
|
+
/**
|
|
43
|
+
* The export conditions mapping each subpath to its source file, as listed in `customConditions`; where a package
|
|
44
|
+
* matches more than one, the key order of its own `exports` decides which applies.
|
|
45
|
+
*/
|
|
46
|
+
conditions: string | readonly string[];
|
|
47
|
+
}): Plugin;
|
|
48
|
+
//# sourceMappingURL=symlinks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symlinks.d.ts","sourceRoot":"","sources":["../../src/vite/symlinks.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC;AAGnC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,QAAQ,CAAC,EAExB,UAAU,EAEV,EAAE;IAEF;;;OAGG;IACH,UAAU,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,CAAA;CAEtC,GAAG,MAAM,CAyET"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright © 2026 Metreeca srl
|
|
3
|
+
*
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* you may not use this file except in compliance with the License.
|
|
6
|
+
* You may obtain a copy of the License at
|
|
7
|
+
*
|
|
8
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
*
|
|
10
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
* See the License for the specific language governing permissions and
|
|
14
|
+
* limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { lstatSync, readFileSync, realpathSync } from "node:fs";
|
|
17
|
+
import { createRequire } from "node:module";
|
|
18
|
+
import { dirname, isAbsolute, join, resolve, sep } from "node:path";
|
|
19
|
+
import { exports } from "resolve.exports";
|
|
20
|
+
/**
|
|
21
|
+
* Creates a plugin running tests against the live source of locally linked packages, with no rebuild.
|
|
22
|
+
*
|
|
23
|
+
* Imports of workspace members and of sibling checkouts linked into `node_modules` resolve to their TypeScript source,
|
|
24
|
+
* so edits are picked up as they are saved. Packages installed from the registry keep resolving to their build.
|
|
25
|
+
*
|
|
26
|
+
* Packages are looked up as Node does, from the `node_modules` nearest to the importer up through its ancestors, so
|
|
27
|
+
* links hoisted to a workspace root are found from any member; imports with no importer start from the Vite root.
|
|
28
|
+
*
|
|
29
|
+
* The plugin replaces `resolve.conditions`, which breaks registry packages whose exports name a condition without
|
|
30
|
+
* publishing its target: Vite does not fall back to `default` when that target is missing from the installed files.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
*
|
|
34
|
+
* Linked packages map each exported subpath to its source under a custom condition, next to the build:
|
|
35
|
+
*
|
|
36
|
+
* ```json
|
|
37
|
+
* {
|
|
38
|
+
* "exports": {
|
|
39
|
+
* ".": { "source": "./src/index.ts", "default": "./dist/index.js" }
|
|
40
|
+
* }
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*
|
|
44
|
+
* The consuming project registers the plugin with the same condition in its Vite or Vitest configuration:
|
|
45
|
+
*
|
|
46
|
+
* ```typescript
|
|
47
|
+
* import { symlinks } from "@metreeca/rack/vite";
|
|
48
|
+
* import { defineConfig } from "vitest/config";
|
|
49
|
+
*
|
|
50
|
+
* export default defineConfig({
|
|
51
|
+
* plugins: [symlinks({ conditions: "source" })]
|
|
52
|
+
* });
|
|
53
|
+
* ```
|
|
54
|
+
*
|
|
55
|
+
* @param options The resolution settings
|
|
56
|
+
*
|
|
57
|
+
* @returns A plugin resolving linked imports to source and leaving all others to the default resolution
|
|
58
|
+
*/
|
|
59
|
+
export function symlinks({ conditions }) {
|
|
60
|
+
const $conditions = typeof conditions === "string" ? [conditions] : conditions;
|
|
61
|
+
const manifests = new Map(); // memoised by link real path
|
|
62
|
+
return {
|
|
63
|
+
name: "symlinks",
|
|
64
|
+
enforce: "pre",
|
|
65
|
+
resolveId(id, importer) {
|
|
66
|
+
const name = id.match(/^(@[^/]+\/)?[^/]+/)?.[0];
|
|
67
|
+
const base = importer && isAbsolute(importer) ? dirname(importer) : this.environment.config.root;
|
|
68
|
+
const link = name && lookup(name, base);
|
|
69
|
+
if (link) {
|
|
70
|
+
try {
|
|
71
|
+
const path = realpathSync(link);
|
|
72
|
+
const target = exports(manifest(path), id, { conditions: $conditions })?.[0];
|
|
73
|
+
return target === undefined ? null : resolve(path, target);
|
|
74
|
+
}
|
|
75
|
+
catch { // subpath not exported or excluded by a null target
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
function lookup(name, directory) {
|
|
85
|
+
const path = (createRequire(join(directory, sep)).resolve.paths(name) ?? [])
|
|
86
|
+
.map(modules => join(modules, name))
|
|
87
|
+
.find(candidate => lstatSync(candidate, { throwIfNoEntry: false }));
|
|
88
|
+
return path !== undefined && lstatSync(path).isSymbolicLink() ? path : undefined;
|
|
89
|
+
}
|
|
90
|
+
function manifest(path) {
|
|
91
|
+
const cached = manifests.get(path);
|
|
92
|
+
if (cached === undefined) {
|
|
93
|
+
const loaded = JSON.parse(readFileSync(join(path, "package.json"), "utf8"));
|
|
94
|
+
manifests.set(path, loaded);
|
|
95
|
+
return loaded;
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
return cached;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=symlinks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symlinks.js","sourceRoot":"","sources":["../../src/vite/symlinks.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,69 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@metreeca/rack",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Everyday tooling for npm package development.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"typescript",
|
|
7
|
+
"tooling",
|
|
8
|
+
"vite"
|
|
9
|
+
],
|
|
10
|
+
"homepage": "https://metreeca.github.io/rack/",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/metreeca/rack/issues",
|
|
13
|
+
"email": "info@metreeca.com"
|
|
14
|
+
},
|
|
15
|
+
"license": "Apache-2.0",
|
|
16
|
+
"author": {
|
|
17
|
+
"name": "Metreeca",
|
|
18
|
+
"email": "info@metreeca.com",
|
|
19
|
+
"url": "https://www.metreeca.com/"
|
|
20
|
+
},
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/metreeca/rack.git"
|
|
24
|
+
},
|
|
25
|
+
"type": "module",
|
|
26
|
+
"sideEffects": false,
|
|
27
|
+
"exports": {
|
|
28
|
+
"./vite": "./dist/vite/index.js",
|
|
29
|
+
"./tool": "./dist/tool/index.js"
|
|
30
|
+
},
|
|
31
|
+
"bin": {
|
|
32
|
+
"cp": "./dist/tool/cp.js",
|
|
33
|
+
"ln": "./dist/tool/ln.js",
|
|
34
|
+
"rm": "./dist/tool/rm.js"
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"README.md",
|
|
38
|
+
"LICENSE",
|
|
39
|
+
"dist"
|
|
40
|
+
],
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=22.22.0"
|
|
43
|
+
},
|
|
44
|
+
"scripts": {
|
|
45
|
+
"clean": "rm -rf dist docs node_modules",
|
|
46
|
+
"prime": "npm ci",
|
|
47
|
+
"setup": "npm ci",
|
|
48
|
+
"build": "rm -rf dist docs && tsc -p tsconfig.build.json && npx typedoc",
|
|
49
|
+
"check": "npx vitest --typecheck run",
|
|
50
|
+
"proof": "npx typedoc && (npx typedoc --watch & npx wds --root-dir docs --watch --open)"
|
|
51
|
+
},
|
|
52
|
+
"dependencies": {
|
|
53
|
+
"resolve.exports": "^2.0.4"
|
|
54
|
+
},
|
|
55
|
+
"devDependencies": {
|
|
56
|
+
"@types/node": "^22.20.5",
|
|
57
|
+
"@web/dev-server": "^1.0.0",
|
|
58
|
+
"typedoc": "^0.28.14",
|
|
59
|
+
"typescript": "^5.9.3",
|
|
60
|
+
"vite": "^8.3.0",
|
|
61
|
+
"vitest": "^4.0.13"
|
|
62
|
+
},
|
|
63
|
+
"peerDependencies": {
|
|
64
|
+
"vite": "^8.0.0"
|
|
65
|
+
},
|
|
66
|
+
"allowScripts": {
|
|
67
|
+
"fsevents": false
|
|
68
|
+
}
|
|
69
|
+
}
|