Skip to content

Commit 5985e18

Browse files
EmericWieedan
andauthored
feat: add include files config option (#623)
Co-authored-by: Aidan Bleser <aidanbleser35@gmail.com>
1 parent 451071c commit 5985e18

File tree

10 files changed

+158
-1
lines changed

10 files changed

+158
-1
lines changed

.changeset/crazy-roses-taste.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"jsrepo": minor
3+
---
4+
5+
feat: Add `includeFiles` to config to allow for serving any file type from a registry
6+

.changeset/rich-memes-bet.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"jsrepo": patch
3+
---
4+
5+
fix: Remove console.log in `build` command
6+

schemas/registry-config.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,13 @@
150150
"type": "string"
151151
}
152152
},
153+
"includeFiles": {
154+
"description": "Additional files to include in the manifest. (Supports glob patterns)",
155+
"type": "array",
156+
"items": {
157+
"type": "string"
158+
}
159+
},
153160
"excludeBlocks": {
154161
"description": "The names of the blocks that should not be included in the manifest.",
155162
"type": "array",

src/commands/build.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const schema = v.object({
1919
outputDir: v.optional(v.string()),
2020
includeBlocks: v.optional(v.array(v.string())),
2121
includeCategories: v.optional(v.array(v.string())),
22+
includeFiles: v.optional(v.array(v.string())),
2223
excludeBlocks: v.optional(v.array(v.string())),
2324
excludeCategories: v.optional(v.array(v.string())),
2425
excludeDeps: v.optional(v.array(v.string())),
@@ -48,6 +49,10 @@ const build = new Command('build')
4849
'--include-categories [categoryNames...]',
4950
'Include only the categories with these names.'
5051
)
52+
.option(
53+
'--include-files [filePatterns...]',
54+
'Additional files to include in the manifest. (Supports glob patterns)'
55+
)
5156
.option('--exclude-blocks [blockNames...]', 'Do not include the blocks with these names.')
5257
.option(
5358
'--exclude-categories [categoryNames...]',
@@ -103,6 +108,7 @@ async function _build(options: Options) {
103108
excludeDeps: options.excludeDeps ?? [],
104109
includeBlocks: options.includeBlocks ?? [],
105110
includeCategories: options.includeCategories ?? [],
111+
includeFiles: options.includeFiles ?? [],
106112
excludeBlocks: options.excludeBlocks ?? [],
107113
excludeCategories: options.excludeCategories ?? [],
108114
allowSubdirectories: options.allowSubdirectories,
@@ -124,6 +130,7 @@ async function _build(options: Options) {
124130
if (options.listCategories) mergedVal.listCategories = options.listCategories;
125131
if (options.includeBlocks) mergedVal.includeBlocks = options.includeBlocks;
126132
if (options.includeCategories) mergedVal.includeCategories = options.includeCategories;
133+
if (options.includeFiles) mergedVal.includeFiles = options.includeFiles;
127134
if (options.excludeBlocks) mergedVal.excludeBlocks = options.excludeBlocks;
128135
if (options.excludeCategories) mergedVal.excludeCategories = options.excludeCategories;
129136
if (options.excludeDeps) mergedVal.excludeDeps = options.excludeDeps;

src/commands/init.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -785,6 +785,7 @@ const _initRegistry = async (options: Options) => {
785785
excludeDeps: [],
786786
includeBlocks: [],
787787
includeCategories: [],
788+
includeFiles: [],
788789
excludeBlocks: [],
789790
excludeCategories: [],
790791
preview: false,

src/commands/publish.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ const schema = v.object({
2727
dirs: v.optional(v.array(v.string())),
2828
includeBlocks: v.optional(v.array(v.string())),
2929
includeCategories: v.optional(v.array(v.string())),
30+
includeFiles: v.optional(v.array(v.string())),
3031
excludeBlocks: v.optional(v.array(v.string())),
3132
excludeCategories: v.optional(v.array(v.string())),
3233
excludeDeps: v.optional(v.array(v.string())),
@@ -109,6 +110,7 @@ async function _publish(options: Options) {
109110
excludeDeps: options.excludeDeps ?? [],
110111
includeBlocks: options.includeBlocks ?? [],
111112
includeCategories: options.includeCategories ?? [],
113+
includeFiles: options.includeFiles ?? [],
112114
excludeBlocks: options.excludeBlocks ?? [],
113115
excludeCategories: options.excludeCategories ?? [],
114116
allowSubdirectories: options.allowSubdirectories,
@@ -131,6 +133,7 @@ async function _publish(options: Options) {
131133
if (options.listCategories) mergedVal.listCategories = options.listCategories;
132134
if (options.includeBlocks) mergedVal.includeBlocks = options.includeBlocks;
133135
if (options.includeCategories) mergedVal.includeCategories = options.includeCategories;
136+
if (options.includeFiles) mergedVal.includeFiles = options.includeFiles;
134137
if (options.excludeBlocks) mergedVal.excludeBlocks = options.excludeBlocks;
135138
if (options.excludeCategories) mergedVal.excludeCategories = options.excludeCategories;
136139
if (options.excludeDeps) mergedVal.excludeDeps = options.excludeDeps;

src/utils/build/index.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import fs from 'node:fs';
22
import color from 'chalk';
33
import { program } from 'commander';
44
import type { Ignore } from 'ignore';
5+
import baseIgnore from 'ignore';
56
import path from 'pathe';
67
import * as v from 'valibot';
78
import { type Block, type Category, categorySchema, type Manifest } from '../../types';
@@ -187,12 +188,15 @@ export function buildBlocksDirectory(
187188

188189
const blockFiles: string[] = [];
189190

191+
const shouldIncludeFile = createShouldIncludeFile(config);
192+
190193
// if the user has enabled allow subdirectories we recursively check each directory and resolve any dependencies
191194
const walkFiles = (base: string, files: string[]) => {
192195
for (const f of files) {
193196
const filePath = path.join(base, f);
194197
// relative to the block root
195198
const relativeFilePath = filePath.slice(blockDir.length + 1);
199+
const relativeToRootDirectory = filePath.replace(cwd, '').replace('/', '');
196200

197201
if (isTestFile(f)) {
198202
hasTests = true;
@@ -213,6 +217,11 @@ export function buildBlocksDirectory(
213217
continue;
214218
}
215219

220+
if (shouldIncludeFile(relativeToRootDirectory)) {
221+
blockFiles.push(relativeFilePath);
222+
continue;
223+
}
224+
216225
if (fs.statSync(filePath).isDirectory()) {
217226
if (!config.allowSubdirectories) {
218227
console.warn(
@@ -411,6 +420,16 @@ export function shouldIncludeCategory(name: string, config: RegistryConfig) {
411420
return true;
412421
}
413422

423+
export function createShouldIncludeFile(config: RegistryConfig) {
424+
if (config.includeFiles.length === 0) return () => false;
425+
426+
// Dispite it's name, the ignore package can also be used to include files.
427+
// It's just a pattern matching library based on the .gitignore syntax.
428+
const ignore = baseIgnore().add(config.includeFiles.map((p) => p.replace(/^(\.\/|\/)/, '')));
429+
430+
return (filePathRelativeToRoot: string) => ignore.ignores(filePathRelativeToRoot);
431+
}
432+
414433
/** Takes the given file and returns the block name */
415434
function transformBlockName(file: string) {
416435
return path.parse(path.basename(file)).name;

src/utils/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ export const registryConfigSchema = v.object({
7676
outputDir: v.optional(v.string()),
7777
includeBlocks: v.optional(v.array(v.string()), []),
7878
includeCategories: v.optional(v.array(v.string()), []),
79+
includeFiles: v.optional(v.array(v.string()), []),
7980
excludeBlocks: v.optional(v.array(v.string()), []),
8081
excludeCategories: v.optional(v.array(v.string()), []),
8182
doNotListBlocks: v.optional(v.array(v.string()), []),

src/utils/language-support/javascript.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import { formatError, type Lang, resolveImports } from '.';
1313
* @returns
1414
*/
1515
export function getJavascriptImports(fileName: string, code: string): string[] {
16-
console.log('oxc', oxc);
1716
const result = oxc.parseSync(fileName, code);
1817

1918
const modules: string[] = [];

tests/build.test.ts

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { afterAll, assert, beforeAll, describe, expect, it } from 'vitest';
44
import { cli } from '../src/cli';
55
import type { Manifest } from '../src/types';
66
import {
7+
createShouldIncludeFile,
78
shouldIncludeBlock,
89
shouldIncludeCategory,
910
shouldListBlock,
@@ -65,6 +66,7 @@ describe('build', () => {
6566
dirs: ['./src', './'],
6667
includeBlocks: [],
6768
includeCategories: [],
69+
includeFiles: ['src/utils/block-with-asset/asset.txt'],
6870
excludeBlocks: [],
6971
excludeCategories: ['src'],
7072
doNotListBlocks: ['noop'],
@@ -206,6 +208,19 @@ export const highlighter = createHighlighterCore({
206208
</script>`
207209
);
208210

211+
fs.mkdirSync('./src/utils/block-with-asset', { recursive: true });
212+
213+
fs.writeFileSync(
214+
'./src/utils/block-with-asset/index.ts',
215+
`import { fs } from 'node:fs';
216+
217+
const result = fs.readFileSync(new URL('./asset.txt', import.meta.url), 'utf-8');
218+
console.log(result);
219+
`
220+
);
221+
222+
fs.writeFileSync('./src/utils/block-with-asset/asset.txt', 'This is an asset file.');
223+
209224
// build
210225

211226
await cli.parseAsync([
@@ -321,6 +336,20 @@ export const highlighter = createHighlighterCore({
321336
'./log': '{{utils/log}}',
322337
},
323338
},
339+
{
340+
_imports_: {},
341+
category: 'utils',
342+
dependencies: [],
343+
devDependencies: [],
344+
directory: 'src/utils/block-with-asset',
345+
docs: false,
346+
files: ['asset.txt', 'index.ts'],
347+
list: true,
348+
localDependencies: [],
349+
name: 'block-with-asset',
350+
subdirectory: true,
351+
tests: false,
352+
},
324353
{
325354
name: 'form1',
326355
category: 'utils',
@@ -395,6 +424,7 @@ const defaultConfig = {
395424
excludeDeps: [],
396425
includeBlocks: [],
397426
includeCategories: [],
427+
includeFiles: [],
398428
excludeBlocks: [],
399429
excludeCategories: [],
400430
};
@@ -518,3 +548,81 @@ describe('shouldIncludeCategory', () => {
518548
).toBe(false);
519549
});
520550
});
551+
552+
describe('shouldIncludeFile', () => {
553+
it('does not list if unspecified', () => {
554+
expect(
555+
createShouldIncludeFile({ ...defaultConfig, includeDocs: false })(
556+
'utils/math/asset.txt'
557+
)
558+
).toBe(false);
559+
});
560+
561+
it('can include a file when referenced directly', () => {
562+
expect(
563+
createShouldIncludeFile({
564+
...defaultConfig,
565+
includeFiles: ['/utils/math/asset.txt'],
566+
includeDocs: false,
567+
})('utils/math/asset.txt')
568+
).toBe(true);
569+
});
570+
571+
it('is lenient to leading slashes', () => {
572+
expect(
573+
createShouldIncludeFile({
574+
...defaultConfig,
575+
includeFiles: ['/utils/math/asset.txt'],
576+
includeDocs: false,
577+
})('utils/math/asset.txt')
578+
).toBe(true);
579+
expect(
580+
createShouldIncludeFile({
581+
...defaultConfig,
582+
includeFiles: ['./utils/math/asset.txt'],
583+
includeDocs: false,
584+
})('utils/math/asset.txt')
585+
).toBe(true);
586+
});
587+
588+
it('it can include all files of a certain extension', () => {
589+
expect(
590+
createShouldIncludeFile({
591+
...defaultConfig,
592+
includeFiles: ['**/*.txt'],
593+
includeDocs: false,
594+
})('utils/math/asset.txt')
595+
).toBe(true);
596+
expect(
597+
createShouldIncludeFile({
598+
...defaultConfig,
599+
includeFiles: ['**/*.png'],
600+
includeDocs: false,
601+
})('utils/math/asset.png')
602+
).toBe(true);
603+
expect(
604+
createShouldIncludeFile({
605+
...defaultConfig,
606+
includeFiles: ['**/*.png'],
607+
includeDocs: false,
608+
})('utils/math/asset.jpg')
609+
).toBe(false);
610+
});
611+
612+
it('it can include all files in a certain directory', () => {
613+
expect(
614+
createShouldIncludeFile({
615+
...defaultConfig,
616+
includeFiles: ['utils/math/files-to-include/**'],
617+
includeDocs: false,
618+
})('utils/math/files-to-include/asset.txt')
619+
).toBe(true);
620+
expect(
621+
createShouldIncludeFile({
622+
...defaultConfig,
623+
includeFiles: ['utils/math/files-to-include/**'],
624+
includeDocs: false,
625+
})('utils/math/files-to-include/image.png')
626+
).toBe(true);
627+
});
628+
});

0 commit comments

Comments
 (0)