Skip to content

Commit cf62378

Browse files
authored
Improve NPM interface (#80)
Signed-off-by: Juan Cruz Viotti <jv@jviotti.com>
1 parent e56c3d1 commit cf62378

File tree

4 files changed

+108
-24
lines changed

4 files changed

+108
-24
lines changed

npm/cjs.test.js

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,36 @@ test('loads schema from nested path', () => {
3636
assert.strictEqual(typeof schema, 'object');
3737
assert.strictEqual(schema.$schema, 'https://json-schema.org/draft/2020-12/schema');
3838
});
39+
40+
test('lazy loads schema via schemas object', () => {
41+
const { schemas } = require('..');
42+
const schema = schemas['2020-12'].misc['schema-like'];
43+
assert.strictEqual(typeof schema, 'object');
44+
assert.strictEqual(schema.title, 'JSON Schema Document');
45+
});
46+
47+
test('caches loaded schemas', () => {
48+
const { schemas } = require('..');
49+
const schema1 = schemas['2020-12'].misc['schema-like'];
50+
const schema2 = schemas['2020-12'].misc['schema-like'];
51+
assert.strictEqual(schema1, schema2);
52+
});
53+
54+
test('handles deeply nested paths', () => {
55+
const { schemas } = require('..');
56+
const schema = schemas['2020-12'].w3c.xmlschema['2001']['hex-binary'];
57+
assert.strictEqual(typeof schema, 'object');
58+
assert.strictEqual(schema.$schema, 'https://json-schema.org/draft/2020-12/schema');
59+
});
60+
61+
test('returns undefined for non-existent directories', () => {
62+
const { schemas } = require('..');
63+
const result = schemas['2020-12'].nonexistent;
64+
assert.strictEqual(result, undefined);
65+
});
66+
67+
test('returns undefined for non-existent files', () => {
68+
const { schemas } = require('..');
69+
const result = schemas['2020-12'].misc['nonexistent-file'];
70+
assert.strictEqual(result, undefined);
71+
});

npm/esm.test.mjs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import test from 'node:test';
22
import assert from 'node:assert';
3-
import getSchema from '@sourcemeta/std';
3+
import getSchema, { schemas } from '@sourcemeta/std';
44

55
test('loads a valid schema', () => {
66
const schema = getSchema('2020-12/misc/schema-like');
@@ -36,3 +36,31 @@ test('loads schema from nested path', () => {
3636
assert.strictEqual(typeof schema, 'object');
3737
assert.strictEqual(schema.$schema, 'https://json-schema.org/draft/2020-12/schema');
3838
});
39+
40+
test('lazy loads schema via schemas object', () => {
41+
const schema = schemas['2020-12'].misc['schema-like'];
42+
assert.strictEqual(typeof schema, 'object');
43+
assert.strictEqual(schema.title, 'JSON Schema Document');
44+
});
45+
46+
test('caches loaded schemas', () => {
47+
const schema1 = schemas['2020-12'].misc['schema-like'];
48+
const schema2 = schemas['2020-12'].misc['schema-like'];
49+
assert.strictEqual(schema1, schema2);
50+
});
51+
52+
test('handles deeply nested paths', () => {
53+
const schema = schemas['2020-12'].w3c.xmlschema['2001']['hex-binary'];
54+
assert.strictEqual(typeof schema, 'object');
55+
assert.strictEqual(schema.$schema, 'https://json-schema.org/draft/2020-12/schema');
56+
});
57+
58+
test('returns undefined for non-existent directories', () => {
59+
const result = schemas['2020-12'].nonexistent;
60+
assert.strictEqual(result, undefined);
61+
});
62+
63+
test('returns undefined for non-existent files', () => {
64+
const result = schemas['2020-12'].misc['nonexistent-file'];
65+
assert.strictEqual(result, undefined);
66+
});

npm/main.js

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,46 @@ function getSchema(schemaPath) {
2020
}
2121
}
2222

23+
const cache = new Map();
24+
25+
function createSchemaProxy(currentPath = '') {
26+
return new Proxy({}, {
27+
get(target, property) {
28+
if (typeof property !== 'string') {
29+
return undefined;
30+
}
31+
32+
const newPath = currentPath ? `${currentPath}/${property}` : property;
33+
34+
if (cache.has(newPath)) {
35+
return cache.get(newPath);
36+
}
37+
38+
const schemaBasePath = path.join(__dirname, '..', 'schemas');
39+
const fullPath = path.join(schemaBasePath, newPath);
40+
41+
const jsonPath = `${fullPath}.json`;
42+
if (fs.existsSync(jsonPath)) {
43+
try {
44+
const content = fs.readFileSync(jsonPath, 'utf8');
45+
const schema = JSON.parse(content);
46+
cache.set(newPath, schema);
47+
return schema;
48+
} catch (error) {
49+
return undefined;
50+
}
51+
}
52+
53+
if (fs.existsSync(fullPath) && fs.statSync(fullPath).isDirectory()) {
54+
const proxy = createSchemaProxy(newPath);
55+
cache.set(newPath, proxy);
56+
return proxy;
57+
}
58+
59+
return undefined;
60+
}
61+
});
62+
}
63+
2364
module.exports = getSchema;
65+
module.exports.schemas = createSchemaProxy();

npm/main.mjs

Lines changed: 4 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,7 @@
1-
import fs from 'fs';
2-
import path from 'path';
3-
import { fileURLToPath } from 'url';
1+
import { createRequire } from 'node:module';
42

5-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
6-
7-
function getSchema(schemaPath) {
8-
if (!schemaPath || typeof schemaPath !== 'string') {
9-
return null;
10-
}
11-
12-
if (schemaPath.includes('..')) {
13-
return null;
14-
}
15-
16-
const absolutePath = path.join(__dirname, '..', 'schemas', `${schemaPath}.json`);
17-
18-
try {
19-
const content = fs.readFileSync(absolutePath, 'utf8');
20-
return JSON.parse(content);
21-
} catch (error) {
22-
return null;
23-
}
24-
}
3+
const require = createRequire(import.meta.url);
4+
const getSchema = require('./main.js');
255

6+
export const schemas = getSchema.schemas;
267
export default getSchema;

0 commit comments

Comments
 (0)