Skip to content

Commit 852325d

Browse files
authored
Merge pull request #1283 from joshunrau/json-schema
refactor instrument schemas and add JSON schema to docs for all instrument types and languages
2 parents 5d1f126 + 9297ce5 commit 852325d

File tree

13 files changed

+1177
-291
lines changed

13 files changed

+1177
-291
lines changed

apps/outreach/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
"lodash-es": "workspace:lodash-es__4.x@*",
1919
"mdast-util-to-string": "^4.0.0",
2020
"reading-time": "^1.5.0",
21-
"tailwind-merge": "^2.6.0"
21+
"tailwind-merge": "^2.6.0",
22+
"zod": "workspace:zod__3.x@*"
2223
},
2324
"devDependencies": {
2425
"@astrojs/check": "^0.9.4",
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
import { getSchemaProps } from '@/lib/instrument-schemas';
3+
4+
const schemaProps = getSchemaProps();
5+
---
6+
7+
<ul>
8+
{
9+
schemaProps.map(({ meta, params }) => (
10+
<li>
11+
<a download href={`/resources/schemas/${params.kind}-instrument-${params.lang}.json`}>
12+
{meta.displayName}
13+
</a>
14+
</li>
15+
))
16+
}
17+
</ul>

apps/outreach/src/components/docs/Licenses.astro

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ const proprietaryLicenses = Array.from(licenses.entries())
4040
<div class="space-y-8">
4141
<section>
4242
<h3>Open Source Licenses (Approved)</h3>
43-
<p class="mb-4 text-slate-700">
43+
<p class="mb-4 text-slate-700 dark:text-slate-300">
4444
The following licenses are pre-approved for direct inclusion in the Open Data Capture repository and public
4545
distribution:
4646
</p>
@@ -61,11 +61,13 @@ const proprietaryLicenses = Array.from(licenses.entries())
6161
))
6262
}
6363
</ul>
64-
<p class="text-slate-700">Please note that instruments in the public domain instruments are also permitted.</p>
64+
<p class="text-slate-700 dark:text-slate-300">
65+
Please note that instruments in the public domain instruments are also permitted.
66+
</p>
6567
</section>
6668
<section>
6769
<h3>Open Source Licenses (Non-Approved)</h3>
68-
<p class="mb-4 text-slate-700">
70+
<p class="text-slate-70 dark:text-slate-3000 mb-4">
6971
These open source licenses are acceptable for public distribution, but due to various clauses are not able to be
7072
included directly in the Open Data Capture repository.
7173
</p>
@@ -89,7 +91,7 @@ const proprietaryLicenses = Array.from(licenses.entries())
8991
</section>
9092
<section>
9193
<h3>Open Source Licenses (Review Required)</h3>
92-
<p class="mb-4 text-slate-700">
94+
<p class="mb-4 text-slate-700 dark:text-slate-300">
9395
The following licenses are considered open source, but have not been reviewed by our team.
9496
</p>
9597
<ul class="tracking-tight">
@@ -112,7 +114,7 @@ const proprietaryLicenses = Array.from(licenses.entries())
112114
</section>
113115
<section>
114116
<h3>Proprietary and Non-Free Licenses</h3>
115-
<p class="mb-4 text-slate-700">
117+
<p class="mb-4 text-slate-700 dark:text-slate-300">
116118
These licenses may not be published publicly by our team. This list includes non-free licenses, as well as any
117119
licenses with restrictions on commercial use.
118120
</p>
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import type { InstrumentLanguage } from '@opendatacapture/runtime-core';
2+
import { capitalize } from 'lodash-es';
3+
4+
const LANGUAGE_NAMES = {
5+
en: 'English',
6+
fr: 'French'
7+
};
8+
9+
export const SCHEMA_KINDS = ['form', 'interactive', 'series', 'any'] as const;
10+
11+
export const SCHEMA_LANGUAGES = ['en', 'fr', ['en', 'fr']] as const satisfies InstrumentLanguage[];
12+
13+
export function getSchemaProps() {
14+
return SCHEMA_KINDS.flatMap((kind) => {
15+
return SCHEMA_LANGUAGES.map((language) => {
16+
let displayLanguage: string;
17+
if (typeof language === 'string') {
18+
displayLanguage = LANGUAGE_NAMES[language];
19+
} else {
20+
displayLanguage = language.map((language) => LANGUAGE_NAMES[language]).join('/');
21+
}
22+
return {
23+
meta: {
24+
displayName: `${capitalize(kind)} Instrument (${displayLanguage})`,
25+
language: language
26+
},
27+
params: {
28+
kind,
29+
lang: Array.isArray(language) ? language.join('-') : language
30+
}
31+
};
32+
});
33+
});
34+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import {
2+
$$AnyInstrument,
3+
$$FormInstrument,
4+
$$InteractiveInstrument,
5+
$$SeriesInstrument
6+
} from '@opendatacapture/schemas/instrument';
7+
import type { APIRoute, GetStaticPaths, InferGetStaticParamsType, InferGetStaticPropsType } from 'astro';
8+
import z from 'zod/v4';
9+
10+
import { getSchemaProps } from '@/lib/instrument-schemas';
11+
12+
type Params = InferGetStaticParamsType<typeof getStaticPaths>;
13+
14+
type Props = InferGetStaticPropsType<typeof getStaticPaths>;
15+
16+
export const getStaticPaths = (() => {
17+
const schemaFactories = {
18+
any: $$AnyInstrument,
19+
form: $$FormInstrument,
20+
interactive: $$InteractiveInstrument,
21+
series: $$SeriesInstrument
22+
} as const;
23+
return getSchemaProps().map(({ meta, params }) => ({
24+
params,
25+
props: { schema: z.toJSONSchema(schemaFactories[params.kind](meta.language)) }
26+
}));
27+
}) satisfies GetStaticPaths;
28+
29+
export const GET: APIRoute<Props, Params> = ({ props }) => {
30+
return new Response(JSON.stringify(props.schema, null, 2));
31+
};
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
title: Instrument Schemas (JSON)
3+
slug: en/docs/reference/instrument-schemas
4+
sidebar:
5+
order: 9
6+
---
7+
8+
import InstrumentSchemas from '@/components/docs/InstrumentSchemas.astro';
9+
10+
While ODC primarily uses Zod for instrument schemas, we provide JSON Schema versions for reference and interoperability with non-TypeScript tools. While these schemas are technically accurate, certain properties that cannot be represented in JSON (such as functions) will default to accepting any value. These versions can be used for building static forms or external integrations. You can find the available schemas for all instrument types and languages below.
11+
12+
<InstrumentSchemas />

0 commit comments

Comments
 (0)