Skip to content

Commit bfedf5c

Browse files
authored
Implement TypeScript codegen (#479)
1 parent d7121d8 commit bfedf5c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+2411
-3
lines changed

MANIFEST.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ include gittaggers.py Makefile LICENSE.txt requirements.txt mypy-requirements.tx
22
include schema_salad/py.typed
33
include schema_salad/avro/*
44
recursive-include schema_salad/java *
5+
recursive-include schema_salad/typescript *
56
include schema_salad/tests/*
67
include schema_salad/tests/test_schema/*.md
78
include schema_salad/tests/test_schema/*.yml

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ install-dependencies: FORCE
5151
pip install --upgrade $(DEVPKGS)
5252
pip install -r requirements.txt -r mypy-requirements.txt -r docs/requirements.txt
5353

54-
## install : install the ${MODULE} module and schema-salad-tool
54+
## install : install the ${MODULE} module and script(s)
5555
install: FORCE
5656
pip install .$(EXTRAS)
5757

@@ -168,7 +168,7 @@ list-author-emails:
168168
@git log --format='%aN,%aE' | sort -u | grep -v 'root'
169169

170170
mypy3: mypy
171-
mypy: $(filter-out setup.py gittagger.py,$(PYSOURCES))
171+
mypy: $(filter-out setup.py,$(PYSOURCES))
172172
if ! test -f $(shell python3 -c 'import ruamel.yaml; import os.path; print(os.path.dirname(ruamel.yaml.__file__))')/py.typed ; \
173173
then \
174174
rm -Rf typeshed/ruamel/yaml ; \

lgtm.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
extraction:
2+
# Define settings for JavaScript analysis
3+
##########################################
4+
javascript:
5+
# The `index` step extracts information from the files in the codebase.
6+
index:
7+
# Specify a list of files and folders to exclude from extraction.
8+
exclude:
9+
- schema_salad/typescript/

schema_salad/codegen.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,13 @@
1313
)
1414
from urllib.parse import urlsplit
1515

16+
1617
from . import schema
1718
from .codegen_base import CodeGenBase
1819
from .exceptions import SchemaSaladException
1920
from .java_codegen import JavaCodeGen
2021
from .python_codegen import PythonCodeGen
22+
from .typescript_codegen import TypeScriptCodeGen
2123
from .ref_resolver import Loader
2224
from .schema import shortname
2325
from .utils import aslist
@@ -68,6 +70,8 @@ def codegen(
6870
package=pkg,
6971
copyright=copyright,
7072
)
73+
elif lang == "typescript":
74+
gen = TypeScriptCodeGen(base, target=target, package=pkg, examples=examples)
7175
else:
7276
raise SchemaSaladException(f"Unsupported code generation language '{lang}'")
7377

schema_salad/main.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,8 @@ def arg_parser() -> argparse.ArgumentParser:
9494
"--codegen",
9595
type=str,
9696
metavar="language",
97-
help="Generate classes in target language, currently supported: python, java",
97+
help="Generate classes in target language, currently supported: "
98+
"python, java, typescript",
9899
)
99100

100101
parser.add_argument(
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import shutil
2+
from pathlib import Path
3+
from typing import Any, Dict, List, Optional, cast
4+
5+
from schema_salad import codegen, ref_resolver
6+
from schema_salad.schema import load_schema
7+
8+
from .util import get_data
9+
10+
11+
def test_cwl_gen(tmp_path: Path) -> None:
12+
topmed_example_path = get_data(
13+
"tests/test_real_cwl/topmed/topmed_variant_calling_pipeline.cwl"
14+
)
15+
assert topmed_example_path
16+
target_dir = tmp_path / "target"
17+
examples_dir = tmp_path / "examples"
18+
19+
target_dir.mkdir()
20+
examples_dir.mkdir()
21+
shutil.copyfile(topmed_example_path, examples_dir / "valid_topmed.cwl")
22+
23+
typescript_codegen(cwl_file_uri, target_dir, examples=examples_dir)
24+
package_json_path = target_dir / "package.json"
25+
assert package_json_path.exists
26+
tests_dir = target_dir / "src" / "test"
27+
assert tests_dir.exists()
28+
with open(tests_dir / "ExampleTest.ts") as f:
29+
assert "topmed" in f.read()
30+
31+
32+
def test_meta_schema_gen(tmp_path: Path) -> None:
33+
target_dir = tmp_path / "target"
34+
target_dir.mkdir()
35+
typescript_codegen(metaschema_file_uri, target_dir)
36+
package_json_path = target_dir / "package.json"
37+
assert package_json_path.exists()
38+
src_dir = target_dir / "src"
39+
assert src_dir.exists()
40+
record_schema_dir = src_dir / "RecordSchema.ts"
41+
assert record_schema_dir.exists()
42+
with open(record_schema_dir) as f:
43+
assert (
44+
"export class RecordSchema extends Saveable implements "
45+
"Internal.RecordSchemaProperties {\n" in f.read()
46+
)
47+
48+
49+
def get_data_uri(resource_path: str) -> str:
50+
path = get_data(resource_path)
51+
assert path
52+
return ref_resolver.file_uri(path)
53+
54+
55+
cwl_file_uri = get_data_uri("tests/test_schema/CommonWorkflowLanguage.yml")
56+
metaschema_file_uri = get_data_uri("metaschema/metaschema.yml")
57+
58+
59+
def typescript_codegen(
60+
file_uri: str, target: Path, examples: Optional[Path] = None
61+
) -> None:
62+
document_loader, avsc_names, schema_metadata, metaschema_loader = load_schema(
63+
file_uri
64+
)
65+
schema_raw_doc = metaschema_loader.fetch(file_uri)
66+
schema_doc, schema_metadata = metaschema_loader.resolve_all(
67+
schema_raw_doc, file_uri
68+
)
69+
codegen.codegen(
70+
"typescript",
71+
cast(List[Dict[str, Any]], schema_doc),
72+
schema_metadata,
73+
document_loader,
74+
target=str(target),
75+
examples=str(examples) if examples else None,
76+
)

schema_salad/typescript/.gitignore

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
# Logs
2+
logs
3+
*.log
4+
npm-debug.log*
5+
yarn-debug.log*
6+
yarn-error.log*
7+
lerna-debug.log*
8+
9+
# Diagnostic reports (https://nodejs.org/api/report.html)
10+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11+
12+
# Runtime data
13+
pids
14+
*.pid
15+
*.seed
16+
*.pid.lock
17+
18+
# Directory for instrumented libs generated by jscoverage/JSCover
19+
lib-cov
20+
21+
# Coverage directory used by tools like istanbul
22+
coverage
23+
*.lcov
24+
25+
# nyc test coverage
26+
.nyc_output
27+
28+
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
29+
.grunt
30+
31+
# Bower dependency directory (https://bower.io/)
32+
bower_components
33+
34+
# node-waf configuration
35+
.lock-wscript
36+
37+
# Compiled binary addons (https://nodejs.org/api/addons.html)
38+
build/Release
39+
40+
# Dependency directories
41+
node_modules/
42+
jspm_packages/
43+
44+
# TypeScript v1 declaration files
45+
typings/
46+
47+
# TypeScript cache
48+
*.tsbuildinfo
49+
50+
# Optional npm cache directory
51+
.npm
52+
53+
# Optional eslint cache
54+
.eslintcache
55+
56+
# Microbundle cache
57+
.rpt2_cache/
58+
.rts2_cache_cjs/
59+
.rts2_cache_es/
60+
.rts2_cache_umd/
61+
62+
# Optional REPL history
63+
.node_repl_history
64+
65+
# Output of 'npm pack'
66+
*.tgz
67+
68+
# Yarn Integrity file
69+
.yarn-integrity
70+
71+
# dotenv environment variables file
72+
.env
73+
.env.test
74+
75+
# parcel-bundler cache (https://parceljs.org/)
76+
.cache
77+
78+
# Next.js build output
79+
.next
80+
81+
# Nuxt.js build / generate output
82+
.nuxt
83+
dist
84+
85+
# Gatsby files
86+
.cache/
87+
# Comment in the public line in if your project uses Gatsby and *not* Next.js
88+
# https://nextjs.org/blog/next-9-1#public-directory-support
89+
# public
90+
91+
# vuepress build output
92+
.vuepress/dist
93+
94+
# Serverless directories
95+
.serverless/
96+
97+
# FuseBox cache
98+
.fusebox/
99+
100+
# DynamoDB Local files
101+
.dynamodb/
102+
103+
# TernJS port file
104+
.tern-port
105+
106+
built/

0 commit comments

Comments
 (0)