From d20c901614824e58bf759b3eaa96354b97b026ac Mon Sep 17 00:00:00 2001 From: Gary Miller Date: Tue, 2 May 2023 14:55:47 +1000 Subject: [PATCH 1/2] working radlc commit b00e8ba6bf22dde60b2bad74cd4650dbac49a26e Author: Gary Miller Date: Tue May 2 14:15:11 2023 +1000 change release name commit 392d95e6cd06fe04db261134f01ae9d03e572e28 Author: Gary Miller Date: Tue May 2 14:06:59 2023 +1000 reverting to a version step commit 1cc6b005141beb969198c55042278fd715438ea1 Author: Gary Miller Date: Tue May 2 13:46:37 2023 +1000 looks like actions/download-artifact@v3 might be case sensative commit 8d70fe4ccdc536ecb74b67fc85b6506fc2acf52a Author: Gary Miller Date: Tue May 2 13:30:23 2023 +1000 fix rust-release.yaml commit dd18a2a449141e570da7270aaecb336bd330f2ec Author: Gary Miller Date: Tue May 2 13:25:06 2023 +1000 change actions/create-release@v1.0.0 and actions/upload-release-asset@v1.0.1 to softprops/action-gh-release@v1 commit 56695d0a5edcbbe34ff66f4d69827eb4771363a3 Author: Gary Miller Date: Tue May 2 12:33:06 2023 +1000 rust release - cache, checkout@v3, rust tooling provided commit ec8128c2504b5a8a47e43a6c0668c40dc9ffed30 Author: Gary Miller Date: Tue May 2 12:03:11 2023 +1000 asset_content_type: application/octet-stream commit 71c11407373235b86a441710edfcaa7d838146c6 Author: Gary Miller Date: Tue May 2 11:34:34 2023 +1000 trim 24 chars from GITHUB_REF commit a6515656ef03a8a1edaec34bde3fd93439512798 Author: Gary Miller Date: Tue May 2 10:56:09 2023 +1000 commit on gm master commit ad56334b8cffc4135f2f7920f44fdedbfd434c34 Author: Gary Miller Date: Tue May 2 10:46:07 2023 +1000 rust-release.yaml commit fe6a159d3c61096ca2507901d197b3a6ac680e84 Author: Gary Miller Date: Tue May 2 09:36:20 2023 +1000 error on unknown fields for AdlWorkspace0 commit 976e9c3a7b415632bcd7aa988cf3db7097dae5fb Author: Gary Miller Date: Mon May 1 19:51:33 2023 +1000 create tsconfig based on config - named_options commit 3a5ed05000b0df0b23fd362f52030a7c475284b6 Author: Gary Miller Date: Mon May 1 17:13:01 2023 +1000 packagable - don't gen index.ts or write runtime's not .ts files commit 52dfa52b6b9e135aa56bbfefdb3e8c35da3f7cb6 Author: Gary Miller Date: Mon May 1 15:47:41 2023 +1000 added args for log init commit d4df19365799d5756e43ed273ecce36b3d7eef5a Author: Gary Miller Date: Mon May 1 11:14:48 2023 +1000 separate local and dep in resolver.ts commit bc5c6abea9fa04db94c531f8cfe2a17e59ebc48b Author: Gary Miller Date: Thu Apr 27 19:43:42 2023 +1000 unioned dir and embedded commit a09b0ca028a05a48905ca8d28d85db773241ef42 Author: Gary Miller Date: Wed Apr 26 20:52:28 2023 +1000 a work version commit 9c5a4016591401b0b210b14283b56e8a3d3124c4 Author: Gary Miller Date: Wed Apr 26 16:57:30 2023 +1000 wip: getting typescript/workspace to work - manual edits commit 2a09c7ed08f449925570464949a31aed302188c7 Author: Gary Miller Date: Wed Apr 26 13:22:22 2023 +1000 step: pnpm add -D typescript @types/node following https://brockherion.dev/blog/posts/setting-up-a-monorepo-with-pnpm-and-typescript/ commit 05f3da5a54b9e712bec87a263f2b1536af1eba5f Author: Gary Miller Date: Wed Apr 26 13:21:28 2023 +1000 added gitinore at typescript/workspace commit dda2c7fbb0497ddd707cb73058dcc7e888110824 Author: Gary Miller Date: Wed Apr 26 13:20:09 2023 +1000 step: pnpm init commit b50c7412b1c0e7ff94c40209df0acd82bd74ba8b Author: Gary Miller Date: Wed Apr 26 13:14:26 2023 +1000 moved typescript/tests to typescript/tests/cli commit 2e2b00ff106a5c9833d26f41a2fd2a4cea5abf88 Author: Gary Miller Date: Mon Apr 24 23:39:51 2023 +1000 wip gen index.ts(s) commit 72067b0269021676b0433130db764dcb1484ef12 Author: Gary Miller Date: Mon Apr 24 11:04:05 2023 +1000 using rust_embed for ts runtime commit 9007c6fc8812beedf23a00b2c3c59c58e4ef1306 Author: Gary Miller Date: Fri Apr 21 16:27:51 2023 +1000 work workspace gens commit 6cc7069536c92a1d50bcefb8dd740e07a6c05092 Author: Gary Miller Date: Fri Apr 21 10:39:16 2023 +1000 moved annontation injection out a bit commit 020682d3598582cad85a086801f279b8d1adbc5a Author: Gary Miller Date: Fri Apr 21 10:37:59 2023 +1000 modified tests needing sys.annotations, fix tsgen to check for type params withs params commit ac20a81740ca17d90c5255e826cec5207b8f2b35 Author: Gary Miller Date: Fri Apr 21 09:29:03 2023 +1000 move embedded_sys_loader details into packaging.adl commit c8c980e7426a6d64aa4b4162c1dca8962fd90d5e Author: Gary Miller Date: Thu Apr 20 20:22:30 2023 +1000 check len type params commit cd2789334340c6b4f3a005183a49b4eaca3effc3 Author: Gary Miller Date: Wed Apr 19 22:12:35 2023 +1000 creating package.json files commit 9743a45743d7c4d51d896db74bd780cbf85cb6f7 Author: Gary Miller Date: Wed Apr 19 17:59:59 2023 +1000 wip generating package.json(s) commit 8aa3ac56a039673db8b1b2d15d17d134c09fb9fa Author: Gary Miller Date: Wed Apr 19 16:04:08 2023 +1000 generating ts in folders for each adl package commit a00210bebf6da8657c2852c2ed613b76cc2c5ada Author: Gary Miller Date: Wed Apr 19 13:12:42 2023 +1000 wip commit c9545fee9a7d091bb79f396527f5d79d45ae45ee Author: Gary Miller Date: Wed Apr 19 00:44:44 2023 +1000 injecting npm_pkg_name as annotation commit ecd01be7d0098383f9c3d872b5f8f04909a5f5c0 Author: Gary Miller Date: Tue Apr 18 22:56:51 2023 +1000 changed tsgen to take TypescriptGenOptions instead of TsOpts commit 036354179ed73a2e60e63d2efa664ddd7ab93550 Author: Gary Miller Date: Tue Apr 18 21:11:06 2023 +1000 simple npm packge import commit 54d3d06771575f98d0f656f28fe752365b9e47a2 Author: Gary Miller Date: Tue Apr 18 17:07:45 2023 +1000 wip : picked from -named attempt commit f4465af8fac9bf65dbd5e1941efd0a7b0c04fdf5 Author: Gary Miller Date: Mon Apr 17 14:20:50 2023 +1000 fix circular ref testing commit 5c940b72fddbfddbffec22e79ab5642b22c2421f Author: Gary Miller Date: Mon Apr 17 13:11:45 2023 +1000 1st working version of a workspace commit 7736092f4e8a39f0d23aa245f2a6870db1d85318 Author: Gary Miller Date: Mon Apr 17 12:07:51 2023 +1000 wip gen workspace commit db5f48ae12ec65ea5e19d884320496e1e31acf42 Author: Gary Miller Date: Fri Apr 14 17:08:56 2023 +1000 wip on work & pkg commit 512ec6be7e724495d3f1e59f9bbed1d0ae597cb5 Author: Gary Miller Date: Fri Apr 14 15:02:01 2023 +1000 wip commit 9285ba42e58c7bd9fca9b77e2eb873d734376202 Author: Gary Miller Date: Fri Apr 14 14:44:42 2023 +1000 wip: define workspace and packaging defs commit 8658ee9457ddc3bf17ad4c11c8d63fedbe547d3e Author: Gary Miller Date: Tue Apr 4 18:48:29 2023 +1000 embedded adl stdlib commit 6d44cc536d10b7da98bd1af7aa1a1ee42e44de6d Author: Gary Miller Date: Tue Apr 4 17:02:09 2023 +1000 capitalise type names commit e46f7e1b618f4036de49026da558fc2336ed98d2 Author: Gary Miller Date: Tue Apr 4 15:41:08 2023 +1000 fix rel_import commit a9d4fc74482f9eda416a7c0e41e159cd4db67de5 Author: Gary Miller Date: Tue Apr 4 14:39:09 2023 +1000 working for protoapp commit 2474bb487cad57e455e178716b07415d63b4c709 Author: Gary Miller Date: Tue Apr 4 12:31:18 2023 +1000 gen TypeToken literal, changed cli args to match adlc commit 7d5b1e22fd0a4aa4f68d1c5463238f31fc04008a Author: Gary Miller Date: Tue Apr 4 10:41:21 2023 +1000 gen doc comments more consistent with adlc commit 6d02bbae427e801c5e48f4a9a67e39aabcead8c3 Author: Gary Miller Date: Mon Apr 3 21:25:36 2023 +1000 added optional output dir to table table data commit 059ddabd1a9b2096543b531d82adbfb2c2568219 Author: Gary Miller Date: Mon Apr 3 21:01:58 2023 +1000 generating resolver commit 7d688412f95bd13751a7f861cbc4f42b32ba095a Author: Gary Miller Date: Mon Apr 3 17:07:46 2023 +1000 modify and copy ts runtime commit bf27d872583df98d00dd668f4c4c7f6430b20663 Author: Gary Miller Date: Mon Apr 3 13:57:49 2023 +1000 wip: generating TS for all tests commit 55102d42a7e9f10a332ec461258fb848378c378b Author: Gary Miller Date: Tue Mar 28 22:02:30 2023 +1100 test module names match filename, added test meta data 'testing_table.json' commit 4a679b3df59d7669c67ac889a54468a97178e1ba Author: Gary Miller Date: Tue Mar 28 21:28:41 2023 +1100 assert_module_file_err commit f7717b98476e72595f2fe2dd855412c5550929ba Author: Gary Miller Date: Tue Mar 28 21:21:50 2023 +1100 modified rust tests to match git mv commit 5412bd4937fec3b4e13bf2b9c4b2bd6da7d1dbde Author: Gary Miller Date: Tue Mar 28 20:41:33 2023 +1100 moved and renamed adl test files commit ea6d9bb46bf0284226b3920e04339b36540ac454 Author: Tim Docker Date: Fri Mar 24 08:31:47 2023 +1100 fix multiline doc string handling commit 95d67114ea5e252fd275efbd108cfecd7c218bdb Author: Tim Docker Date: Fri Mar 24 08:04:58 2023 +1100 more codegen commit 0e56f2ae51e4af20fbaad1deebe00d4001c355d9 Author: Gary Miller Date: Thu Mar 23 21:22:03 2023 +1100 tsgen localnames, primitives and type_params for union and struct underscore before unused type params fix: compiler warnings commit d3fee8772f87382fc8fbef4d18051395412da067 Author: Tim Docker Date: Thu Mar 23 10:03:36 2023 +1100 more codegen commit 82eb63f32c3c53875c643dbd4d51b16257eb5b6b Author: Tim Docker Date: Wed Mar 22 09:26:08 2023 +1100 starting to flesh out rust codegen commit 1b59a318cf89dd91a03c3f4f6f6232b502ac09d2 Author: Tim Docker Date: Tue Mar 21 22:38:42 2023 +1100 added expected rust output for test 2 commit ef2fc45647e94c278543c633473bdbc37b432e3f Author: Tim Docker Date: Tue Mar 21 22:31:32 2023 +1100 fix resolver so that O(n) lookups now use hashing commit 9ad88b1816971e522e0513af92dafd95f88de3bb Merge: 4b06e953 378f21da Author: Tim Docker Date: Fri Mar 17 17:15:26 2023 +1100 Merge branch 'master' into rust-tooling commit 4b06e953d1901f1eb124c97c70cb5355a648c043 Author: Gary Miller Date: Fri Mar 17 13:11:33 2023 +1100 adding tim's comment on #184 commit 2c404350a72aa1d34627a08276f9d2362f2d2349 Author: Gary Miller Date: Thu Mar 16 19:07:55 2023 +1100 Start of tsgen tooling commit e752e7db8cc832ace7df864dab8cd9d5ab25d856 Author: Tim Docker Date: Wed Mar 15 21:49:23 2023 +1100 fix refs to relocated adl test files commit 60644735b9b2961e4de10a8ebde79ea28de89c15 Author: Tim Docker Date: Sun Feb 12 20:44:10 2023 +1100 generate structured rust module tree commit 476e8316e6ad4d090867670bee376fa38ee3aad3 Author: Tim Docker Date: Sat Feb 11 22:04:18 2023 +1100 switch to using clap derive for command line parsing commit 4e4ea7ca7a8c4e67c14a6789517e57e95aa5e056 Author: Tim Docker Date: Sat Feb 11 04:35:14 2023 +1100 make test adl files into top level dir, and make names consistent with module names commit 2d3f3aa2117277da4e6aa08b4d215c6baa2b4624 Author: Tim Docker Date: Sat Feb 11 04:26:54 2023 +1100 wip: rust generation commit a4328c6de4cd4d8f3514d4e9b4fa447b9b49964c Author: Gary Miller Date: Tue Mar 14 18:18:08 2023 +1100 fix: 'cargo test' working commit 4efbedc7e137a0f870558be046a2009c30cbdc6f Author: Tim Docker Date: Fri Dec 9 14:33:20 2022 +1300 remove spans from the ast until we work out how to reconcile them with abstract loading commit a7030899d8f29e190a50fd4da6f844b0c6ee469e Author: Tim Docker Date: Fri Dec 9 08:30:16 2022 +1300 simplified error handling in resolver commit dcc79e1e460115435c50fdcaa7050ecb83880358 Author: Tim Docker Date: Fri Dec 9 08:14:47 2022 +1300 use env_logger framework commit 806f5c7bf2f959c096252ae96b42b292e6eb50db Author: Tim Docker Date: Fri Dec 9 08:11:20 2022 +1300 added duplicate checks commit cdac963a8cdfbf6a7dfaa7c576b7e03326efba4c Author: Tim Docker Date: Thu Dec 8 22:51:01 2022 +1300 added a doc describing ADL processing steps commit 8c0a940bfee53f1b3bd73cd5528bd7b6006ed23f Author: Tim Docker Date: Thu Dec 8 16:49:59 2022 +1300 include local references in emitted ast commit 8135a066901b5e56d283c06763cc75d3a1be2896 Author: Tim Docker Date: Thu Dec 8 13:36:29 2022 +1300 Added an ast cli command commit c8be33c07e6c9cedb6f724a97fc8470370488a32 Author: Tim Docker Date: Thu Dec 8 12:21:59 2022 +1300 fleshing out the resolver commit e43f444473fac04d9904c16e97cc75675551efc8 Author: Tim Docker Date: Wed Dec 7 21:43:50 2022 +1300 improved parser error messages commit 0805b16ec17a67bc25177ff8bf30b0acc6a23abc Author: Tim Docker Date: Wed Dec 7 16:08:53 2022 +1300 fleshing out verification command commit a360977fe5fe49a171ae18b741346bf5d44f90bb Author: Tim Docker Date: Wed Dec 7 13:55:39 2022 +1300 boilerplate for a cli commit 653f15ffaa7271b11f7b76e3584701cc4bc18966 Author: Tim Docker Date: Fri Aug 19 12:35:30 2022 +1000 wip: loader commit 2ef114e389a49d7152b3ce521ef6b24ce6abf06f Author: Tim Docker Date: Thu Aug 18 17:19:27 2022 +1000 wip: resolver commit 73a45b42516b8bb5242edeb5a7ca95f480a57f44 Author: Tim Docker Date: Tue Aug 16 09:55:03 2022 +1000 tests for apply_explicit_annotations commit 156f0c037adf35a75ad926962b46ce171926d3ad Author: Tim Docker Date: Mon Aug 15 21:58:15 2022 +1000 implemented apply_explicit_annotations commit 1d4c6a6e5e3183c6e32693804fa4b9d0f0be9f39 Author: Tim Docker Date: Mon Aug 15 20:23:14 2022 +1000 fix up warnings commit e29d2e00353f1f3ba04414d3eefba82a4e5b9b13 Author: Tim Docker Date: Mon Aug 15 20:19:39 2022 +1000 fix parsing of docstrings and annotations commit 9acb07739ef559f23581ae2cc7303e35694e36e4 Author: Tim Docker Date: Mon Aug 15 15:51:18 2022 +1000 parse (defunct?) decl version numbers if present commit aa5720c1e12c8406ae244da877f1003e674284a0 Author: Tim Docker Date: Sun May 8 18:59:50 2022 +1000 located parsing commit 40e6c99e917585a84af20f3740cf15da0b7e31a6 Author: Tim Docker Date: Thu Apr 28 22:12:53 2022 +1000 Factor scratch build script commit 05b12ae0b7e140eb1b7b5cb070b4fd8bc53844f4 Author: Tim Docker Date: Wed Apr 27 11:34:04 2022 +1000 Split parser modules into separate files commit bddb2eb4b8bac71592bcf586d08e869e06227d7c Author: Tim Docker Date: Wed Apr 27 11:27:53 2022 +1000 Added field level annotations commit 010ed7d6683f270f501031c23c33222a99824243 Author: Tim Docker Date: Wed Apr 27 10:56:16 2022 +1000 Added imports to parser commit ee21025c694d451732c2c02cdd9e6ee2b9fb6c2b Author: Tim Docker Date: Tue Apr 26 19:02:38 2022 +1000 Added parsing of explicit annotations commit 0c2fe8ef7800d8a1d49680ee49282b13f5496de2 Author: Tim Docker Date: Tue Apr 26 09:25:24 2022 +1000 Simplify with imports commit d2f60b130514e63e18911dabdf39914b70854837 Author: Tim Docker Date: Thu Apr 21 17:27:57 2022 +1000 Annotations and docstrings commit 74203ec0d290d3650af5151604cb36f26915488d Author: Tim Docker Date: Thu Apr 21 10:34:48 2022 +1000 Improve json string processing commit c8db1e906d352c6c711903d2f0aab4c6c6e8ea59 Author: Tim Docker Date: Thu Apr 21 08:28:23 2022 +1000 json parsing commit 9f5511fbd55ac476278dae735ce9d6473a8c98d1 Author: Tim Docker Date: Thu Apr 14 14:33:47 2022 +1000 parser fixes commit 92233dbdcffee9238f42e9b29fa3f7da65546c11 Author: Tim Docker Date: Wed Apr 6 14:09:23 2022 +1000 WIP: rust parser commit b21241360232d0909c3111a6116e818a742545d6 Author: Tim Docker Date: Sun Apr 3 15:04:22 2022 +1000 WIP: rust parser commit 6acb467460e467b34eda25068b99d4067b812a84 Author: Tim Docker Date: Sun Apr 3 15:04:02 2022 +1000 WIP: rust parser commit 3b23dd8ef48c249c81e45c02a3e142fdd90288a0 Author: Tim Docker Date: Sun Apr 3 14:05:03 2022 +1000 WIP: rust parser commit df8c786db498d86dd8634fea593fce41ef3208e5 Author: Tim Docker Date: Sun Apr 3 10:06:49 2022 +1000 Starter project for rust tooling commit 1d818b059b1e21ef9ef6415d686d06cb91aac23f Author: Tim Docker Date: Sun Apr 3 15:03:31 2022 +1000 Add Debug to derived traits in rust code commit eed543b8d092ccbb4ca36b05667bf28a81bf3568 Author: Tim Docker Date: Sun Apr 3 10:03:49 2022 +1000 Adding missing mapentry to published rust runtime --- .github/workflows/rust-release.yaml | 74 ++ .gitignore | 2 + Cargo.lock | 765 ++++++++++++++++ Cargo.toml | 4 + adl/adl.work.json | 61 ++ adl/adl.work1.json | 92 ++ adl/adl.work2.json | 99 ++ adl/adl.work3.json | 60 ++ adl/adlc/adl.pkg.json | 12 + .../lib/adl => adl/adlc}/adlc/config/cpp.adl | 0 .../adl => adl/adlc}/adlc/config/haskell.adl | 0 .../lib/adl => adl/adlc}/adlc/config/java.adl | 0 .../lib/adl => adl/adlc}/adlc/config/rust.adl | 0 .../adlc}/adlc/config/typescript.adl | 3 + adl/adlc/adlc/packaging.adl | 259 ++++++ adl/adlc/adlc/testing_table.adl | 18 + adl/stdlib/adl.pkg.json | 5 + adl/stdlib/sys/adlast2.adl | 166 ++++ adl/stdlib/sys/types.adl-rs | 10 +- .../input => adl/tests/demo1}/picture.adl | 0 .../input => adl/tests/demo1}/picture.adl-rs | 0 .../test.adl => adl/tests/test1/test1.adl | 0 .../test.adl => adl/tests/test10/test10.adl | 2 +- .../test.adl => adl/tests/test11/test11.adl | 2 +- .../test.adl => adl/tests/test12/test12.adl | 2 +- .../test.adl => adl/tests/test13/test13.adl | 2 +- .../test.adl => adl/tests/test14/test14.adl | 1 + .../test.adl => adl/tests/test15/test15.adl | 2 +- .../test.adl => adl/tests/test16/test16.adl | 2 +- .../input => adl/tests/test16}/test2.adl | 0 .../test.adl => adl/tests/test17/test17.adl | 0 .../test.adl => adl/tests/test18/test18.adl | 0 .../tests/test18/test18.adl-rs | 0 adl/tests/test19/test19.adl | 15 + adl/tests/test19/test19_01.adl | 11 + adl/tests/test19/test19_02.adl | 12 + .../test.adl => adl/tests/test2/test2.adl | 6 +- .../tests/test2/test2.adl-hs | 0 adl/tests/test2/test2_01.adl | 42 + .../test.adl => adl/tests/test20/test20.adl | 0 .../test.adl => adl/tests/test21/test21.adl | 2 +- .../input => adl/tests/test22}/test22a.adl | 0 .../input => adl/tests/test22}/test22b.adl | 0 .../input => adl/tests/test23}/test23.adl | 0 .../input => adl/tests/test24}/test24.adl | 0 adl/tests/test24/test24_01.adl | 31 + adl/tests/test24/test24_02.adl | 33 + .../input => adl/tests/test25}/admin.adl | 0 .../input => adl/tests/test26}/test26.adl | 2 +- .../input => adl/tests/test27}/test27.adl | 0 .../input => adl/tests/test27}/test27a.adl | 0 .../input => adl/tests/test28}/test28.adl | 0 .../input => adl/tests/test29}/test29.adl | 0 .../test.adl => adl/tests/test3/test3.adl | 0 adl/tests/test30/test30.adl | 19 + adl/tests/test30/test30_01.adl | 19 + adl/tests/test30/test30_02.adl | 21 + adl/tests/test30/test30_03.adl | 14 + adl/tests/test30/test30_04.adl | 15 + adl/tests/test31/lib/adl.pkg.json | 12 + adl/tests/test31/lib/common.adl | 94 ++ adl/tests/test31/lib/common.adl-java | 82 ++ adl/tests/test31/lib/common/adminui/api.adl | 168 ++++ .../test31/lib/common/adminui/api.adl-java | 6 + .../test31/lib/common/adminui/config.adl | 35 + adl/tests/test31/lib/common/adminui/db.adl | 40 + .../test31/lib/common/adminui/db.adl-java | 6 + adl/tests/test31/lib/common/config/aws.adl | 46 + .../test31/lib/common/config/aws.adl-java | 7 + adl/tests/test31/lib/common/config/azure.adl | 15 + adl/tests/test31/lib/common/config/db.adl | 67 ++ .../test31/lib/common/config/db.adl-java | 7 + .../test31/lib/common/config/emailer.adl | 22 + .../test31/lib/common/config/emailer.adl-java | 7 + .../test31/lib/common/config/frontend.adl | 22 + .../lib/common/config/frontend.adl-java | 8 + adl/tests/test31/lib/common/config/google.adl | 12 + .../test31/lib/common/config/google.adl-java | 8 + adl/tests/test31/lib/common/config/jwt.adl | 10 + .../test31/lib/common/config/jwt.adl-java | 7 + adl/tests/test31/lib/common/config/log.adl | 69 ++ .../test31/lib/common/config/log.adl-java | 12 + adl/tests/test31/lib/common/config/okta.adl | 32 + .../test31/lib/common/config/okta.adl-java | 12 + adl/tests/test31/lib/common/config/server.adl | 3 + adl/tests/test31/lib/common/config/sms.adl | 32 + .../test31/lib/common/config/sms.adl-java | 7 + .../test31/lib/common/config/storage.adl | 30 + adl/tests/test31/lib/common/db.adl | 78 ++ adl/tests/test31/lib/common/db.adl-java | 32 + adl/tests/test31/lib/common/flyway/api.adl | 119 +++ .../test31/lib/common/flyway/api.adl-java | 7 + .../lib/common/flyway/example_patterns.adl | 103 +++ .../common/flyway/example_patterns.adl-java | 7 + .../test31/lib/common/flyway/internals.adl | 112 +++ .../lib/common/flyway/internals.adl-java | 7 + adl/tests/test31/lib/common/http.adl | 152 ++++ adl/tests/test31/lib/common/http.adl-java | 7 + adl/tests/test31/lib/common/strings.adl | 46 + adl/tests/test31/lib/common/tabular.adl | 83 ++ adl/tests/test31/lib/common/tabular.adl-java | 8 + adl/tests/test31/lib/common/ui.adl | 51 ++ adl/tests/test31/lib/common/ui.adl-java | 7 + adl/tests/test31/proj/adl.pkg.json | 17 + .../test31/proj/protoclient/protoapp/api.adl | 149 ++++ .../proj/protoclient/protoapp/config.adl | 51 ++ .../test31/proj/protoclient/protoapp/db.adl | 57 ++ .../proj/protoclient/protoapp/uiconfig.adl | 17 + adl/tests/test32/test32a.adl | 9 + adl/tests/test32/test32b.adl | 9 + .../test.adl => adl/tests/test4/test4.adl | 0 .../tests/test4/test4.adl-cpp | 0 .../tests/test4/test4.adl-hs | 0 .../tests/test4/test4.adl-java | 0 .../tests/test4/test4.adl-rs | 0 .../test.adl => adl/tests/test5/test5.adl | 0 .../tests/test5/test5.adl-hs | 0 .../tests/test5/test5.adl-rs | 0 .../test.adl => adl/tests/test6/test6.adl | 0 .../test.adl => adl/tests/test7/test7.adl | 0 .../test.adl => adl/tests/test8/test8.adl | 2 +- .../test.adl => adl/tests/test9/test9.adl | 2 +- adl/tests/testing_table.json | 90 ++ docs/processing.md | 48 + .../ADL/Compiler/Backends/Rust/Internal.hs | 4 +- haskell/compiler/lib/adl/adlc | 1 + haskell/compiler/tests/Main.hs | 19 +- .../demo1/rs-output/demo1/adl/picture.rs | 8 +- .../test14/rs-output/test14/adl/test14.rs | 4 +- .../test18/rs-output/test18/adl/test18.rs | 8 +- haskell/compiler/tests/test19/input/test.adl | 20 - .../tests/test2/rs-output/test2/adl/test2.rs | 12 +- .../test20/rs-output/test20/adl/test20.rs | 4 +- .../test29/rs-output/test29/adl/test29.rs | 2 +- .../tests/test3/rs-output/test3/adl/test3.rs | 12 +- .../test4/rs-output/test4/adl/sys/types.rs | 2 +- .../tests/test4/rs-output/test4/adl/test4.rs | 2 +- .../tests/test5/rs-output/test5/adl/test5.rs | 34 +- .../test6/rs-output/test6/adl/sys/adlast.rs | 26 +- .../test6/rs-output/test6/adl/sys/dynamic.rs | 2 +- .../test6/rs-output/test6/adl/sys/types.rs | 2 +- .../tests/test7/rs-output/test7/adl/test7.rs | 4 +- haskell/tools/scratch-build.sh | 114 ++- rust/compiler/.gitignore | 1 + rust/compiler/Cargo.toml | 26 + rust/compiler/Readme.md | 44 + rust/compiler/genadl.sh | 29 + rust/compiler/src/adlgen/adlc/config/mod.rs | 1 + rust/compiler/src/adlgen/adlc/config/rust.rs | 62 ++ rust/compiler/src/adlgen/adlc/mod.rs | 3 + rust/compiler/src/adlgen/adlc/packaging.rs | 842 ++++++++++++++++++ .../compiler/src/adlgen/adlc/testing_table.rs | 81 ++ rust/compiler/src/adlgen/mod.rs | 2 + rust/compiler/src/adlgen/sys/adlast2.rs | 377 ++++++++ rust/compiler/src/adlgen/sys/annotations.rs | 23 + rust/compiler/src/adlgen/sys/mod.rs | 3 + rust/compiler/src/adlgen/sys/types.rs | 13 + rust/compiler/src/adlrt/custom/mod.rs | 1 + rust/compiler/src/adlrt/custom/sys/mod.rs | 1 + .../src/adlrt/custom/sys/types/map.rs | 71 ++ .../src/adlrt/custom/sys/types/mapentry.rs | 20 + .../src/adlrt/custom/sys/types/maybe.rs | 57 ++ .../src/adlrt/custom/sys/types/mod.rs | 6 + .../src/adlrt/custom/sys/types/pair.rs | 49 + .../src/adlrt/custom/sys/types/result.rs | 61 ++ .../src/adlrt/custom/sys/types/set.rs | 48 + rust/compiler/src/adlrt/mod.rs | 1 + rust/compiler/src/adlstdlib/mod.rs | 87 ++ rust/compiler/src/cli/ast.rs | 44 + rust/compiler/src/cli/mod.rs | 362 ++++++++ rust/compiler/src/cli/rust/generate.rs | 256 ++++++ rust/compiler/src/cli/rust/mod.rs | 56 ++ rust/compiler/src/cli/rust/rsfile.rs | 80 ++ rust/compiler/src/cli/tsgen/astgen.rs | 198 ++++ rust/compiler/src/cli/tsgen/defaultval.rs | 656 ++++++++++++++ rust/compiler/src/cli/tsgen/generate.rs | 633 +++++++++++++ rust/compiler/src/cli/tsgen/mod.rs | 606 +++++++++++++ rust/compiler/src/cli/tsgen/tests.rs | 204 +++++ .../compiler/src/cli/tsgen/ts-runtime}/adl.ts | 0 .../src/cli/tsgen/ts-runtime}/dynamic.ts | 0 .../src/cli/tsgen/ts-runtime}/json.ts | 0 .../cli/tsgen/ts-runtime/package-dist.json | 10 + .../src/cli/tsgen/ts-runtime/package.json | 18 + .../src/cli/tsgen/ts-runtime}/sys/adlast.ts | 0 .../src/cli/tsgen/ts-runtime}/sys/dynamic.ts | 0 .../src/cli/tsgen/ts-runtime}/sys/types.ts | 0 .../src/cli/tsgen/ts-runtime/tsconfig.json | 13 + .../src/cli/tsgen/ts-runtime}/utils.ts | 0 rust/compiler/src/cli/tsgen/utils.rs | 359 ++++++++ rust/compiler/src/cli/verify.rs | 18 + rust/compiler/src/cli/workspace.rs | 268 ++++++ rust/compiler/src/lib.rs | 9 + rust/compiler/src/main.rs | 9 + rust/compiler/src/parser/mod.rs | 670 ++++++++++++++ rust/compiler/src/parser/tests.rs | 378 ++++++++ rust/compiler/src/processing/annotations.rs | 298 +++++++ rust/compiler/src/processing/checks.rs | 48 + rust/compiler/src/processing/loader.rs | 255 ++++++ rust/compiler/src/processing/mod.rs | 32 + rust/compiler/src/processing/primitives.rs | 50 ++ rust/compiler/src/processing/resolver.rs | 484 ++++++++++ rust/compiler/src/processing/writer.rs | 97 ++ rust/compiler/src/utils/ast.rs | 30 + rust/compiler/src/utils/mod.rs | 1 + rust/runtime/custom/sys/types/map.rs | 19 +- rust/runtime/custom/sys/types/mapentry.rs | 2 +- rust/runtime/custom/sys/types/maybe.rs | 4 +- rust/runtime/custom/sys/types/pair.rs | 2 +- rust/runtime/custom/sys/types/result.rs | 2 +- typescript/cli/runtime/adl.ts | 84 ++ typescript/cli/runtime/dynamic.ts | 20 + typescript/cli/runtime/json.ts | 514 +++++++++++ typescript/cli/runtime/sys/adlast.ts | 274 ++++++ typescript/cli/runtime/sys/dynamic.ts | 23 + typescript/cli/runtime/sys/types.ts | 93 ++ typescript/cli/runtime/utils.ts | 77 ++ .../{ => cli}/tests/deno-1.10.2/.gitignore | 0 .../tests/deno-1.10.2/example.tests.ts | 0 typescript/{ => cli}/tests/example.adl | 0 typescript/{ => cli}/tests/run-tests.sh | 0 .../{ => cli}/tests/ts-3.5.2/.gitignore | 0 .../{ => cli}/tests/ts-3.5.2/example.spec.ts | 0 .../{ => cli}/tests/ts-3.5.2/package.json | 0 .../{ => cli}/tests/ts-3.5.2/tsconfig.json | 0 .../{ => cli}/tests/ts-3.5.2/tslint.json | 0 typescript/{ => cli}/tests/ts-3.5.2/yarn.lock | 0 .../{ => cli}/tests/ts-3.8.3/.gitignore | 0 .../{ => cli}/tests/ts-3.8.3/example.spec.ts | 0 .../{ => cli}/tests/ts-3.8.3/package.json | 0 .../{ => cli}/tests/ts-3.8.3/tsconfig.json | 0 .../{ => cli}/tests/ts-3.8.3/tslint.json | 0 typescript/{ => cli}/tests/ts-3.8.3/yarn.lock | 0 .../{ => cli}/tests/ts-4.2.4/.gitignore | 0 .../{ => cli}/tests/ts-4.2.4/example.spec.ts | 0 .../{ => cli}/tests/ts-4.2.4/package.json | 0 .../{ => cli}/tests/ts-4.2.4/tsconfig.json | 0 .../{ => cli}/tests/ts-4.2.4/tslint.json | 0 typescript/{ => cli}/tests/ts-4.2.4/yarn.lock | 0 .../{ => cli}/tests/ts-4.6.3/.gitignore | 0 .../{ => cli}/tests/ts-4.6.3/example.spec.ts | 0 .../{ => cli}/tests/ts-4.6.3/package.json | 0 .../{ => cli}/tests/ts-4.6.3/tsconfig.json | 0 .../{ => cli}/tests/ts-4.6.3/tslint.json | 0 typescript/{ => cli}/tests/ts-4.6.3/yarn.lock | 0 typescript/workspace/.gitignore | 2 + typescript/workspace/adl.work.json | 109 +++ typescript/workspace/adl/lib/adl.pkg.json | 12 + typescript/workspace/adl/lib/common.adl | 94 ++ typescript/workspace/adl/lib/common.adl-java | 82 ++ .../workspace/adl/lib/common/adminui/api.adl | 168 ++++ .../adl/lib/common/adminui/api.adl-java | 6 + .../adl/lib/common/adminui/config.adl | 35 + .../workspace/adl/lib/common/adminui/db.adl | 40 + .../adl/lib/common/adminui/db.adl-java | 6 + .../workspace/adl/lib/common/config/aws.adl | 46 + .../adl/lib/common/config/aws.adl-java | 7 + .../workspace/adl/lib/common/config/azure.adl | 15 + .../workspace/adl/lib/common/config/db.adl | 67 ++ .../adl/lib/common/config/db.adl-java | 7 + .../adl/lib/common/config/emailer.adl | 22 + .../adl/lib/common/config/emailer.adl-java | 7 + .../adl/lib/common/config/frontend.adl | 22 + .../adl/lib/common/config/frontend.adl-java | 8 + .../adl/lib/common/config/google.adl | 12 + .../adl/lib/common/config/google.adl-java | 8 + .../workspace/adl/lib/common/config/jwt.adl | 10 + .../adl/lib/common/config/jwt.adl-java | 7 + .../workspace/adl/lib/common/config/log.adl | 69 ++ .../adl/lib/common/config/log.adl-java | 12 + .../workspace/adl/lib/common/config/okta.adl | 32 + .../adl/lib/common/config/okta.adl-java | 12 + .../workspace/adl/lib/common/config/sms.adl | 32 + .../adl/lib/common/config/sms.adl-java | 7 + .../adl/lib/common/config/storage.adl | 30 + typescript/workspace/adl/lib/common/db.adl | 78 ++ .../workspace/adl/lib/common/db.adl-java | 32 + .../workspace/adl/lib/common/flyway/api.adl | 119 +++ .../adl/lib/common/flyway/api.adl-java | 7 + .../lib/common/flyway/example_patterns.adl | 103 +++ .../common/flyway/example_patterns.adl-java | 7 + .../adl/lib/common/flyway/internals.adl | 112 +++ .../adl/lib/common/flyway/internals.adl-java | 7 + typescript/workspace/adl/lib/common/http.adl | 152 ++++ .../workspace/adl/lib/common/http.adl-java | 7 + .../workspace/adl/lib/common/strings.adl | 46 + .../workspace/adl/lib/common/tabular.adl | 83 ++ .../workspace/adl/lib/common/tabular.adl-java | 8 + typescript/workspace/adl/lib/common/ui.adl | 51 ++ .../workspace/adl/lib/common/ui.adl-java | 7 + typescript/workspace/adl/proj/adl.pkg.json | 17 + .../adl/proj/protoclient/protoapp/api.adl | 149 ++++ .../adl/proj/protoclient/protoapp/config.adl | 51 ++ .../adl/proj/protoclient/protoapp/db.adl | 57 ++ .../proj/protoclient/protoapp/uiconfig.adl | 17 + .../workspace/generated/common/.adl-manifest | 30 + .../workspace/generated/common/_/common.ts | 310 +++++++ .../workspace/generated/common/_/index.ts | 2 + .../workspace/generated/common/adminui/api.ts | 455 ++++++++++ .../generated/common/adminui/config.ts | 79 ++ .../workspace/generated/common/adminui/db.ts | 70 ++ .../generated/common/adminui/index.ts | 4 + .../workspace/generated/common/config/aws.ts | 196 ++++ .../generated/common/config/azure.ts | 68 ++ .../workspace/generated/common/config/db.ts | 124 +++ .../generated/common/config/emailer.ts | 73 ++ .../generated/common/config/frontend.ts | 56 ++ .../generated/common/config/google.ts | 42 + .../generated/common/config/index.ts | 12 + .../workspace/generated/common/config/jwt.ts | 36 + .../workspace/generated/common/config/log.ts | 250 ++++++ .../workspace/generated/common/config/okta.ts | 69 ++ .../workspace/generated/common/config/sms.ts | 112 +++ .../generated/common/config/storage.ts | 90 ++ typescript/workspace/generated/common/db.ts | 173 ++++ .../workspace/generated/common/flyway/api.ts | 419 +++++++++ .../common/flyway/example_patterns.ts | 54 ++ .../generated/common/flyway/index.ts | 4 + .../generated/common/flyway/internals.ts | 385 ++++++++ typescript/workspace/generated/common/http.ts | 467 ++++++++++ .../workspace/generated/common/index.ts | 10 + .../generated/common/package-dist.json | 12 + .../workspace/generated/common/package.json | 16 + .../workspace/generated/common/resolver.ts | 60 ++ .../workspace/generated/common/strings.ts | 100 +++ .../workspace/generated/common/tabular.ts | 359 ++++++++ .../workspace/generated/common/tsconfig.json | 17 + typescript/workspace/generated/common/ui.ts | 141 +++ .../generated/protoclient/.adl-manifest | 8 + .../workspace/generated/protoclient/index.ts | 2 + .../generated/protoclient/package.json | 18 + .../generated/protoclient/protoapp/api.ts | 365 ++++++++ .../generated/protoclient/protoapp/config.ts | 136 +++ .../generated/protoclient/protoapp/db.ts | 153 ++++ .../generated/protoclient/protoapp/index.ts | 5 + .../protoclient/protoapp/uiconfig.ts | 48 + .../generated/protoclient/resolver.ts | 24 + .../generated/protoclient/tsconfig.json | 17 + typescript/workspace/generated/runtime/adl.ts | 84 ++ .../workspace/generated/runtime/dynamic.ts | 20 + .../workspace/generated/runtime/json.ts | 514 +++++++++++ .../generated/runtime/package-dist.json | 10 + .../workspace/generated/runtime/package.json | 18 + .../workspace/generated/runtime/sys/adlast.ts | 274 ++++++ .../generated/runtime/sys/dynamic.ts | 23 + .../workspace/generated/runtime/sys/types.ts | 93 ++ .../workspace/generated/runtime/tsconfig.json | 13 + .../workspace/generated/runtime/utils.ts | 77 ++ .../workspace/generated/sys/.adl-manifest | 8 + typescript/workspace/generated/sys/adlast.ts | 448 ++++++++++ typescript/workspace/generated/sys/adlast2.ts | 736 +++++++++++++++ .../workspace/generated/sys/annotations.ts | 66 ++ typescript/workspace/generated/sys/dynamic.ts | 37 + typescript/workspace/generated/sys/index.ts | 6 + .../workspace/generated/sys/package.json | 16 + .../workspace/generated/sys/resolver.ts | 22 + .../workspace/generated/sys/tsconfig.json | 17 + typescript/workspace/generated/sys/types.ts | 167 ++++ typescript/workspace/package.json | 16 + .../workspace/packages/tsconfig/README.md | 3 + .../workspace/packages/tsconfig/base.json | 22 + .../workspace/packages/tsconfig/nextjs.json | 22 + .../workspace/packages/tsconfig/package.json | 10 + .../packages/tsconfig/react-library.json | 11 + typescript/workspace/pnpm-lock.yaml | 97 ++ typescript/workspace/pnpm-workspace.yaml | 7 + 365 files changed, 23320 insertions(+), 162 deletions(-) create mode 100644 .github/workflows/rust-release.yaml create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 adl/adl.work.json create mode 100644 adl/adl.work1.json create mode 100644 adl/adl.work2.json create mode 100644 adl/adl.work3.json create mode 100644 adl/adlc/adl.pkg.json rename {haskell/compiler/lib/adl => adl/adlc}/adlc/config/cpp.adl (100%) rename {haskell/compiler/lib/adl => adl/adlc}/adlc/config/haskell.adl (100%) rename {haskell/compiler/lib/adl => adl/adlc}/adlc/config/java.adl (100%) rename {haskell/compiler/lib/adl => adl/adlc}/adlc/config/rust.adl (100%) rename {haskell/compiler/lib/adl => adl/adlc}/adlc/config/typescript.adl (59%) create mode 100644 adl/adlc/adlc/packaging.adl create mode 100644 adl/adlc/adlc/testing_table.adl create mode 100644 adl/stdlib/adl.pkg.json create mode 100644 adl/stdlib/sys/adlast2.adl rename {haskell/compiler/tests/demo1/input => adl/tests/demo1}/picture.adl (100%) rename {haskell/compiler/tests/demo1/input => adl/tests/demo1}/picture.adl-rs (100%) rename haskell/compiler/tests/test1/input/test.adl => adl/tests/test1/test1.adl (100%) rename haskell/compiler/tests/test10/input/test.adl => adl/tests/test10/test10.adl (86%) rename haskell/compiler/tests/test11/input/test.adl => adl/tests/test11/test11.adl (86%) rename haskell/compiler/tests/test12/input/test.adl => adl/tests/test12/test12.adl (90%) rename haskell/compiler/tests/test13/input/test.adl => adl/tests/test13/test13.adl (93%) rename haskell/compiler/tests/test14/input/test.adl => adl/tests/test14/test14.adl (91%) rename haskell/compiler/tests/test15/input/test.adl => adl/tests/test15/test15.adl (94%) rename haskell/compiler/tests/test16/input/test.adl => adl/tests/test16/test16.adl (75%) rename {haskell/compiler/tests/test16/input => adl/tests/test16}/test2.adl (100%) rename haskell/compiler/tests/test17/input/test.adl => adl/tests/test17/test17.adl (100%) rename haskell/compiler/tests/test18/input/test.adl => adl/tests/test18/test18.adl (100%) rename haskell/compiler/tests/test18/input/test.adl-rs => adl/tests/test18/test18.adl-rs (100%) create mode 100644 adl/tests/test19/test19.adl create mode 100644 adl/tests/test19/test19_01.adl create mode 100644 adl/tests/test19/test19_02.adl rename haskell/compiler/tests/test2/input/test.adl => adl/tests/test2/test2.adl (78%) rename haskell/compiler/tests/test2/input/test.adl-hs => adl/tests/test2/test2.adl-hs (100%) create mode 100644 adl/tests/test2/test2_01.adl rename haskell/compiler/tests/test20/input/test.adl => adl/tests/test20/test20.adl (100%) rename haskell/compiler/tests/test21/input/test.adl => adl/tests/test21/test21.adl (96%) rename {haskell/compiler/tests/test22/input => adl/tests/test22}/test22a.adl (100%) rename {haskell/compiler/tests/test22/input => adl/tests/test22}/test22b.adl (100%) rename {haskell/compiler/tests/test23/input => adl/tests/test23}/test23.adl (100%) rename {haskell/compiler/tests/test24/input => adl/tests/test24}/test24.adl (100%) create mode 100644 adl/tests/test24/test24_01.adl create mode 100644 adl/tests/test24/test24_02.adl rename {haskell/compiler/tests/test25/input => adl/tests/test25}/admin.adl (100%) rename {haskell/compiler/tests/test26/input => adl/tests/test26}/test26.adl (76%) rename {haskell/compiler/tests/test27/input => adl/tests/test27}/test27.adl (100%) rename {haskell/compiler/tests/test27/input => adl/tests/test27}/test27a.adl (100%) rename {haskell/compiler/tests/test28/input => adl/tests/test28}/test28.adl (100%) rename {haskell/compiler/tests/test29/input => adl/tests/test29}/test29.adl (100%) rename haskell/compiler/tests/test3/input/test.adl => adl/tests/test3/test3.adl (100%) create mode 100644 adl/tests/test30/test30.adl create mode 100644 adl/tests/test30/test30_01.adl create mode 100644 adl/tests/test30/test30_02.adl create mode 100644 adl/tests/test30/test30_03.adl create mode 100644 adl/tests/test30/test30_04.adl create mode 100644 adl/tests/test31/lib/adl.pkg.json create mode 100644 adl/tests/test31/lib/common.adl create mode 100644 adl/tests/test31/lib/common.adl-java create mode 100644 adl/tests/test31/lib/common/adminui/api.adl create mode 100644 adl/tests/test31/lib/common/adminui/api.adl-java create mode 100644 adl/tests/test31/lib/common/adminui/config.adl create mode 100644 adl/tests/test31/lib/common/adminui/db.adl create mode 100644 adl/tests/test31/lib/common/adminui/db.adl-java create mode 100644 adl/tests/test31/lib/common/config/aws.adl create mode 100644 adl/tests/test31/lib/common/config/aws.adl-java create mode 100644 adl/tests/test31/lib/common/config/azure.adl create mode 100644 adl/tests/test31/lib/common/config/db.adl create mode 100644 adl/tests/test31/lib/common/config/db.adl-java create mode 100644 adl/tests/test31/lib/common/config/emailer.adl create mode 100644 adl/tests/test31/lib/common/config/emailer.adl-java create mode 100644 adl/tests/test31/lib/common/config/frontend.adl create mode 100644 adl/tests/test31/lib/common/config/frontend.adl-java create mode 100644 adl/tests/test31/lib/common/config/google.adl create mode 100644 adl/tests/test31/lib/common/config/google.adl-java create mode 100644 adl/tests/test31/lib/common/config/jwt.adl create mode 100644 adl/tests/test31/lib/common/config/jwt.adl-java create mode 100644 adl/tests/test31/lib/common/config/log.adl create mode 100644 adl/tests/test31/lib/common/config/log.adl-java create mode 100644 adl/tests/test31/lib/common/config/okta.adl create mode 100644 adl/tests/test31/lib/common/config/okta.adl-java create mode 100644 adl/tests/test31/lib/common/config/server.adl create mode 100644 adl/tests/test31/lib/common/config/sms.adl create mode 100644 adl/tests/test31/lib/common/config/sms.adl-java create mode 100644 adl/tests/test31/lib/common/config/storage.adl create mode 100644 adl/tests/test31/lib/common/db.adl create mode 100644 adl/tests/test31/lib/common/db.adl-java create mode 100644 adl/tests/test31/lib/common/flyway/api.adl create mode 100644 adl/tests/test31/lib/common/flyway/api.adl-java create mode 100644 adl/tests/test31/lib/common/flyway/example_patterns.adl create mode 100644 adl/tests/test31/lib/common/flyway/example_patterns.adl-java create mode 100644 adl/tests/test31/lib/common/flyway/internals.adl create mode 100644 adl/tests/test31/lib/common/flyway/internals.adl-java create mode 100644 adl/tests/test31/lib/common/http.adl create mode 100644 adl/tests/test31/lib/common/http.adl-java create mode 100644 adl/tests/test31/lib/common/strings.adl create mode 100644 adl/tests/test31/lib/common/tabular.adl create mode 100644 adl/tests/test31/lib/common/tabular.adl-java create mode 100644 adl/tests/test31/lib/common/ui.adl create mode 100644 adl/tests/test31/lib/common/ui.adl-java create mode 100644 adl/tests/test31/proj/adl.pkg.json create mode 100644 adl/tests/test31/proj/protoclient/protoapp/api.adl create mode 100644 adl/tests/test31/proj/protoclient/protoapp/config.adl create mode 100644 adl/tests/test31/proj/protoclient/protoapp/db.adl create mode 100644 adl/tests/test31/proj/protoclient/protoapp/uiconfig.adl create mode 100644 adl/tests/test32/test32a.adl create mode 100644 adl/tests/test32/test32b.adl rename haskell/compiler/tests/test4/input/test.adl => adl/tests/test4/test4.adl (100%) rename haskell/compiler/tests/test4/input/test.adl-cpp => adl/tests/test4/test4.adl-cpp (100%) rename haskell/compiler/tests/test4/input/test.adl-hs => adl/tests/test4/test4.adl-hs (100%) rename haskell/compiler/tests/test4/input/test.adl-java => adl/tests/test4/test4.adl-java (100%) rename haskell/compiler/tests/test4/input/test.adl-rs => adl/tests/test4/test4.adl-rs (100%) rename haskell/compiler/tests/test5/input/test.adl => adl/tests/test5/test5.adl (100%) rename haskell/compiler/tests/test5/input/test.adl-hs => adl/tests/test5/test5.adl-hs (100%) rename haskell/compiler/tests/test5/input/test.adl-rs => adl/tests/test5/test5.adl-rs (100%) rename haskell/compiler/tests/test6/input/test.adl => adl/tests/test6/test6.adl (100%) rename haskell/compiler/tests/test7/input/test.adl => adl/tests/test7/test7.adl (100%) rename haskell/compiler/tests/test8/input/test.adl => adl/tests/test8/test8.adl (81%) rename haskell/compiler/tests/test9/input/test.adl => adl/tests/test9/test9.adl (81%) create mode 100644 adl/tests/testing_table.json create mode 100644 docs/processing.md create mode 120000 haskell/compiler/lib/adl/adlc delete mode 100644 haskell/compiler/tests/test19/input/test.adl create mode 100644 rust/compiler/.gitignore create mode 100644 rust/compiler/Cargo.toml create mode 100644 rust/compiler/Readme.md create mode 100755 rust/compiler/genadl.sh create mode 100644 rust/compiler/src/adlgen/adlc/config/mod.rs create mode 100644 rust/compiler/src/adlgen/adlc/config/rust.rs create mode 100644 rust/compiler/src/adlgen/adlc/mod.rs create mode 100644 rust/compiler/src/adlgen/adlc/packaging.rs create mode 100644 rust/compiler/src/adlgen/adlc/testing_table.rs create mode 100644 rust/compiler/src/adlgen/mod.rs create mode 100644 rust/compiler/src/adlgen/sys/adlast2.rs create mode 100644 rust/compiler/src/adlgen/sys/annotations.rs create mode 100644 rust/compiler/src/adlgen/sys/mod.rs create mode 100644 rust/compiler/src/adlgen/sys/types.rs create mode 100644 rust/compiler/src/adlrt/custom/mod.rs create mode 100644 rust/compiler/src/adlrt/custom/sys/mod.rs create mode 100644 rust/compiler/src/adlrt/custom/sys/types/map.rs create mode 100644 rust/compiler/src/adlrt/custom/sys/types/mapentry.rs create mode 100644 rust/compiler/src/adlrt/custom/sys/types/maybe.rs create mode 100644 rust/compiler/src/adlrt/custom/sys/types/mod.rs create mode 100644 rust/compiler/src/adlrt/custom/sys/types/pair.rs create mode 100644 rust/compiler/src/adlrt/custom/sys/types/result.rs create mode 100644 rust/compiler/src/adlrt/custom/sys/types/set.rs create mode 100644 rust/compiler/src/adlrt/mod.rs create mode 100644 rust/compiler/src/adlstdlib/mod.rs create mode 100644 rust/compiler/src/cli/ast.rs create mode 100644 rust/compiler/src/cli/mod.rs create mode 100644 rust/compiler/src/cli/rust/generate.rs create mode 100644 rust/compiler/src/cli/rust/mod.rs create mode 100644 rust/compiler/src/cli/rust/rsfile.rs create mode 100644 rust/compiler/src/cli/tsgen/astgen.rs create mode 100644 rust/compiler/src/cli/tsgen/defaultval.rs create mode 100644 rust/compiler/src/cli/tsgen/generate.rs create mode 100644 rust/compiler/src/cli/tsgen/mod.rs create mode 100644 rust/compiler/src/cli/tsgen/tests.rs rename {typescript/runtime => rust/compiler/src/cli/tsgen/ts-runtime}/adl.ts (100%) rename {typescript/runtime => rust/compiler/src/cli/tsgen/ts-runtime}/dynamic.ts (100%) rename {typescript/runtime => rust/compiler/src/cli/tsgen/ts-runtime}/json.ts (100%) create mode 100644 rust/compiler/src/cli/tsgen/ts-runtime/package-dist.json create mode 100644 rust/compiler/src/cli/tsgen/ts-runtime/package.json rename {typescript/runtime => rust/compiler/src/cli/tsgen/ts-runtime}/sys/adlast.ts (100%) rename {typescript/runtime => rust/compiler/src/cli/tsgen/ts-runtime}/sys/dynamic.ts (100%) rename {typescript/runtime => rust/compiler/src/cli/tsgen/ts-runtime}/sys/types.ts (100%) create mode 100644 rust/compiler/src/cli/tsgen/ts-runtime/tsconfig.json rename {typescript/runtime => rust/compiler/src/cli/tsgen/ts-runtime}/utils.ts (100%) create mode 100644 rust/compiler/src/cli/tsgen/utils.rs create mode 100644 rust/compiler/src/cli/verify.rs create mode 100644 rust/compiler/src/cli/workspace.rs create mode 100644 rust/compiler/src/lib.rs create mode 100644 rust/compiler/src/main.rs create mode 100644 rust/compiler/src/parser/mod.rs create mode 100644 rust/compiler/src/parser/tests.rs create mode 100644 rust/compiler/src/processing/annotations.rs create mode 100644 rust/compiler/src/processing/checks.rs create mode 100644 rust/compiler/src/processing/loader.rs create mode 100644 rust/compiler/src/processing/mod.rs create mode 100644 rust/compiler/src/processing/primitives.rs create mode 100644 rust/compiler/src/processing/resolver.rs create mode 100644 rust/compiler/src/processing/writer.rs create mode 100644 rust/compiler/src/utils/ast.rs create mode 100644 rust/compiler/src/utils/mod.rs create mode 100644 typescript/cli/runtime/adl.ts create mode 100644 typescript/cli/runtime/dynamic.ts create mode 100644 typescript/cli/runtime/json.ts create mode 100644 typescript/cli/runtime/sys/adlast.ts create mode 100644 typescript/cli/runtime/sys/dynamic.ts create mode 100644 typescript/cli/runtime/sys/types.ts create mode 100644 typescript/cli/runtime/utils.ts rename typescript/{ => cli}/tests/deno-1.10.2/.gitignore (100%) rename typescript/{ => cli}/tests/deno-1.10.2/example.tests.ts (100%) rename typescript/{ => cli}/tests/example.adl (100%) rename typescript/{ => cli}/tests/run-tests.sh (100%) rename typescript/{ => cli}/tests/ts-3.5.2/.gitignore (100%) rename typescript/{ => cli}/tests/ts-3.5.2/example.spec.ts (100%) rename typescript/{ => cli}/tests/ts-3.5.2/package.json (100%) rename typescript/{ => cli}/tests/ts-3.5.2/tsconfig.json (100%) rename typescript/{ => cli}/tests/ts-3.5.2/tslint.json (100%) rename typescript/{ => cli}/tests/ts-3.5.2/yarn.lock (100%) rename typescript/{ => cli}/tests/ts-3.8.3/.gitignore (100%) rename typescript/{ => cli}/tests/ts-3.8.3/example.spec.ts (100%) rename typescript/{ => cli}/tests/ts-3.8.3/package.json (100%) rename typescript/{ => cli}/tests/ts-3.8.3/tsconfig.json (100%) rename typescript/{ => cli}/tests/ts-3.8.3/tslint.json (100%) rename typescript/{ => cli}/tests/ts-3.8.3/yarn.lock (100%) rename typescript/{ => cli}/tests/ts-4.2.4/.gitignore (100%) rename typescript/{ => cli}/tests/ts-4.2.4/example.spec.ts (100%) rename typescript/{ => cli}/tests/ts-4.2.4/package.json (100%) rename typescript/{ => cli}/tests/ts-4.2.4/tsconfig.json (100%) rename typescript/{ => cli}/tests/ts-4.2.4/tslint.json (100%) rename typescript/{ => cli}/tests/ts-4.2.4/yarn.lock (100%) rename typescript/{ => cli}/tests/ts-4.6.3/.gitignore (100%) rename typescript/{ => cli}/tests/ts-4.6.3/example.spec.ts (100%) rename typescript/{ => cli}/tests/ts-4.6.3/package.json (100%) rename typescript/{ => cli}/tests/ts-4.6.3/tsconfig.json (100%) rename typescript/{ => cli}/tests/ts-4.6.3/tslint.json (100%) rename typescript/{ => cli}/tests/ts-4.6.3/yarn.lock (100%) create mode 100644 typescript/workspace/.gitignore create mode 100644 typescript/workspace/adl.work.json create mode 100644 typescript/workspace/adl/lib/adl.pkg.json create mode 100644 typescript/workspace/adl/lib/common.adl create mode 100644 typescript/workspace/adl/lib/common.adl-java create mode 100644 typescript/workspace/adl/lib/common/adminui/api.adl create mode 100644 typescript/workspace/adl/lib/common/adminui/api.adl-java create mode 100644 typescript/workspace/adl/lib/common/adminui/config.adl create mode 100644 typescript/workspace/adl/lib/common/adminui/db.adl create mode 100644 typescript/workspace/adl/lib/common/adminui/db.adl-java create mode 100644 typescript/workspace/adl/lib/common/config/aws.adl create mode 100644 typescript/workspace/adl/lib/common/config/aws.adl-java create mode 100644 typescript/workspace/adl/lib/common/config/azure.adl create mode 100644 typescript/workspace/adl/lib/common/config/db.adl create mode 100644 typescript/workspace/adl/lib/common/config/db.adl-java create mode 100644 typescript/workspace/adl/lib/common/config/emailer.adl create mode 100644 typescript/workspace/adl/lib/common/config/emailer.adl-java create mode 100644 typescript/workspace/adl/lib/common/config/frontend.adl create mode 100644 typescript/workspace/adl/lib/common/config/frontend.adl-java create mode 100644 typescript/workspace/adl/lib/common/config/google.adl create mode 100644 typescript/workspace/adl/lib/common/config/google.adl-java create mode 100644 typescript/workspace/adl/lib/common/config/jwt.adl create mode 100644 typescript/workspace/adl/lib/common/config/jwt.adl-java create mode 100644 typescript/workspace/adl/lib/common/config/log.adl create mode 100644 typescript/workspace/adl/lib/common/config/log.adl-java create mode 100644 typescript/workspace/adl/lib/common/config/okta.adl create mode 100644 typescript/workspace/adl/lib/common/config/okta.adl-java create mode 100644 typescript/workspace/adl/lib/common/config/sms.adl create mode 100644 typescript/workspace/adl/lib/common/config/sms.adl-java create mode 100644 typescript/workspace/adl/lib/common/config/storage.adl create mode 100644 typescript/workspace/adl/lib/common/db.adl create mode 100644 typescript/workspace/adl/lib/common/db.adl-java create mode 100644 typescript/workspace/adl/lib/common/flyway/api.adl create mode 100644 typescript/workspace/adl/lib/common/flyway/api.adl-java create mode 100644 typescript/workspace/adl/lib/common/flyway/example_patterns.adl create mode 100644 typescript/workspace/adl/lib/common/flyway/example_patterns.adl-java create mode 100644 typescript/workspace/adl/lib/common/flyway/internals.adl create mode 100644 typescript/workspace/adl/lib/common/flyway/internals.adl-java create mode 100644 typescript/workspace/adl/lib/common/http.adl create mode 100644 typescript/workspace/adl/lib/common/http.adl-java create mode 100644 typescript/workspace/adl/lib/common/strings.adl create mode 100644 typescript/workspace/adl/lib/common/tabular.adl create mode 100644 typescript/workspace/adl/lib/common/tabular.adl-java create mode 100644 typescript/workspace/adl/lib/common/ui.adl create mode 100644 typescript/workspace/adl/lib/common/ui.adl-java create mode 100644 typescript/workspace/adl/proj/adl.pkg.json create mode 100644 typescript/workspace/adl/proj/protoclient/protoapp/api.adl create mode 100644 typescript/workspace/adl/proj/protoclient/protoapp/config.adl create mode 100644 typescript/workspace/adl/proj/protoclient/protoapp/db.adl create mode 100644 typescript/workspace/adl/proj/protoclient/protoapp/uiconfig.adl create mode 100644 typescript/workspace/generated/common/.adl-manifest create mode 100644 typescript/workspace/generated/common/_/common.ts create mode 100644 typescript/workspace/generated/common/_/index.ts create mode 100644 typescript/workspace/generated/common/adminui/api.ts create mode 100644 typescript/workspace/generated/common/adminui/config.ts create mode 100644 typescript/workspace/generated/common/adminui/db.ts create mode 100644 typescript/workspace/generated/common/adminui/index.ts create mode 100644 typescript/workspace/generated/common/config/aws.ts create mode 100644 typescript/workspace/generated/common/config/azure.ts create mode 100644 typescript/workspace/generated/common/config/db.ts create mode 100644 typescript/workspace/generated/common/config/emailer.ts create mode 100644 typescript/workspace/generated/common/config/frontend.ts create mode 100644 typescript/workspace/generated/common/config/google.ts create mode 100644 typescript/workspace/generated/common/config/index.ts create mode 100644 typescript/workspace/generated/common/config/jwt.ts create mode 100644 typescript/workspace/generated/common/config/log.ts create mode 100644 typescript/workspace/generated/common/config/okta.ts create mode 100644 typescript/workspace/generated/common/config/sms.ts create mode 100644 typescript/workspace/generated/common/config/storage.ts create mode 100644 typescript/workspace/generated/common/db.ts create mode 100644 typescript/workspace/generated/common/flyway/api.ts create mode 100644 typescript/workspace/generated/common/flyway/example_patterns.ts create mode 100644 typescript/workspace/generated/common/flyway/index.ts create mode 100644 typescript/workspace/generated/common/flyway/internals.ts create mode 100644 typescript/workspace/generated/common/http.ts create mode 100644 typescript/workspace/generated/common/index.ts create mode 100644 typescript/workspace/generated/common/package-dist.json create mode 100644 typescript/workspace/generated/common/package.json create mode 100644 typescript/workspace/generated/common/resolver.ts create mode 100644 typescript/workspace/generated/common/strings.ts create mode 100644 typescript/workspace/generated/common/tabular.ts create mode 100644 typescript/workspace/generated/common/tsconfig.json create mode 100644 typescript/workspace/generated/common/ui.ts create mode 100644 typescript/workspace/generated/protoclient/.adl-manifest create mode 100644 typescript/workspace/generated/protoclient/index.ts create mode 100644 typescript/workspace/generated/protoclient/package.json create mode 100644 typescript/workspace/generated/protoclient/protoapp/api.ts create mode 100644 typescript/workspace/generated/protoclient/protoapp/config.ts create mode 100644 typescript/workspace/generated/protoclient/protoapp/db.ts create mode 100644 typescript/workspace/generated/protoclient/protoapp/index.ts create mode 100644 typescript/workspace/generated/protoclient/protoapp/uiconfig.ts create mode 100644 typescript/workspace/generated/protoclient/resolver.ts create mode 100644 typescript/workspace/generated/protoclient/tsconfig.json create mode 100644 typescript/workspace/generated/runtime/adl.ts create mode 100644 typescript/workspace/generated/runtime/dynamic.ts create mode 100644 typescript/workspace/generated/runtime/json.ts create mode 100644 typescript/workspace/generated/runtime/package-dist.json create mode 100644 typescript/workspace/generated/runtime/package.json create mode 100644 typescript/workspace/generated/runtime/sys/adlast.ts create mode 100644 typescript/workspace/generated/runtime/sys/dynamic.ts create mode 100644 typescript/workspace/generated/runtime/sys/types.ts create mode 100644 typescript/workspace/generated/runtime/tsconfig.json create mode 100644 typescript/workspace/generated/runtime/utils.ts create mode 100644 typescript/workspace/generated/sys/.adl-manifest create mode 100644 typescript/workspace/generated/sys/adlast.ts create mode 100644 typescript/workspace/generated/sys/adlast2.ts create mode 100644 typescript/workspace/generated/sys/annotations.ts create mode 100644 typescript/workspace/generated/sys/dynamic.ts create mode 100644 typescript/workspace/generated/sys/index.ts create mode 100644 typescript/workspace/generated/sys/package.json create mode 100644 typescript/workspace/generated/sys/resolver.ts create mode 100644 typescript/workspace/generated/sys/tsconfig.json create mode 100644 typescript/workspace/generated/sys/types.ts create mode 100644 typescript/workspace/package.json create mode 100644 typescript/workspace/packages/tsconfig/README.md create mode 100644 typescript/workspace/packages/tsconfig/base.json create mode 100644 typescript/workspace/packages/tsconfig/nextjs.json create mode 100644 typescript/workspace/packages/tsconfig/package.json create mode 100644 typescript/workspace/packages/tsconfig/react-library.json create mode 100644 typescript/workspace/pnpm-lock.yaml create mode 100644 typescript/workspace/pnpm-workspace.yaml diff --git a/.github/workflows/rust-release.yaml b/.github/workflows/rust-release.yaml new file mode 100644 index 00000000..32295dfa --- /dev/null +++ b/.github/workflows/rust-release.yaml @@ -0,0 +1,74 @@ +name: rust release + +on: + push: + tags: + - rust/compiler/v[0-9]* + +jobs: + build: + name: Build + runs-on: ${{ matrix.os }} + strategy: + matrix: + os: [ubuntu-20.04, macos-latest] + + steps: + - uses: actions/checkout@v3 + # Fetch all history so git describe works + - run: | + git fetch --prune --unshallow + + # When rustup is updated, it tries to replace its binary, which on Windows is somehow locked. + # This can result in the CI failure, see: https://github.com/rust-lang/rustup/issues/3029 + - run: | + rustup set auto-self-update disable + rustup toolchain install nightly --profile minimal + + # caching doesn't work across tags + # https://docs.github.com/en/actions/using-workflows/caching-dependencies-to-speed-up-workflows#restrictions-for-accessing-a-cache + # - uses: Swatinem/rust-cache@v2 + + - run: cargo +nightly build --release + + - uses: actions/upload-artifact@v3 + with: + name: radlc-${{ runner.os }} + path: target/release/radlc + + release: + name: Create Github Release + needs: [build] + runs-on: ubuntu-latest + steps: + + - name: Determine version + id: version + run: + echo "version=${GITHUB_REF:24}" >> $GITHUB_OUTPUT + + - name: Fetch macOS build + uses: actions/download-artifact@v3 + with: + name: radlc-macOS + path: radlc-macOS + + - name: Fetch linux build + uses: actions/download-artifact@v3 + with: + name: radlc-Linux + path: radlc-Linux + + - run: | + mv radlc-macOS/radlc ./radlc-${{ steps.version.outputs.version }}-osx + mv radlc-Linux/radlc ./radlc-${{ steps.version.outputs.version }}-linux + ls -al + + - name: Create Release + id: create_release + uses: softprops/action-gh-release@v1 + with: + name: Release rust/compiler ${{ steps.version.outputs.version }} + files: | + radlc-${{ steps.version.outputs.version }}-linux + radlc-${{ steps.version.outputs.version }}-osx diff --git a/.gitignore b/.gitignore index 1d70e823..d692445f 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,5 @@ cpp/runtime/ltmain.sh cpp/runtime/missing cpp/runtime/build/ cpp/runtime/test-driver + +target/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000..2f27e868 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,765 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "0.7.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" +dependencies = [ + "memchr", +] + +[[package]] +name = "anyhow" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224afbd727c3d6e4b90103ece64b8d1b67fbb1973b1046c2281eed3f3803f800" + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "backtrace" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "backtrace-on-stack-overflow" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fd2d70527f3737a1ad17355e260706c1badebabd1fa06a7a053407380df841b" +dependencies = [ + "backtrace", + "libc", + "nix", +] + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] + +[[package]] +name = "bytecount" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c676a478f63e9fa2dd5368a42f28bba0d6c560b775f38583c8bbaa7fcd67c9c" + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "4.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d7ae14b20b94cb02149ed21a86c423859cbe18dc7ed69845cace50e52b40a5" +dependencies = [ + "bitflags", + "clap_derive", + "clap_lex", + "is-terminal", + "once_cell", + "strsim", + "termcolor", +] + +[[package]] +name = "clap_derive" +version = "4.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44bec8e5c9d09e439c4335b1af0abaab56dcf3b94999a936e1bb47b9134288f0" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "350b9cf31731f9957399229e9b2adc51eeabdfbe9d71d9a0552275fd12710d09" +dependencies = [ + "os_str_bytes", +] + +[[package]] +name = "compiler" +version = "0.1.0" +dependencies = [ + "anyhow", + "backtrace-on-stack-overflow", + "clap", + "convert_case", + "env_logger", + "genco", + "log", + "nom", + "nom_locate", + "regex", + "rust-embed", + "serde", + "serde_ignored", + "serde_json", +] + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "cpufeatures" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "280a9f2d8b3a38871a3c8a46fb80db65e5e5ed97da80c4d08bf27fb63e35e181" +dependencies = [ + "libc", +] + +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + +[[package]] +name = "digest" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +dependencies = [ + "block-buffer", + "crypto-common", +] + +[[package]] +name = "env_logger" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85cdab6a89accf66733ad5a1693a4dcced6aeff64602b634530dd73c1f3ee9f0" +dependencies = [ + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "errno" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f639046355ee4f37944e44f60642c6f3a7efa3cf6b78c78a0d989a8ce6c396a1" +dependencies = [ + "errno-dragonfly", + "libc", + "winapi", +] + +[[package]] +name = "errno-dragonfly" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "genco" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43de41c8ce1ed5ac84a1b11fb3e4ef604bf6773068798490eaa95e8151abad20" +dependencies = [ + "genco-macros", + "relative-path", + "smallvec", +] + +[[package]] +name = "genco-macros" +version = "0.17.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c85fd34848b1f708e6344a4af6f7bfc05172ae20ce4b35c8e417efffb4f306aa" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + +[[package]] +name = "gimli" +version = "0.27.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" + +[[package]] +name = "heck" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" + +[[package]] +name = "io-lifetimes" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfa919a82ea574332e2de6e74b4c36e74d41982b335080fa59d4ef31be20fdf3" +dependencies = [ + "libc", + "windows-sys", +] + +[[package]] +name = "is-terminal" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b6b32576413a8e69b90e952e4a026476040d81017b80445deda5f2d3921857" +dependencies = [ + "hermit-abi", + "io-lifetimes", + "rustix", + "windows-sys", +] + +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[package]] +name = "libc" +version = "0.2.140" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" + +[[package]] +name = "linux-raw-sys" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f051f77a7c8e6957c0696eac88f26b0117e54f52d3fc682ab19397a8812846a4" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "memoffset" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +dependencies = [ + "autocfg", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "nix" +version = "0.23.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f3790c00a0150112de0f4cd161e3d7fc4b2d8a5542ffc35f099a2562aecb35c" +dependencies = [ + "bitflags", + "cc", + "cfg-if", + "libc", + "memoffset", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "nom_locate" +version = "4.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e299bf5ea7b212e811e71174c5d1a5d065c4c0ad0c8691ecb1f97e3e66025e" +dependencies = [ + "bytecount", + "memchr", + "nom", +] + +[[package]] +name = "object" +version = "0.30.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" + +[[package]] +name = "os_str_bytes" +version = "6.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b7820b9daea5457c9f21c69448905d723fbd21136ccf521748f23fd49e723ee" + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro2" +version = "1.0.52" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d0e1ae9e836cc3beddd63db0df682593d7e2d3d891ae8c9083d2113e1744224" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex" +version = "1.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" + +[[package]] +name = "relative-path" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bf2521270932c3c7bed1a59151222bd7643c79310f2916f01925e1e16255698" + +[[package]] +name = "rust-embed" +version = "6.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b68543d5527e158213414a92832d2aab11a84d2571a5eb021ebe22c43aab066" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "6.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d4e0f0ced47ded9a68374ac145edd65a6c1fa13a96447b873660b2a568a0fd7" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "7.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512b0ab6853f7e14e3c8754acb43d6f748bb9ced66aa5915a6553ac8213f7731" +dependencies = [ + "sha2", + "walkdir", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4a36c42d1873f9a77c53bde094f9664d9891bc604a45b4798fd2c389ed12e5b" + +[[package]] +name = "rustix" +version = "0.36.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd5c6ff11fecd55b40746d1995a02f2eb375bf8c00d192d521ee09f42bef37bc" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys", +] + +[[package]] +name = "ryu" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" + +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "serde" +version = "1.0.156" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "314b5b092c0ade17c00142951e50ced110ec27cea304b1037c6969246c2469a4" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.156" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7e29c4601e36bcec74a223228dce795f4cd3616341a4af93520ca1a837c087d" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_ignored" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94eb4a4087ba8bdf14a9208ac44fddbf55c01a6195f7edfc511ddaff6cae45a6" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_json" +version = "1.0.94" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c533a59c9d8a93a09c6ab31f0fd5e5f4dd1b8fc9434804029839884765d04ea" +dependencies = [ + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "sha2" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + +[[package]] +name = "smallvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termcolor" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "typenum" +version = "1.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" + +[[package]] +name = "unicode-ident" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" + +[[package]] +name = "unicode-segmentation" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" + +[[package]] +name = "version_check" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" + +[[package]] +name = "walkdir" +version = "2.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000..8045673d --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,4 @@ +[workspace] +members = [ + "rust/compiler", +] \ No newline at end of file diff --git a/adl/adl.work.json b/adl/adl.work.json new file mode 100644 index 00000000..1ed06448 --- /dev/null +++ b/adl/adl.work.json @@ -0,0 +1,61 @@ +{ + "adlc": "0.0.0", + "runtimes": [ + { + "ts_runtime": { + "output_dir": "../generated/typescript/tests", + "strip_first": false + } + } + ], + "embedded_sys_loader" : { "just": { + "path": "", + "ts_opts": { + "npm_pkg_name": "@adl-lang/sys", + "npm_version": "1.0.0", + "extra_dependencies": { + "base64-js": "^1.5.1" + }, + "extra_dev_dependencies": { + "tsconfig": "workspace:*", + "typescript": "^4.9.3" + } + } + }}, + "use": [ + { + "path": "./adlc", + "ts_opts": { + "npm_pkg_name": "@adl-lang/adlc" + } + }, + { + "path": "./tests/test31/lib", + "ts_opts": { + "npm_pkg_name": "@adl-lang/common" + } + }, + { + "path": "./stdlib", + "ts_opts": { + "npm_pkg_name": "@adl-lang/sys" + } + }, + { + "path": "./tests/test31/proj", + "ts_opts": { + "npm_pkg_name": "@adl-lang/protoclient", + "runtime_opts": { + "package_ref": {"name": "@adl-lang/runtime", "version": "1.0.0"} + }, + "outputs": { + "gen": { + "output_dir": "../generated/typescript/tests/test31", + "manifest": "../generated/typescript/tests/test31/.adl-manifest" + } + }, + "include_resolver": true + } + } + ] +} \ No newline at end of file diff --git a/adl/adl.work1.json b/adl/adl.work1.json new file mode 100644 index 00000000..dcd940c3 --- /dev/null +++ b/adl/adl.work1.json @@ -0,0 +1,92 @@ +{ + "adlc": "0.0.0", + "use_embedded_sys_loader": true, + "runtimes": [ + { + "ts_runtime": { + "output_dir": "../generated1/runtime", + "npm_pkg_name": "@adl-lang/runtime" + } + } + ], + "embedded_sys_loader" : { "just": { + "path": "", + "ts_opts": { + "npm_pkg_name": "@adl-lang/sys", + "npm_version": "1.0.0", + "extra_dependencies": { + "base64-js": "^1.5.1" + }, + "extra_dev_dependencies": { + "tsconfig": "workspace:*", + "typescript": "^4.9.3" + } + } + }}, + "use": [ + { + "path": "./adlc", + "ts_opts": { + "npm_pkg_name": "@adl-lang/adlc", + "extra_dev_dependencies": { + "tsconfig": "workspace:*", + "typescript": "^4.9.3" + }, + "runtime_opts": { + "workspace_ref": "@adl-lang/runtime" + }, + "outputs": { + "gen": { + "output_dir": "../generated1/adlc", + "manifest": "../generated1/adlc/.adl-manifest" + } + }, + "include_resolver": false + } + }, + { + "path": "./tests/test31/lib", + "ts_opts": { + "npm_pkg_name": "@adl-lang/common", + "extra_dev_dependencies": { + "tsconfig": "workspace:*", + "typescript": "^4.9.3" + }, + "runtime_opts": { + "workspace_ref": "@adl-lang/runtime" + }, + "outputs": { + "gen": { + "output_dir": "../generated1/common", + "manifest": "../generated1/common/.adl-manifest", + "strip_first": false + } + }, + "include_resolver": false + } + }, + { + "path": "./tests/test31/proj", + "ts_opts": { + "npm_pkg_name": "@adl-lang/protoclient", + "extra_dependencies": { + "base64-js": "^1.5.1" + }, + "extra_dev_dependencies": { + "tsconfig": "workspace:*", + "typescript": "^4.9.3" + }, + "runtime_opts": { + "workspace_ref": "@adl-lang/runtime" + }, + "outputs": { + "gen": { + "output_dir": "../generated1/test31", + "manifest": "../generated1/test31/.adl-manifest" + } + }, + "include_resolver": true + } + } + ] +} diff --git a/adl/adl.work2.json b/adl/adl.work2.json new file mode 100644 index 00000000..103345cb --- /dev/null +++ b/adl/adl.work2.json @@ -0,0 +1,99 @@ +{ + "adlc": "0.0.0", + "use_embedded_sys_loader": true, + "runtimes": [ + { + "ts_runtime": { + "output_dir": "../generated2/runtime", + "npm_pkg_name": "@adl-lang/runtime" + } + } + ], + "embedded_sys_loader": "nothing", + "use": [ + { + "path": "./adlc", + "ts_opts": { + "npm_pkg_name": "@adl-lang/adlc", + "extra_dev_dependencies": { + "tsconfig": "workspace:*", + "typescript": "^4.9.3" + }, + "runtime_opts": { + "workspace_ref": "@adl-lang/runtime" + }, + "outputs": { + "gen": { + "output_dir": "../generated2/adlc", + "manifest": "../generated2/adlc/.adl-manifest" + } + }, + "include_resolver": false + } + }, + { + "path": "./tests/test31/lib", + "ts_opts": { + "npm_pkg_name": "@adl-lang/common", + "extra_dev_dependencies": { + "tsconfig": "workspace:*", + "typescript": "^4.9.3" + }, + "runtime_opts": { + "workspace_ref": "@adl-lang/runtime" + }, + "outputs": { + "gen": { + "output_dir": "../generated2/common", + "manifest": "../generated2/common/.adl-manifest", + "strip_first": false + } + }, + "include_resolver": false + } + }, + { + "path": "./stdlib", + "ts_opts": { + "npm_pkg_name": "@adl-lang/sys", + "extra_dev_dependencies": { + "tsconfig": "workspace:*", + "typescript": "^4.9.3" + }, + "runtime_opts": { + "workspace_ref": "@adl-lang/runtime" + }, + "outputs": { + "gen": { + "output_dir": "../generated2/sys", + "manifest": "../generated2/sys/.adl-manifest" + } + }, + "include_resolver": false + } + }, + { + "path": "./tests/test31/proj", + "ts_opts": { + "npm_pkg_name": "@adl-lang/protoclient", + "extra_dependencies": { + "base64-js": "^1.5.1" + }, + "extra_dev_dependencies": { + "tsconfig": "workspace:*", + "typescript": "^4.9.3" + }, + "runtime_opts": { + "workspace_ref": "@adl-lang/runtime" + }, + "outputs": { + "gen": { + "output_dir": "../generated2/test31", + "manifest": "../generated2/test31/.adl-manifest" + } + }, + "include_resolver": true + } + } + ] +} diff --git a/adl/adl.work3.json b/adl/adl.work3.json new file mode 100644 index 00000000..f4ed7d59 --- /dev/null +++ b/adl/adl.work3.json @@ -0,0 +1,60 @@ +{ + "adlc": "0.0.0", + "use_embedded_sys_loader": true, + "runtimes": [ + ], + "embedded_sys_loader" : { "just": { + "path": "", + "ts_opts": { + "npm_pkg_name": "@adl-lang/sys", + "npm_version": "1.0.0", + "extra_dependencies": { + "base64-js": "^1.5.1" + }, + "extra_dev_dependencies": { + "tsconfig": "workspace:*", + "typescript": "^4.9.3" + } + } + }}, + + "use": [ + { + "path": "./adlc", + "ts_opts": { + "npm_pkg_name": "@adl-lang/adlc" + } + }, + { + "path": "./tests/test31/lib", + "ts_opts": { + "npm_pkg_name": "@adl-lang/common" + } + }, + { + "path": "./tests/test31/proj", + "ts_opts": { + "npm_pkg_name": "@adl-lang/protoclient", + "generate_transitive": true, + "extra_dependencies": { + "base64-js": "^1.5.1" + }, + "extra_dev_dependencies": { + "tsconfig": "workspace:*", + "typescript": "^4.9.3" + }, + "runtime_opts": { + "generate": {} + }, + "outputs": { + "gen": { + "output_dir": "../generated3/test31", + "manifest": "../generated3/test31/.adl-manifest", + "strip_first": false + } + }, + "include_resolver": true + } + } + ] +} diff --git a/adl/adlc/adl.pkg.json b/adl/adlc/adl.pkg.json new file mode 100644 index 00000000..d141760c --- /dev/null +++ b/adl/adlc/adl.pkg.json @@ -0,0 +1,12 @@ +{ + "path" : "github.com/adl-lang/adl/adl/adlc", + "global_alias": "adlc", + "adlc": "0.0.0", + "requires": [ + { + "ref": { + "alias": "sys" + } + } + ] +} \ No newline at end of file diff --git a/haskell/compiler/lib/adl/adlc/config/cpp.adl b/adl/adlc/adlc/config/cpp.adl similarity index 100% rename from haskell/compiler/lib/adl/adlc/config/cpp.adl rename to adl/adlc/adlc/config/cpp.adl diff --git a/haskell/compiler/lib/adl/adlc/config/haskell.adl b/adl/adlc/adlc/config/haskell.adl similarity index 100% rename from haskell/compiler/lib/adl/adlc/config/haskell.adl rename to adl/adlc/adlc/config/haskell.adl diff --git a/haskell/compiler/lib/adl/adlc/config/java.adl b/adl/adlc/adlc/config/java.adl similarity index 100% rename from haskell/compiler/lib/adl/adlc/config/java.adl rename to adl/adlc/adlc/config/java.adl diff --git a/haskell/compiler/lib/adl/adlc/config/rust.adl b/adl/adlc/adlc/config/rust.adl similarity index 100% rename from haskell/compiler/lib/adl/adlc/config/rust.adl rename to adl/adlc/adlc/config/rust.adl diff --git a/haskell/compiler/lib/adl/adlc/config/typescript.adl b/adl/adlc/adlc/config/typescript.adl similarity index 59% rename from haskell/compiler/lib/adl/adlc/config/typescript.adl rename to adl/adlc/adlc/config/typescript.adl index 78081f8b..b1aeca63 100644 --- a/haskell/compiler/lib/adl/adlc/config/typescript.adl +++ b/adl/adlc/adlc/config/typescript.adl @@ -1,5 +1,8 @@ module adlc.config.typescript { +/// ADL module annotation to specify a target npm package this module belongs to. +type NpmPackage = String; + /// ADL module or declaration annotation to control /// whether code is actually generated. diff --git a/adl/adlc/adlc/packaging.adl b/adl/adlc/adlc/packaging.adl new file mode 100644 index 00000000..8e830c28 --- /dev/null +++ b/adl/adlc/adlc/packaging.adl @@ -0,0 +1,259 @@ +// This is based on Golang's modules and workspace. +// e.g. see https://go.dev/ref/mod#workspaces + +module adlc.packaging { + +import sys.types.Pair; +import sys.types.Maybe; +import sys.adlast2.ScopedName; +import sys.adlast2.Module1; + +// AdlWorkspace0 is the serilization format +type AdlWorkspace0 = AdlWorkspace; +type AdlWorkspace1 = AdlWorkspace; +type AdlWorkspace2 = AdlWorkspace; + +type LoaderWorkspace = AdlWorkspace; + +type Payload0 = AdlPackageRef; + +struct Payload1 { + AdlPackageRef p_ref; + AdlPackage pkg; +}; + +struct Payload2 { + AdlPackageRef p_ref; + AdlPackage pkg; + Vector modules; +}; + +/// Expected to live in a file named `adl.work.json` +struct AdlWorkspace { + String adlc; + Vector use; + StringMap named_options = {}; + Vector runtimes = []; + // Maybe embedded_sys_loader; +}; + +struct NamedOpts { + TsNamedOpts ts_opts = {}; +}; + +struct TsNamedOpts { + Nullable runtime_opts = null; + Nullable> scripts = null; + Nullable> dependencies = null; + Nullable> dev_dependencies = null; + Nullable tsconfig = null; +}; + +union RuntimeOpts { + TsWriteRuntime ts_runtime; +}; + +struct TsWriteRuntime { + String output_dir; + ReferenceableScopeOption referenceable = "local"; + String npm_pkg_name = "@adl-lang/runtime"; + TsStyle ts_style = "tsc"; + // Bool strip_first = true; +}; + +/// The struct in AdlWorkspace::use required by the WorkspaceLoader +struct LoaderRef { + LoaderRefType ref; + InjectAnnotations loader_inject_annotate = []; + InjectAnnotations resolver_inject_annotate = []; +}; + +union LoaderRefType { + DirLoaderRef dir; + EmbeddedLoaderRef embedded; +}; + +struct DirLoaderRef { + String path; + Nullable global_alias = null; +}; + +struct EmbeddedLoaderRef { + EmbeddedPkg alias; +}; + +type InjectAnnotations = Vector; + +union InjectAnnotation { + Pair module_; +}; + +struct AdlPackageRef { + AdlPackageRefType ref; + Nullable named_opts = null; + Nullable ts_opts = null; +}; + +union AdlPackageRefType { + DirectoryRef dir; + /// An ADL module embed in the ADL compiler + EmbeddedRef embedded; +}; + +struct EmbeddedRef { + EmbeddedPkg alias; +}; + +union EmbeddedPkg { + Void sys; + Void adlc; +}; + +struct DirectoryRef { + // path must be to a directory directly under the folder containing the `adl.work.json` file. + String path; +}; + +struct TypescriptGenOptions { + String npm_pkg_name; + String npm_version = "1.0.0"; + StringMap extra_dependencies = {}; + StringMap extra_dev_dependencies = {}; + Nullable outputs = null; + Nullable tsconfig = null; + StringMap scripts = {}; + TsRuntimeOpt runtime_opts = {"package_ref": {"name": "@adl-lang/runtime", "version": "^1.0.0"}}; + Bool generate_transitive = false; + Bool include_resolver = false; + TsStyle ts_style = "tsc"; + ModuleSrc modules = "all"; + Bool capitalize_branch_names_in_types = true; + Bool capitalize_type_names = true; + +// Vector<> searchDir; +// --merge-adlext=EXT +// --verbose +// --no-overwrite +// --exclude-ast +// --excluded-ast-annotations=SCOPEDNAMES +}; + +union TsRuntimeOpt { + String workspace_ref; + NpmPackageRef package_ref; + TsGenRuntime generate; +}; + +struct TsGenRuntime { + // this is currently hardcoded to "./runtime" + // String runtimeDir; +}; + +union OutputOpts { + GenOutput gen; + // PkgRef ref; +}; + +// struct PkgRef { +// }; + +struct GenOutput { + ReferenceableScopeOption referenceable = "local"; + String output_dir; + Nullable manifest = null; + // When creating the path for output ts files delete the first part of the module name + // This needs to be false for "generate_transitive" and + // packages like "common" where the module and directory at the top level named the same. + // Bool strip_first = true; +}; + +union TsStyle { + Void tsc; + Void deno; +}; + +union ModuleSrc { + Void all; + Vector modules; +}; + +union ReferenceableScopeOption { + /// Generated code will only be referred internal to the repo + Void local; + /// Generated code can be published via a package manager (e.g. npm) + Void remote; +}; + +/// Expected to live in a file named `adl.pkg.json` +struct AdlPackage { + String path; + Nullable global_alias = null; + /// Version + String adlc; + Vector requires = []; + Vector excludes = []; + Vector replaces = []; + Vector retracts = []; +}; + +struct PackageDirective { + String path; + Nullable repo = null; +}; + +struct Require { + PkgRef ref; + Nullable version = null; + Bool indirect = false; +}; + +union PkgRef { + String path; + String alias; +}; + +struct Exclude { + String path; + String version; +}; + +struct Replace { + String path; + Nullable version; +}; + +struct Retract { + String version; + Nullable comment = null; +}; + +struct NpmPackage { + String name; + String version; + StringMap scripts = {}; + StringMap dependencies = {}; + @SerializedName "devDependencies" + StringMap dev_dependencies = {}; +}; + +// the bits of tsconfig we need +struct TsConfig { + Nullable extends; + Vector include; + Vector exclude; + TsCompilerOptions compilerOptions; +}; + +struct TsCompilerOptions { + String outDir; + Vector lib; +}; + +struct NpmPackageRef { + String name; + VersionSpec version; +}; + +type VersionSpec = String; + +}; diff --git a/adl/adlc/adlc/testing_table.adl b/adl/adlc/adlc/testing_table.adl new file mode 100644 index 00000000..fd019d45 --- /dev/null +++ b/adl/adlc/adlc/testing_table.adl @@ -0,0 +1,18 @@ +module adlc.testing_table { + +type TestFilesMetaData = Vector; + +struct TestFileMetaData { + String module_root; + Vector lib_paths = []; + /// If null then 'build/adlc_out/$module_root' is used + Nullable output_dir = null; + Vector modules; + Bool fail = false; + Bool skip = false; + String title = ""; + Vector description = []; + Vector keywords = []; +}; + +}; \ No newline at end of file diff --git a/adl/stdlib/adl.pkg.json b/adl/stdlib/adl.pkg.json new file mode 100644 index 00000000..d3118de6 --- /dev/null +++ b/adl/stdlib/adl.pkg.json @@ -0,0 +1,5 @@ +{ + "path" : "github.com/adl-lang/adl/adl/stdlib/sys", + "global_alias": "sys", + "adlc": "0.0.0" +} \ No newline at end of file diff --git a/adl/stdlib/sys/adlast2.adl b/adl/stdlib/sys/adlast2.adl new file mode 100644 index 00000000..7fad6a0e --- /dev/null +++ b/adl/stdlib/sys/adlast2.adl @@ -0,0 +1,166 @@ +module sys.adlast2 +{ +// Types to represent an ADL syntax tree + +import sys.types.*; + +type ModuleName = String; +type Ident = String; + +type Annotations = Map; + +struct ScopedName +{ + ModuleName moduleName; + Ident name; +}; + +struct TypeExpr +{ + R typeRef; + Vector> parameters; +}; + +struct Field +{ + Ident name; + Ident serializedName; + TE typeExpr; + Maybe default; + Annotations annotations; +}; + +struct Struct +{ + Vector typeParams; + Vector> fields; +}; + +struct Union +{ + Vector typeParams; + Vector> fields; +}; + +struct TypeDef +{ + Vector typeParams; + TE typeExpr; +}; + +struct NewType +{ + Vector typeParams; + TE typeExpr; + Maybe default; +}; + +union DeclType +{ + Struct struct_; + Union union_; + TypeDef type_; + NewType newtype_; +}; + +struct Decl +{ + Ident name; + Maybe version; + DeclType type_; + Annotations annotations; +}; + +struct ScopedDecl +{ + ModuleName moduleName; + Decl decl; +}; + +type DeclVersions = Vector>; + +union Import +{ + ModuleName moduleName; + ScopedName scopedName; +}; + +struct Module +{ + ModuleName name; + Vector imports; + Vector> decls; + Annotations annotations; +}; + +/// The Span start..end contains all values with start <= x < end. It is empty if start >= end. +struct Span { + Word64 start; + Word64 end; +}; + +struct Spanned { + T value; + Span span; +}; + +union PrimitiveType { + Void Void; + Void Bool; + Void Int8; + Void Int16; + Void Int32; + Void Int64; + Void Word8; + Void Word16; + Void Word32; + Void Word64; + Void Float; + Void Double; + Void Json; + Void ByteVector; + Void String; + Void Vector; + Void StringMap; + Void Nullable; + Void TypeToken; +}; + +union TypeRef { + ScopedName scopedName; + Ident localName; + PrimitiveType primitive; + Ident typeParam; +}; + +// AST after initial parsing +type TypeExpr0 = TypeExpr; +type Field0 = Field; +type Struct0 = Struct; +type Union0 = Union; +type DeclType0 = DeclType; +type Decl0 = Decl; +type Module0 = Module; + + +// AST after name resolution +type TypeExpr1 = TypeExpr; +type Field1 = Field; +type Struct1 = Struct; +type Union1 = Union; +type DeclType1 = DeclType; +type Decl1 = Decl; +type Module1 = Module; + +// Used to output the ADL AST +type AdlAst = StringMap; +struct AstModule +{ + ModuleName name; + Vector imports; + StringMap> decls; + Annotations annotations; +}; + + +}; diff --git a/adl/stdlib/sys/types.adl-rs b/adl/stdlib/sys/types.adl-rs index a76e0cf4..c565e302 100644 --- a/adl/stdlib/sys/types.adl-rs +++ b/adl/stdlib/sys/types.adl-rs @@ -5,19 +5,19 @@ import adlc.config.rust.*; annotation Maybe RustCustomType { "rustname" : "{{STDLIBMODULE}}::custom::sys::types::maybe::Maybe", "helpers" : "{{STDLIBMODULE}}::custom::sys::types::maybe::Maybe", - "stdTraits": ["Eq", "PartialEq", "Hash", "Serialize", "Deserialize", "Clone"] + "stdTraits": ["Eq", "PartialEq", "Hash", "Serialize", "Deserialize", "Debug", "Clone"] }; annotation MapEntry RustCustomType { "rustname" : "{{STDLIBMODULE}}::custom::sys::types::mapentry::MapEntry", "helpers" : "{{STDLIBMODULE}}::custom::sys::types::mapentry::MapEntry", - "stdTraits": ["Eq", "PartialEq", "Hash", "Serialize", "Deserialize", "Clone"] + "stdTraits": ["Eq", "PartialEq", "Hash", "Serialize", "Deserialize", "Debug", "Clone"] }; annotation Map RustCustomType { "rustname" : "{{STDLIBMODULE}}::custom::sys::types::map::Map", "helpers" : "{{STDLIBMODULE}}::custom::sys::types::map::Map", - "stdTraits": ["Eq", "PartialEq", "Serialize", "Deserialize", "Clone"] + "stdTraits": ["Eq", "PartialEq", "Serialize", "Deserialize", "Debug", "Clone"] }; annotation Set RustCustomType { @@ -29,12 +29,12 @@ annotation Set RustCustomType { annotation Pair RustCustomType { "rustname" : "{{STDLIBMODULE}}::custom::sys::types::pair::Pair", "helpers" : "{{STDLIBMODULE}}::custom::sys::types::pair::Pair", - "stdTraits": ["Eq", "PartialEq", "Hash", "Serialize", "Deserialize", "Clone"] + "stdTraits": ["Eq", "PartialEq", "Hash", "Serialize", "Deserialize", "Debug", "Clone"] }; annotation Result RustCustomType { "rustname" : "{{STDLIBMODULE}}::custom::sys::types::result::Result", "helpers" : "{{STDLIBMODULE}}::custom::sys::types::result::Result", - "stdTraits": ["Eq", "PartialEq", "Hash", "Serialize", "Deserialize", "Clone"] + "stdTraits": ["Eq", "PartialEq", "Hash", "Serialize", "Deserialize", "Debug", "Clone"] }; }; diff --git a/haskell/compiler/tests/demo1/input/picture.adl b/adl/tests/demo1/picture.adl similarity index 100% rename from haskell/compiler/tests/demo1/input/picture.adl rename to adl/tests/demo1/picture.adl diff --git a/haskell/compiler/tests/demo1/input/picture.adl-rs b/adl/tests/demo1/picture.adl-rs similarity index 100% rename from haskell/compiler/tests/demo1/input/picture.adl-rs rename to adl/tests/demo1/picture.adl-rs diff --git a/haskell/compiler/tests/test1/input/test.adl b/adl/tests/test1/test1.adl similarity index 100% rename from haskell/compiler/tests/test1/input/test.adl rename to adl/tests/test1/test1.adl diff --git a/haskell/compiler/tests/test10/input/test.adl b/adl/tests/test10/test10.adl similarity index 86% rename from haskell/compiler/tests/test10/input/test.adl rename to adl/tests/test10/test10.adl index 7f48ad17..93899698 100644 --- a/haskell/compiler/tests/test10/input/test.adl +++ b/adl/tests/test10/test10.adl @@ -1,4 +1,4 @@ -module Test +module test10 { struct X#1 { diff --git a/haskell/compiler/tests/test11/input/test.adl b/adl/tests/test11/test11.adl similarity index 86% rename from haskell/compiler/tests/test11/input/test.adl rename to adl/tests/test11/test11.adl index 2ba06ea2..5fcec722 100644 --- a/haskell/compiler/tests/test11/input/test.adl +++ b/adl/tests/test11/test11.adl @@ -1,4 +1,4 @@ -module Test +module test11 { struct X#1 { diff --git a/haskell/compiler/tests/test12/input/test.adl b/adl/tests/test12/test12.adl similarity index 90% rename from haskell/compiler/tests/test12/input/test.adl rename to adl/tests/test12/test12.adl index ca4cb1a6..0fc01212 100644 --- a/haskell/compiler/tests/test12/input/test.adl +++ b/adl/tests/test12/test12.adl @@ -1,4 +1,4 @@ -module Test +module test12 { struct X { diff --git a/haskell/compiler/tests/test13/input/test.adl b/adl/tests/test13/test13.adl similarity index 93% rename from haskell/compiler/tests/test13/input/test.adl rename to adl/tests/test13/test13.adl index 0e65e8b7..05bd664b 100644 --- a/haskell/compiler/tests/test13/input/test.adl +++ b/adl/tests/test13/test13.adl @@ -1,4 +1,4 @@ -module Test +module test13 { struct X { diff --git a/haskell/compiler/tests/test14/input/test.adl b/adl/tests/test14/test14.adl similarity index 91% rename from haskell/compiler/tests/test14/input/test.adl rename to adl/tests/test14/test14.adl index 4028e706..c6f17401 100644 --- a/haskell/compiler/tests/test14/input/test.adl +++ b/adl/tests/test14/test14.adl @@ -12,6 +12,7 @@ module test14 union unsigned { Void null; + Int64 string; }; newtype Factory = String; diff --git a/haskell/compiler/tests/test15/input/test.adl b/adl/tests/test15/test15.adl similarity index 94% rename from haskell/compiler/tests/test15/input/test.adl rename to adl/tests/test15/test15.adl index 8ba3c41f..0f1e9006 100644 --- a/haskell/compiler/tests/test15/input/test.adl +++ b/adl/tests/test15/test15.adl @@ -1,4 +1,4 @@ -module test +module test15 { /// A monomorphic struct struct A diff --git a/haskell/compiler/tests/test16/input/test.adl b/adl/tests/test16/test16.adl similarity index 75% rename from haskell/compiler/tests/test16/input/test.adl rename to adl/tests/test16/test16.adl index 4e0b4529..ff2246de 100644 --- a/haskell/compiler/tests/test16/input/test.adl +++ b/adl/tests/test16/test16.adl @@ -1,4 +1,4 @@ -module test +module test16 { import test2.A; diff --git a/haskell/compiler/tests/test16/input/test2.adl b/adl/tests/test16/test2.adl similarity index 100% rename from haskell/compiler/tests/test16/input/test2.adl rename to adl/tests/test16/test2.adl diff --git a/haskell/compiler/tests/test17/input/test.adl b/adl/tests/test17/test17.adl similarity index 100% rename from haskell/compiler/tests/test17/input/test.adl rename to adl/tests/test17/test17.adl diff --git a/haskell/compiler/tests/test18/input/test.adl b/adl/tests/test18/test18.adl similarity index 100% rename from haskell/compiler/tests/test18/input/test.adl rename to adl/tests/test18/test18.adl diff --git a/haskell/compiler/tests/test18/input/test.adl-rs b/adl/tests/test18/test18.adl-rs similarity index 100% rename from haskell/compiler/tests/test18/input/test.adl-rs rename to adl/tests/test18/test18.adl-rs diff --git a/adl/tests/test19/test19.adl b/adl/tests/test19/test19.adl new file mode 100644 index 00000000..4890bae5 --- /dev/null +++ b/adl/tests/test19/test19.adl @@ -0,0 +1,15 @@ +module test19 +{ +struct Pair +{ + A a; + B b; +}; + +// OK: +newtype T1 = Pair; + +// OK: +newtype T2 = Pair; + +}; diff --git a/adl/tests/test19/test19_01.adl b/adl/tests/test19/test19_01.adl new file mode 100644 index 00000000..715a901b --- /dev/null +++ b/adl/tests/test19/test19_01.adl @@ -0,0 +1,11 @@ +module test19_01 +{ +struct Pair +{ + A a; + B b; +}; + +// ERROR: Incorrect number of arguments +newtype T3 = Pair; +}; diff --git a/adl/tests/test19/test19_02.adl b/adl/tests/test19/test19_02.adl new file mode 100644 index 00000000..3ffaca73 --- /dev/null +++ b/adl/tests/test19/test19_02.adl @@ -0,0 +1,12 @@ +module test19_02 +{ +// ERROR: Type parameters should never take arguments +struct A { + T abc; +}; + +type I = X; + + + +}; diff --git a/haskell/compiler/tests/test2/input/test.adl b/adl/tests/test2/test2.adl similarity index 78% rename from haskell/compiler/tests/test2/input/test.adl rename to adl/tests/test2/test2.adl index 7de8e0e6..b01cfe10 100644 --- a/haskell/compiler/tests/test2/input/test.adl +++ b/adl/tests/test2/test2.adl @@ -3,7 +3,7 @@ module test2 // Simple structures -@Doc "An empty structure." +@sys.annotations.Doc "An empty structure." struct S0 { }; @@ -17,7 +17,7 @@ struct S1 String y; }; -@Doc "A structure containing a vector." +@sys.annotations.Doc "A structure containing a vector." struct S2 { String f1; @@ -25,7 +25,7 @@ struct S2 Vector f3; }; -@Doc "A generic structure." +@sys.annotations.Doc "A generic structure." struct S3 { String f1; diff --git a/haskell/compiler/tests/test2/input/test.adl-hs b/adl/tests/test2/test2.adl-hs similarity index 100% rename from haskell/compiler/tests/test2/input/test.adl-hs rename to adl/tests/test2/test2.adl-hs diff --git a/adl/tests/test2/test2_01.adl b/adl/tests/test2/test2_01.adl new file mode 100644 index 00000000..58ea5758 --- /dev/null +++ b/adl/tests/test2/test2_01.adl @@ -0,0 +1,42 @@ +module test2_01 +{ + +/// A structure containing primitives. +/// +/// It has two fields: an integer x and a String y. +struct s1 +{ + /// here is x + Int32 x; + /// why is a crooked letter + String y; +}; + +/// This is a union +union U1 { + /// a is for apple; + String a; + /// + Void b; + /// c is for cookie + Void c; +}; + + +/// This is an enum +union E1 { + /// a is for apple; + Void a; + /// + Void b; + /// c is for cookie + Void c; +}; + +/// this is a type alias +type T1 = String; + +/// this is a new type +newtype NT1 = String; + +}; diff --git a/haskell/compiler/tests/test20/input/test.adl b/adl/tests/test20/test20.adl similarity index 100% rename from haskell/compiler/tests/test20/input/test.adl rename to adl/tests/test20/test20.adl diff --git a/haskell/compiler/tests/test21/input/test.adl b/adl/tests/test21/test21.adl similarity index 96% rename from haskell/compiler/tests/test21/input/test.adl rename to adl/tests/test21/test21.adl index 80ccf3f1..ee7cd656 100644 --- a/haskell/compiler/tests/test21/input/test.adl +++ b/adl/tests/test21/test21.adl @@ -1,5 +1,5 @@ @Ann1 100 -module test +module test21 { // Some annotation types; diff --git a/haskell/compiler/tests/test22/input/test22a.adl b/adl/tests/test22/test22a.adl similarity index 100% rename from haskell/compiler/tests/test22/input/test22a.adl rename to adl/tests/test22/test22a.adl diff --git a/haskell/compiler/tests/test22/input/test22b.adl b/adl/tests/test22/test22b.adl similarity index 100% rename from haskell/compiler/tests/test22/input/test22b.adl rename to adl/tests/test22/test22b.adl diff --git a/haskell/compiler/tests/test23/input/test23.adl b/adl/tests/test23/test23.adl similarity index 100% rename from haskell/compiler/tests/test23/input/test23.adl rename to adl/tests/test23/test23.adl diff --git a/haskell/compiler/tests/test24/input/test24.adl b/adl/tests/test24/test24.adl similarity index 100% rename from haskell/compiler/tests/test24/input/test24.adl rename to adl/tests/test24/test24.adl diff --git a/adl/tests/test24/test24_01.adl b/adl/tests/test24/test24_01.adl new file mode 100644 index 00000000..b942f1ed --- /dev/null +++ b/adl/tests/test24/test24_01.adl @@ -0,0 +1,31 @@ +module test24_01 +{ + struct PostReq { + String path; + TypeToken reqBodyType = null; + TypeToken respType = null; + }; + + struct CrudReqs { + PostReq create; + PostReq read; + }; + + struct Service { + PostReq hello = { + "path": "/hello" + }; + PostReq,Nullable,T> farewell = { + "path": "/farewell" + }; + + CrudReqs blobs = { + "create": { + "path": "/blobs/create" + }, + "read": { + "path": "/blobs/read" + } + }; + }; +}; diff --git a/adl/tests/test24/test24_02.adl b/adl/tests/test24/test24_02.adl new file mode 100644 index 00000000..f46d581c --- /dev/null +++ b/adl/tests/test24/test24_02.adl @@ -0,0 +1,33 @@ +module test24_02 +{ + struct PostReq { + String path; + TypeToken reqBodyType = null; + TypeToken respType = null; + }; + + struct CrudReqs { + PostReq create; + PostReq read; + }; + + struct Service { + PostReq hello = { + "path": "/hello" + }; + PostReq,Nullable,T> farewell = { + "path": "/farewell" + }; + + Vector abc = ["abc"]; + + CrudReqs blobs = { + "create": { + "path": "/blobs/create" + }, + "read": { + "path": "/blobs/read" + } + }; + }; +}; diff --git a/haskell/compiler/tests/test25/input/admin.adl b/adl/tests/test25/admin.adl similarity index 100% rename from haskell/compiler/tests/test25/input/admin.adl rename to adl/tests/test25/admin.adl diff --git a/haskell/compiler/tests/test26/input/test26.adl b/adl/tests/test26/test26.adl similarity index 76% rename from haskell/compiler/tests/test26/input/test26.adl rename to adl/tests/test26/test26.adl index ef4a8e41..b5af8eae 100644 --- a/haskell/compiler/tests/test26/input/test26.adl +++ b/adl/tests/test26/test26.adl @@ -13,7 +13,7 @@ module test26 S2 s2; }; - @SerializedWithInternalTag {"tag":"kind"} + @sys.annotations.SerializedWithInternalTag {"tag":"kind"} union U2 { S1 s1; S2 s2; diff --git a/haskell/compiler/tests/test27/input/test27.adl b/adl/tests/test27/test27.adl similarity index 100% rename from haskell/compiler/tests/test27/input/test27.adl rename to adl/tests/test27/test27.adl diff --git a/haskell/compiler/tests/test27/input/test27a.adl b/adl/tests/test27/test27a.adl similarity index 100% rename from haskell/compiler/tests/test27/input/test27a.adl rename to adl/tests/test27/test27a.adl diff --git a/haskell/compiler/tests/test28/input/test28.adl b/adl/tests/test28/test28.adl similarity index 100% rename from haskell/compiler/tests/test28/input/test28.adl rename to adl/tests/test28/test28.adl diff --git a/haskell/compiler/tests/test29/input/test29.adl b/adl/tests/test29/test29.adl similarity index 100% rename from haskell/compiler/tests/test29/input/test29.adl rename to adl/tests/test29/test29.adl diff --git a/haskell/compiler/tests/test3/input/test.adl b/adl/tests/test3/test3.adl similarity index 100% rename from haskell/compiler/tests/test3/input/test.adl rename to adl/tests/test3/test3.adl diff --git a/adl/tests/test30/test30.adl b/adl/tests/test30/test30.adl new file mode 100644 index 00000000..4395bf0d --- /dev/null +++ b/adl/tests/test30/test30.adl @@ -0,0 +1,19 @@ +// Testing the edge cases the Doc and SerializedName annotations. +module test30 { + +/// Stuff bugs bunny says to Docs -- note the "Docs" not "Doc". +struct Docs { + String quote; +}; + +/// Alternate names for serialized TV formats. +// @Doc "alterate ways of doing a doc comment" +struct SerializedName { + @SerializedName "xzy" + String title; + String country; + Vector alternates; +}; + + +}; diff --git a/adl/tests/test30/test30_01.adl b/adl/tests/test30/test30_01.adl new file mode 100644 index 00000000..0291c3d2 --- /dev/null +++ b/adl/tests/test30/test30_01.adl @@ -0,0 +1,19 @@ +// Testing the edge cases the Doc and SerializedName annotations. +module test30_01 { + +/// Stuff bugs bunny says to Doc. +struct Doc { + String quote; +}; + +/// Alternate names for serialized TV formats. +// @Doc "alterate ways of doing a doc comment" +struct SerializedName { + @SerializedName "xzy" + String title; + String country; + Vector alternates; +}; + + +}; diff --git a/adl/tests/test30/test30_02.adl b/adl/tests/test30/test30_02.adl new file mode 100644 index 00000000..1dfdd679 --- /dev/null +++ b/adl/tests/test30/test30_02.adl @@ -0,0 +1,21 @@ +// Testing the edge cases the Doc and SerializedName annotations. +module test30_02 { + +/// Stuff bugs bunny says to Doc. +struct Docs { + String quote; +}; + +/// Alternate names for serialized TV formats. +// @Doc "alterate ways of doing a doc comment" +// @Doc { "quote" : "whats up"} +struct SerializedName { + // @Doc "changed its json name" + @SerializedName "xzy" + String title; + String country; + Vector alternates; +}; + + +}; diff --git a/adl/tests/test30/test30_03.adl b/adl/tests/test30/test30_03.adl new file mode 100644 index 00000000..ca69f0f5 --- /dev/null +++ b/adl/tests/test30/test30_03.adl @@ -0,0 +1,14 @@ +// Testing the edge cases the Doc and SerializedName annotations. +module test30_03 { + +/// Alternate names for serialized TV formats. +struct SerializedName { + @SerializedName "aaa" + String title; + String country; + @SerializedName {"aaa":"zyx","country":"","alternates":[]} + Vector alternates = [{"aaa":"bbb","country":"","alternates":[]}]; +}; + + +}; diff --git a/adl/tests/test30/test30_04.adl b/adl/tests/test30/test30_04.adl new file mode 100644 index 00000000..4d5b6799 --- /dev/null +++ b/adl/tests/test30/test30_04.adl @@ -0,0 +1,15 @@ +// Testing the edge cases the Doc and SerializedName annotations. +module test30_04 { + +type SerializedName = String; + +struct Names { + @SerializedName "aaa" + String title; + String country; + @SerializedName "zyx" + Vector alternates = ["bbb","country"]; +}; + + +}; diff --git a/adl/tests/test31/lib/adl.pkg.json b/adl/tests/test31/lib/adl.pkg.json new file mode 100644 index 00000000..c6f51718 --- /dev/null +++ b/adl/tests/test31/lib/adl.pkg.json @@ -0,0 +1,12 @@ +{ + "path" : "github.com/adl-lang/adl/adl/tests/test31/lib", + "global_alias": "common", + "adlc": "0.0.0", + "requires": [ + { + "ref": { + "alias": "sys" + } + } + ] +} \ No newline at end of file diff --git a/adl/tests/test31/lib/common.adl b/adl/tests/test31/lib/common.adl new file mode 100644 index 00000000..d8c48a78 --- /dev/null +++ b/adl/tests/test31/lib/common.adl @@ -0,0 +1,94 @@ +module common { + +import common.strings.StringNE; +import common.db.DbColumnType; + +/// A instant in time, represented as milliseconds from +/// the epoch of "1970-01-01T00:00:00Z +newtype Instant = Int64; + +/// A date in ISO8601 format +newtype LocalDate = String = "1970-01-01"; + +/// A time in ISO8601 format +newtype LocalTime = String = "00:00:00"; + +/// A datetime in ISO8601 format +newtype LocalDateTime = String = "1970-01-01T00:00:00"; + +/// The day of the week +union DayOfWeek { + Void monday; + Void tuesday; + Void wednesday; + Void thursday; + Void friday; + Void saturday; + Void sunday; +}; + +/// A duration in ISO8601 format +@DbColumnType "interval" +newtype Duration = String = "P1D"; + +/// An IANA timezone +newtype Timezone = StringNE; + +/// A holder for paginated results +struct Paginated { + + /// The paginated items + Vector items; + + /// The offset used for this query + Int64 current_offset; + + /// The size of the entire date set + Int64 total_size; +}; + +/// Empty Struct (Used mostly for Void RPC responses) +struct Unit {}; + +/// Phantom type to capture a StringMap with a named string key type: +type StringKeyMap = StringMap; + +/// Naming aid for strings used as keys +type Key = String; + +/// A value of type T along with the Key +struct WithKey { + Key key; + T value; +}; + +/// Postgres array of strings type that is serialized in to a list of Strings +@DbColumnType "text[]" +newtype StringList = Vector; + +// Postgres tsvector type for plain text searching +@DbColumnType "tsvector" +newtype TSVector = String; + +/// Postgres Geography type that is serialized using GeoJson +// Maps to postgres database as 'geography' column +// See https://postgis.net/workshops/postgis-intro/geography.html#casting-to-geometry +@DbColumnType "geography" +newtype GeographyGeoJson = String; + +/// Postgres Geometry type +// Maps to postgres database as 'geometry' column +// Serialise to/from WKT (Well Known Text) in the string +@DbColumnType "geometry" +newtype GeometryWKT = String; + + +/// A floating point decimal value +// +// In principle, the json format allows numbers with arbitrary decimal precision. However +// support for this is dependent on individual client libraries, and crucially the +// JSON.parse() function in browsers converts json numbers to a binary floating point +// double representation. Hence we take the safe option and serialize as JSON strings. +@DbColumnType "numeric" +newtype BigDecimal = String; +}; diff --git a/adl/tests/test31/lib/common.adl-java b/adl/tests/test31/lib/common.adl-java new file mode 100644 index 00000000..4b922fc2 --- /dev/null +++ b/adl/tests/test31/lib/common.adl-java @@ -0,0 +1,82 @@ +module common +{ +import adlc.config.java.*; +import common.db.JavaDbCustomType; +import sys.types.Set; + +annotation JavaPackage "au.com.helixta.adl.common"; + +annotation Instant JavaCustomType { + "javaname" : "java.time.Instant", + "helpers" : "au.com.helixta.adl.custom.InstantHelpers" +}; + +annotation LocalDate JavaCustomType { + "javaname" : "java.time.LocalDate", + "helpers" : "au.com.helixta.adl.custom.LocalDateHelpers" +}; + +annotation LocalTime JavaCustomType { + "javaname" : "java.time.LocalTime", + "helpers" : "au.com.helixta.adl.custom.LocalTimeHelpers" +}; + +annotation LocalDateTime JavaCustomType { + "javaname" : "java.time.LocalDateTime", + "helpers" : "au.com.helixta.adl.custom.LocalDateTimeHelpers" +}; + +annotation DayOfWeek JavaCustomType { + "javaname" : "java.time.DayOfWeek", + "helpers" : "au.com.helixta.adl.custom.DayOfWeekHelpers" +}; + +annotation GeographyGeoJson JavaCustomType { + "javaname" : "org.postgis.PGgeometry", + "helpers": "au.com.helixta.adl.custom.PGgeometryHelpers" +}; + +annotation GeographyGeoJson JavaDbCustomType { + "javaDbType": "org.postgis.PGgeometry", + "helpers": "au.com.helixta.adl.custom.PGgeometryHelpers" +}; + +annotation GeometryWKT JavaCustomType { + "javaname" : "org.postgis.PGgeometry", + "helpers": "au.com.helixta.adl.custom.PGgeometryWKTHelpers" +}; + +annotation GeometryWKT JavaDbCustomType { + "javaDbType" : "org.postgis.PGgeometry", + "helpers": "au.com.helixta.adl.custom.PGgeometryWKTHelpers" +}; + +annotation TSVector JavaDbCustomType { + "javaDbType" : "String", + "helpers": "au.com.helixta.adl.custom.TSVectorHelpers" +}; + +annotation StringList JavaDbCustomType { + "javaDbType" : "au.com.helixta.nofrills.sql.StringList", + "helpers": "au.com.helixta.adl.custom.StringListHelpers" +}; + +annotation StringList JavaCustomType { + "javaname" : "au.com.helixta.nofrills.sql.StringList", + "helpers": "au.com.helixta.adl.custom.StringListHelpers" +}; + +annotation BigDecimal JavaCustomType { + "javaname" : "java.math.BigDecimal", + "helpers": "au.com.helixta.adl.custom.BigDecimalHelpers" +}; + +annotation BigDecimal JavaDbCustomType { + "javaDbType" : "java.math.BigDecimal", + "helpers": "au.com.helixta.adl.custom.BigDecimalHelpers" +}; + +/// Force adlc java runtime to include HashSetHelpers.java +newtype SetStrings = Set; + +}; diff --git a/adl/tests/test31/lib/common/adminui/api.adl b/adl/tests/test31/lib/common/adminui/api.adl new file mode 100644 index 00000000..a9217501 --- /dev/null +++ b/adl/tests/test31/lib/common/adminui/api.adl @@ -0,0 +1,168 @@ +module common.adminui.api { + +import sys.adlast.TypeExpr; +import sys.adlast.ModuleName; +import sys.adlast.ScopedName; +import sys.types.Maybe; +import common.Unit; +import common.db.DbKey; +import common.db.WithDbId; +import common.Paginated; +import common.tabular.TableQuery; +import common.http.HttpPost; +import common.adminui.db.MetaAdlDecl; + +import common.flyway.api.FlywayReq; +import common.flyway.api.FlywayResp; + +// An adl value serialised via the standard schema +type AdlValue = Json; + +// A Row in a table is a map of Adl values +type DbRow = StringMap; +type DbId = DbKey; + +/// Endpoints supporting CRUD for the Admin UI, +/// along with metadata access. +struct AdminApiRequests { + + /// Query the tables available for admin access + HttpPost> queryTables = { + "path" : "/admin/meta/tables", + "security" : {"tokenWithRole": "admin"} + }; + + /// Query the ADL declarations used in the column + /// type declarations + HttpPost> queryDecls = { + "path" : "/admin/meta/decls", + "security" : {"tokenWithRole": "admin"} + }; + + /// Query rows from a table, specifying pagination, + /// filtering and sorting. As per it's return type, this method + /// can only be used for tables with a string primary key + /// called `id`. + HttpPost>> query = { + "path" : "/admin/query", + "security" : {"tokenWithRole": "admin"} + }; + + /// Query rows from a table without requiring a primary key, specifying pagination, + /// filtering and sorting. + HttpPost> queryWithoutIds = { + "path" : "/admin/query-without-ids", + "security" : {"tokenWithRole": "admin"} + }; + + /// Create a new row in a table + HttpPost> create = { + "path" : "/admin/create", + "security" : {"tokenWithRole": "admin"} + }; + + /// Update a single existing row in a table + HttpPost> update = { + "path" : "/admin/update", + "security" : {"tokenWithRole": "admin"} + }; + + /// Delete a single existing row in a table + HttpPost> delete = { + "path" : "/admin/delete", + "security" : {"tokenWithRole": "admin"} + }; + + /// Fetch descriptive strings for db keys + HttpPost,Vector> dbKeyLabels = { + "path" : "/admin/dbkeylabels", + "security" : {"tokenWithRole": "admin"} + }; + + /// Flyway migration handled by adminui + HttpPost flyway = { + "path" : "/admin/flyway", + "security" : {"tokenWithRole": "admin"} + }; +}; + +struct QueryReq { + String table; + + /// The columns to be included in the result. If empty, all + /// columns will be included. + Vector columns; + + TableQuery query; +}; + +struct Table { + String name; + String label; + String description; + Bool hasIdPrimaryKey; + + /// If true, the current user is allowed to query existingRows + Bool allowQuery; + + /// If true, the current user is allowed to insert new rows + Bool allowInsert; + + /// If true, the current user is allowed to delete rows + Bool allowDelete; + + /// If true, the current user is allowed to update rows + Bool allowUpdate; + + Vector columns; + ModuleName declModuleName; + String declName; +}; + +union Access { + Void readOnly; + Void readWrite; +}; + +struct TableColumn { + String name; + String label; + String description; + TypeExpr typeExpr; + Maybe defaultValue; + Bool generated; + Access access; +}; + +struct CreateReq { + String table; + DbRow values; +}; + +struct UpdateReq { + String table; + WithDbId values; +}; + +struct DeleteReq { + String table; + DbId id; +}; + +union DbResult { + T ok; + String dbError; +}; + +struct DbKeyLabelReq { + ScopedName scopedName; + String id; +}; + +struct DbKeyLabelResp { + ScopedName scopedName; + String id; + String label; +}; + +}; diff --git a/adl/tests/test31/lib/common/adminui/api.adl-java b/adl/tests/test31/lib/common/adminui/api.adl-java new file mode 100644 index 00000000..106a2ff7 --- /dev/null +++ b/adl/tests/test31/lib/common/adminui/api.adl-java @@ -0,0 +1,6 @@ +module common.adminui.api +{ +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.adminui.api"; +}; diff --git a/adl/tests/test31/lib/common/adminui/config.adl b/adl/tests/test31/lib/common/adminui/config.adl new file mode 100644 index 00000000..dfc90669 --- /dev/null +++ b/adl/tests/test31/lib/common/adminui/config.adl @@ -0,0 +1,35 @@ +module common.adminui.config { + +import common.config.frontend.ThreadPoolConfig; +import common.config.log.LogConfig; +import common.config.log.ClientLogConfig; +import common.config.db.PostgreSqlConfig; + +/// Configuration for the adminui server +struct ServerConfig { + /// Port to listen for requests + Int16 port; + + /// Environment name, e.g. dev, uat, prod + String environment; + + /// Name of the release / code version + String releaseName; + + /// Secret used to sign JWT tokens + String jwtSecret; + + /// Database config + PostgreSqlConfig db; + + /// Server-side logging config + LogConfig logging; + + /// Frontend threadpool configuration + ThreadPoolConfig threadPool; + + // DB Migration config, if null flyway is not available. + Nullable flyway = null; +}; + +}; diff --git a/adl/tests/test31/lib/common/adminui/db.adl b/adl/tests/test31/lib/common/adminui/db.adl new file mode 100644 index 00000000..27132a7e --- /dev/null +++ b/adl/tests/test31/lib/common/adminui/db.adl @@ -0,0 +1,40 @@ +module common.adminui.db { + +import sys.adlast.Decl; +import sys.adlast.ModuleName; +import common.db.DbTable; +import common.db.DbColumnName; +import common.Instant; + +struct MetaTable { + String name; + String description; + ModuleName declModuleName; + String declName; +}; + +annotation MetaTable DbTable { + "withPrimaryKey": [ + "name" + ], + "uniquenessConstraints": [ + ["name"] + ] +}; + +struct MetaAdlDecl { + ModuleName moduleName; + String name; + Decl decl; +}; + +annotation MetaAdlDecl DbTable { + "withPrimaryKey": [ + "moduleName", "name" + ], + "uniquenessConstraints": [ + ["moduleName", "name"] + ] +}; + +}; diff --git a/adl/tests/test31/lib/common/adminui/db.adl-java b/adl/tests/test31/lib/common/adminui/db.adl-java new file mode 100644 index 00000000..472873e2 --- /dev/null +++ b/adl/tests/test31/lib/common/adminui/db.adl-java @@ -0,0 +1,6 @@ +module common.adminui.db +{ +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.adminui.db"; +}; diff --git a/adl/tests/test31/lib/common/config/aws.adl b/adl/tests/test31/lib/common/config/aws.adl new file mode 100644 index 00000000..075a970e --- /dev/null +++ b/adl/tests/test31/lib/common/config/aws.adl @@ -0,0 +1,46 @@ +module common.config.aws +{ + +struct AwsCredentials { + String accessKey; + String secretKey; +}; + +/// The methods available to obtain AWS credentials +union AwsCredentialsProvider { + Void useEnvVariables; + Void useInstanceProfile; + AwsCredentials value; +}; + +/// The methods available to determine the AWS region +union AwsRegionProvider { + Void fromInstance; + String value; +}; + +struct S3Location { + /// The name on of an S3 bucket + String s3Bucket; + + /// The S3 path prefix for the storage + String s3Prefix; +}; + +/// Description of an AWS SQS queue +struct QueueDetails { + /// The amount of time to keep the connection open while waiting for queue messages. + Int32 waitTimeSeconds = 10; + String queueUrl = ""; +}; + + +/// Configuration of an S3 client +struct S3ClientConfig { + S3Location location; + AwsRegionProvider region; + AwsCredentialsProvider credentials; +}; + + +}; diff --git a/adl/tests/test31/lib/common/config/aws.adl-java b/adl/tests/test31/lib/common/config/aws.adl-java new file mode 100644 index 00000000..0ffa32cf --- /dev/null +++ b/adl/tests/test31/lib/common/config/aws.adl-java @@ -0,0 +1,7 @@ +module common.config.aws +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.config.aws"; +}; diff --git a/adl/tests/test31/lib/common/config/azure.adl b/adl/tests/test31/lib/common/config/azure.adl new file mode 100644 index 00000000..8d07e641 --- /dev/null +++ b/adl/tests/test31/lib/common/config/azure.adl @@ -0,0 +1,15 @@ +module common.config.azure { + + /// Methods available to obtain Azure credentials + union AzureCredentialsProvider { + /// A shared access signature string + String sharedAccessSignature; + }; + + /// Config parameters for an Azure Blob Client + struct AzureBlobClientConfig { + String blobstoreUri; + AzureCredentialsProvider credentials; + String container; + }; +}; diff --git a/adl/tests/test31/lib/common/config/db.adl b/adl/tests/test31/lib/common/config/db.adl new file mode 100644 index 00000000..34a5adf6 --- /dev/null +++ b/adl/tests/test31/lib/common/config/db.adl @@ -0,0 +1,67 @@ +module common.config.db +{ + +// Connection details for a postgres server +struct PostgreSqlConfig +{ + String host; + Int32 port; + + // the database name + String dbname; + + // login parameters + String user; + String password; + + // The size of the connection pool + Int32 poolSize = 5; + + // true to enable the postgis extensions + Bool postgisEnabled = false; + + /// The amount of time to wait before refreshing a connection + Int32 minRefreshDelayMillis = 60000; + + /// The amount of time to wait for a free connection before timing out + Int32 connectionWaitMillis = 5000; + + /// The root cert to be used for ssl connections + Nullable sslRootCert = null; + + /// The ssl connection mode + PostgresqlSslMode sslMode = "prefer"; +}; + +union PostgresqlSslMode { + Void disable; + Void allow; + Void prefer; + Void require; + + @SerializedName "verify-ca" + Void verifyCa; + + @SerializedName "verify-full" + Void verifyFull; +}; + + +// Connection details for a microsoft SQL server +struct SqlServerConfig +{ + String host; + Int32 port; + + // the database name + String dbname; + + // login parameters + String user; + String password; + + // The size of the connection pool + Int32 poolSize = 5; +}; + +}; diff --git a/adl/tests/test31/lib/common/config/db.adl-java b/adl/tests/test31/lib/common/config/db.adl-java new file mode 100644 index 00000000..ad45d24e --- /dev/null +++ b/adl/tests/test31/lib/common/config/db.adl-java @@ -0,0 +1,7 @@ +module common.config.db +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.config.db"; +}; diff --git a/adl/tests/test31/lib/common/config/emailer.adl b/adl/tests/test31/lib/common/config/emailer.adl new file mode 100644 index 00000000..f662a8d8 --- /dev/null +++ b/adl/tests/test31/lib/common/config/emailer.adl @@ -0,0 +1,22 @@ +module common.config.emailer +{ +import common.config.aws.AwsCredentialsProvider; +import common.config.aws.AwsRegionProvider; + +/// Configuration for the emailer used +union EmailerConfig { + /// Fake emailer, just prints outgoing email info to stdout + Void fake; + + /// SES emailer implementation + SesConfig ses; + +}; + +/// Configuration for AWS SES emailer implementation +struct SesConfig { + AwsCredentialsProvider credentials; + AwsRegionProvider region; +}; + +}; diff --git a/adl/tests/test31/lib/common/config/emailer.adl-java b/adl/tests/test31/lib/common/config/emailer.adl-java new file mode 100644 index 00000000..0982d4ce --- /dev/null +++ b/adl/tests/test31/lib/common/config/emailer.adl-java @@ -0,0 +1,7 @@ +module common.config.emailer +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.config.emailer"; +}; diff --git a/adl/tests/test31/lib/common/config/frontend.adl b/adl/tests/test31/lib/common/config/frontend.adl new file mode 100644 index 00000000..f194854f --- /dev/null +++ b/adl/tests/test31/lib/common/config/frontend.adl @@ -0,0 +1,22 @@ +module common.config.frontend { + +/// Configuration for a consumer which processes work from a queue with a bounded thread pool. +/// +/// e.g. Useful for configuring jetty's request thread pool. +/// +// TODO: Java custom type to map this to au.com.helixta.util.concurrent.ThreadPoolConfig +struct ThreadPoolConfig { + /// Maximum number of threads that can be spawned to handle requests + Int32 maxThreads; + + /// Minimum number of threads ready for jetty to handle requests + Int32 minThreads; + + /// How long a thread can be idle before it is candidate to be stopped + Int32 idleTimeoutMillis; + + /// Maximum number of pending requests before new ones are dropped + Int32 queueSize; +}; + +}; diff --git a/adl/tests/test31/lib/common/config/frontend.adl-java b/adl/tests/test31/lib/common/config/frontend.adl-java new file mode 100644 index 00000000..1e7586a7 --- /dev/null +++ b/adl/tests/test31/lib/common/config/frontend.adl-java @@ -0,0 +1,8 @@ +module common.config.frontend +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.config.frontend"; +}; + diff --git a/adl/tests/test31/lib/common/config/google.adl b/adl/tests/test31/lib/common/config/google.adl new file mode 100644 index 00000000..6aeb3bf4 --- /dev/null +++ b/adl/tests/test31/lib/common/config/google.adl @@ -0,0 +1,12 @@ +module common.config.google +{ + +/// Connection parameters for google services +struct GoogleConfig { + String clientId; + String clientSecret; + String accessToken; + String refreshToken; +}; + +}; diff --git a/adl/tests/test31/lib/common/config/google.adl-java b/adl/tests/test31/lib/common/config/google.adl-java new file mode 100644 index 00000000..b134c62c --- /dev/null +++ b/adl/tests/test31/lib/common/config/google.adl-java @@ -0,0 +1,8 @@ +module common.config.google +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.config.google"; +}; + diff --git a/adl/tests/test31/lib/common/config/jwt.adl b/adl/tests/test31/lib/common/config/jwt.adl new file mode 100644 index 00000000..86ba18b6 --- /dev/null +++ b/adl/tests/test31/lib/common/config/jwt.adl @@ -0,0 +1,10 @@ +module common.config.jwt +{ + +/// Secret and expiry of the JWT token +struct JwtConfig { + String secret; + Double expiryInMinutes; +}; + +}; diff --git a/adl/tests/test31/lib/common/config/jwt.adl-java b/adl/tests/test31/lib/common/config/jwt.adl-java new file mode 100644 index 00000000..c9ece9b4 --- /dev/null +++ b/adl/tests/test31/lib/common/config/jwt.adl-java @@ -0,0 +1,7 @@ +module common.config.jwt +{ + import adlc.config.java.*; + + annotation JavaPackage "au.com.helixta.adl.common.config.jwt"; + +}; diff --git a/adl/tests/test31/lib/common/config/log.adl b/adl/tests/test31/lib/common/config/log.adl new file mode 100644 index 00000000..f91dbc62 --- /dev/null +++ b/adl/tests/test31/lib/common/config/log.adl @@ -0,0 +1,69 @@ +module common.config.log +{ + +import common.config.aws.AwsCredentialsProvider; +import common.config.aws.AwsRegionProvider; + +// Configuration for logging +union LogLevel { + Void DEBUG; + Void INFO; + Void WARN; + Void ERROR; + Void NONE; + Void TRACE; +}; + +struct StdoutConfig { + LogLevel level; +}; + +struct FluentdConfig { + LogLevel level; + String hostname; + Int32 port; + String tag; +}; + +/// Server side Rollbar config +/// NOTE: Name is `ServerRollbarConfig` due to being named prior to adding +/// `ClientRollbarConfig` +struct RollbarConfig { + LogLevel level; + String serverToken; + String env = ""; +}; + +/// Server side logging, i.e. reporting errors originating from the server +/// NOTE: Name is not `ServerLogConfig` due to being named prior to adding +/// `ClientLogConfig` +struct LogConfig { + Nullable stdout = {"level" : "INFO"}; + Nullable fluentd = null; + Nullable rollbar = null; + Nullable cloudwatch = null; +}; + +/// Client side Rollbar config, i.e. from Rollbar JS +struct ClientRollbarConfig { + String accessToken; + String env = ""; +}; + +/// Client side logging, i.e. reporting errors originating from the client +struct ClientLogConfig { + Nullable rollbar = null; +}; + +/// Logging of metrics to cloudwatch +struct CloudWatchMetricLogConfig { + AwsCredentialsProvider credentials; + AwsRegionProvider region; + String env; + String namespace; + /// A whitelist of metrics that should be sent to CloudWatch. Users should be + /// aware that making this list too big can quickly cause costs to increase + Vector metricsToSend; +}; + +}; diff --git a/adl/tests/test31/lib/common/config/log.adl-java b/adl/tests/test31/lib/common/config/log.adl-java new file mode 100644 index 00000000..3daf592d --- /dev/null +++ b/adl/tests/test31/lib/common/config/log.adl-java @@ -0,0 +1,12 @@ +module common.config.log +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.config.log"; + +annotation LogLevel JavaCustomType { + "javaname" : "au.com.helixta.log.Log.Level", + "helpers" : "au.com.helixta.adl.custom.LogLevelHelpers" +}; +}; diff --git a/adl/tests/test31/lib/common/config/okta.adl b/adl/tests/test31/lib/common/config/okta.adl new file mode 100644 index 00000000..92c073d4 --- /dev/null +++ b/adl/tests/test31/lib/common/config/okta.adl @@ -0,0 +1,32 @@ +module common.config.okta +{ +import sys.types.Maybe; + +/// Config parameters for setting up open ID authentication using Okta +struct OktaConfig { + + // NOTE(Barry): The following parameters are sufficient to use for the + // majority of our applications; however, the Okta implementation was written + // for Sydney Airport which has many other features that are bespoke to that + // application. The Java binding for this ADL type ignores all of the extra + // config parameters that are not necessary (i.e. sets them to empty + // strings). + + /// ID of the client application + String clientId; + /// Secret of the client application + String clientSecret; + /// Hostname of the okta instance + String clientHost; + /// Endpoint which users should be redirected to to complete authorization + String authorizeEndpoint; + /// The URL supplied to okta to redirect the user to after authorization is + /// complete + String redirectUrl; + /// API key used for performing actions in okta, not required if the app does + /// not use this functionality + Maybe apiKey; +}; + + +}; diff --git a/adl/tests/test31/lib/common/config/okta.adl-java b/adl/tests/test31/lib/common/config/okta.adl-java new file mode 100644 index 00000000..b8474fbf --- /dev/null +++ b/adl/tests/test31/lib/common/config/okta.adl-java @@ -0,0 +1,12 @@ +module common.config.okta +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.config.okta"; + +annotation OktaConfig JavaCustomType { + "javaname" : "au.com.helixta.service.auth.OktaCfg", + "helpers" : "au.com.helixta.adl.custom.OktaConfigHelpers" +}; +}; diff --git a/adl/tests/test31/lib/common/config/server.adl b/adl/tests/test31/lib/common/config/server.adl new file mode 100644 index 00000000..964e07e6 --- /dev/null +++ b/adl/tests/test31/lib/common/config/server.adl @@ -0,0 +1,3 @@ +module common.config.server +{ +}; diff --git a/adl/tests/test31/lib/common/config/sms.adl b/adl/tests/test31/lib/common/config/sms.adl new file mode 100644 index 00000000..95af4094 --- /dev/null +++ b/adl/tests/test31/lib/common/config/sms.adl @@ -0,0 +1,32 @@ +module common.config.sms +{ +import common.config.aws.AwsCredentialsProvider; +import common.config.aws.AwsRegionProvider; +import common.strings.StringNE; + +/// Configuration for the sms provider used +union SmsConfig { + /// Fake sms, just prints outgoing message info to stdout + Void fake; + + /// Twilio implementation + TwilioConfig twilio; + + /// AWS SNS implementation + AwsSnsConfig sns; + +}; + +/// Configuration for twilio +struct TwilioConfig { + StringNE accountSid; + StringNE authToken; +}; + +/// Configuration for AWS SMS implementation +struct AwsSnsConfig { + AwsCredentialsProvider credentials; + AwsRegionProvider region; +}; + +}; diff --git a/adl/tests/test31/lib/common/config/sms.adl-java b/adl/tests/test31/lib/common/config/sms.adl-java new file mode 100644 index 00000000..d614f75c --- /dev/null +++ b/adl/tests/test31/lib/common/config/sms.adl-java @@ -0,0 +1,7 @@ +module common.config.sms +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.config.sms"; +}; diff --git a/adl/tests/test31/lib/common/config/storage.adl b/adl/tests/test31/lib/common/config/storage.adl new file mode 100644 index 00000000..5b3b7b6f --- /dev/null +++ b/adl/tests/test31/lib/common/config/storage.adl @@ -0,0 +1,30 @@ +module common.config.storage { + + struct LocalBlobstoreConfig { + /// The directory in which the blobstore files will be stored + String directory; + + /// The host of the server to be used for serving public files, e.g. "http://localhost" + String publicHost; + + /// The path on which blobstore objects are publically accessible e.g. "/files" + String publicPath; + }; + + struct LocalFileStoreConfig { + /// The directory in which the blobstore files will be stored + String directory; + + /// The host of the server to be used for serving public files, e.g. "http://localhost" + String publicHost; + + /// The path on which blobstore objects are publically accessible e.g. "/files" + String publicPath; + + /// False if the data in the FileStore is to be immutable + Bool allowOverwrite; + }; + + + +}; diff --git a/adl/tests/test31/lib/common/db.adl b/adl/tests/test31/lib/common/db.adl new file mode 100644 index 00000000..c5af92c7 --- /dev/null +++ b/adl/tests/test31/lib/common/db.adl @@ -0,0 +1,78 @@ +module common.db { + +// Annotation to indicate that an ADL struct is to be +// mapped to a database table +struct DbTable +{ + // If non empty, specifies the table name in the + // database. Otherwise it will be derived from the + // name of the adl struct + String tableName = ""; + + // If true, the generated db table will containing + // a text column `id`, which will be the primary key. + Bool withIdPrimaryKey = false; + + // If provided, use the given fields as the table's primary key + Vector withPrimaryKey = []; + + // Indexes for the table + Vector> indexes = []; + + // Uniqueness constraints over the table + Vector> uniquenessConstraints = []; + + // Additional SQL to be run after all tables have been + // created + Vector extraSql = []; + + // The textual columns used to assemble a label for the row + // (to be shown in UIs alongside the id) + Vector label = []; +}; + +// Annotation to indicate that an ADL struct is to be +// mapped to a database view. +struct DbView { + + // If non empty, specifies the view name in the + // database. Otherwise it will be derived from the + // name of the adl struct + String viewName = ""; + + // If true, the view will containing + // a text column `id`, which will be the primary key. + Bool withIdPrimaryKey = false; + + // If non empty the sql required to create the view. + // If empty, then it's assumed that the view corresponding + // is created by some other means + Vector viewSql = []; +}; + + +/// Field level annotation to override the name of the +/// database column. +type DbColumnName = String; + +/// Field or type level annotation to override the type of the +/// database column. +type DbColumnType = String; + +/// Field level annotation to indicate that a column value +/// is generated, and hence need not be requested from or edited +/// by a user. +type DbColumnGenerated = Void; + +/// A reference for a database stored value, referenced by a +/// string primary key. +newtype DbKey = String; + +/// A value of type T along with a unique db identifier +struct WithDbId +{ + DbKey id; + T value; +}; + +}; diff --git a/adl/tests/test31/lib/common/db.adl-java b/adl/tests/test31/lib/common/db.adl-java new file mode 100644 index 00000000..a16294b9 --- /dev/null +++ b/adl/tests/test31/lib/common/db.adl-java @@ -0,0 +1,32 @@ +module common.db +{ +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.db"; + +/// Annotation to control how java custom types are mapped to the +/// database +struct JavaDbCustomType { + /// The type returned from a db query + String javaDbType; + + /// The class in which to look for fromDb and toDb static functions + String helpers; +}; + +/// Annotation to control which format of java db table class is emitted +union JavaDbTableVersion { + Void v1; + Void v2; +}; + + +// Use a custom type for DbKey, primarily so that we can override the +// toString implementation +annotation DbKey JavaCustomType { + "javaname" : "au.com.helixta.adl.custom.DbKey", + "helpers": "au.com.helixta.adl.custom.DbKeyHelpers" +}; + +}; + diff --git a/adl/tests/test31/lib/common/flyway/api.adl b/adl/tests/test31/lib/common/flyway/api.adl new file mode 100644 index 00000000..d1ad8c40 --- /dev/null +++ b/adl/tests/test31/lib/common/flyway/api.adl @@ -0,0 +1,119 @@ +module common.flyway.api { + +import common.flyway.internals.FlywayAction; +import common.flyway.internals.FlywayContext; +import common.http.HttpPost; + +type FlywayApi = HttpPost; + +union FlywayReq { + /// Show pending migrations + Void plan; + /// Apply pending migrations + Void apply; + /// Something customized + AdvancedFlywayReq advanced; +}; + +/// Information passed when access via API +struct AdvancedFlywayReq { + FlywayReqContextOpt context = "application"; + FlywayAction action; +}; + +union FlywayReqContextOpt { + /// Derive the context from the app config + /// Throw exception if it app is not configured with a flyway context + Void application; + /// The first ctx in bootstrapable->bootstrap. + /// Throw exception if it doesn't exist + Void bootstrap; + /// Overide the application flyway config + FlywayContext customCtx; +}; + +union FlywayResp { + String error; + String msg; + FlywayCleanResult clean; + FlywayInfo info; + FlywayMigrateResult migrationResult; + FlywayBaselineResult baselineResult; + Vector sequence; +}; + +struct FlywayInfo { + String schemaVersion; + Vector migrations; +}; + +struct FlywayMigrationInfo { + String category; + String version; + String description; + String type_; + String installed_on; + String state; +}; + +struct FlywayMigrateResult { + String message; + // OperationResultBase + String flywayVersion; + String database; + Vector warnings; + String operation; + // MigrateResult + Nullable initialSchemaVersion; + Nullable targetSchemaVersion; + Nullable schemaName; + Vector migrations; + Nullable migrationsExecuted; +}; + +struct FlywayBaselineResult { + // OperationResultBase + String flywayVersion; + String database; + Vector warnings; + String operation; + // BaselineResult + Bool successfullyBaselined; + Nullable baselineVersion; +}; + +struct FlywayCleanResult { + // OperationResultBase + String flywayVersion; + String database; + Vector warnings; + String operation; + // BaselineResult + Vector schemasCleaned; + Vector schemasDropped; +}; + +struct FlywayMigrateOutput { + String category; + String version; + String description; + String type_; + String filepath; + Int32 executionTime; +}; + +// struct FlywaySchemaHistory { +// Int32 installed_rank; // | integer | not null +// Nullable version; // | character varying(50) | +// String description; // | character varying(200) | not null +// String type_; // | character varying(20) | not null +// String script; // | character varying(1000) | not null +// Nullable checksum; // | integer | +// String installed_by; // | character varying(100) | not null +// Instant installed_on; // | timestamp without time zone | not null default now() +// Int32 execution_time; // | integer | not null +// Bool success; // | boolean | not null +// }; + + +}; diff --git a/adl/tests/test31/lib/common/flyway/api.adl-java b/adl/tests/test31/lib/common/flyway/api.adl-java new file mode 100644 index 00000000..9c2b227f --- /dev/null +++ b/adl/tests/test31/lib/common/flyway/api.adl-java @@ -0,0 +1,7 @@ +module common.flyway.api { + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.flyway.api"; + +}; diff --git a/adl/tests/test31/lib/common/flyway/example_patterns.adl b/adl/tests/test31/lib/common/flyway/example_patterns.adl new file mode 100644 index 00000000..9a7ba433 --- /dev/null +++ b/adl/tests/test31/lib/common/flyway/example_patterns.adl @@ -0,0 +1,103 @@ +// These are example configs which in a project would likely be constructed in code +// and used when calling FlywayUtils +module common.flyway.example_patterns { + +import common.flyway.internals.FlywayCommand; + + +// Example application config. +union FlywayConfig { + // bootstraps by applying "create migrations" & baseline existing migrations + // startup applies new migrations. + Void mixed_mode_latest; + // bootstraps by applying "create migrations" & baseline existing migrations + // startup does not apply migrations. Migrations can be applied via adminui. + Void mixed_mode_manual; + // bootstraps by applying all migrations from scratch. + // startup applies new migrations. + Void migration_mode_latest; + // customize the flyway app startup + FlywayCommand advanced; +}; + + +type ExampleFlywayCommand = StringMap; + +annotation ExampleFlywayCommand { +// Tim's preferred model for fastdev, which works the same, but runs +// any pending migrations when the server is started + "mixedmode_latest": + { + "ctx": { + "sqlMigrationDir": "/app/sql/migrations", + "javaMigrationPackage": "app/java/migrations" + }, + "bootstrap": [ + { + "withContext": { + "ctx": { + "schemaHistoryTable": "flyway_bootstrap_schema_history", + "sqlMigrationDir": "/app/sql/create", + "javaMigrationPackage": "app/java/createmigrations" + }, + "action": { + "sequence": [ + "baseline_zero", + "migrate" + ] + } + } + }, + "baseline_latest", + "migrate" + ], + "action": "migrate" + } +, +// Tim's preferred model for prod, which bootstraps a new db from create scripts +// and baselines to the last migration. Subsequent migrations are run from the adminui + "mixedmode_manual": + { + "ctx": { + "sqlMigrationDir": "/app/sql/migrations", + "javaMigrationPackage": "app/java/migrations" + }, + "bootstrap": [ + { + "withContext": { + "ctx": { + "schemaHistoryTable": "flyway_bootstrap_schema_history", + "sqlMigrationDir": "/app/sql/create", + "javaMigrationPackage": "app/java/createmigrations" + }, + "action": { + "sequence": [ + "baseline_zero", + "migrate" + ] + } + } + }, + "baseline_latest", + "migrate" + ], + "action": null + } +, +// Paul's preferred model for prod (I think) which bootstraps +// by applying all migrations from scratch + "migration_mode_latest": + { + "ctx": { + "sqlMigrationDir": "/app/sql/migrations", + "javaMigrationPackage": "app/java/migrations" + }, + "bootstrap": [ + "baseline_zero", + "migrate" + ], + "action": "migrate" + } +}; + +}; diff --git a/adl/tests/test31/lib/common/flyway/example_patterns.adl-java b/adl/tests/test31/lib/common/flyway/example_patterns.adl-java new file mode 100644 index 00000000..6fd24eb1 --- /dev/null +++ b/adl/tests/test31/lib/common/flyway/example_patterns.adl-java @@ -0,0 +1,7 @@ +module common.flyway.example_patterns { + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.flyway.example_patterns"; + +}; diff --git a/adl/tests/test31/lib/common/flyway/internals.adl b/adl/tests/test31/lib/common/flyway/internals.adl new file mode 100644 index 00000000..64d13279 --- /dev/null +++ b/adl/tests/test31/lib/common/flyway/internals.adl @@ -0,0 +1,112 @@ +module common.flyway.internals { + +struct FlywayCommand { + FlywayContext ctx; + /// The action to take on application startup + Vector bootstrap = []; + Nullable action; +}; + +/// Contextual information required to run flyway +struct FlywayContext { + /// The name of the flyway history table. + /// Useful to override for bootstraping. + String schemaHistoryTable = "flyway_schema_history"; + /// The location from which db migrations are loaded + String sqlMigrationDir = "/app/sql/migrations"; + /// The package from which java based db migrations are loaded + Nullable javaMigrationPackage = "app/java/migrations"; + /// DB connection retries, with 1 second between retries + Int32 connect_retries = 3; +}; + +union FlywayAction { + /// Get migration info, the a combintation of the flyway schema history and future migrations. + Void info; + // Baseline actions + Void baseline_zero; + Void baseline_one; + Void baseline_latest; + String baseline_version; + // Migration actions + /// Migrate to lastest with default options + Void migrate; + MigrateLatestAction migrate_latest; + MigrateAction migrate_to_version; + // other + Vector sequence; + FlywayCtxAction withContext; +}; + +struct FlywayCtxAction { + /// The context in normal (non-bootstrap) mode + FlywayContext ctx; + /// Array of actions to run on bootstrap + FlywayAction action; +}; + +struct MigrateLatestAction { + /// migration options + MigrateOptionsOptions options = "defaults"; +}; + +struct MigrateAction { + /// migration options + MigrateOptionsOptions options = "defaults"; + String version; +}; + +union MigrateOptionsOptions { + Void defaults; + Void ignoreMissingMigrations; + Void ignoreIgnoredMigrations; + Void outOfOrder; + Void dontValidateOnMigrate; + MigrateOptions custom = {}; +}; + +struct MigrateOptions { + /// Ignore missing migrations when reading the schema history table. These are migrations that were performed by an + /// older deployment of the application that are no longer available in this version. + // Not the Flyway default + Bool ignoreMissingMigrations = true; + /// Ignore ignored migrations when reading the schema history table. These are migrations that were added in between + /// already migrated migrations in this version. + // Not the Flyway default + Bool ignoreIgnoredMigrations= true; + /// Ignore pending migrations when reading the schema history table. These are migrations that are available on the + /// classpath but have not yet been performed by an application deployment. + /// This can be useful for verifying that in-development migration changes don't contain any validation-breaking changes + /// of migrations that have already been applied to a production environment, e.g. as part of a CI/CD process, without + /// failing because of the existence of new migration versions. + Bool ignorePendingMigrations = false; + /// Ignore future migrations when reading the schema history table. These are migrations that were performed by a + /// newer deployment of the application that are not yet available in this version. For example: we have migrations + /// available on the classpath up to version 3.0. The schema history table indicates that a migration to version 4.0 + /// (unknown to us) has already been applied. Instead of bombing out (fail fast) with an exception, a + /// warning is logged and Flyway continues normally. This is useful for situations where one must be able to redeploy + /// an older version of the application after the database has been migrated by a newer one. + Bool ignoreFutureMigrations = true; + /// Whether to validate migrations and callbacks whose scripts do not obey the correct naming convention. A failure can be + /// useful to check that errors such as case sensitivity in migration prefixes have been corrected. + Bool validateMigrationNaming = false; + /// Whether to automatically call validate or not when running migrate. (default: {@code true}) + Bool validateOnMigrate = true; + /// Whether to automatically call clean or not when a validation error occurs. (default: {@code false}) + ///

This is exclusively intended as a convenience for development. even though we + /// strongly recommend not to change migration scripts once they have been checked into SCM and run, this provides a + /// way of dealing with this case in a smooth manner. The database will be wiped clean automatically, ensuring that + /// the next migration will bring you back to the state checked into SCM.

+ ///

Warning ! Do not enable in production !

+ Bool cleanOnValidationError = false; + /// Whether to disable clean. (default: {@code false}) + ///

This is especially useful for production environments where running clean can be quite a career limiting move.

+ Bool cleanDisabled = false; + /// Allows migrations to be run "out of order". + ///

If you already have versions 1 and 3 applied, and now a version 2 is found, + /// it will be applied too instead of being ignored.

+ Bool outOfOrder = false; +}; + + +}; diff --git a/adl/tests/test31/lib/common/flyway/internals.adl-java b/adl/tests/test31/lib/common/flyway/internals.adl-java new file mode 100644 index 00000000..c17b1343 --- /dev/null +++ b/adl/tests/test31/lib/common/flyway/internals.adl-java @@ -0,0 +1,7 @@ +module common.flyway.internals { + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.flyway.internals"; + +}; diff --git a/adl/tests/test31/lib/common/http.adl b/adl/tests/test31/lib/common/http.adl new file mode 100644 index 00000000..ce930b76 --- /dev/null +++ b/adl/tests/test31/lib/common/http.adl @@ -0,0 +1,152 @@ +module common.http { + +import sys.types.Set; + +/// A marker type to associate the output response +/// type for an http Get request. +type Get = Void; + +/// A marker type to associate the input request and output response +/// types for an http put request. +type Put = Void; + +/// A marker type to associate the input request and output response +/// types for an http post request. +type Post = Void; + +/// An annotation indicating the URL path for a request +type Path = String; + +/// An annotation indicating that a request requires an Authorization http header +type AuthHeader = Void; + +/// An annotation indicating that a request is idemponent, and can hence be safely +/// retried on failure. +type Idempotent = Void; + +/// An annotation indicating that a request can be made idempotent if the caller +/// provides an Idempotency-Key header with a unique value. +type IdempotentWithKey = Void; + +/// The standard message body for errors +struct PublicErrorData { + String publicMessage; +}; + +/// New request types + +struct HttpGet { + String path; + HttpSecurity security; + Nullable rateLimit = null; + TypeToken respType = null; +}; + +struct HttpGetStream { + String path; + HttpSecurity security; + TypeToken respItemType = null; +}; + +struct HttpGet2 { + String path; + HttpSecurity security; + Nullable rateLimit = null; + TypeToken

paramsType = null; + TypeToken respType = null; +}; + +struct HttpPut { + String path; + HttpSecurity security; + Nullable rateLimit = null; + TypeToken reqType = null; + TypeToken respType = null; +}; + +struct HttpPost { + String path; + HttpSecurity security; + Nullable rateLimit = null; + TypeToken reqType = null; + TypeToken respType = null; +}; + +struct HttpPost2 { + String path; + HttpSecurity security; + Nullable rateLimit = null; + TypeToken

paramsType = null; + TypeToken reqType = null; + TypeToken respType = null; +}; + +struct HttpDelete { + String path; + HttpSecurity security; + TypeToken

paramsType = null; + TypeToken respType = null; +}; + +union HttpSecurity { + // The endpoint is publically accessible + Void public; + + // A token is required to access the endpoint + Void token; + + // A token containing the specified role is required + // for access + String tokenWithRole; +}; + + +struct HttpRateLimit { + Word32 maxRequests; + RateLimitTimeUnit perTimeUnit; +}; + +union RateLimitTimeUnit { + Void second; + Void minute; + Void hour; +}; + +/// API decl or request annotation to specify +/// the non-success response codes we want +/// included in the generated open API. The +/// Json should have exactly the structure of +/// the OpenApi responses map +type OpenApiOtherResponses = Json; + + +/// API annotation to specify the available +/// server endpoints. The Json should have +/// exactly the structure of the OpenApi +/// servers map +type OpenApiServers = Json; + +/// Marker annotation to indicate that an endpoint +/// or (defaulted) field should be left out of the +/// generated openapi +type OpenApiExclude = Bool; + +/// API annotation to specify additional api +/// information. The Json should have +/// exactly the structure of the OpenApi +/// info map +type OpenApiInfo = Json; + +/// API decl annotation to specify +/// the security schema in use +union SecurityScheme { + Void httpBearer; + HeaderApiKeyScheme apiKey; +}; + +struct HeaderApiKeyScheme { + String headerName; +}; + +}; + diff --git a/adl/tests/test31/lib/common/http.adl-java b/adl/tests/test31/lib/common/http.adl-java new file mode 100644 index 00000000..79db148e --- /dev/null +++ b/adl/tests/test31/lib/common/http.adl-java @@ -0,0 +1,7 @@ +module common.http +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.http"; +}; diff --git a/adl/tests/test31/lib/common/strings.adl b/adl/tests/test31/lib/common/strings.adl new file mode 100644 index 00000000..e080e8ce --- /dev/null +++ b/adl/tests/test31/lib/common/strings.adl @@ -0,0 +1,46 @@ +/// Some string type aliases, with attributes to derive UI validation +module common.strings +{ + +import common.ui.ValidRegex; + +/// A string that isn't empty, and isn't only whitespace. +type StringNE = String; + +annotation StringNE ValidRegex { + "regex" : "^.*\\S+.*$", + "description" : "non empty", + "returnGroup" : 0 +}; + +/// An alphanumeric string, with hyphens for separation. +type StringANH = String; + +/// A multi line, free-form text string +type StringML = String; + +annotation StringANH ValidRegex { + "regex" : "^[A-Za-z][A-Za-z0-9-]*$", + "description" : "alphanumeric", + "returnGroup" : 0 +}; + +/// An email address +type EmailAddress = String; + +// see https://stackoverflow.com/questions/201323/how-to-validate-an-email-address-using-a-regular-expression +// The regex below allows whitespace before and after the email address, but the first match group excludes these. +annotation EmailAddress ValidRegex { + "regex" : "^\\s*((?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\]))\\s*$", + "description" : "an email address", + "returnGroup" : 1 +}; + +/// A markdown text string +type StringMD = String; + +/// A password, which cannot be empty. Other constraints +/// are application specific. +type Password = String; + +}; diff --git a/adl/tests/test31/lib/common/tabular.adl b/adl/tests/test31/lib/common/tabular.adl new file mode 100644 index 00000000..1f8ca5a3 --- /dev/null +++ b/adl/tests/test31/lib/common/tabular.adl @@ -0,0 +1,83 @@ +/// Common definitions for querying tabular data +module common.tabular +{ + +import common.strings.StringNE; +import common.Instant; +import common.LocalDate; + +type FieldName = StringNE; + +struct ExprLike { Expr expr; String pattern; Bool caseSensitive = true; }; +struct ExprIn { Expr expr; Vector exprs; }; +struct ExprComparison { Expr expr1; Expr expr2; }; + +union FieldPredicate { + ExprComparison equalTo; + ExprIn in; + ExprLike like; + Expr isnull; + FieldPredicate not; + ExprComparison greaterThan; + ExprComparison lessThan; + Vector and; + Vector or; + Bool literal; +}; + +union Expr { + String string; + Int32 int; + Bool bool; + LocalDate date; + Instant instant; + + FieldName field; + Void currentDate; + Vector concat; +}; + +union SortDirection { + Void ascending; + Void descending; +}; + +struct SortField { FieldName field; SortDirection direction; }; + + +// A view of a table +struct TableView +{ + // The columns to show + Vector columns; + + // A filter controlling which rows to show + FieldPredicate filter = {"literal":true}; + + // How the results should be sorted + Vector sorting = []; +}; + +// The structure we pass to specify a page of values to be +// loaded. +struct TableQuery { + // By default we match all rows + FieldPredicate filter = {"literal":true}; + + // Sorting order + Vector sorting = []; + + // Pagination offset + Int32 offset = 0; + + // Number of items to return (-1 => all) + Int32 count = -1; +}; + +// A trivial single element struct, to enable non-struct +// values to be shown in tables +struct SingleField { + T value; +}; + +}; diff --git a/adl/tests/test31/lib/common/tabular.adl-java b/adl/tests/test31/lib/common/tabular.adl-java new file mode 100644 index 00000000..ec8c810b --- /dev/null +++ b/adl/tests/test31/lib/common/tabular.adl-java @@ -0,0 +1,8 @@ +module common.tabular +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.tabular"; + +}; diff --git a/adl/tests/test31/lib/common/ui.adl b/adl/tests/test31/lib/common/ui.adl new file mode 100644 index 00000000..82331de5 --- /dev/null +++ b/adl/tests/test31/lib/common/ui.adl @@ -0,0 +1,51 @@ +module common.ui +{ + +import sys.types.Pair; + +// UI Annotations + +// field annotation specifying the label to be shown on forms and +// table headings +type FormLabel = String; + +// field annotation allocating a field to a display group. An empty +// group key means that the field is to be shown ungrouped. +type FormGroupKey = String; + +// struct annotation for groups +struct FormGroups { + // The default group for unannotated fields + FormGroupKey defaultKey; + + // The text labels for each group + Vector> labels; +}; + +/// An field/type alias annotation to constrain the +/// values allowed by a string to the enumerated values +struct ValidValues { + /// The allowed values + Vector values; + + /// A (short) user readable string describing the + /// expected text. + String description; +}; + +/// An field/type alias annotation to constrain the +/// values allowed by a string to a regular expression +struct ValidRegex { + /// The regexp that must be matched + String regex; + + /// A (short) user readable string describing the + /// expected text. + String description; + + /// The regex group index to return if matches + /// 0 is the entire string + Int8 returnGroup = 0; +}; + +}; diff --git a/adl/tests/test31/lib/common/ui.adl-java b/adl/tests/test31/lib/common/ui.adl-java new file mode 100644 index 00000000..0b9567be --- /dev/null +++ b/adl/tests/test31/lib/common/ui.adl-java @@ -0,0 +1,7 @@ +module common.ui +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.ui"; +}; diff --git a/adl/tests/test31/proj/adl.pkg.json b/adl/tests/test31/proj/adl.pkg.json new file mode 100644 index 00000000..e1337369 --- /dev/null +++ b/adl/tests/test31/proj/adl.pkg.json @@ -0,0 +1,17 @@ +{ + "path": "github.com/adl-lang/adl/adl/tests/test31/proj", + "global_alias": "protoclient", + "adlc": "0.0.0", + "requires": [ + { + "ref": { + "alias": "sys" + } + }, + { + "ref": { + "alias": "common" + } + } + ] +} \ No newline at end of file diff --git a/adl/tests/test31/proj/protoclient/protoapp/api.adl b/adl/tests/test31/proj/protoclient/protoapp/api.adl new file mode 100644 index 00000000..966fe5f2 --- /dev/null +++ b/adl/tests/test31/proj/protoclient/protoapp/api.adl @@ -0,0 +1,149 @@ +module protoclient.protoapp.api { + +import sys.types.Map; + +import common.Instant; +import common.db.WithDbId; +import common.config.log.LogLevel; +import common.tabular.TableQuery; +import common.Paginated; +import common.Unit; +import common.http.HttpPost; +import common.http.HttpGet; +import common.strings.Password; +import common.strings.StringML; +import common.strings.StringNE; + +import protoclient.protoapp.db.AppUser; +import protoclient.protoapp.db.AppUserId; +import protoclient.protoapp.db.MessageId; + +struct X { + +}; + +/// The app API +struct ApiRequests { + X x; + // Vector y; + Map imamap; + /// Login a user + HttpPost>> with_prim = { + "path": "/login", + "security" : "public" + }; + + /// Login a user + HttpPost login = { + "path": "/login", + "security" : "public" + }; + + /// Post a message to the noticeboard + HttpPost newMessage = { + "path": "/messages/new", + "security" : "token" + }; + + /// Get recent noticeboard messages + HttpPost > recentMessages = { + "path": "/messages/recent", + "security" : "token" + }; + + /// Gets the logged in user details + // NOTE: Fails with 401 if the token is invalid or user does not exist + HttpGet whoAmI = { + "path": "/whoami", + "security" : "token" + }; + + /// Create a new user + HttpPost createUser = { + "path": "/users/create", + "security" : {"tokenWithRole": "admin"} + }; + + /// Update an existing user + HttpPost, Unit> updateUser = { + "path": "/users/update", + "security" : {"tokenWithRole": "admin"} + }; + + /// Delete an existing user + HttpPost deleteUser = { + "path": "/users/delete", + "security" : {"tokenWithRole": "admin"} + }; + + /// Query existing users sorted and filters according to the + /// TableQuery request. + HttpPost>> queryUsers = { + "path": "/users/query", + "security" : {"tokenWithRole": "admin"} + }; + + /// Logs an error from the client app without user information, i.e. when the + /// user has not logged in + HttpPost logClientErrorPublic = { + "path": "/client/log/public", + "security": "public", + "rateLimit": { "maxRequests": 6, "perTimeUnit": "minute" } + }; + + /// Logs an error from the client app and includes user information + HttpPost logClientErrorUser = { + "path": "/client/log/user", + "security": "token" + }; +}; + +struct UserProfile { + AppUserId id; + String fullname; + String email; + Bool isAdmin; +}; + +/// Details for a user +struct UserReq { + String fullname; + String email; + Password password; +}; + +struct LoginReq { + StringNE email; + Password password; +}; + +union LoginResp { + StringNE accessToken; + Void invalidCredentials; +}; + +struct NewMessageReq { + StringML message; +}; + +struct RecentMessagesReq { + // Pagination offset + Int32 offset = 0; + + // Number of items to return + Int32 count = 20; +}; + +struct Message { + MessageId id; + Instant postedAt; + String userFullName; + StringML message; +}; + +struct ClientLogReq { + LogLevel level; + String error; + Nullable stacktrace; +}; +}; diff --git a/adl/tests/test31/proj/protoclient/protoapp/config.adl b/adl/tests/test31/proj/protoclient/protoapp/config.adl new file mode 100644 index 00000000..481975ff --- /dev/null +++ b/adl/tests/test31/proj/protoclient/protoapp/config.adl @@ -0,0 +1,51 @@ +module protoclient.protoapp.config { + +import common.config.frontend.ThreadPoolConfig; +import common.config.log.LogConfig; +import common.config.log.FluentdConfig; +import common.config.db.PostgreSqlConfig; + +/// Configuration for the server +struct ServerConfig { + /// Port to listen for requests + Int16 port; + + /// Environment name, e.g. dev, uat, prod + String environment; + + /// Name of the release / code version + String releaseName; + + /// The shared secret that will be present on requests + /// made by the cron webhook system. + String cronSharedSecret; + + /// Secret used to sign JWT tokens + String jwtSecret; + + /// Database config + PostgreSqlConfig db; + + /// Server-side logging config + LogConfig logging; + + /// Client-side logging config + /// If not provided all client logs will appear in the server logs + Nullable clientLogging = null; + + /// Frontend threadpool configuration + ThreadPoolConfig threadPool; + + // If set, apply automatic migrations on startup + Nullable flyway = null; +}; + +type ClientLogConfig = FluentdConfig; + +union LocalFlywayConfig { + Void fastdev; + Void deployed; + common.flyway.internals.FlywayCommand advanced; +}; + +}; diff --git a/adl/tests/test31/proj/protoclient/protoapp/db.adl b/adl/tests/test31/proj/protoclient/protoapp/db.adl new file mode 100644 index 00000000..2445717f --- /dev/null +++ b/adl/tests/test31/proj/protoclient/protoapp/db.adl @@ -0,0 +1,57 @@ +module protoclient.protoapp.db { + +import common.strings.StringML; +import common.strings.StringNE; +import common.db.DbTable; +import common.db.DbKey; +import common.Instant; + + +struct Trade { + Vector commodities; + Instant date; +}; + +annotation Trade DbTable { + "withIdPrimaryKey" : true +}; + + +struct Commodity { + String code; +}; + +/// Details for a user +struct AppUser { + StringNE fullname; + StringNE email; + Bool isAdmin; + StringNE hashedPassword = ""; +}; + +// Annotation to specify that there is a db table for user, +// with an id primary key, and a index over username. +annotation AppUser DbTable { + "withIdPrimaryKey" : true, + "indexes" : [["email"]], + "label" : ["fullname"] +}; + +type AppUserId = DbKey; + +/// messages posted on the noticeboard +struct Message { + Instant postedAt; + DbKey postedBy; + StringML message; +}; + +annotation Message DbTable { + "withIdPrimaryKey" : true, + "indexes" : [["posted_at"]] +}; + +type MessageId = DbKey; + + +}; diff --git a/adl/tests/test31/proj/protoclient/protoapp/uiconfig.adl b/adl/tests/test31/proj/protoclient/protoapp/uiconfig.adl new file mode 100644 index 00000000..aa62bfb2 --- /dev/null +++ b/adl/tests/test31/proj/protoclient/protoapp/uiconfig.adl @@ -0,0 +1,17 @@ +module protoclient.protoapp.uiconfig { + +import common.config.log.ClientRollbarConfig; + +/// Configuration for the web frontend. +struct UiConfig { + /// Application title + String title = ""; + + /// Environment name, e.g. dev, uat, prod + String environment; + + /// Name of the release / code version + String releaseName; +}; + +}; diff --git a/adl/tests/test32/test32a.adl b/adl/tests/test32/test32a.adl new file mode 100644 index 00000000..4984c897 --- /dev/null +++ b/adl/tests/test32/test32a.adl @@ -0,0 +1,9 @@ + +module test32a +{ + import test32b.Y; + + struct X { + Y field; + }; +}; \ No newline at end of file diff --git a/adl/tests/test32/test32b.adl b/adl/tests/test32/test32b.adl new file mode 100644 index 00000000..0de817ad --- /dev/null +++ b/adl/tests/test32/test32b.adl @@ -0,0 +1,9 @@ + +module test32b +{ + import test32a.X; + + struct Y { + X field; + }; +}; \ No newline at end of file diff --git a/haskell/compiler/tests/test4/input/test.adl b/adl/tests/test4/test4.adl similarity index 100% rename from haskell/compiler/tests/test4/input/test.adl rename to adl/tests/test4/test4.adl diff --git a/haskell/compiler/tests/test4/input/test.adl-cpp b/adl/tests/test4/test4.adl-cpp similarity index 100% rename from haskell/compiler/tests/test4/input/test.adl-cpp rename to adl/tests/test4/test4.adl-cpp diff --git a/haskell/compiler/tests/test4/input/test.adl-hs b/adl/tests/test4/test4.adl-hs similarity index 100% rename from haskell/compiler/tests/test4/input/test.adl-hs rename to adl/tests/test4/test4.adl-hs diff --git a/haskell/compiler/tests/test4/input/test.adl-java b/adl/tests/test4/test4.adl-java similarity index 100% rename from haskell/compiler/tests/test4/input/test.adl-java rename to adl/tests/test4/test4.adl-java diff --git a/haskell/compiler/tests/test4/input/test.adl-rs b/adl/tests/test4/test4.adl-rs similarity index 100% rename from haskell/compiler/tests/test4/input/test.adl-rs rename to adl/tests/test4/test4.adl-rs diff --git a/haskell/compiler/tests/test5/input/test.adl b/adl/tests/test5/test5.adl similarity index 100% rename from haskell/compiler/tests/test5/input/test.adl rename to adl/tests/test5/test5.adl diff --git a/haskell/compiler/tests/test5/input/test.adl-hs b/adl/tests/test5/test5.adl-hs similarity index 100% rename from haskell/compiler/tests/test5/input/test.adl-hs rename to adl/tests/test5/test5.adl-hs diff --git a/haskell/compiler/tests/test5/input/test.adl-rs b/adl/tests/test5/test5.adl-rs similarity index 100% rename from haskell/compiler/tests/test5/input/test.adl-rs rename to adl/tests/test5/test5.adl-rs diff --git a/haskell/compiler/tests/test6/input/test.adl b/adl/tests/test6/test6.adl similarity index 100% rename from haskell/compiler/tests/test6/input/test.adl rename to adl/tests/test6/test6.adl diff --git a/haskell/compiler/tests/test7/input/test.adl b/adl/tests/test7/test7.adl similarity index 100% rename from haskell/compiler/tests/test7/input/test.adl rename to adl/tests/test7/test7.adl diff --git a/haskell/compiler/tests/test8/input/test.adl b/adl/tests/test8/test8.adl similarity index 81% rename from haskell/compiler/tests/test8/input/test.adl rename to adl/tests/test8/test8.adl index fc530343..21b76781 100644 --- a/haskell/compiler/tests/test8/input/test.adl +++ b/adl/tests/test8/test8.adl @@ -1,4 +1,4 @@ -module Test +module test8 { struct X { diff --git a/haskell/compiler/tests/test9/input/test.adl b/adl/tests/test9/test9.adl similarity index 81% rename from haskell/compiler/tests/test9/input/test.adl rename to adl/tests/test9/test9.adl index 12757907..e93a60b6 100644 --- a/haskell/compiler/tests/test9/input/test.adl +++ b/adl/tests/test9/test9.adl @@ -1,4 +1,4 @@ -module Test +module test9 { struct X { diff --git a/adl/tests/testing_table.json b/adl/tests/testing_table.json new file mode 100644 index 00000000..8af60257 --- /dev/null +++ b/adl/tests/testing_table.json @@ -0,0 +1,90 @@ +[ + { "module_root": "test1", "modules": ["test1" ] }, + { "module_root": "test2", "modules": ["test2" ], "keywords": ["@Doc", "doc comment", "recursive type", "generic"]}, + { "module_root": "test2", "modules": ["test2_01" ], "keywords": ["doc comments for each decl type"]}, + { "module_root": "test3", "modules": ["test3" ], "keywords": ["default values"]}, + { "module_root": "test4", "modules": ["test4" ], "keywords": ["default values", "newtype with default", "custom mappers"] }, + { "module_root": "test5", "modules": ["test5" ], "keywords": ["union", "mutual recursion"] }, + { "module_root": "test6", "modules": ["test6" ] }, + { "module_root": "test7", "modules": ["test7" ] }, + { "module_root": "test8", "modules": ["test8" ], "fail": true, "title": "dup decl name" }, + { "module_root": "test9", "modules": ["test9" ], "fail": true, "title": "decl version numbers" }, + { "module_root": "test10", "modules": ["test10" ], "fail": true, "title": "decl version numbers" }, + { "module_root": "test11", "modules": ["test11" ], "fail": true, "title": "decl version numbers - missing numbers" }, + { "module_root": "test12", "modules": ["test12" ], "fail": true, "title": "dup field name" }, + { "module_root": "test13", "modules": ["test13" ], "fail": true, "title": "dup & missing type params" }, + { "module_root": "test14", "modules": ["test14" ], "keywords": ["language keywords"]}, + { "module_root": "test15", "modules": ["test15" ], "keywords": ["doc comment", "monomorphic struct", "polymorphic union"] }, + { "module_root": "test16", "modules": ["test16" ] }, + { "module_root": "test16", "modules": ["test16" ] }, + { "module_root": "test16", "modules": ["test2" ] }, + { "module_root": "test17", "modules": ["test17" ] }, + { "module_root": "test18", "modules": ["test18" ], "keywords": ["mutual recursion"] }, + { "module_root": "test19", "modules": ["test19" ] }, + { "module_root": "test19", "modules": ["test19_01"], "fail": true, "title": "Mismatch number of type params." }, + { "module_root": "test19", "modules": ["test19_02"], "fail": true }, + { "module_root": "test20", "modules": ["test20" ] }, + { "module_root": "test21", "modules": ["test21" ] }, + { "module_root": "test22", "modules": ["test22a", "test22b"] }, + { "module_root": "test23", "modules": ["test23" ] }, + { "module_root": "test24", "modules": ["test24" ] }, + { "module_root": "test24", "modules": ["test24_01"], "fail": true, "title": "token type with hanging type param" }, + { "module_root": "test24", "modules": ["test24_02"], "fail": true, "title": "default value with hanging type param" }, + { "module_root": "test25", "modules": ["admin" ] }, + { "module_root": "test26", "modules": ["test26" ] }, + { "module_root": "test27", "modules": ["test27" ] }, + { "module_root": "test27", "modules": ["test27a" ] }, + { "module_root": "test28", "modules": ["test28" ] }, + { "module_root": "test29", "modules": ["test29" ] }, + { + "module_root": "test30", + "modules": ["test30" ], + "title": "adlc ✅, cargo run ast ✅" + }, + { + "module_root": "test30", + "modules": ["test30_01" ], + "title": "adlc ❌, cargo run ast ✅", + "description": [ + "\n error message from adlc", + "In module test30_01 :", + "Invalid literal for annotation Doc of Doc: expected an object", + " Invalid literal for annotation Doc of SerializedName: expected an object" + ] + }, + { + "module_root": "test30", + "modules": ["test30_02" ], + "title": "adlc ❌, cargo run ast ✅", + "fail": true, + "skip": true, + "description": [ + "\n cargo run ast currently succeeds, but the output is incorrect.", + "The annotations scoped_name moduleName is test30_02, but the v is a string primative" + ] + }, + { + "module_root": "test30", + "modules": ["test30_03" ], + "title": "adlc ✅, cargo run ast ✅", + "description": ["This one works"] + }, + { + "module_root": "test30", + "modules": ["test30_04" ], + "title": "adlc ✅, cargo run ast ✅", + "description": [ + "This one works - but there an ambiguit as to what the annotation should refer to.", + "It is resolved as sys.annotation.SerializedName" + ] + }, + { + "module_root": "test31/proj", + "output_dir": "test_app/protoapp/src/adlgen", + "modules": ["protoclient.protoapp.api" ], + "title": "protoapp", + "lib_paths": [ "test31/lib" ] + }, + { "module_root": "test32", "modules": ["test32a", "test32b"], "fail": true, "title": "Circular module reference"}, + { "module_root": "demo1", "modules": ["picture" ] } +] diff --git a/docs/processing.md b/docs/processing.md new file mode 100644 index 00000000..f5606b49 --- /dev/null +++ b/docs/processing.md @@ -0,0 +1,48 @@ +This describes the phases of ADL processing from initial parsing through to being validated and ready for code generation. + +# Phases + +## 1. parse module adl file(s) +A single adl file is expected to be called X.adl, where X is the module hierarchy. Confirm the the module name in the file matches the directory name. Also load any extra files with name X.adl_Y, according to configuration. A files named X.adl_Y normally contain language Xspecific declarations or annotations to be merged into model X. Hence these should be merged into a single module for further processing. + +## 2. apply explicit annotations +All annotations are associated with a module, declaration, or field. However they can be specified either as a prefix, or as a free floating *explicit annotation*. This phase attaches all explicit annotations to their associated element of the parse tree, and reports an error if this cannot be done. + +## 3. check decl versioning +Ensure that for all the decls associated with a name, either + * we have one unversioned decl + * we have have a consistently versioned set + +## 4. lift serialized names +Serialised names are a first class item in the AST, by default equal to the field names, but are overriden by the `@SerializedName` attribute + +## 5. check for duplicates +Raise an error if there are any duplicate declarations in a module, or any duplicate fields in a struct or union, or any deplicate type parameters in a generic declaration. + +## 6. resolution +Useful further interpretatiion of the ADL cannot be done until external references are resolved. This phase involves the following stages: + +* find the name of all modules referenced from the current module, by looking at imports and fully scoped references. +* resolve each of those modules, storing the results of each +* Add in default imports (ie `sys/annotations.adl`) +* rewrite the current module by deciding the kind of each type ref (either a primitive, a decl in another module, or a type parameters) +* fail if any type ref in the current module cannot be resolved. + +Note the above process is recursive, and a error should be generated in the case of mutually recursive modules. + +## 7. check type constructor applications +Check that every usage of a type constructure is passed the correct number of parameters according to it's declaration. + +## 8. check default values +Confirm that: +* there are no default overrides for parameterised types +* the JSON literal for each default override has the appropriate type + +## 9. check annotations +Confirm that the JSON literal for each annotation has the correct type. + + + + + + diff --git a/haskell/compiler/adlc-lib1/ADL/Compiler/Backends/Rust/Internal.hs b/haskell/compiler/adlc-lib1/ADL/Compiler/Backends/Rust/Internal.hs index c5e3af77..ef5e613a 100644 --- a/haskell/compiler/adlc-lib1/ADL/Compiler/Backends/Rust/Internal.hs +++ b/haskell/compiler/adlc-lib1/ADL/Compiler/Backends/Rust/Internal.hs @@ -497,8 +497,8 @@ stdTraitsForFields1 sns tbmap fields = foldr S.intersection defaultStdTraits [st stdTraitsForFields :: [Field CResolvedType] -> StdTraits stdTraitsForFields = stdTraitsForFields1 S.empty M.empty -defaultStdTraits = S.fromList ["PartialEq", "Eq", "Hash", "Serialize", "Deserialize", "Clone"] -noeqStdTraits = S.fromList ["PartialEq", "Serialize", "Deserialize", "Clone"] +defaultStdTraits = S.fromList ["PartialEq", "Eq", "Hash", "Serialize", "Deserialize", "Clone", "Debug"] +noeqStdTraits = S.fromList ["PartialEq", "Serialize", "Deserialize", "Clone", "Debug"] type TypeBindingMap = M.Map Ident (TypeExpr CResolvedType) diff --git a/haskell/compiler/lib/adl/adlc b/haskell/compiler/lib/adl/adlc new file mode 120000 index 00000000..915760b0 --- /dev/null +++ b/haskell/compiler/lib/adl/adlc @@ -0,0 +1 @@ +../../../../adl/adlc \ No newline at end of file diff --git a/haskell/compiler/tests/Main.hs b/haskell/compiler/tests/Main.hs index e59d0bde..0621a76f 100644 --- a/haskell/compiler/tests/Main.hs +++ b/haskell/compiler/tests/Main.hs @@ -188,6 +188,9 @@ runRsBackend ipaths mpaths epath rsModule = do stdsrc :: FilePath stdsrc = "../../../haskell/compiler/lib/adl" +testsrc :: FilePath +testsrc = "../../../adl/tests" + stdfiles, stdHsCustomTypes, stdCppCustomTypes :: [FilePath] stdfiles = map (combine stdsrc) ["sys/types.adl", "sys/adlast.adl", "sys/dynamic.adl"] stdHsCustomTypes = ["../../compiler/lib/adl/sys/types/hs-custom-types.json"] @@ -227,10 +230,10 @@ runTests = do describe "adlc haskell backend" $ do it "generates expected code for an empty module" $ do - collectResults (runHaskellBackend1 "test1/input/test.adl") + collectResults (runHaskellBackend [stdsrc] [testsrc "test1/test1.adl"] "test1/hs-output") `shouldReturn` MatchOutput it "generates expected code for various structures" $ do - collectResults (runHaskellBackend1 "test2/input/test.adl") + collectResults (runHaskellBackend [stdsrc] [testsrc "test2/test2.adl"] "test2/hs-output") `shouldReturn` MatchOutput it "generates expected code for structures with default overrides" $ do collectResults (runHaskellBackend1 "test3/input/test.adl") @@ -274,10 +277,10 @@ runTests = do describe "adlc cpp backend" $ do it "generates expected code for an empty module" $ do - collectResults (runCppBackend1 "test1/input/test.adl") + collectResults (runCppBackend [stdsrc] [testsrc "test1/test1.adl"] "test1/cpp-output" "") `shouldReturn` MatchOutput it "generates expected code for various structures" $ do - collectResults (runCppBackend1 "test2/input/test.adl") + collectResults (runCppBackend [stdsrc] [testsrc "test2/test2.adl"] "test2/cpp-output" "") `shouldReturn` MatchOutput it "generates expected code for structures with default overrides" $ do collectResults (runCppBackend1 "test3/input/test.adl") @@ -321,7 +324,7 @@ runTests = do describe "adlc java backend" $ do it "generates expected code for various structures" $ do - collectResults (runJavaBackend1 "test2/input/test.adl") + collectResults (runJavaBackend [stdsrc] [testsrc "test2/test2.adl"] "test2/java-output" id) `shouldReturn` MatchOutput it "generates expected code for structures with default overrides" $ do collectResults (runJavaBackend1 "test3/input/test.adl") @@ -392,7 +395,7 @@ runTests = do describe "adlc typescript backend" $ do it "generates expected output for various structures" $ - collectResults (runTsBackend id [stdsrc] ["test2/input/test.adl"] "test2/ts-output") + collectResults (runTsBackend id [stdsrc] [testsrc "test2/test2.adl"] "test2/ts-output") `shouldReturn` MatchOutput it "generates expected code for structures with default overrides" $ do collectResults (runTsBackend id [stdsrc] ["test3/input/test.adl"] "test3/ts-output") @@ -422,10 +425,10 @@ runTests = do describe "adlc rust backend" $ do it "generates expected code for an empty module" $ do - collectResults (runRsBackend [stdsrc] ["test1/input/test.adl"] "test1/rs-output" "test1::adl") + collectResults (runRsBackend [stdsrc] [testsrc "test1/test1.adl"] "test1/rs-output" "test1::adl") `shouldReturn` MatchOutput it "generates expected output for various structures" $ - collectResults (runRsBackend [stdsrc] ["test2/input/test.adl"] "test2/rs-output" "test2::adl") + collectResults (runRsBackend [stdsrc] [testsrc "test2/test2.adl"] "test2/rs-output" "test2::adl") `shouldReturn` MatchOutput it "generates expected code for structures with default overrides" $ do collectResults (runRsBackend [stdsrc] ["test3/input/test.adl"] "test3/rs-output" "test3::adl") diff --git a/haskell/compiler/tests/demo1/rs-output/demo1/adl/picture.rs b/haskell/compiler/tests/demo1/rs-output/demo1/adl/picture.rs index a6cf6399..ffe210d5 100644 --- a/haskell/compiler/tests/demo1/rs-output/demo1/adl/picture.rs +++ b/haskell/compiler/tests/demo1/rs-output/demo1/adl/picture.rs @@ -3,7 +3,7 @@ use serde::Deserialize; use serde::Serialize; -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub enum Picture { #[serde(rename="circle")] Circle(Circle), @@ -18,7 +18,7 @@ pub enum Picture { Translated(Box>), } -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub struct Circle { pub radius: f64, } @@ -31,7 +31,7 @@ impl Circle { } } -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub struct Rectangle { pub width: f64, @@ -47,7 +47,7 @@ impl Rectangle { } } -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub struct Translated { #[serde(default="Translated::::def_xoffset")] pub xoffset: f64, diff --git a/haskell/compiler/tests/test14/rs-output/test14/adl/test14.rs b/haskell/compiler/tests/test14/rs-output/test14/adl/test14.rs index 74f22d5b..0428b197 100644 --- a/haskell/compiler/tests/test14/rs-output/test14/adl/test14.rs +++ b/haskell/compiler/tests/test14/rs-output/test14/adl/test14.rs @@ -5,7 +5,7 @@ use serde::Deserializer; use serde::Serialize; use serde::Serializer; -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub struct Switch { pub double: f64, @@ -32,7 +32,7 @@ impl Switch { } } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum Unsigned { #[serde(rename="null")] Null, diff --git a/haskell/compiler/tests/test18/rs-output/test18/adl/test18.rs b/haskell/compiler/tests/test18/rs-output/test18/adl/test18.rs index 0a2aa1f3..91c26868 100644 --- a/haskell/compiler/tests/test18/rs-output/test18/adl/test18.rs +++ b/haskell/compiler/tests/test18/rs-output/test18/adl/test18.rs @@ -3,7 +3,7 @@ use serde::Deserialize; use serde::Serialize; -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub enum X1 { #[serde(rename="f1")] F1(f64), @@ -12,7 +12,7 @@ pub enum X1 { F2(Box), } -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub enum Y1 { #[serde(rename="f1")] F1(String), @@ -21,7 +21,7 @@ pub enum Y1 { F2(Box), } -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub struct X2 { #[serde(rename="f1")] pub f_1: f64, @@ -39,7 +39,7 @@ impl X2 { } } -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub struct Y2 { #[serde(rename="f1")] pub f_1: String, diff --git a/haskell/compiler/tests/test19/input/test.adl b/haskell/compiler/tests/test19/input/test.adl deleted file mode 100644 index 2254a902..00000000 --- a/haskell/compiler/tests/test19/input/test.adl +++ /dev/null @@ -1,20 +0,0 @@ -module test -{ -struct Pair -{ - A a; - B b; -}; - -// OK: -newtype T1 = Pair; - -// OK: -newtype T2 = Pair; - -// ERROR: Incorrect number of arguments -newtype T3 = Pair; - -// ERROR: Type parameters should never take arguments -type I = X; -}; diff --git a/haskell/compiler/tests/test2/rs-output/test2/adl/test2.rs b/haskell/compiler/tests/test2/rs-output/test2/adl/test2.rs index 835ce91c..38fdc8ea 100644 --- a/haskell/compiler/tests/test2/rs-output/test2/adl/test2.rs +++ b/haskell/compiler/tests/test2/rs-output/test2/adl/test2.rs @@ -6,7 +6,7 @@ use serde::Serialize; /** * An empty structure. */ -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct S0 { } @@ -21,7 +21,7 @@ impl S0 { * A structure containing primitives. * It has two fields: an integer x and a String y. */ -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct S1 { pub x: i32, @@ -40,7 +40,7 @@ impl S1 { /** * A structure containing a vector. */ -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub struct S2 { #[serde(rename="f1")] pub f_1: String, @@ -65,7 +65,7 @@ impl S2 { /** * A generic structure. */ -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub struct S3 { #[serde(rename="f1")] pub f_1: String, @@ -91,7 +91,7 @@ impl S3 { } } -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub struct S4 { #[serde(rename="f1")] pub f_1: S3, @@ -109,7 +109,7 @@ impl S4 { } } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct Tree { pub value: T, diff --git a/haskell/compiler/tests/test20/rs-output/test20/adl/test20.rs b/haskell/compiler/tests/test20/rs-output/test20/adl/test20.rs index fa34cf0e..173eab7c 100644 --- a/haskell/compiler/tests/test20/rs-output/test20/adl/test20.rs +++ b/haskell/compiler/tests/test20/rs-output/test20/adl/test20.rs @@ -3,7 +3,7 @@ use serde::Deserialize; use serde::Serialize; -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum Role { #[serde(rename="u")] Underling, @@ -15,7 +15,7 @@ pub enum Role { SuperBoss, } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct Person { #[serde(rename="fn")] pub first_name: String, diff --git a/haskell/compiler/tests/test29/rs-output/test29/adl/test29.rs b/haskell/compiler/tests/test29/rs-output/test29/adl/test29.rs index 724dee9b..572d162a 100644 --- a/haskell/compiler/tests/test29/rs-output/test29/adl/test29.rs +++ b/haskell/compiler/tests/test29/rs-output/test29/adl/test29.rs @@ -6,7 +6,7 @@ use serde::Serialize; /** * An example with weird "quoting" conventions, designed to break things */ -#[derive(Clone,Deserialize,Eq,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,PartialEq,Serialize)] pub struct Test { /** * "foo" as a field diff --git a/haskell/compiler/tests/test3/rs-output/test3/adl/test3.rs b/haskell/compiler/tests/test3/rs-output/test3/adl/test3.rs index 3839a7ca..a34a87c8 100644 --- a/haskell/compiler/tests/test3/rs-output/test3/adl/test3.rs +++ b/haskell/compiler/tests/test3/rs-output/test3/adl/test3.rs @@ -5,7 +5,7 @@ use serde::Deserialize; use serde::Serialize; use serde_json; -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct A { pub f_int: i16, @@ -29,7 +29,7 @@ impl A { } } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct XY { pub x: T, @@ -45,7 +45,7 @@ impl XY { } } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct B { pub f_t: T, @@ -67,7 +67,7 @@ impl B { } } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum U { #[serde(rename="f_int")] FInt(i16), @@ -79,7 +79,7 @@ pub enum U { FVoid, } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum E { #[serde(rename="v1")] V1, @@ -88,7 +88,7 @@ pub enum E { V2, } -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub struct S { #[serde(default="S::::def_f_void")] pub f_void: (), diff --git a/haskell/compiler/tests/test4/rs-output/test4/adl/sys/types.rs b/haskell/compiler/tests/test4/rs-output/test4/adl/sys/types.rs index d826c32c..8e03d5ca 100644 --- a/haskell/compiler/tests/test4/rs-output/test4/adl/sys/types.rs +++ b/haskell/compiler/tests/test4/rs-output/test4/adl/sys/types.rs @@ -3,7 +3,7 @@ use serde::Deserialize; use serde::Serialize; -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum Either { #[serde(rename="left")] Left(T1), diff --git a/haskell/compiler/tests/test4/rs-output/test4/adl/test4.rs b/haskell/compiler/tests/test4/rs-output/test4/adl/test4.rs index 1d80f7b5..fa84ecde 100644 --- a/haskell/compiler/tests/test4/rs-output/test4/adl/test4.rs +++ b/haskell/compiler/tests/test4/rs-output/test4/adl/test4.rs @@ -12,7 +12,7 @@ use crate::test4::customtypes::datehelpers; use serde::Deserialize; use serde::Serialize; -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct CDate0 { pub year: i16, diff --git a/haskell/compiler/tests/test5/rs-output/test5/adl/test5.rs b/haskell/compiler/tests/test5/rs-output/test5/adl/test5.rs index a47d7dcc..9d22aa13 100644 --- a/haskell/compiler/tests/test5/rs-output/test5/adl/test5.rs +++ b/haskell/compiler/tests/test5/rs-output/test5/adl/test5.rs @@ -3,25 +3,25 @@ use serde::Deserialize; use serde::Serialize; -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum U1 { #[serde(rename="v")] V, } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum U2 { #[serde(rename="v")] V(i16), } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum U3 { #[serde(rename="v")] V(i16), } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct S1 { #[serde(default="S1::def_f")] pub f: i16, @@ -39,31 +39,31 @@ impl S1 { } } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum U4 { #[serde(rename="v")] V(S1), } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum U5 { #[serde(rename="v")] V(S1), } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum U6 { #[serde(rename="v")] V(U3), } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum U7 { #[serde(rename="v")] V(U3), } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum U8 { #[serde(rename="v1")] V1(S1), @@ -72,7 +72,7 @@ pub enum U8 { V2(i16), } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum U9 { #[serde(rename="v1")] V1(T), @@ -84,7 +84,7 @@ pub enum U9 { V3, } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct S { #[serde(default="S::def_f_1")] #[serde(rename="f1")] @@ -121,7 +121,7 @@ impl S { } } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum List { #[serde(rename="null")] Null, @@ -130,7 +130,7 @@ pub enum List { Cell(Cell), } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct Cell { pub head: T, @@ -146,7 +146,7 @@ impl Cell { } } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum U10 { #[serde(rename="v1")] V1(i16), @@ -155,7 +155,7 @@ pub enum U10 { V2, } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct S10 { #[serde(default="S10::def_f_1")] #[serde(rename="f1")] @@ -201,7 +201,7 @@ impl S10 { } } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum U11 { #[serde(rename="VALUE1")] V1(i16), @@ -210,7 +210,7 @@ pub enum U11 { V2, } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct S11 { #[serde(default="S11::def_f_1")] #[serde(rename="f1")] diff --git a/haskell/compiler/tests/test6/rs-output/test6/adl/sys/adlast.rs b/haskell/compiler/tests/test6/rs-output/test6/adl/sys/adlast.rs index 8dfa387a..b8b1b89a 100644 --- a/haskell/compiler/tests/test6/rs-output/test6/adl/sys/adlast.rs +++ b/haskell/compiler/tests/test6/rs-output/test6/adl/sys/adlast.rs @@ -11,7 +11,7 @@ pub type Ident = String; pub type Annotations = Map; -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct ScopedName { #[serde(rename="moduleName")] pub module_name: ModuleName, @@ -28,7 +28,7 @@ impl ScopedName { } } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum TypeRef { #[serde(rename="primitive")] Primitive(Ident), @@ -40,7 +40,7 @@ pub enum TypeRef { Reference(ScopedName), } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct TypeExpr { #[serde(rename="typeRef")] pub type_ref: TypeRef, @@ -57,7 +57,7 @@ impl TypeExpr { } } -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub struct Field { pub name: Ident, @@ -84,7 +84,7 @@ impl Field { } } -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub struct Struct { #[serde(rename="typeParams")] pub type_params: Vec, @@ -101,7 +101,7 @@ impl Struct { } } -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub struct Union { #[serde(rename="typeParams")] pub type_params: Vec, @@ -118,7 +118,7 @@ impl Union { } } -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct TypeDef { #[serde(rename="typeParams")] pub type_params: Vec, @@ -136,7 +136,7 @@ impl TypeDef { } } -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub struct NewType { #[serde(rename="typeParams")] pub type_params: Vec, @@ -157,7 +157,7 @@ impl NewType { } } -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub enum DeclType { #[serde(rename="struct_")] Struct(Struct), @@ -172,7 +172,7 @@ pub enum DeclType { Newtype(NewType), } -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub struct Decl { pub name: Ident, @@ -195,7 +195,7 @@ impl Decl { } } -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub struct ScopedDecl { #[serde(rename="moduleName")] pub module_name: ModuleName, @@ -214,7 +214,7 @@ impl ScopedDecl { pub type DeclVersions = Vec; -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum Import { #[serde(rename="moduleName")] ModuleName(ModuleName), @@ -223,7 +223,7 @@ pub enum Import { ScopedName(ScopedName), } -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub struct Module { pub name: ModuleName, diff --git a/haskell/compiler/tests/test6/rs-output/test6/adl/sys/dynamic.rs b/haskell/compiler/tests/test6/rs-output/test6/adl/sys/dynamic.rs index c5e920ef..0a45b90e 100644 --- a/haskell/compiler/tests/test6/rs-output/test6/adl/sys/dynamic.rs +++ b/haskell/compiler/tests/test6/rs-output/test6/adl/sys/dynamic.rs @@ -7,7 +7,7 @@ use serde::Serialize; /** * A serialised value along with its type */ -#[derive(Clone,Deserialize,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] pub struct Dynamic { #[serde(rename="typeExpr")] pub type_expr: TypeExpr, diff --git a/haskell/compiler/tests/test6/rs-output/test6/adl/sys/types.rs b/haskell/compiler/tests/test6/rs-output/test6/adl/sys/types.rs index d826c32c..8e03d5ca 100644 --- a/haskell/compiler/tests/test6/rs-output/test6/adl/sys/types.rs +++ b/haskell/compiler/tests/test6/rs-output/test6/adl/sys/types.rs @@ -3,7 +3,7 @@ use serde::Deserialize; use serde::Serialize; -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub enum Either { #[serde(rename="left")] Left(T1), diff --git a/haskell/compiler/tests/test7/rs-output/test7/adl/test7.rs b/haskell/compiler/tests/test7/rs-output/test7/adl/test7.rs index 412ef837..214f6c90 100644 --- a/haskell/compiler/tests/test7/rs-output/test7/adl/test7.rs +++ b/haskell/compiler/tests/test7/rs-output/test7/adl/test7.rs @@ -6,7 +6,7 @@ use serde::Serialize; use serde::Serializer; use std::marker::PhantomData; -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct Point { pub x: T, @@ -302,7 +302,7 @@ impl<'de, X> Deserialize<'de> for Point2 pub type IntPoint1A = IntPoint1; -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct S { #[serde(rename="f1")] pub f_1: IntPoint1A, diff --git a/haskell/tools/scratch-build.sh b/haskell/tools/scratch-build.sh index 218485f2..2220b4c0 100755 --- a/haskell/tools/scratch-build.sh +++ b/haskell/tools/scratch-build.sh @@ -10,49 +10,71 @@ adlcb () { stack exec adlc-bootstrap -- haskell --package=ADL --no-overwrite -I$ADL_STDLIB_DIR "$@" } -# Start clean, and build the bootstrap compiler -stack clean -stack build --flag adl-compiler:bootstrap adl-compiler:adlc-bootstrap - -# Generate the haskell code for the per-language annotation types -adlcb -I $CONFIG_ADL_DIR -O compiler/adlc-lib1 $CONFIG_ADL_DIR/haskell.adl -adlcb -I $CONFIG_ADL_DIR -O compiler/adlc-lib1 $CONFIG_ADL_DIR/cpp.adl -adlcb -I $CONFIG_ADL_DIR -O compiler/adlc-lib1 $CONFIG_ADL_DIR/java.adl -adlcb -I $CONFIG_ADL_DIR -O compiler/adlc-lib1 $CONFIG_ADL_DIR/typescript.adl -adlcb -I $CONFIG_ADL_DIR -O compiler/adlc-lib1 $CONFIG_ADL_DIR/rust.adl - -# Generate ADL specified elements of the haskell runtime -adlcb -O runtime/src $ADL_STDLIB_DIR/sys/types.adl -adlcb -O runtime/src $ADL_STDLIB_DIR/sys/adlast.adl - -# Build and test the compiler itself -stack build --test adl-compiler - -# Generate ADL specified elements of the typescript runtime -# these are in the style "template" so they can be converted -# to tsc or deno style later -stack exec adlc -- typescript \ - --no-overwrite \ - --exclude-ast \ - --verbose \ - --ts-style template \ - -O ../typescript/runtime \ - -I $ADL_STDLIB_DIR \ - $ADL_STDLIB_DIR/sys/types.adl $ADL_STDLIB_DIR/sys/adlast.adl $ADL_STDLIB_DIR/sys/dynamic.adl - -# Generate ADL specified elements of the c++ runtime -CPP_RUNTIME_DIR=../cpp/runtime/src-generated -stack exec adlc -- cpp \ - --no-overwrite \ - --verbose \ - --include-prefix adl \ - -O $CPP_RUNTIME_DIR \ - -I $ADL_STDLIB_DIR \ - $ADL_STDLIB_DIR/sys/types.adl $ADL_STDLIB_DIR/sys/adlast.adl $ADL_STDLIB_DIR/sys/dynamic.adl - -# Run some tests for each target language -stack build generated-tests -(cd ../typescript/tests; ./run-tests.sh) -(cd ../java; gradle build; gradle test) -(cd ../rust/tests; cargo build; cargo test) -(cd ../cpp/tests; ./run-tests.sh) +build_adlc () { + # Start clean, and build the bootstrap compiler + stack clean + stack build --flag adl-compiler:bootstrap adl-compiler:adlc-bootstrap + + # Generate the haskell code for the per-language annotation types + adlcb -I $CONFIG_ADL_DIR -O compiler/adlc-lib1 $CONFIG_ADL_DIR/haskell.adl + adlcb -I $CONFIG_ADL_DIR -O compiler/adlc-lib1 $CONFIG_ADL_DIR/cpp.adl + adlcb -I $CONFIG_ADL_DIR -O compiler/adlc-lib1 $CONFIG_ADL_DIR/java.adl + adlcb -I $CONFIG_ADL_DIR -O compiler/adlc-lib1 $CONFIG_ADL_DIR/typescript.adl + adlcb -I $CONFIG_ADL_DIR -O compiler/adlc-lib1 $CONFIG_ADL_DIR/rust.adl + + # Generate ADL specified elements of the haskell runtime + adlcb -O runtime/src $ADL_STDLIB_DIR/sys/types.adl + adlcb -O runtime/src $ADL_STDLIB_DIR/sys/adlast.adl + + # Build and test the compiler itself + stack build --test adl-compiler +} + +build_runtimes() { + # Generate ADL specified elements of the typescript runtime + # these are in the style "template" so they can be converted + # to tsc or deno style later + stack exec adlc -- typescript \ + --no-overwrite \ + --exclude-ast \ + --verbose \ + --ts-style template \ + -O ../typescript/runtime \ + -I $ADL_STDLIB_DIR \ + $ADL_STDLIB_DIR/sys/types.adl $ADL_STDLIB_DIR/sys/adlast.adl $ADL_STDLIB_DIR/sys/dynamic.adl + + # Generate ADL specified elements of the c++ runtime + CPP_RUNTIME_DIR=../cpp/runtime/src-generated + stack exec adlc -- cpp \ + --no-overwrite \ + --verbose \ + --include-prefix adl \ + -O $CPP_RUNTIME_DIR \ + -I $ADL_STDLIB_DIR \ + $ADL_STDLIB_DIR/sys/types.adl $ADL_STDLIB_DIR/sys/adlast.adl $ADL_STDLIB_DIR/sys/dynamic.adl + + # Generate ADL modules for the rust compiler tooling + stack exec adlc -- rust \ + --no-overwrite \ + --verbose \ + --generate-transitive \ + --outputdir ../rust/compiler/src \ + --module adlgen \ + --runtime-module adlrt \ + --include-rt \ + --searchdir $ADL_STDLIB_DIR \ + $ADL_STDLIB_DIR/sys/adlast2.adl +} + +run_tests() { + # Run some tests for each target language + stack build generated-tests + (cd ../typescript/tests; ./run-tests.sh) + (cd ../java; gradle build; gradle test) + (cd ../rust/tests; cargo build; cargo test) + (cd ../cpp/tests; ./run-tests.sh) +} + +# build_adlc +build_runtimes +# run_tests diff --git a/rust/compiler/.gitignore b/rust/compiler/.gitignore new file mode 100644 index 00000000..9f970225 --- /dev/null +++ b/rust/compiler/.gitignore @@ -0,0 +1 @@ +target/ \ No newline at end of file diff --git a/rust/compiler/Cargo.toml b/rust/compiler/Cargo.toml new file mode 100644 index 00000000..bdb33c7a --- /dev/null +++ b/rust/compiler/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "compiler" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[[bin]] +name = "radlc" +path = "src/main.rs" + +[dependencies] +anyhow = "1.0.61" +clap = { version = "4.1.4", features = ["derive"] } +serde = { version = "1.0.130", features=["derive"] } +serde_json = "1.0.68" +nom = "7.0.0" +nom_locate = "4.0.0" +env_logger = "0.10.0" +log = "0.4.17" +genco = "0.17.3" +convert_case = "0.6.0" +backtrace-on-stack-overflow = "0.3.0" +regex = "1.7.3" +rust-embed = "6.6.1" +serde_ignored = "0.1.7" diff --git a/rust/compiler/Readme.md b/rust/compiler/Readme.md new file mode 100644 index 00000000..82b13d13 --- /dev/null +++ b/rust/compiler/Readme.md @@ -0,0 +1,44 @@ +# Developer notes + +This document is for notes when developing this module. + +## Useful commands + + +### Generate TS for all ADL specified in `adl/tests/testing_table.json` +``` +cargo +nightly test --package compiler --lib -- cli::tsgen::tests::generate_ts_from_test_files --exact --nocapture +``` + +### Generate TS for a specified ADL module + +``` +cargo +nightly run tsgen --searchdir ../../adl/stdlib --searchdir ../../adl/tests/test3 --outdir ts-src --manifest ts-src/manifest.json --capitalize-branch-names-in-types test3 +``` + +### Generate an AST using `adlc` and `cargo run`, sort the JSON and compare in VSCODE. +``` +cargo +nightly run ast --searchdir ../../adl/stdlib --searchdir ../../adl/tests/test30 test30_04 | jq -S . > build/ast/test30_04.rust.sorted.ast.json +adlc ast --searchdir ../../adl/stdlib --searchdir ../../adl/tests/test4 --combined-output=build/ast/test30_04.adlc.ast.json ../../adl/tests/test30/test30_04.adl +cd build/ast +jq -S . test30_04.adlc.ast.json > test30_04.adlc.sorted.ast.json +code -d test30_04.adlc.sorted.ast.json test30_04.rust.sorted.ast.json +``` + +### Testing Workspace Gen +``` +cargo +nightly run gen ../../adl/tests/test31/proj + +cargo +nightly run gen -f adl.work1.json ../../adl/tests/test31/proj + +cargo +nightly run gen -f adl.work2.json ../../adl/tests/test31/proj + +cargo +nightly run gen -f adl.work3.json ../../adl/tests/test31/proj +``` + +### Cross compile for linux from mac + +``` +rustup target add x86_64-unknown-linux-musl +RUSTFLAGS="-Clink-self-contained=yes -Clinker=rust-lld" cargo build --release --target x86_64-unknown-linux-musl +``` \ No newline at end of file diff --git a/rust/compiler/genadl.sh b/rust/compiler/genadl.sh new file mode 100755 index 00000000..639e4c96 --- /dev/null +++ b/rust/compiler/genadl.sh @@ -0,0 +1,29 @@ +#!/bin/bash -xe + +RUST_COMPILER_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )" +cd $RUST_COMPILER_DIR + +ADL_STDLIB_DIR=../../haskell/compiler/lib/adl + +adlc rust \ + --no-overwrite \ + --verbose \ + --generate-transitive \ + --outputdir ./src \ + --module adlgen \ + --runtime-module adlrt \ + --include-rt \ + --searchdir $ADL_STDLIB_DIR \ + $ADL_STDLIB_DIR/sys/adlast2.adl $ADL_STDLIB_DIR/adlc/adlc/packaging.adl $ADL_STDLIB_DIR/adlc/adlc/testing_table.adl + +# ADL_DIR=../../adl + +# adlc rust \ +# --no-overwrite \ +# --verbose \ +# --generate-transitive \ +# --outputdir ./src \ +# --module adlgen_dev \ +# --runtime-module adlrt \ +# --searchdir $ADL_DIR/stdlib \ +# $ADL_DIR/adlc/adlc/testing_table.adl diff --git a/rust/compiler/src/adlgen/adlc/config/mod.rs b/rust/compiler/src/adlgen/adlc/config/mod.rs new file mode 100644 index 00000000..1671ed04 --- /dev/null +++ b/rust/compiler/src/adlgen/adlc/config/mod.rs @@ -0,0 +1 @@ +pub mod rust; \ No newline at end of file diff --git a/rust/compiler/src/adlgen/adlc/config/rust.rs b/rust/compiler/src/adlgen/adlc/config/rust.rs new file mode 100644 index 00000000..218e3157 --- /dev/null +++ b/rust/compiler/src/adlgen/adlc/config/rust.rs @@ -0,0 +1,62 @@ +// @generated from adl module adlc.config.rust + +use serde::Deserialize; +use serde::Serialize; + +/** + * ADL module or declaration annotation to control + * whether code is actually generated. + */ +pub type RustGenerate = bool; + +/** + * ADL field annotation giving explicit control over + * how a field should be stored. + */ +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub enum RustStorageModel { + /** + * Standard inline storage + */ + #[serde(rename="standard")] + Standard, + + /** + * Store the value in a Box<> + */ + #[serde(rename="boxed")] + Boxed, +} + +/** + * ADL declaration annotation to specify that a custom type + * should be used + */ +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct RustCustomType { + pub rustname: String, + + pub helpers: String, + + #[serde(default="RustCustomType::def_generate_orig_adl_type")] + #[serde(rename="generateOrigADLType")] + pub generate_orig_adl_type: String, + + #[serde(rename="stdTraits")] + pub std_traits: Vec, +} + +impl RustCustomType { + pub fn new(rustname: String, helpers: String, std_traits: Vec) -> RustCustomType { + RustCustomType { + rustname: rustname, + helpers: helpers, + generate_orig_adl_type: RustCustomType::def_generate_orig_adl_type(), + std_traits: std_traits, + } + } + + pub fn def_generate_orig_adl_type() -> String { + "".to_string() + } +} diff --git a/rust/compiler/src/adlgen/adlc/mod.rs b/rust/compiler/src/adlgen/adlc/mod.rs new file mode 100644 index 00000000..cbf8cac6 --- /dev/null +++ b/rust/compiler/src/adlgen/adlc/mod.rs @@ -0,0 +1,3 @@ +pub mod config; +pub mod packaging; +pub mod testing_table; \ No newline at end of file diff --git a/rust/compiler/src/adlgen/adlc/packaging.rs b/rust/compiler/src/adlgen/adlc/packaging.rs new file mode 100644 index 00000000..d5233c46 --- /dev/null +++ b/rust/compiler/src/adlgen/adlc/packaging.rs @@ -0,0 +1,842 @@ +// @generated from adl module adlc.packaging + +use crate::adlgen::sys::adlast2::Module1; +use crate::adlgen::sys::adlast2::ScopedName; +use crate::adlrt::custom::sys::types::pair::Pair; +use serde::Deserialize; +use serde::Serialize; + +pub type AdlWorkspace0 = AdlWorkspace; + +pub type AdlWorkspace1 = AdlWorkspace; + +pub type AdlWorkspace2 = AdlWorkspace; + +pub type LoaderWorkspace = AdlWorkspace; + +pub type Payload0 = AdlPackageRef; + +#[derive(Clone,Debug,Deserialize,Eq,PartialEq,Serialize)] +pub struct Payload1 { + pub p_ref: AdlPackageRef, + + pub pkg: AdlPackage, +} + +impl Payload1 { + pub fn new(p_ref: AdlPackageRef, pkg: AdlPackage) -> Payload1 { + Payload1 { + p_ref: p_ref, + pkg: pkg, + } + } +} + +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] +pub struct Payload2 { + pub p_ref: AdlPackageRef, + + pub pkg: AdlPackage, + + pub modules: Vec, +} + +impl Payload2 { + pub fn new(p_ref: AdlPackageRef, pkg: AdlPackage, modules: Vec) -> Payload2 { + Payload2 { + p_ref: p_ref, + pkg: pkg, + modules: modules, + } + } +} + +/** + * Expected to live in a file named `adl.work.json` + */ +#[derive(Clone,Debug,Deserialize,Eq,PartialEq,Serialize)] +pub struct AdlWorkspace { + pub adlc: String, + + #[serde(rename="use")] + pub r#use: Vec, + + #[serde(default="AdlWorkspace::::def_named_options")] + pub named_options: std::collections::HashMap, + + #[serde(default="AdlWorkspace::::def_runtimes")] + pub runtimes: Vec, +} + +impl AdlWorkspace { + pub fn new(adlc: String, r#use: Vec) -> AdlWorkspace { + AdlWorkspace { + adlc: adlc, + r#use: r#use, + named_options: AdlWorkspace::::def_named_options(), + runtimes: AdlWorkspace::::def_runtimes(), + } + } + + pub fn def_named_options() -> std::collections::HashMap { + [].iter().cloned().collect() + } + + pub fn def_runtimes() -> Vec { + vec![] + } +} + +#[derive(Clone,Debug,Deserialize,Eq,PartialEq,Serialize)] +pub struct NamedOpts { + #[serde(default="NamedOpts::def_ts_opts")] + pub ts_opts: TsNamedOpts, +} + +impl NamedOpts { + pub fn new() -> NamedOpts { + NamedOpts { + ts_opts: NamedOpts::def_ts_opts(), + } + } + + pub fn def_ts_opts() -> TsNamedOpts { + TsNamedOpts{runtime_opts : None, scripts : None, dependencies : None, dev_dependencies : None, tsconfig : None} + } +} + +#[derive(Clone,Debug,Deserialize,Eq,PartialEq,Serialize)] +pub struct TsNamedOpts { + #[serde(default="TsNamedOpts::def_runtime_opts")] + pub runtime_opts: Option, + + #[serde(default="TsNamedOpts::def_scripts")] + pub scripts: Option>, + + #[serde(default="TsNamedOpts::def_dependencies")] + pub dependencies: Option>, + + #[serde(default="TsNamedOpts::def_dev_dependencies")] + pub dev_dependencies: Option>, + + #[serde(default="TsNamedOpts::def_tsconfig")] + pub tsconfig: Option, +} + +impl TsNamedOpts { + pub fn new() -> TsNamedOpts { + TsNamedOpts { + runtime_opts: TsNamedOpts::def_runtime_opts(), + scripts: TsNamedOpts::def_scripts(), + dependencies: TsNamedOpts::def_dependencies(), + dev_dependencies: TsNamedOpts::def_dev_dependencies(), + tsconfig: TsNamedOpts::def_tsconfig(), + } + } + + pub fn def_runtime_opts() -> Option { + None + } + + pub fn def_scripts() -> Option> { + None + } + + pub fn def_dependencies() -> Option> { + None + } + + pub fn def_dev_dependencies() -> Option> { + None + } + + pub fn def_tsconfig() -> Option { + None + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub enum RuntimeOpts { + #[serde(rename="ts_runtime")] + TsRuntime(TsWriteRuntime), +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct TsWriteRuntime { + pub output_dir: String, + + #[serde(default="TsWriteRuntime::def_referenceable")] + pub referenceable: ReferenceableScopeOption, + + #[serde(default="TsWriteRuntime::def_npm_pkg_name")] + pub npm_pkg_name: String, + + #[serde(default="TsWriteRuntime::def_ts_style")] + pub ts_style: TsStyle, +} + +impl TsWriteRuntime { + pub fn new(output_dir: String) -> TsWriteRuntime { + TsWriteRuntime { + output_dir: output_dir, + referenceable: TsWriteRuntime::def_referenceable(), + npm_pkg_name: TsWriteRuntime::def_npm_pkg_name(), + ts_style: TsWriteRuntime::def_ts_style(), + } + } + + pub fn def_referenceable() -> ReferenceableScopeOption { + ReferenceableScopeOption::Local + } + + pub fn def_npm_pkg_name() -> String { + "@adl-lang/runtime".to_string() + } + + pub fn def_ts_style() -> TsStyle { + TsStyle::Tsc + } +} + +/** + * The struct in AdlWorkspace::use required by the WorkspaceLoader + */ +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] +pub struct LoaderRef { + #[serde(rename="ref")] + pub r#ref: LoaderRefType, + + #[serde(default="LoaderRef::def_loader_inject_annotate")] + pub loader_inject_annotate: InjectAnnotations, + + #[serde(default="LoaderRef::def_resolver_inject_annotate")] + pub resolver_inject_annotate: InjectAnnotations, +} + +impl LoaderRef { + pub fn new(r#ref: LoaderRefType) -> LoaderRef { + LoaderRef { + r#ref: r#ref, + loader_inject_annotate: LoaderRef::def_loader_inject_annotate(), + resolver_inject_annotate: LoaderRef::def_resolver_inject_annotate(), + } + } + + pub fn def_loader_inject_annotate() -> InjectAnnotations { + vec![] + } + + pub fn def_resolver_inject_annotate() -> InjectAnnotations { + vec![] + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub enum LoaderRefType { + #[serde(rename="dir")] + Dir(DirLoaderRef), + + #[serde(rename="embedded")] + Embedded(EmbeddedLoaderRef), +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct DirLoaderRef { + pub path: String, + + #[serde(default="DirLoaderRef::def_global_alias")] + pub global_alias: Option, +} + +impl DirLoaderRef { + pub fn new(path: String) -> DirLoaderRef { + DirLoaderRef { + path: path, + global_alias: DirLoaderRef::def_global_alias(), + } + } + + pub fn def_global_alias() -> Option { + None + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct EmbeddedLoaderRef { + pub alias: EmbeddedPkg, +} + +impl EmbeddedLoaderRef { + pub fn new(alias: EmbeddedPkg) -> EmbeddedLoaderRef { + EmbeddedLoaderRef { + alias: alias, + } + } +} + +pub type InjectAnnotations = Vec; + +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] +pub enum InjectAnnotation { + #[serde(rename="module_")] + Module(Pair), +} + +#[derive(Clone,Debug,Deserialize,Eq,PartialEq,Serialize)] +pub struct AdlPackageRef { + #[serde(rename="ref")] + pub r#ref: AdlPackageRefType, + + #[serde(default="AdlPackageRef::def_named_opts")] + pub named_opts: Option, + + #[serde(default="AdlPackageRef::def_ts_opts")] + pub ts_opts: Option, +} + +impl AdlPackageRef { + pub fn new(r#ref: AdlPackageRefType) -> AdlPackageRef { + AdlPackageRef { + r#ref: r#ref, + named_opts: AdlPackageRef::def_named_opts(), + ts_opts: AdlPackageRef::def_ts_opts(), + } + } + + pub fn def_named_opts() -> Option { + None + } + + pub fn def_ts_opts() -> Option { + None + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub enum AdlPackageRefType { + #[serde(rename="dir")] + Dir(DirectoryRef), + + /** + * An ADL module embed in the ADL compiler + */ + #[serde(rename="embedded")] + Embedded(EmbeddedRef), +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct EmbeddedRef { + pub alias: EmbeddedPkg, +} + +impl EmbeddedRef { + pub fn new(alias: EmbeddedPkg) -> EmbeddedRef { + EmbeddedRef { + alias: alias, + } + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub enum EmbeddedPkg { + #[serde(rename="sys")] + Sys, + + #[serde(rename="adlc")] + Adlc, +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct DirectoryRef { + pub path: String, +} + +impl DirectoryRef { + pub fn new(path: String) -> DirectoryRef { + DirectoryRef { + path: path, + } + } +} + +#[derive(Clone,Debug,Deserialize,Eq,PartialEq,Serialize)] +pub struct TypescriptGenOptions { + pub npm_pkg_name: String, + + #[serde(default="TypescriptGenOptions::def_npm_version")] + pub npm_version: String, + + #[serde(default="TypescriptGenOptions::def_extra_dependencies")] + pub extra_dependencies: std::collections::HashMap, + + #[serde(default="TypescriptGenOptions::def_extra_dev_dependencies")] + pub extra_dev_dependencies: std::collections::HashMap, + + #[serde(default="TypescriptGenOptions::def_outputs")] + pub outputs: Option, + + #[serde(default="TypescriptGenOptions::def_tsconfig")] + pub tsconfig: Option, + + #[serde(default="TypescriptGenOptions::def_scripts")] + pub scripts: std::collections::HashMap, + + #[serde(default="TypescriptGenOptions::def_runtime_opts")] + pub runtime_opts: TsRuntimeOpt, + + #[serde(default="TypescriptGenOptions::def_generate_transitive")] + pub generate_transitive: bool, + + #[serde(default="TypescriptGenOptions::def_include_resolver")] + pub include_resolver: bool, + + #[serde(default="TypescriptGenOptions::def_ts_style")] + pub ts_style: TsStyle, + + #[serde(default="TypescriptGenOptions::def_modules")] + pub modules: ModuleSrc, + + #[serde(default="TypescriptGenOptions::def_capitalize_branch_names_in_types")] + pub capitalize_branch_names_in_types: bool, + + #[serde(default="TypescriptGenOptions::def_capitalize_type_names")] + pub capitalize_type_names: bool, +} + +impl TypescriptGenOptions { + pub fn new(npm_pkg_name: String) -> TypescriptGenOptions { + TypescriptGenOptions { + npm_pkg_name: npm_pkg_name, + npm_version: TypescriptGenOptions::def_npm_version(), + extra_dependencies: TypescriptGenOptions::def_extra_dependencies(), + extra_dev_dependencies: TypescriptGenOptions::def_extra_dev_dependencies(), + outputs: TypescriptGenOptions::def_outputs(), + tsconfig: TypescriptGenOptions::def_tsconfig(), + scripts: TypescriptGenOptions::def_scripts(), + runtime_opts: TypescriptGenOptions::def_runtime_opts(), + generate_transitive: TypescriptGenOptions::def_generate_transitive(), + include_resolver: TypescriptGenOptions::def_include_resolver(), + ts_style: TypescriptGenOptions::def_ts_style(), + modules: TypescriptGenOptions::def_modules(), + capitalize_branch_names_in_types: TypescriptGenOptions::def_capitalize_branch_names_in_types(), + capitalize_type_names: TypescriptGenOptions::def_capitalize_type_names(), + } + } + + pub fn def_npm_version() -> String { + "1.0.0".to_string() + } + + pub fn def_extra_dependencies() -> std::collections::HashMap { + [].iter().cloned().collect() + } + + pub fn def_extra_dev_dependencies() -> std::collections::HashMap { + [].iter().cloned().collect() + } + + pub fn def_outputs() -> Option { + None + } + + pub fn def_tsconfig() -> Option { + None + } + + pub fn def_scripts() -> std::collections::HashMap { + [].iter().cloned().collect() + } + + pub fn def_runtime_opts() -> TsRuntimeOpt { + TsRuntimeOpt::PackageRef(NpmPackageRef{name : "@adl-lang/runtime".to_string(), version : "^1.0.0".to_string()}) + } + + pub fn def_generate_transitive() -> bool { + false + } + + pub fn def_include_resolver() -> bool { + false + } + + pub fn def_ts_style() -> TsStyle { + TsStyle::Tsc + } + + pub fn def_modules() -> ModuleSrc { + ModuleSrc::All + } + + pub fn def_capitalize_branch_names_in_types() -> bool { + true + } + + pub fn def_capitalize_type_names() -> bool { + true + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub enum TsRuntimeOpt { + #[serde(rename="workspace_ref")] + WorkspaceRef(String), + + #[serde(rename="package_ref")] + PackageRef(NpmPackageRef), + + #[serde(rename="generate")] + Generate(TsGenRuntime), +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct TsGenRuntime { +} + +impl TsGenRuntime { + pub fn new() -> TsGenRuntime { + TsGenRuntime { + } + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub enum OutputOpts { + #[serde(rename="gen")] + Gen(GenOutput), +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct GenOutput { + #[serde(default="GenOutput::def_referenceable")] + pub referenceable: ReferenceableScopeOption, + + pub output_dir: String, + + #[serde(default="GenOutput::def_manifest")] + pub manifest: Option, +} + +impl GenOutput { + pub fn new(output_dir: String) -> GenOutput { + GenOutput { + referenceable: GenOutput::def_referenceable(), + output_dir: output_dir, + manifest: GenOutput::def_manifest(), + } + } + + pub fn def_referenceable() -> ReferenceableScopeOption { + ReferenceableScopeOption::Local + } + + pub fn def_manifest() -> Option { + None + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub enum TsStyle { + #[serde(rename="tsc")] + Tsc, + + #[serde(rename="deno")] + Deno, +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub enum ModuleSrc { + #[serde(rename="all")] + All, + + #[serde(rename="modules")] + Modules(Vec), +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub enum ReferenceableScopeOption { + /** + * Generated code will only be referred internal to the repo + */ + #[serde(rename="local")] + Local, + + /** + * Generated code can be published via a package manager (e.g. npm) + */ + #[serde(rename="remote")] + Remote, +} + +/** + * Expected to live in a file named `adl.pkg.json` + */ +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct AdlPackage { + pub path: String, + + #[serde(default="AdlPackage::def_global_alias")] + pub global_alias: Option, + + /** + * Version + */ + pub adlc: String, + + #[serde(default="AdlPackage::def_requires")] + pub requires: Vec, + + #[serde(default="AdlPackage::def_excludes")] + pub excludes: Vec, + + #[serde(default="AdlPackage::def_replaces")] + pub replaces: Vec, + + #[serde(default="AdlPackage::def_retracts")] + pub retracts: Vec, +} + +impl AdlPackage { + pub fn new(path: String, adlc: String) -> AdlPackage { + AdlPackage { + path: path, + global_alias: AdlPackage::def_global_alias(), + adlc: adlc, + requires: AdlPackage::def_requires(), + excludes: AdlPackage::def_excludes(), + replaces: AdlPackage::def_replaces(), + retracts: AdlPackage::def_retracts(), + } + } + + pub fn def_global_alias() -> Option { + None + } + + pub fn def_requires() -> Vec { + vec![] + } + + pub fn def_excludes() -> Vec { + vec![] + } + + pub fn def_replaces() -> Vec { + vec![] + } + + pub fn def_retracts() -> Vec { + vec![] + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct PackageDirective { + pub path: String, + + #[serde(default="PackageDirective::def_repo")] + pub repo: Option, +} + +impl PackageDirective { + pub fn new(path: String) -> PackageDirective { + PackageDirective { + path: path, + repo: PackageDirective::def_repo(), + } + } + + pub fn def_repo() -> Option { + None + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct Require { + #[serde(rename="ref")] + pub r#ref: PkgRef, + + #[serde(default="Require::def_version")] + pub version: Option, + + #[serde(default="Require::def_indirect")] + pub indirect: bool, +} + +impl Require { + pub fn new(r#ref: PkgRef) -> Require { + Require { + r#ref: r#ref, + version: Require::def_version(), + indirect: Require::def_indirect(), + } + } + + pub fn def_version() -> Option { + None + } + + pub fn def_indirect() -> bool { + false + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub enum PkgRef { + #[serde(rename="path")] + Path(String), + + #[serde(rename="alias")] + Alias(String), +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct Exclude { + pub path: String, + + pub version: String, +} + +impl Exclude { + pub fn new(path: String, version: String) -> Exclude { + Exclude { + path: path, + version: version, + } + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct Replace { + pub path: String, + + pub version: Option, +} + +impl Replace { + pub fn new(path: String, version: Option) -> Replace { + Replace { + path: path, + version: version, + } + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct Retract { + pub version: String, + + #[serde(default="Retract::def_comment")] + pub comment: Option, +} + +impl Retract { + pub fn new(version: String) -> Retract { + Retract { + version: version, + comment: Retract::def_comment(), + } + } + + pub fn def_comment() -> Option { + None + } +} + +#[derive(Clone,Debug,Deserialize,Eq,PartialEq,Serialize)] +pub struct NpmPackage { + pub name: String, + + pub version: String, + + #[serde(default="NpmPackage::def_scripts")] + pub scripts: std::collections::HashMap, + + #[serde(default="NpmPackage::def_dependencies")] + pub dependencies: std::collections::HashMap, + + #[serde(default="NpmPackage::def_dev_dependencies")] + #[serde(rename="devDependencies")] + pub dev_dependencies: std::collections::HashMap, +} + +impl NpmPackage { + pub fn new(name: String, version: String) -> NpmPackage { + NpmPackage { + name: name, + version: version, + scripts: NpmPackage::def_scripts(), + dependencies: NpmPackage::def_dependencies(), + dev_dependencies: NpmPackage::def_dev_dependencies(), + } + } + + pub fn def_scripts() -> std::collections::HashMap { + [].iter().cloned().collect() + } + + pub fn def_dependencies() -> std::collections::HashMap { + [].iter().cloned().collect() + } + + pub fn def_dev_dependencies() -> std::collections::HashMap { + [].iter().cloned().collect() + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct TsConfig { + pub extends: Option, + + pub include: Vec, + + pub exclude: Vec, + + #[serde(rename="compilerOptions")] + pub compiler_options: TsCompilerOptions, +} + +impl TsConfig { + pub fn new(extends: Option, include: Vec, exclude: Vec, compiler_options: TsCompilerOptions) -> TsConfig { + TsConfig { + extends: extends, + include: include, + exclude: exclude, + compiler_options: compiler_options, + } + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct TsCompilerOptions { + #[serde(rename="outDir")] + pub out_dir: String, + + pub lib: Vec, +} + +impl TsCompilerOptions { + pub fn new(out_dir: String, lib: Vec) -> TsCompilerOptions { + TsCompilerOptions { + out_dir: out_dir, + lib: lib, + } + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct NpmPackageRef { + pub name: String, + + pub version: VersionSpec, +} + +impl NpmPackageRef { + pub fn new(name: String, version: VersionSpec) -> NpmPackageRef { + NpmPackageRef { + name: name, + version: version, + } + } +} + +pub type VersionSpec = String; diff --git a/rust/compiler/src/adlgen/adlc/testing_table.rs b/rust/compiler/src/adlgen/adlc/testing_table.rs new file mode 100644 index 00000000..d89ea0a6 --- /dev/null +++ b/rust/compiler/src/adlgen/adlc/testing_table.rs @@ -0,0 +1,81 @@ +// @generated from adl module adlc.testing_table + +use serde::Deserialize; +use serde::Serialize; + +pub type TestFilesMetaData = Vec; + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct TestFileMetaData { + pub module_root: String, + + #[serde(default="TestFileMetaData::def_lib_paths")] + pub lib_paths: Vec, + + /** + * If null then 'build/adlc_out/$module_root' is used + */ + #[serde(default="TestFileMetaData::def_output_dir")] + pub output_dir: Option, + + pub modules: Vec, + + #[serde(default="TestFileMetaData::def_fail")] + pub fail: bool, + + #[serde(default="TestFileMetaData::def_skip")] + pub skip: bool, + + #[serde(default="TestFileMetaData::def_title")] + pub title: String, + + #[serde(default="TestFileMetaData::def_description")] + pub description: Vec, + + #[serde(default="TestFileMetaData::def_keywords")] + pub keywords: Vec, +} + +impl TestFileMetaData { + pub fn new(module_root: String, modules: Vec) -> TestFileMetaData { + TestFileMetaData { + module_root: module_root, + lib_paths: TestFileMetaData::def_lib_paths(), + output_dir: TestFileMetaData::def_output_dir(), + modules: modules, + fail: TestFileMetaData::def_fail(), + skip: TestFileMetaData::def_skip(), + title: TestFileMetaData::def_title(), + description: TestFileMetaData::def_description(), + keywords: TestFileMetaData::def_keywords(), + } + } + + pub fn def_lib_paths() -> Vec { + vec![] + } + + pub fn def_output_dir() -> Option { + None + } + + pub fn def_fail() -> bool { + false + } + + pub fn def_skip() -> bool { + false + } + + pub fn def_title() -> String { + "".to_string() + } + + pub fn def_description() -> Vec { + vec![] + } + + pub fn def_keywords() -> Vec { + vec![] + } +} diff --git a/rust/compiler/src/adlgen/mod.rs b/rust/compiler/src/adlgen/mod.rs new file mode 100644 index 00000000..b9c64637 --- /dev/null +++ b/rust/compiler/src/adlgen/mod.rs @@ -0,0 +1,2 @@ +pub mod adlc; +pub mod sys; \ No newline at end of file diff --git a/rust/compiler/src/adlgen/sys/adlast2.rs b/rust/compiler/src/adlgen/sys/adlast2.rs new file mode 100644 index 00000000..df103107 --- /dev/null +++ b/rust/compiler/src/adlgen/sys/adlast2.rs @@ -0,0 +1,377 @@ +// @generated from adl module sys.adlast2 + +use crate::adlrt::custom::sys::types::map::Map; +use crate::adlrt::custom::sys::types::maybe::Maybe; +use serde::Deserialize; +use serde::Serialize; + +pub type ModuleName = String; + +pub type Ident = String; + +pub type Annotations = Map; + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct ScopedName { + #[serde(rename="moduleName")] + pub module_name: ModuleName, + + pub name: Ident, +} + +impl ScopedName { + pub fn new(module_name: ModuleName, name: Ident) -> ScopedName { + ScopedName { + module_name: module_name, + name: name, + } + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct TypeExpr { + #[serde(rename="typeRef")] + pub type_ref: R, + + pub parameters: Vec>, +} + +impl TypeExpr { + pub fn new(type_ref: R, parameters: Vec>) -> TypeExpr { + TypeExpr { + type_ref: type_ref, + parameters: parameters, + } + } +} + +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] +pub struct Field { + pub name: Ident, + + #[serde(rename="serializedName")] + pub serialized_name: Ident, + + #[serde(rename="typeExpr")] + pub type_expr: TE, + + pub default: Maybe, + + pub annotations: Annotations, +} + +impl Field { + pub fn new(name: Ident, serialized_name: Ident, type_expr: TE, default: Maybe, annotations: Annotations) -> Field { + Field { + name: name, + serialized_name: serialized_name, + type_expr: type_expr, + default: default, + annotations: annotations, + } + } +} + +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] +pub struct Struct { + #[serde(rename="typeParams")] + pub type_params: Vec, + + pub fields: Vec>, +} + +impl Struct { + pub fn new(type_params: Vec, fields: Vec>) -> Struct { + Struct { + type_params: type_params, + fields: fields, + } + } +} + +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] +pub struct Union { + #[serde(rename="typeParams")] + pub type_params: Vec, + + pub fields: Vec>, +} + +impl Union { + pub fn new(type_params: Vec, fields: Vec>) -> Union { + Union { + type_params: type_params, + fields: fields, + } + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct TypeDef { + #[serde(rename="typeParams")] + pub type_params: Vec, + + #[serde(rename="typeExpr")] + pub type_expr: TE, +} + +impl TypeDef { + pub fn new(type_params: Vec, type_expr: TE) -> TypeDef { + TypeDef { + type_params: type_params, + type_expr: type_expr, + } + } +} + +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] +pub struct NewType { + #[serde(rename="typeParams")] + pub type_params: Vec, + + #[serde(rename="typeExpr")] + pub type_expr: TE, + + pub default: Maybe, +} + +impl NewType { + pub fn new(type_params: Vec, type_expr: TE, default: Maybe) -> NewType { + NewType { + type_params: type_params, + type_expr: type_expr, + default: default, + } + } +} + +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] +pub enum DeclType { + #[serde(rename="struct_")] + Struct(Struct), + + #[serde(rename="union_")] + Union(Union), + + #[serde(rename="type_")] + Type(TypeDef), + + #[serde(rename="newtype_")] + Newtype(NewType), +} + +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] +pub struct Decl { + pub name: Ident, + + pub version: Maybe, + + #[serde(rename="type_")] + pub r#type: DeclType, + + pub annotations: Annotations, +} + +impl Decl { + pub fn new(name: Ident, version: Maybe, r#type: DeclType, annotations: Annotations) -> Decl { + Decl { + name: name, + version: version, + r#type: r#type, + annotations: annotations, + } + } +} + +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] +pub struct ScopedDecl { + #[serde(rename="moduleName")] + pub module_name: ModuleName, + + pub decl: Decl, +} + +impl ScopedDecl { + pub fn new(module_name: ModuleName, decl: Decl) -> ScopedDecl { + ScopedDecl { + module_name: module_name, + decl: decl, + } + } +} + +pub type DeclVersions = Vec>; + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub enum Import { + #[serde(rename="moduleName")] + ModuleName(ModuleName), + + #[serde(rename="scopedName")] + ScopedName(ScopedName), +} + +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] +pub struct Module { + pub name: ModuleName, + + pub imports: Vec, + + pub decls: Vec>, + + pub annotations: Annotations, +} + +impl Module { + pub fn new(name: ModuleName, imports: Vec, decls: Vec>, annotations: Annotations) -> Module { + Module { + name: name, + imports: imports, + decls: decls, + annotations: annotations, + } + } +} + +/** + * The Span start..end contains all values with start <= x < end. It is empty if start >= end. + */ +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct Span { + pub start: u64, + + pub end: u64, +} + +impl Span { + pub fn new(start: u64, end: u64) -> Span { + Span { + start: start, + end: end, + } + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct Spanned { + pub value: T, + + pub span: Span, +} + +impl Spanned { + pub fn new(value: T, span: Span) -> Spanned { + Spanned { + value: value, + span: span, + } + } +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub enum PrimitiveType { + Void, + + Bool, + + Int8, + + Int16, + + Int32, + + Int64, + + Word8, + + Word16, + + Word32, + + Word64, + + Float, + + Double, + + Json, + + ByteVector, + + String, + + Vector, + + StringMap, + + Nullable, + + TypeToken, +} + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub enum TypeRef { + #[serde(rename="scopedName")] + ScopedName(ScopedName), + + #[serde(rename="localName")] + LocalName(Ident), + + #[serde(rename="primitive")] + Primitive(PrimitiveType), + + #[serde(rename="typeParam")] + TypeParam(Ident), +} + +pub type TypeExpr0 = TypeExpr; + +pub type Field0 = Field; + +pub type Struct0 = Struct; + +pub type Union0 = Union; + +pub type DeclType0 = DeclType; + +pub type Decl0 = Decl; + +pub type Module0 = Module; + +pub type TypeExpr1 = TypeExpr; + +pub type Field1 = Field; + +pub type Struct1 = Struct; + +pub type Union1 = Union; + +pub type DeclType1 = DeclType; + +pub type Decl1 = Decl; + +pub type Module1 = Module; + +pub type AdlAst = std::collections::HashMap; + +#[derive(Clone,Debug,Deserialize,PartialEq,Serialize)] +pub struct AstModule { + pub name: ModuleName, + + pub imports: Vec, + + pub decls: std::collections::HashMap>, + + pub annotations: Annotations, +} + +impl AstModule { + pub fn new(name: ModuleName, imports: Vec, decls: std::collections::HashMap>, annotations: Annotations) -> AstModule { + AstModule { + name: name, + imports: imports, + decls: decls, + annotations: annotations, + } + } +} diff --git a/rust/compiler/src/adlgen/sys/annotations.rs b/rust/compiler/src/adlgen/sys/annotations.rs new file mode 100644 index 00000000..29e6a1ca --- /dev/null +++ b/rust/compiler/src/adlgen/sys/annotations.rs @@ -0,0 +1,23 @@ +// @generated from adl module sys.annotations + +use serde::Deserialize; +use serde::Serialize; + +pub type Doc = String; + +pub type SerializedName = String; + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct SerializedWithInternalTag { + pub tag: String, +} + +impl SerializedWithInternalTag { + pub fn new(tag: String) -> SerializedWithInternalTag { + SerializedWithInternalTag { + tag: tag, + } + } +} + +pub type CustomSerialization = bool; diff --git a/rust/compiler/src/adlgen/sys/mod.rs b/rust/compiler/src/adlgen/sys/mod.rs new file mode 100644 index 00000000..28438141 --- /dev/null +++ b/rust/compiler/src/adlgen/sys/mod.rs @@ -0,0 +1,3 @@ +pub mod adlast2; +pub mod annotations; +pub mod types; \ No newline at end of file diff --git a/rust/compiler/src/adlgen/sys/types.rs b/rust/compiler/src/adlgen/sys/types.rs new file mode 100644 index 00000000..8e03d5ca --- /dev/null +++ b/rust/compiler/src/adlgen/sys/types.rs @@ -0,0 +1,13 @@ +// @generated from adl module sys.types + +use serde::Deserialize; +use serde::Serialize; + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub enum Either { + #[serde(rename="left")] + Left(T1), + + #[serde(rename="right")] + Right(T2), +} diff --git a/rust/compiler/src/adlrt/custom/mod.rs b/rust/compiler/src/adlrt/custom/mod.rs new file mode 100644 index 00000000..86cd4493 --- /dev/null +++ b/rust/compiler/src/adlrt/custom/mod.rs @@ -0,0 +1 @@ +pub mod sys; diff --git a/rust/compiler/src/adlrt/custom/sys/mod.rs b/rust/compiler/src/adlrt/custom/sys/mod.rs new file mode 100644 index 00000000..cd408564 --- /dev/null +++ b/rust/compiler/src/adlrt/custom/sys/mod.rs @@ -0,0 +1 @@ +pub mod types; diff --git a/rust/compiler/src/adlrt/custom/sys/types/map.rs b/rust/compiler/src/adlrt/custom/sys/types/map.rs new file mode 100644 index 00000000..a1c93ca8 --- /dev/null +++ b/rust/compiler/src/adlrt/custom/sys/types/map.rs @@ -0,0 +1,71 @@ +use serde::{Deserialize, Deserializer}; +use serde::{Serialize, Serializer}; +use std::collections::HashMap; +use std::iter::FromIterator; +use std::hash::Hash; +use std::result; +use super::mapentry::MapEntry; + + +#[derive(Clone,Eq,PartialEq, Debug)] +pub struct Map(pub HashMap); + +impl Map { + pub fn new(v: Vec>) -> Map + { + let mut hm = HashMap::new(); + for MapEntry{key,value} in v { + hm.insert(key,value); + } + Map(hm) + } +} + +impl FromIterator<(K,V)> for Map +where + K: Eq + Hash, +{ + fn from_iter>(iter: T) -> Map { + let mut hm = HashMap::new(); + for (k,v) in iter { + hm.insert(k,v); + } + Map(hm) + } + +} + +impl Serialize for Map +where + K: Serialize + Eq + Hash, + V: Serialize, +{ + fn serialize(&self, serializer: S) -> result::Result + where + S: Serializer, + { + let mut ventries: Vec> = Vec::new(); + for (key, value) in &self.0 { + ventries.push(MapEntry{key, value}); + } + MapImpl(ventries).serialize(serializer) + } +} + +impl<'de, K, V> Deserialize<'de> for Map +where + K: Deserialize<'de> + Eq + Hash, + V: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> result::Result + where + D: Deserializer<'de>, + { + let m = MapImpl::::deserialize(deserializer)?; + Ok(Map::new(m.0)) + } +} + +#[derive(Deserialize,Eq,Hash,PartialEq,Serialize)] +struct MapImpl(pub Vec>); + diff --git a/rust/compiler/src/adlrt/custom/sys/types/mapentry.rs b/rust/compiler/src/adlrt/custom/sys/types/mapentry.rs new file mode 100644 index 00000000..d143415f --- /dev/null +++ b/rust/compiler/src/adlrt/custom/sys/types/mapentry.rs @@ -0,0 +1,20 @@ +use serde::{Deserialize}; +use serde::{Serialize}; + +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] +pub struct MapEntry { + #[serde(rename="k")] + pub key: K, + + #[serde(rename="v")] + pub value: V, +} + +impl MapEntry { + pub fn new(key: K, value: V) -> MapEntry { + MapEntry { + key: key, + value: value, + } + } +} diff --git a/rust/compiler/src/adlrt/custom/sys/types/maybe.rs b/rust/compiler/src/adlrt/custom/sys/types/maybe.rs new file mode 100644 index 00000000..252b228d --- /dev/null +++ b/rust/compiler/src/adlrt/custom/sys/types/maybe.rs @@ -0,0 +1,57 @@ +use serde::{Deserialize, Deserializer}; +use serde::{Serialize, Serializer}; +use std::result; + +// Maybe is a custom mapping to Option, +// with ADL compatible serialization + +#[derive(Clone,Debug,Eq,Hash,PartialEq)] +pub struct Maybe (pub Option); + +impl Maybe { + pub fn nothing() -> Maybe { + Maybe(Option::None) + } + + pub fn just(t: T) -> Maybe { + Maybe(Option::Some(t)) + } +} + +impl Serialize for Maybe { + fn serialize(&self, serializer: S) -> result::Result + where + S: Serializer, + { + let m: MaybeImpl<&T> = match self { + Maybe(Option::None) => MaybeImpl::Nothing, + Maybe(Option::Some(v)) => MaybeImpl::Just(v), + }; + m.serialize(serializer) + } +} + +impl<'de, T: Deserialize<'de>> Deserialize<'de> for Maybe { + fn deserialize(deserializer: D) -> result::Result + where + D: Deserializer<'de>, + { + let m = MaybeImpl::deserialize(deserializer)?; + match m { + MaybeImpl::Just(v) => Ok(Maybe(Option::Some(v))), + MaybeImpl::Nothing => Ok(Maybe(Option::None)), + } + } +} + +#[derive(Deserialize,Serialize)] +enum MaybeImpl { + #[serde(rename="nothing")] + Nothing, + + #[serde(rename="just")] + Just(T), +} + + + diff --git a/rust/compiler/src/adlrt/custom/sys/types/mod.rs b/rust/compiler/src/adlrt/custom/sys/types/mod.rs new file mode 100644 index 00000000..ad9171a9 --- /dev/null +++ b/rust/compiler/src/adlrt/custom/sys/types/mod.rs @@ -0,0 +1,6 @@ +pub mod mapentry; +pub mod map; +pub mod maybe; +pub mod pair; +pub mod result; +pub mod set; diff --git a/rust/compiler/src/adlrt/custom/sys/types/pair.rs b/rust/compiler/src/adlrt/custom/sys/types/pair.rs new file mode 100644 index 00000000..9a058b10 --- /dev/null +++ b/rust/compiler/src/adlrt/custom/sys/types/pair.rs @@ -0,0 +1,49 @@ +use serde::{Deserialize, Deserializer}; +use serde::{Serialize, Serializer}; +use std::result; + +#[derive(Clone,Debug,Eq,Hash,PartialEq)] +pub struct Pair (pub (A,B)); + +impl Pair { + pub fn new(a: A, b: B) -> Pair { + Pair((a, b)) + } +} + +impl Serialize for Pair +where + A: Serialize, + B: Serialize, +{ + fn serialize(&self, serializer: S) -> result::Result + where + S: Serializer, + { + let Pair((a, b)) = self; + PairImpl { v_1: a, v_2: b }.serialize(serializer) + } +} + +impl<'de, A, B> Deserialize<'de> for Pair +where + A: Deserialize<'de>, + B: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> result::Result + where + D: Deserializer<'de>, + { + let m = PairImpl::::deserialize(deserializer)?; + Ok(Pair((m.v_1, m.v_2))) + } +} + +#[derive(Deserialize,Serialize)] +struct PairImpl { + #[serde(rename="v1")] + pub v_1: A, + + #[serde(rename="v2")] + pub v_2: B, +} diff --git a/rust/compiler/src/adlrt/custom/sys/types/result.rs b/rust/compiler/src/adlrt/custom/sys/types/result.rs new file mode 100644 index 00000000..2b10b851 --- /dev/null +++ b/rust/compiler/src/adlrt/custom/sys/types/result.rs @@ -0,0 +1,61 @@ +use serde::{Deserialize, Deserializer}; +use serde::{Serialize, Serializer}; + + +#[derive(Clone,Debug,Eq,Hash,PartialEq)] +pub struct Result(pub std::result::Result); + +impl Result { + pub fn ok(value: T) -> Result { + Result(Ok(value)) + } + + pub fn err(e: E) -> Result { + Result(Err(e)) + } +} + +impl Serialize for Result +where + T: Serialize, + E: Serialize, +{ + fn serialize(&self, serializer: S) -> std::result::Result + where + S: Serializer, + { + let m = match &self.0 { + Ok(v) => ResultImpl::Ok(v), + Err(e) => ResultImpl::Error(e), + }; + m.serialize(serializer) + } +} + +impl<'de, T, E> Deserialize<'de> for Result +where + T: Deserialize<'de>, + E: Deserialize<'de>, +{ + fn deserialize(deserializer: D) -> std::result::Result + where + D: Deserializer<'de>, + { + let m = ResultImpl::deserialize(deserializer)?; + Ok(match m { + ResultImpl::Ok(v) => Result::ok(v), + ResultImpl::Error(e) => Result::err(e), + }) + } +} + + +#[derive(Deserialize,Serialize)] +enum ResultImpl { + #[serde(rename="ok")] + Ok(T), + + #[serde(rename="error")] + Error(E), +} + diff --git a/rust/compiler/src/adlrt/custom/sys/types/set.rs b/rust/compiler/src/adlrt/custom/sys/types/set.rs new file mode 100644 index 00000000..fcf58940 --- /dev/null +++ b/rust/compiler/src/adlrt/custom/sys/types/set.rs @@ -0,0 +1,48 @@ +use serde::{Deserialize, Deserializer}; +use serde::{Serialize, Serializer}; +use std::collections::HashSet; +use std::hash::Hash; +use std::result; + +#[derive(Clone,Eq,PartialEq)] +pub struct Set(HashSet); + +impl Set { + pub fn new(v: Vec) -> Set + { + Set(v.into_iter().collect()) + } +} + +impl Serialize for Set +where + T: Serialize + Eq + Hash, +{ + fn serialize(&self, serializer: S) -> result::Result + where + S: Serializer, + { + let mut vpairs: Vec<&T> = Vec::new(); + for t in &self.0 { + vpairs.push(t); + } + SetImpl(vpairs).serialize(serializer) + } +} + +impl<'de, T> Deserialize<'de> for Set +where + T: Deserialize<'de> + Eq + Hash, +{ + fn deserialize(deserializer: D) -> result::Result + where + D: Deserializer<'de>, + { + let m = SetImpl::::deserialize(deserializer)?; + Ok(Set(m.0.into_iter().collect())) + } +} + + +#[derive(Deserialize,Serialize)] +struct SetImpl(pub Vec); diff --git a/rust/compiler/src/adlrt/mod.rs b/rust/compiler/src/adlrt/mod.rs new file mode 100644 index 00000000..d5f90568 --- /dev/null +++ b/rust/compiler/src/adlrt/mod.rs @@ -0,0 +1 @@ +pub mod custom; diff --git a/rust/compiler/src/adlstdlib/mod.rs b/rust/compiler/src/adlstdlib/mod.rs new file mode 100644 index 00000000..d0bbfbb2 --- /dev/null +++ b/rust/compiler/src/adlstdlib/mod.rs @@ -0,0 +1,87 @@ +use std::{borrow::Cow, path::PathBuf}; + +use anyhow::anyhow; + +use rust_embed::{EmbeddedFile, RustEmbed}; + +use crate::{ + adlgen::{adlc::packaging::EmbeddedPkg, sys::adlast2::ModuleName}, + cli::StdlibOpt, +}; + +#[derive(RustEmbed)] +#[folder = "../../adl/stdlib/"] +struct StdlibAsset; + +#[derive(RustEmbed)] +#[folder = "../../adl/adlc/"] +struct AdlcAsset; + +pub fn get_file_names(em: EmbeddedPkg) -> Vec { + match em { + EmbeddedPkg::Sys => StdlibAsset::iter().map(String::from).map(PathBuf::from).collect(), + EmbeddedPkg::Adlc => AdlcAsset::iter().map(String::from).map(PathBuf::from).collect(), + } +} + +// fn str_from_cow(name: Cow) -> PathBuf { +// PathBuf::from(name.to_string()); +// path.to_str().unwrap().to_string() +// } + +pub fn get_adl_pkg(em: EmbeddedPkg) -> Option> { + let d = match em { + EmbeddedPkg::Sys => StdlibAsset::get("adl.pkg.json"), + EmbeddedPkg::Adlc => AdlcAsset::get("adl.pkg.json"), + }; + d.map(|d| d.data) +} + +pub fn get_stdlib(em: EmbeddedPkg, mn: &ModuleName, ext: &str) -> Option> { + let mut fname = mn.replace(".", "/"); + fname.push_str(".adl"); + if ext != "" { + fname.push_str("-"); + fname.push_str(ext); + } + let get = match em { + EmbeddedPkg::Sys => StdlibAsset::get, + EmbeddedPkg::Adlc => AdlcAsset::get, + }; + if let Some(f) = get(fname.as_str()) { + return Some(f.data); + }; + None +} + +pub(crate) fn dump_stdlib(opts: &crate::cli::DumpStdlibOpts) -> Result<(), anyhow::Error> { + std::fs::create_dir_all(&opts.outputdir) + .map_err(|_| anyhow!("can't create output dir '{:?}'", opts.outputdir))?; + match opts.lib { + StdlibOpt::Sys => { + for name in StdlibAsset::iter() { + fun_name(opts.outputdir.clone(), name, StdlibAsset::get)?; + } + } + StdlibOpt::Adlc => { + for name in AdlcAsset::iter() { + fun_name(opts.outputdir.clone(), name, StdlibAsset::get)?; + } + } + }; + Ok(()) +} + +type Getter = fn(&str) -> Option; + +fn fun_name(mut path: PathBuf, name: Cow<'_, str>, get: Getter) -> Result<(), anyhow::Error> { + path.push(name.as_ref()); + Ok(if let Some(data) = get(name.as_ref()) { + std::fs::create_dir_all(path.parent().unwrap()) + .map_err(|_| anyhow!("can't create output dir for '{:?}'", &path))?; + std::fs::write(&path, data.data.as_ref()) + .map_err(|s| anyhow!("can't write file '{:?}' error {}", &path, s))?; + } else { + return Err(anyhow!("could get the contents for {}", name)); + }) +} diff --git a/rust/compiler/src/cli/ast.rs b/rust/compiler/src/cli/ast.rs new file mode 100644 index 00000000..07ff2b8e --- /dev/null +++ b/rust/compiler/src/cli/ast.rs @@ -0,0 +1,44 @@ +use std::collections::{HashMap}; + +use super::AstOpts; + +use anyhow::anyhow; +use serde::Serialize; + +use crate::adlgen::sys::adlast2::{AdlAst, AstModule}; +use crate::processing::loader::loader_from_search_paths; +use crate::processing::resolver::{Resolver}; + +pub fn ast(opts: &AstOpts) -> anyhow::Result<()> { + let loader = loader_from_search_paths(&opts.search.path); + let mut resolver = Resolver::new(loader); + for m in &opts.modules { + let r = resolver.add_module(m); + match r { + Ok(()) => (), + Err(e) => return Err(anyhow!("Failed to load module {}: {:?}", m, e)), + } + } + + let mut adlast = AdlAst::new(); + + resolver.get_module_names().iter().for_each(|mn| { + let m = resolver.get_module(&mn).unwrap(); + let decls: HashMap<_, _> = m.decls.iter().map(|d| (d.name.clone(), d.clone())).collect(); + let m_ast = AstModule { + name: m.name.clone(), + imports: m.imports.clone(), + decls, + annotations: m.annotations.clone(), + }; + adlast.insert(mn.to_string(), m_ast); + }); + + let mut buf = Vec::new(); + let formatter = serde_json::ser::PrettyFormatter::with_indent(b" "); + let mut ser = serde_json::Serializer::with_formatter(&mut buf, formatter); + adlast.serialize(&mut ser).unwrap(); + println!("{}", String::from_utf8(buf).unwrap()); + + Ok(()) +} diff --git a/rust/compiler/src/cli/mod.rs b/rust/compiler/src/cli/mod.rs new file mode 100644 index 00000000..3b4ae9a9 --- /dev/null +++ b/rust/compiler/src/cli/mod.rs @@ -0,0 +1,362 @@ +use std::{path::PathBuf, fmt::Display, io}; + +use anyhow::{anyhow, Error}; +use clap::{Args, Parser}; +use log::{LevelFilter, Record}; +use std::str::FromStr; + +use env_logger::{Builder, Env, fmt::Formatter}; +use std::io::Write; + +use crate::{ + adlgen::adlc::packaging::{ + GenOutput, ModuleSrc, NpmPackageRef, ReferenceableScopeOption, TsGenRuntime, TsRuntimeOpt, + TypescriptGenOptions, AdlPackageRefType, DirectoryRef, + }, + processing::loader::loader_from_search_paths, +}; +// use std::path{Path, PathBuf}; + +pub mod ast; +pub mod rust; +pub mod tsgen; +pub mod verify; +pub mod workspace; + +pub fn formatter(buf: &mut Formatter, record: &Record<'_>) -> io::Result<()> { + let level = buf.default_styled_level(record.level()); + let timestamp = buf.timestamp(); + let mut location = String::new(); + if let (Some(f), Some(l)) = (record.file(), record.line()) { + location.push_str(format!(" {}:{}", f, l).as_str()); + } + if let Some(m) = record.module_path() { + location.push_str(format!(" {}", m).as_str()); + } + writeln!(buf, "[{timestamp} {level}{location}] {}", record.args()) +} + +fn init_logger(module: Option, level: Option) { + + // let formatter = |buf: &mut Formatter, record: &Record<'_>| { + // let level = buf.default_styled_level(record.level()); + // let timestamp = buf.timestamp(); + // let mut location = String::new(); + // if let (Some(f), Some(l)) = (record.file(), record.line()) { + // location.push_str(format!(" {}:{}", f, l).as_str()); + // } + // if let Some(m) = record.module_path() { + // location.push_str(format!(" {}", m).as_str()); + // } + // writeln!(buf, "[{timestamp} {level}{location}] {}", record.args()) + // }; + + match (&module, level) { + (None, None) => Builder::from_env(Env::default()).format(formatter).init(), + (None, Some(l)) => Builder::from_env(Env::default()).format(formatter).filter_level(l).init(), + (Some(m), None) => Builder::from_env(Env::default()).format(formatter).filter(Some(m.as_str()), log::LevelFilter::Warn).init(), + (Some(m), Some(l)) => Builder::from_env(Env::default()).format(formatter).filter(Some(m.as_str()), l).init(), + } +} + +pub fn run_cli() -> i32 { + let cli = Cli::parse(); + + init_logger(cli.log_filter_module, cli.loglevel); + + let r = match cli.command { + Command::Gen(opts) => workspace::workspace(&opts), + Command::Verify(opts) => verify::verify(&opts), + Command::Ast(opts) => ast::ast(&opts), + Command::Rust(opts) => rust::rust(&opts), + Command::Tsgen(opts) => { + if let Some(d) = opts.runtime_dir { + if d != "./runtime" { + eprintln!("only value for runtime_dir which is supported in './runtime'"); + return 1; + } + } + let loader = loader_from_search_paths(&opts.search.path); + let ts_opts = TypescriptGenOptions { + npm_pkg_name: opts.npm_pkg_name, + npm_version: TypescriptGenOptions::def_npm_version(), + extra_dependencies: TypescriptGenOptions::def_extra_dependencies(), + extra_dev_dependencies: TypescriptGenOptions::def_extra_dev_dependencies(), + tsconfig: TypescriptGenOptions::def_tsconfig(), + scripts: TypescriptGenOptions::def_scripts(), + outputs: Some(crate::adlgen::adlc::packaging::OutputOpts::Gen(GenOutput { + referenceable: ReferenceableScopeOption::Local, + output_dir: opts.output.outputdir.to_str().unwrap().to_string(), + manifest: opts + .output + .manifest + .map(|m| m.to_str().unwrap().to_string()), + })), + runtime_opts: if opts.include_rt { + TsRuntimeOpt::Generate(TsGenRuntime{ + // runtime_dir: match opts.runtime_dir { + // Some(d) => d, + // None => "runtime".to_string(), + // }, + }) + } else { + match opts.runtime_pkg { + Some(d) => TsRuntimeOpt::PackageRef(NpmPackageRef { + name: d, + version: "^1.0.0".to_string(), + }), + None => TypescriptGenOptions::def_runtime_opts(), + } + }, + generate_transitive: opts.generate_transitive, + include_resolver: opts.include_resolver, + ts_style: match opts.ts_style { + Some(style) => match style { + TsStyle::Tsc => crate::adlgen::adlc::packaging::TsStyle::Tsc, + TsStyle::Deno => crate::adlgen::adlc::packaging::TsStyle::Deno, + }, + None => crate::adlgen::adlc::packaging::TsStyle::Tsc, + }, + modules: ModuleSrc::Modules(opts.modules), + capitalize_branch_names_in_types: opts.capitalize_branch_names_in_types, + capitalize_type_names: opts.capitalize_type_names, + }; + let empty = vec![]; + tsgen::tsgen(false, false, loader, &ts_opts, None, AdlPackageRefType::Dir(DirectoryRef{ path: ".".to_string() }), empty) + } + Command::WriteStdlib(opts) => crate::adlstdlib::dump_stdlib(&opts), + }; + match r { + Ok(_) => 0, + Err(err) => { + log::error!("{}", err); + 1 + } + } +} + +#[derive(Parser, Debug)] +#[command(name = "adlc")] +#[command(author = "Tim Docker")] +#[command(version = "0.1")] +#[command(about = "ADL code generation cli tool", long_about = None)] +struct Cli { + #[arg(short,long, + help = "Set the loglevel. Overrides RUST_LOG if only level is specified.", + long_help = "Set the loglevel. Overrides RUST_LOG if only level is specified, if level and module are specified here or in RUST_LOG, then the result is a combination of the env var and cli args. Possible values [OFF, ERROR, WARN, INFO, DEBUG, TRACE]")] + loglevel: Option, + + #[arg(short = 'm',long, + help = "Set the module to filter. Can be used in conjunction with the env var RUST_LOG.", + )] + log_filter_module: Option, + + #[command(subcommand)] + command: Command, +} + +#[derive(Debug, Parser)] +pub enum Command { + /// generate source based on Workspace & Packages files (adl.work.json & adl.pkg.json) + Gen(GenOpts), + /// verify ADL + Verify(VerifyOpts), + /// generate the json AST for some ADL modules + Ast(AstOpts), + /// generate rust code for the some ADL modules + Rust(RustOpts), + /// generate typescript code for the some ADL modules + #[clap(name = "typescript")] + Tsgen(TsOpts), + /// dump the embedded stdlib to the filesystem. + WriteStdlib(DumpStdlibOpts), +} + +#[derive(Debug, Args)] +pub struct GenOpts { + /// The module where the code is generated, relative to crate root + #[arg(default_value_t={".".to_string()})] + pub dir: String, + + /// The workspace file to use relative to the dir + #[arg(long, short='f', default_value_t={"adl.work.json".to_string()})] + pub workspace_filename: String, + + /// The package filenames to look for in the pkg dir specified in the use fields + #[arg(long, short='p', default_value_t={"adl.pkg.json".to_string()})] + pub package_filenames: String, +} + +#[derive(Debug, Args)] +pub struct DumpStdlibOpts { + /// writes generated code to the specified directory + #[arg(long, short = 'O', value_name = "DIR")] + pub outputdir: PathBuf, + + /// Select the style of typescript to be generated + // #[clap(arg_senum)] + #[arg(long, default_value_t={StdlibOpt::Sys})] + pub lib: StdlibOpt, //=sys|adlc +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum StdlibOpt { + Sys, + Adlc, +} + +impl Display for StdlibOpt { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + StdlibOpt::Sys => write!(f, "sys"), + StdlibOpt::Adlc => write!(f, "adlc"), + } + } +} + +impl FromStr for StdlibOpt { + type Err = Error; + + fn from_str(s: &str) -> Result { + match s.to_ascii_lowercase().as_str() { + "sys" => Ok(StdlibOpt::Sys), + "adlc" => Ok(StdlibOpt::Adlc), + _ => Err(anyhow!("must be one of 'sys' or 'adlc'")), + } + } +} + +#[derive(Debug, Args)] +pub struct VerifyOpts { + #[clap(flatten)] + pub search: AdlSearchOpts, + + pub modules: Vec, +} + +#[derive(Debug, Args)] +pub struct AstOpts { + #[clap(flatten)] + pub search: AdlSearchOpts, + + /// writes the AST to the specified file" + #[arg(long, short = 'O', value_name = "FILE")] + pub outfile: Option, + + pub modules: Vec, +} + +#[derive(Debug, Args)] +pub struct RustOpts { + #[clap(flatten)] + pub search: AdlSearchOpts, + + #[clap(flatten)] + pub output: OutputOpts, + + /// Generate the runtime code + #[arg(long)] + pub include_runtime: bool, + + /// The module where the code is generated, relative to crate root + #[arg(long, value_name="RSMODULE", default_value_t={"adl".to_string()})] + pub module: String, + + /// The module where the runtime is located, relative to crate root + #[arg(long, value_name="RSMODULE", default_value_t={"adlrt".to_string()})] + pub runtime_module: String, + + #[arg(value_name = "ADLMODULE")] + pub modules: Vec, +} + +#[derive(Debug, Args)] +pub struct TsOpts { + #[clap(flatten)] + pub search: AdlSearchOpts, + + #[clap(flatten)] + pub output: OutputOpts, + + /// Generate the runtime code + #[arg(long)] + pub include_rt: bool, + + /// Set the directory where runtime code is written (relative to output dir). + #[arg(long, short = 'R', value_name = "DIR")] + pub runtime_dir: Option, + + #[arg(long)] + pub runtime_pkg: Option, + + /// Also generate code for the transitive dependencies of the specified adl files (default: true) + #[arg(long, default_value_t = true)] + pub generate_transitive: bool, + + /// The name to use in the package.json file + #[arg(long, default_value_t = String::from("my_data"))] + pub npm_pkg_name: String, + + /// Generate the resolver map for all generated adl files (default: true) + #[arg(long, default_value_t = true)] + include_resolver: bool, + + /// Select the style of typescript to be generated + // #[clap(arg_senum)] + #[arg(long)] + pub ts_style: Option, //=tsc|deno + + #[arg(value_name = "ADLMODULE")] + pub modules: Vec, + + /// When creating the path for output ts files delete the first part of the module name + #[arg(long, default_value_t = true)] + pub strip_first: bool, + + /// If set capitalizes branch (field) name in the exported interfaces (used to generate backward code). + /// + /// Has a risk of creating name clashes between branches with only differ in case. + /// Set to true to preserve backward compatiblity. + #[arg(long)] + pub capitalize_branch_names_in_types: bool, + + /// Capitalizes type names (default: true). + #[arg(long, default_value_t = true)] + pub capitalize_type_names: bool, +} + +#[derive(Debug, Copy, Clone, PartialEq)] +pub enum TsStyle { + Tsc, + Deno, +} + +impl FromStr for TsStyle { + type Err = Error; + + fn from_str(s: &str) -> Result { + match s.to_ascii_lowercase().as_str() { + "tsc" => Ok(TsStyle::Tsc), + "deno" => Ok(TsStyle::Deno), + _ => Err(anyhow!("must be one of 'tsc' or 'deno'")), + } + } +} + +#[derive(Debug, Args)] +pub struct AdlSearchOpts { + /// adds the given directory to the ADL search path + #[arg(long = "searchdir", short = 'I', value_name = "DIR")] + pub path: Vec, +} + +#[derive(Debug, Args)] +pub struct OutputOpts { + /// writes generated code to the specified directory + #[arg(long, short = 'O', value_name = "DIR")] + pub outputdir: PathBuf, + + /// write a manifest file recording generated files + #[arg(long, value_name = "FILE")] + pub manifest: Option, +} diff --git a/rust/compiler/src/cli/rust/generate.rs b/rust/compiler/src/cli/rust/generate.rs new file mode 100644 index 00000000..048b9e54 --- /dev/null +++ b/rust/compiler/src/cli/rust/generate.rs @@ -0,0 +1,256 @@ +use super::RustOpts; +use std::collections::{HashMap, HashSet}; +use std::path::PathBuf; +use convert_case::{Case, Casing}; + + +use crate::adlgen::sys::adlast2::{self as adlast, PrimitiveType}; +use crate::processing::resolver::{Module1, Resolver, TypeExpr1}; +use crate::processing::writer::TreeWriter; + +use crate::cli::rust::rsfile::RSFile; +use crate::fmtln; + + +/// Generate the tree of mod.rs files that link together the generated code +pub fn gen_rs_mod_files(opts: &RustOpts, resolver: &Resolver, writer: &mut TreeWriter) -> anyhow::Result<()> { + + // build a map of parent rust modules and their children + let mut modfiles: HashMap,HashSet> = HashMap::new(); + for m in resolver.get_module_names() { + let msplit: Vec<&str> = m.split(".").collect(); + for i in 0..msplit.len() { + let rsmod = msplit.get(i).unwrap(); + let parent = &msplit[0..i]; + let parent: Vec = parent.iter().map(|m| m.to_string()).collect(); + let e = modfiles.entry(parent).or_default(); + e.insert(rsmod.to_string()); + } + } + + for (rsmod,children) in modfiles { + let mut children = children.into_iter().collect::>(); + children.sort(); + + let mut path = PathBuf::new(); + path.push(opts.module.clone()); + for el in rsmod { + path.push(el); + } + path.push("mod.rs"); + let lines: Vec = children + .iter() + .map( |m| format!("pub mod {};", m)) + .collect(); + writer.write(&path, lines.join("\n"))? + }; + Ok(()) +} + +pub fn gen_module(m: &Module1) -> anyhow::Result { + let mut out = RSFile::new(m.name.clone()); + out.import("serde", "Deserialize"); + out.import("serde", "Serialize"); + + for d in m.decls.iter() { + match &d.r#type { + adlast::DeclType::Struct(s) => gen_struct(m, d, &s, &mut out)?, + adlast::DeclType::Type(t) => gen_type(m, d, &t, &mut out)?, + _ => {} + } + } + Ok(out.to_string()) +} + + +fn gen_struct( + _m: &Module1, + d: &adlast::Decl1, + s: &adlast::Struct1, + out: &mut RSFile, +) -> anyhow::Result<()> { + let efields: Vec> = s.fields + .iter() + .map(|field| ExtendedField::new(field, out)) + .collect(); + + let ctor_params: String = efields + .iter() + .map(|ef| format!("{}: {}", ef.rs_field_name, ef.type_str)) + .collect::>() + .join(", "); + + let type_name = rs_type_name_from_adl(&d.name); + let type_params = fmt_type_params(&s.type_params); + + if let Some(serde_json::Value::String(doc)) = d.annotations.0.get(&ann_doc()) { + out.pushlns(fmt_doc_comment(doc)); + } + + fmtln!(out, "pub struct {}{} {{", type_name, type_params ); + for (i,ef) in efields.iter().enumerate() { + if i != 0 { + fmtln!(out, ""); + } + if ef.rs_field_name != ef.field.serialized_name { + fmtln!(out, " #[serde(rename=\"{}\")]", ef.field.serialized_name); + } + fmtln!(out, " pub {}: {},", ef.rs_field_name, ef.type_str); + } + fmtln!(out, "}}"); + fmtln!(out, ""); + fmtln!(out, "impl{} {}{} {{", type_params, type_name, type_params); + fmtln!(out, " pub fn new({}) -> {}{} {{", ctor_params, type_name, type_params); + fmtln!(out, " {} {{", type_name); + for ef in &efields { + fmtln!(out, " {}: {},", ef.rs_field_name, ef.rs_field_name); + } + fmtln!(out, " }}"); + fmtln!(out, " }}"); + fmtln!(out, "}}"); + fmtln!(out, ""); + Ok(()) +} + +fn gen_type( + _m: &Module1, + d: &adlast::Decl1, + t: &adlast::TypeDef, + out: &mut RSFile, +) -> anyhow::Result<()> { + + let teg = TypeExprGen::new(&t.type_expr); + let type_name = rs_type_name_from_adl(&d.name); + let type_params = fmt_type_params(&t.type_params); + let aliased_type = teg.gen_type(out); + fmtln!(out, "pub type {}{} = {};", type_name, type_params, aliased_type); + fmtln!(out, ""); + + Ok(()) +} + +struct ExtendedField<'a> { + field: &'a adlast::Field1, + rs_field_name: String, + type_str: String, + type_expr_gen: TypeExprGen, +} + +impl <'a> ExtendedField<'a> { + fn new(field: &'a adlast::Field1, out: &mut RSFile) -> Self { + let type_expr_gen = TypeExprGen::new(&field.type_expr); + let type_str = type_expr_gen.gen_type(out); + let rs_field_name = rs_field_name_from_adl(&field.name); + ExtendedField{field, rs_field_name, type_str, type_expr_gen} + } +} + +trait TypeCodeGen { + fn gen_type(&self, rsfile: &mut RSFile) -> String; +} + +struct TypeExprGen { + type_ref: adlast::TypeRef, + params: Vec>, +} + +impl TypeExprGen { + fn new(type_expr: &TypeExpr1) -> Self { + let params = type_expr.parameters + .iter() + .map(|te| Box::new(TypeExprGen::new(te)) as Box) + .collect(); + TypeExprGen { + type_ref: type_expr.type_ref.clone(), + params, + } + } +} + +impl TypeCodeGen for TypeExprGen { + fn gen_type(&self, rsfile: &mut RSFile) -> String { + + let params: Vec = self.params + .iter() + .map(|p| p.gen_type(rsfile)) + .collect(); + + match &self.type_ref { + adlast::TypeRef::LocalName(ln) => format!("{}{}", ln,fmt_type_params(¶ms)), + adlast::TypeRef::ScopedName(sn) => { + let name = rsfile.import(&sn.module_name, &sn.name); + format!("{}{}", name, fmt_type_params(¶ms)) + }, + adlast::TypeRef::Primitive(p) => { + match p { + PrimitiveType::Void => "()".to_owned(), + PrimitiveType::Bool => "bool".to_owned(), + PrimitiveType::Int8 => "i8".to_owned(), + PrimitiveType::Int16 => "i16".to_owned(), + PrimitiveType::Int32 => "i32".to_owned(), + PrimitiveType::Int64 => "i64".to_owned(), + PrimitiveType::Word8 => "u8".to_owned(), + PrimitiveType::Word16 => "u16".to_owned(), + PrimitiveType::Word32 => "u32".to_owned(), + PrimitiveType::Word64 => "u64".to_owned(), + PrimitiveType::Float => "f32".to_owned(), + PrimitiveType::Double => "f64".to_owned(), + PrimitiveType::Json => { + rsfile.import("serde_json", "Value") + }, + PrimitiveType::ByteVector => "Vec".to_owned(), + PrimitiveType::String => "String".to_owned(), + PrimitiveType::Vector => format!("Vec{}", fmt_type_params(¶ms)), + PrimitiveType::StringMap => { + let hash_map = rsfile.import("std::collections", "StringMap"); + format!("{}", hash_map, params.join(",")) + } + PrimitiveType::Nullable => format!("Option{}", fmt_type_params(¶ms)), + PrimitiveType::TypeToken => { + let phantom_data = rsfile.import("std::marker", "PhantomData"); + phantom_data + } + } + }, + adlast::TypeRef::TypeParam(t) => t.to_string(), + } + } +} + +fn fmt_type_params(params: &[String]) -> String { + if params.len() == 0 { + "".to_owned() + } else { + format!("<{}>", params.join(".")) + } +} + +fn fmt_doc_comment(doc_str: &str) -> Vec { + let mut lines = Vec::new(); + lines.push("/**".to_owned()); + for s in doc_str.lines() { + let s = s.trim(); + if s != "" { + lines.push(format!(" * {}", s)) + } + } + lines.push(" */".to_owned()); + lines +} + +fn rs_field_name_from_adl(adl_field_name: &str) -> String { + // TODO: deal with reserved words + adl_field_name.to_case(Case::Snake) +} + +fn rs_type_name_from_adl(adl_type_name: &str) -> String { + // TODO: deal with reserved words + adl_type_name.to_case(Case::UpperCamel) +} + +fn ann_doc() -> adlast::ScopedName { + adlast::ScopedName { + module_name: "sys.annotations".to_owned(), + name: "Doc".to_owned(), + } +} diff --git a/rust/compiler/src/cli/rust/mod.rs b/rust/compiler/src/cli/rust/mod.rs new file mode 100644 index 00000000..768d966b --- /dev/null +++ b/rust/compiler/src/cli/rust/mod.rs @@ -0,0 +1,56 @@ +use super::RustOpts; +use std::path::PathBuf; + +use anyhow::anyhow; + +use crate::adlgen::sys::adlast2::{self as adlast}; +use crate::processing::loader::loader_from_search_paths; +use crate::processing::resolver::{Module1, Resolver}; +use crate::processing::writer::TreeWriter; + +use generate::{gen_module, gen_rs_mod_files}; + +mod rsfile; +mod generate; + +pub fn rust(opts: &RustOpts) -> anyhow::Result<()> { + let loader = loader_from_search_paths(&opts.search.path); + let mut resolver = Resolver::new(loader); + for m in &opts.modules { + let r = resolver.add_module(m); + match r { + Ok(()) => (), + Err(e) => return Err(anyhow!("Failed to load module {}: {:?}", m, e)), + } + } + let modules: Vec = resolver + .get_module_names() + .into_iter() + .map(|mn| resolver.get_module(&mn).unwrap()) + .collect(); + + let mut writer = TreeWriter::new( + opts.output.outputdir.clone(), + opts.output.manifest.clone(), + )?; + + for m in modules { + let path = path_from_module_name(opts, m.name.to_owned()); + let code = gen_module(&m).unwrap(); + writer.write(path.as_path(), code)?; + } + + gen_rs_mod_files(opts, &resolver, &mut writer)?; + + Ok(()) +} + +fn path_from_module_name(opts: &RustOpts, mname: adlast::ModuleName) -> PathBuf { + let mut path = PathBuf::new(); + path.push(opts.module.clone()); + for el in mname.split(".") { + path.push(el); + } + path.set_extension("rs"); + return path; +} diff --git a/rust/compiler/src/cli/rust/rsfile.rs b/rust/compiler/src/cli/rust/rsfile.rs new file mode 100644 index 00000000..c1a4c286 --- /dev/null +++ b/rust/compiler/src/cli/rust/rsfile.rs @@ -0,0 +1,80 @@ +use std::collections::{BTreeSet}; + + +/// In memory representation of a rust file during codegen +pub struct RSFile { + module_name: String, + body: Vec, + imports: BTreeSet, + imported_names: BTreeSet, + +} + +impl RSFile { + pub fn new(module_name: String) -> Self { + RSFile{ + module_name, + body: Vec::new(), + imports: BTreeSet::new(), + imported_names: BTreeSet::new(), + } + } + + pub fn pushln(&mut self, text: String ) { + self.body.push(text); + } + + pub fn pushlns(&mut self, lines: Vec ) { + for l in lines { + self.body.push(l); + } + } + + pub fn import(&mut self, rs_module: &str, rs_name: &str) -> String { + let rsi = RustScopedImport{ + rs_module: rs_module.to_owned(), + rs_name: rs_name.to_owned(), + }; + if self.imports.contains(&rsi) { + // Use the already imported local name + rs_name.to_owned() + } else { + if self.imported_names.contains(rs_name) { + // Use the fully scoped name as the local name is already in use + format!("{}::{}", rs_module, rs_name) + } else { + // Add the import + self.imported_names.insert(rs_name.to_owned()); + self.imports.insert(rsi); + rs_name.to_owned() + } + } + } + + pub fn to_string(&self) -> String { + let mut lines = Vec::new(); + lines.push(format!("// @generated from adl module {}",self.module_name)); + lines.push("".to_owned()); + for rsi in &self.imports { + lines.push(format!("use {}::{};", rsi.rs_module, rsi.rs_name)); + } + lines.push("".to_owned()); + for l in &self.body { + lines.push(l.clone()) + } + lines.join("\n") + } +} + +#[macro_export] +macro_rules! fmtln { + ($dst:expr, $($arg:tt)*) => { + $dst.pushln(format!($($arg)*)) + }; +} + +#[derive(Eq,PartialEq,Ord,PartialOrd)] +struct RustScopedImport { + rs_module: String, + rs_name: String, +} \ No newline at end of file diff --git a/rust/compiler/src/cli/tsgen/astgen.rs b/rust/compiler/src/cli/tsgen/astgen.rs new file mode 100644 index 00000000..187a2ddb --- /dev/null +++ b/rust/compiler/src/cli/tsgen/astgen.rs @@ -0,0 +1,198 @@ +use std::cmp::Ordering; +use genco::tokens::{Item, ItemStr}; + +use crate::adlgen::sys::adlast2::{ + Annotations, Decl, DeclType, Field, Ident, NewType, ScopedName, Struct, + TypeDef, TypeExpr, TypeRef, Union, +}; +use crate::adlrt::custom::sys::types::maybe::Maybe; +use genco::prelude::*; + +const DQ: &str = "\""; + +pub struct TsScopedDeclGenVisitor<'a> { + pub module_name: &'a String, + pub t: &'a mut Tokens, +} + +impl TsScopedDeclGenVisitor<'_> { + fn lit(&mut self, s: &'static str) { + self.t.append(Item::Literal(ItemStr::Static(s))); + } +} + +impl TsScopedDeclGenVisitor<'_> { + fn visit_annotations(&mut self, d: &Annotations) { + let mut keys: Vec<&ScopedName> = d.0.keys().collect(); + keys.sort_by(|a, b| { + if &a.module_name == &b.module_name { + if a.name == b.name { + Ordering::Equal + } else if a.name > b.name { + Ordering::Greater + } else { + Ordering::Less + } + } else if a.module_name > b.module_name { + Ordering::Greater + } else { + Ordering::Less + } + }); + quote_in! { self.t => "annotations":$("[") }; + keys.iter().fold(false, |rest, key| { + if **key == crate::parser::docstring_scoped_name() { + return rest; + } + if rest { + self.lit(","); + } + self.lit("{"); + let jv = &serde_json::to_string(d.0.get(key).unwrap()).unwrap(); + quote_in! { self.t => "value":$jv,} + quote_in! { self.t => "key": } + self.lit("{"); + quote_in! { self.t => "moduleName":$DQ$(&key.module_name)$DQ,"name":$DQ$(&key.name)$DQ } + self.lit("}"); + self.lit("}"); + return true; + }); + quote_in! { self.t => $("]") }; + } + + pub fn visit_decl(&mut self, d: &Decl>) { + self.lit("{"); + self.visit_annotations(&d.annotations); + self.lit(","); + self.visit_decl_type(&d.r#type); + self.lit(","); + self.visit_decl_name(&d.name); + self.lit(","); + quote_in! { self.t => "version":{"kind":"nothing"}}; + self.lit("}"); + } + fn visit_decl_name(&mut self, n: &String) { + quote_in! { self.t => "name":$("\"")$n$("\"")}; + } + fn visit_decl_type(&mut self, r#type: &DeclType>) { + self.lit("\"type_\":{"); + match r#type { + DeclType::Struct(dt) => self.visit_struct(dt), + DeclType::Union(dt) => self.visit_union(dt), + DeclType::Newtype(dt) => self.visit_newtype(dt), + DeclType::Type(dt) => self.visit_typealias(dt), + } + self.lit("}"); + } + fn visit_struct(&mut self, dt: &Struct>) { + quote_in! { self.t => "kind":"struct_","value":$("{") } + self.visit_type_params(&dt.type_params); + self.lit(","); + self.lit("\"fields\":["); + dt.fields.iter().fold(false, |rest, f| { + if rest { + self.lit(","); + } + self.visit_field(f); + return true; + }); + self.lit("]"); + self.lit("}"); + } + fn visit_union(&mut self, dt: &Union>) { + quote_in! { self.t => "kind":"union_","value":$("{") } + self.visit_type_params(&dt.type_params); + self.lit(","); + self.lit("\"fields\":["); + dt.fields.iter().fold(false, |rest, f| { + if rest { + self.lit(","); + } + self.visit_field(f); + return true; + }); + self.lit("]"); + self.lit("}"); + } + fn visit_newtype(&mut self, dt: &NewType>) { + quote_in! { self.t => "kind":"newtype_","value":$("{") } + self.visit_type_params(&dt.type_params); + self.lit(","); + self.visit_default(&dt.default); + self.lit(","); + quote_in! { self.t => "typeExpr":} + self.visit_type_expr(&dt.type_expr); + self.lit("}"); + } + fn visit_typealias(&mut self, dt: &TypeDef>) { + quote_in! { self.t => "kind":"type_","value":$("{") } + self.visit_type_params(&dt.type_params); + self.lit(","); + quote_in! { self.t => "typeExpr":} + self.visit_type_expr(&dt.type_expr); + self.lit("}"); + } + fn visit_type_params(&mut self, tps: &Vec) { + quote_in! { self.t => "typeParams":[$(for tp in tps join (,) => $DQ$tp$DQ)]} + } + fn visit_field(&mut self, f: &Field>) { + self.lit("{"); + self.visit_annotations(&f.annotations); + self.lit(","); + quote_in! { self.t => "serializedName":$("\"")$(&f.serialized_name)$("\""), } + self.visit_default(&f.default); + self.lit(","); + quote_in! { self.t => "name":$("\"")$(&f.name)$("\"")}; + self.lit(","); + quote_in! { self.t => "typeExpr":} + self.visit_type_expr(&f.type_expr); + self.lit("}"); + } + fn visit_default(&mut self, f: &Maybe) { + quote_in! { self.t => "default":$("{")}; + match f { + Maybe(None) => { + quote_in! { self.t => "kind":"nothing"} + } + Maybe(Some(v)) => { + let jv = &serde_json::to_string(&v).unwrap(); + quote_in! { self.t => "kind":"just","value":$(jv)}; + } + } + quote_in! { self.t => $("}")}; + } + fn visit_type_expr(&mut self, te: &TypeExpr) { + quote_in! { self.t => $("{")} + self.visit_type_ref(&te.type_ref); + quote_in! { self.t => ,"parameters":$("[")} + te.parameters.iter().fold(false, |rest, p| { + if rest { + self.lit(","); + } + self.visit_type_expr(p); + return true; + }); + self.lit("]"); + self.lit("}"); + } + fn visit_type_ref(&mut self, te: &TypeRef) { + quote_in! { self.t => "typeRef":$("{")} + match te { + TypeRef::ScopedName(n) => { + quote_in! { self.t => "kind":"reference","value":{"moduleName":$("\"")$(&n.module_name)$("\""),"name":$("\"")$(&n.name)$("\"")}}; + } + TypeRef::LocalName(n) => { + quote_in! { self.t => "kind":"reference","value":{"moduleName":$("\"")$(self.module_name)$("\""),"name":$("\"")$(n)$("\"")}}; + } + TypeRef::Primitive(n) => { + let p = crate::processing::primitives::str_from_prim(n.clone()); + // let p = &serde_json::to_string(n).unwrap(); + quote_in! { self.t => "kind":"primitive","value":$DQ$p$DQ}; + } + TypeRef::TypeParam(n) => { + quote_in! { self.t => "kind":"typeParam","value":$("\"")$n$("\"")}; + } + } + self.lit("}"); + } +} \ No newline at end of file diff --git a/rust/compiler/src/cli/tsgen/defaultval.rs b/rust/compiler/src/cli/tsgen/defaultval.rs new file mode 100644 index 00000000..7e5e7710 --- /dev/null +++ b/rust/compiler/src/cli/tsgen/defaultval.rs @@ -0,0 +1,656 @@ +use std::collections::HashMap; + +use anyhow::anyhow; +use convert_case::{Case, Casing}; +use serde_json::Value; + +use crate::adlgen::sys::adlast2::{ + DeclType, PrimitiveType, ScopedName, TypeExpr, TypeRef, Decl1, Module1, Field1, Union1, +}; +use crate::processing::resolver::Resolver; +use genco::prelude::*; + +const DQ: &str = "\""; +const OC: &str = "{"; +const CC: &str = "}"; +const OP: &str = "("; +const CP: &str = ")"; +const OSB: &str = "["; +const CSB: &str = "]"; + +pub struct ResolverModule<'a> { + pub module: &'a Module1, + pub resolver: &'a Resolver, +} + +pub struct TsDefaultValue<'a> { + pub ctx: &'a ResolverModule<'a>, + pub decl: &'a Decl1, + pub type_map: &'a HashMap>, + // pub depth: Box, +} + +impl TsDefaultValue<'_> { + fn create_wrapped_err(&self, f_name: &String, msg: String) -> anyhow::Result<()> { + return Err(anyhow!( + "Error in {}.{}::{}.\n\t{}", + self.ctx.module.name, + self.decl.name, + f_name, + msg, + )); + } + + fn create_err_union(&self, f_name: &String, val: &Value) -> anyhow::Result<()> { + let x = serde_json::to_string(val).unwrap(); + // todo!(); + return Err(anyhow!( + "Union expected a JSON object with one elememnt. For {}.{}::{} received '{}'", + self.ctx.module.name, + self.decl.name, + f_name, + x + )); + } + + fn create_err_union_te(&self, b_name: &String) -> anyhow::Result<()> { + return Err(anyhow!( + "Union branch with serialized_name not found. For {}.{} branch name '{}'", + self.ctx.module.name, + self.decl.name, + b_name + )); + } + + fn create_err_union_void_branch(&self, b_name: &String) -> anyhow::Result<()> { + return Err(anyhow!( + "Union branch type Void expected. For {}.{} branch name '{}'", + self.ctx.module.name, + self.decl.name, + b_name + )); + } + + fn create_err(&self, typename: &str, f_name: &String, val: &Value) -> anyhow::Result<()> { + let x = serde_json::to_string(val).unwrap(); + // todo!(); + return Err(anyhow!( + "default value does not match. Expected '{}' for {}.{}::{} received '{}'", + typename, + self.ctx.module.name, + self.decl.name, + f_name, + x + )); + } + + fn create_err_def_val_with_tp(&self, typename: &str, f_name: &String, tp: &String) -> anyhow::Result<()> { + return Err(anyhow!( + "default values cannot be created for decls with type parameters. For {} in {}.{}::{} hanging type param '{}'", + typename, + self.ctx.module.name, + self.decl.name, + f_name, + tp + )); + } + + fn create_err_msg( + &self, + typename: &str, + f_name: &String, + val: &Value, + msg: String, + ) -> anyhow::Result<()> { + let x = serde_json::to_string(val).unwrap(); + return Err(anyhow!( + "default value does not match. Expected '{}' for {}.{}::{} received '{}'\n{}", + typename, + self.ctx.module.name, + self.decl.name, + f_name, + x, + msg, + )); + } + + fn create_err_mismatch_type_params( + &self, + decl_name: &String, + got: usize, + expected: usize, + ) -> anyhow::Result<()> { + return Err(anyhow!( + "Mismatched number of type parameters. Type constructur for '{}.{}' expected {} arguments, but was passed {}", + self.ctx.module.name, + decl_name, + got, + expected, + )); + } + + fn create_err_missing_val(&self, f_name: &String) -> anyhow::Result<()> { + return Err(anyhow!( + "Missing value or default value. {}.{}::{}", + self.ctx.module.name, + self.decl.name, + f_name, + )); + } + + fn create_err_missing_type_param(&self, f_name: &String, tp: &String) -> anyhow::Result<()> { + return Err(anyhow!( + "Missing type param. {}.{}::{}<{}>", + self.ctx.module.name, + self.decl.name, + f_name, + tp, + )); + } + + fn create_err_resolve_scoped_name( + &self, + f_name: &String, + sn: &ScopedName, + ) -> anyhow::Result<()> { + return Err(anyhow!( + "Cannot resolve scoped name {}.{}. {}.{}::{}", + sn.module_name, + sn.name, + self.ctx.module.name, + self.decl.name, + f_name, + )); + } + + fn create_err_resolve_module( + &self, + f_name: &String, + module_name: &String, + ) -> anyhow::Result<()> { + return Err(anyhow!( + "Cannot resolve module name {}. From {}.{}::{}", + module_name, + self.ctx.module.name, + self.decl.name, + f_name, + )); + } +} + +impl TsDefaultValue<'_> { + pub fn gen_default_value( + &self, + t: &mut Tokens, + field: &Field1, + val: Option<&Value>, + ) -> anyhow::Result<()> { + let val1 = match val { + Some(v) => v, + None => match &field.default.0 { + Some(v) => v, + None => { + return self.create_err_missing_val(&field.name); + } + }, + }; + self.gen_type_expr(t, &field.name, &field.type_expr, val1)?; + Ok(()) + } + + pub fn gen_type_expr( + &self, + t: &mut Tokens, + f_name: &String, + type_expr: &TypeExpr, + val: &Value, + ) -> anyhow::Result<()> { + match &type_expr.type_ref { + TypeRef::ScopedName(sn) => { + let resolver = self.ctx.resolver; + if let Some(m_remote) = resolver.get_module(&sn.module_name) { + if let Some(decl) = resolver.get_decl(sn) { + let dvg = TsDefaultValue { + ctx: &ResolverModule { + module: &m_remote, + resolver, + }, + decl, + type_map: self.type_map, + }; + // gen_decl wraps errors + dvg.gen_decl(t, decl, type_expr, f_name, val)? + } else { + return self.create_err_resolve_scoped_name(f_name, sn); + } + } else { + return self.create_err_resolve_module(f_name, &sn.module_name); + } + } + TypeRef::LocalName(d) => { + let sn = &ScopedName { + module_name: self.ctx.module.name.clone(), + name: d.clone(), + }; + if let Some(decl) = self.ctx.resolver.get_decl(sn) { + // gen_decl wraps errors + self.gen_decl(t, decl, type_expr, f_name, val)? + } else { + return self.create_err_resolve_scoped_name(f_name, sn); + } + } + TypeRef::Primitive(d) => { + self.gen_primitive(t, &f_name, d, val, &type_expr.parameters)?; + } + TypeRef::TypeParam(d) => { + // if self.depth.to_be() > 30 { + // todo!() + // } + // self.depth = Box::new(self.depth.to_be()+1); + if let Some(te) = self.type_map.get(d) { + self.gen_type_expr(t, f_name, te, val)?; + } else { + return self.create_err_missing_type_param(&f_name, d); + } + } + } + return Ok(()); + } + + /// Creates a new TsDefaultValue for decl arg with a new type_map and calls gen_type_ref. + /// Wraps an errors so there is context. + fn gen_decl( + &self, + t: &mut Tokens, + decl: &Decl1, + type_expr: &TypeExpr, + f_name: &String, + val: &Value, + ) -> anyhow::Result<()> { + let type_params = crate::utils::ast::get_type_params(decl); + if type_expr.parameters.len() != type_params.len() { + return self.create_err_mismatch_type_params( + &decl.name, + type_params.len(), + type_expr.parameters.len(), + ); + } + let mut type_map: HashMap> = HashMap::new(); + for (i, tp) in type_params.iter().enumerate() { + let te_p = type_expr.parameters.get(i).unwrap(); + // TODO is this enough, or does it need to be in a loop? + // I don't think so, but ... + // loop { + if let TypeRef::TypeParam(tp0) = &te_p.type_ref { + if let Some(te_p2) = self.type_map.get(tp0) { + type_map.insert(tp.to_string(), te_p2); + } else { + // decl with type_param on left but not on the right (transitively). + // if this is not ok with will be caught later. + } + } else { + type_map.insert(tp.to_string(), te_p); + } + // else { + // break; + // } + // } + } + let tsgen_te = &mut TsDefaultValue { + ctx: self.ctx, + type_map: &type_map, + decl, + // depth: Box::new(0), + }; + let inner = tsgen_te.gen_type_ref(t, &f_name, val); + if let Err(e) = inner { + return self.create_wrapped_err(f_name, e.to_string()); + } + return Ok(()); + } + + fn gen_type_ref( + &self, + t: &mut Tokens, + f_name: &String, + val: &Value, + ) -> anyhow::Result<()> { + match &self.decl.r#type { + DeclType::Struct(ty) => { + if let Some(obj) = val.as_object() { + quote_in! { *t => $OC }; + let mut rest = false; + for f0 in &ty.fields { + let dvg = &mut TsDefaultValue { + ctx: self.ctx, + decl: self.decl, + type_map: &self.type_map, + // depth: Box::new(0), + }; + if rest { + quote_in! { *t => ,$[' '] }; + } else { + rest = true; + } + quote_in! { *t => $(&f0.name) :$[' ']} + dvg.gen_default_value(t, &f0, obj.get(&f0.serialized_name))?; + // let inner = dvg.gen_default_value(t, &f0, obj.get(&f0.serialized_name)); + // if let Err(e) = inner { + // return self.create_wrapped_err( f_name, e.to_string()); + // } + } + quote_in! { *t => $CC }; + } else { + return self.create_err("object", f_name, val); + } + } + DeclType::Union(ty) => match val { + Value::String(b_name) => { + if is_enum(ty) { + quote_in! { *t => $DQ$(b_name)$DQ }; + return Ok(()); + } + let te = ty.fields.iter().find(|f| f.serialized_name == *b_name); + if let Some(te0) = te { + match &te0.type_expr.type_ref { + TypeRef::Primitive(p) => match p { + PrimitiveType::Void => {} + _ => { + return self.create_err_union_void_branch(b_name); + } + }, + _ => { + return self.create_err_union_void_branch(b_name); + } + } + quote_in! { *t => $OC }; + quote_in! { *t => kind : $DQ$(b_name)$DQ }; + quote_in! { *t => $CC }; + } else { + return self.create_err_union_te(b_name); + } + } + Value::Object(obj) => { + let keys: Vec<&String> = obj.keys().collect(); + if keys.len() != 1 { + return self.create_err_union(f_name, val); + } + let ser_name = keys[0]; + let b_val = obj.get(ser_name); + let branch = ty.fields.iter().find(|f| f.serialized_name == *ser_name); + if let Some(branch) = branch { + quote_in! { *t => $OC }; + quote_in! { *t => kind : $DQ$(&branch.name)$DQ, value :$[' ']}; + self.gen_default_value(t, branch, b_val)?; + quote_in! { *t => $CC }; + } else { + return self.create_err_union_te(ser_name); + } + } + _ => return self.create_err("object or string", f_name, val), + }, + DeclType::Type(ty) => { + self.gen_type_expr(t, f_name, &ty.type_expr, val)?; + } + DeclType::Newtype(ty) => { + self.gen_type_expr(t, f_name, &ty.type_expr, val)?; + } + }; + Ok(()) + } + + fn gen_primitive( + &self, + t: &mut Tokens, + f_name: &String, + type_: &PrimitiveType, + val: &Value, + type_params: &Vec>, + ) -> anyhow::Result<()> { + match type_ { + PrimitiveType::Void => { + if let Some(_) = val.as_null() { + quote_in! { *t => null } + } else { + return self.create_err("Void", f_name, val); + } + } + PrimitiveType::Bool => { + if let Some(v) = val.as_bool() { + if v { + quote_in! { *t => true } + } else { + quote_in! { *t => false } + } + } else { + return self.create_err("Bool", f_name, val); + } + } + PrimitiveType::Int8 => { + if let Some(v) = val.as_i64() { + // TODO check bounds + quote_in! { *t => $(v) } + } else { + return self.create_err("Int8", f_name, val); + } + } + PrimitiveType::Int16 => { + if let Some(v) = val.as_i64() { + // TODO check bounds + quote_in! { *t => $(v) } + } else { + return self.create_err("Int16", f_name, val); + } + } + PrimitiveType::Int32 => { + if let Some(v) = val.as_i64() { + // TODO check bounds + quote_in! { *t => $(v) } + } else { + return self.create_err("Int32", f_name, val); + } + } + PrimitiveType::Int64 => { + if let Some(v) = val.as_i64() { + // TODO check bounds + quote_in! { *t => $(v) } + } else { + return self.create_err("Int64", f_name, val); + } + } + PrimitiveType::Word8 => { + if let Some(v) = val.as_u64() { + // TODO check bounds + quote_in! { *t => $(v) } + } else { + return self.create_err("Word8", f_name, val); + } + } + PrimitiveType::Word16 => { + if let Some(v) = val.as_u64() { + // TODO check bounds + quote_in! { *t => $(v) } + } else { + return self.create_err("Word8", f_name, val); + } + } + PrimitiveType::Word32 => { + if let Some(v) = val.as_u64() { + // TODO check bounds + quote_in! { *t => $(v) } + } else { + return self.create_err("Word8", f_name, val); + } + } + PrimitiveType::Word64 => { + if let Some(v) = val.as_u64() { + // TODO check bounds + quote_in! { *t => $(v) } + } else { + return self.create_err("Word8", f_name, val); + } + } + PrimitiveType::Float => { + if let Some(v) = val.as_f64() { + // Is there a standard JS float format? + let v = format!("{}", v); + quote_in! { *t => $(v) } + } else { + return self.create_err("Float", f_name, val); + } + } + PrimitiveType::Double => { + if let Some(v) = val.as_f64() { + let v = format!("{}", v); + quote_in! { *t => $(v) } + } else { + return self.create_err("Float", f_name, val); + } + } + PrimitiveType::Json => match serde_json::to_string(val) { + Ok(x) => { + quote_in! { *t => $x }; + } + Err(e) => { + return self.create_err_msg("Json", f_name, val, e.to_string()); + } + }, + PrimitiveType::ByteVector => { + // duplicating existing adlc, but it's not quite correct. + // needs to import b64 + + // todo check valid base64 encoding + if let Some(v) = val.as_str() { + quote_in! { *t => b64.toByteArray($DQ$(v)$DQ) } + } else { + return self.create_err("Bytes", f_name, val); + } + } + PrimitiveType::String => { + if let Some(v) = val.as_str() { + quote_in! { *t => $DQ$(v)$DQ } + } else { + return self.create_err("String", f_name, val); + } + } + PrimitiveType::Vector => { + if let Some(vs) = val.as_array() { + quote_in! { *t => $OSB } + let mut rest = false; + for v in vs { + if rest { + quote_in! { *t => ,$[' '] }; + } else { + rest = true; + } + // we have already checked that type_params.len() == 1 + self.gen_type_expr(t, f_name, type_params.get(0).unwrap(), v)?; + } + quote_in! { *t => $CSB } + } else { + return self.create_err("Vector", f_name, val); + } + } + PrimitiveType::StringMap => { + if let Some(vs) = val.as_object() { + quote_in! { *t => $OC } + let mut rest = false; + // serde use a BTreeMap, same a Haskell. + // If `preserve_order` feature is used for serde an index map would and the order would be different. + for (k, v) in vs { + if rest { + quote_in! { *t => ,$[' '] }; + } else { + rest = true; + } + quote_in! { *t => $DQ$(k)$DQ :$[' '] }; + // we have already checked that type_params.len() == 1 + self.gen_type_expr(t, f_name, type_params.get(0).unwrap(), v)?; + } + quote_in! { *t => $CC } + } else { + return self.create_err("StringMap", f_name, val); + } + } + PrimitiveType::Nullable => { + if val.is_null() { + quote_in! { *t => null } + } else { + self.gen_type_expr(t, f_name, type_params.get(0).unwrap(), val)?; + } + } + PrimitiveType::TypeToken => { + if None == val.as_null() { + return self.create_err("TypeToken", f_name, val); + } + let param = type_params.get(0).unwrap(); + match ¶m.type_ref { + TypeRef::TypeParam(tp) => { + if let Some(te) = self.type_map.get(tp) { + self.gen_token_type(t, f_name, te)?; + } else { + return self.create_err_def_val_with_tp("TypeToken", f_name, tp); + // quote_in! { *t => BUG:texprTypeVariable({{$(tp)}}) }; + } + }, + _ => todo!() + } + } + } + + Ok(()) + } + + fn gen_token_type( + &self, + t: &mut Tokens, + f_name: &String, + te: &TypeExpr, + ) -> anyhow::Result<()> { + match &te.type_ref { + TypeRef::ScopedName(sn) => { + let i_name = sn.module_name.replace(".", "_").to_case(Case::Snake); + quote_in! { *t => $(i_name).texpr$(&sn.name)$OP }; + for tp in &te.parameters { + self.gen_token_type(t, f_name, tp)?; + } + quote_in! { *t => $CP }; + } + TypeRef::LocalName(ln) => { + quote_in! { *t => texpr$(ln)$OP }; + for tp in &te.parameters { + self.gen_token_type(t, f_name, tp)?; + } + quote_in! { *t => $CP }; + }, + TypeRef::Primitive(p) => { + let pname = format!("{:?}", p); + quote_in! { *t => ADL.texpr$(pname)$OP }; + for tp in &te.parameters { + self.gen_token_type(t, f_name, tp)?; + } + quote_in! { *t => $CP }; + }, + TypeRef::TypeParam(tp) => { + dbg!(tp); + todo!(); + }, + } + + Ok(()) + } + +} + +pub fn is_enum(m: &Union1) -> bool { + m.fields + .iter() + .find(|f| match &f.type_expr.type_ref { + TypeRef::Primitive(p) => match p { + PrimitiveType::Void => false, + _ => true, + }, + _ => true, + }) + .is_none() +} diff --git a/rust/compiler/src/cli/tsgen/generate.rs b/rust/compiler/src/cli/tsgen/generate.rs new file mode 100644 index 00000000..823d05df --- /dev/null +++ b/rust/compiler/src/cli/tsgen/generate.rs @@ -0,0 +1,633 @@ +use convert_case::{Case, Casing}; +use std::collections::HashMap; + +use anyhow::anyhow; + +use genco::prelude::js::Import as JsImport; +use genco::prelude::*; +use genco::tokens::{Item, ItemStr}; + +use crate::adlgen::adlc::packaging::TypescriptGenOptions; +use crate::adlgen::sys::adlast2::{ + Annotations, Decl1, DeclType, Module1, NewType, PrimitiveType, ScopedName, Struct1, TypeDef, + TypeExpr, TypeRef, Union1, +}; +use crate::parser::docstring_scoped_name; +use crate::processing::resolver::Resolver; +use crate::utils::ast::get_type_params; + +use super::utils::{get_npm_pkg, npm_pkg_import, rel_import}; + +const SP: &str = " "; +const SQ: &str = "'"; + +pub struct TsGenVisitor<'a> { + pub npm_pkg: &'a Option, + pub module: &'a Module1, + pub resolver: &'a Resolver, + pub adlr: JsImport, + pub map: &'a mut HashMap, + pub opts: &'a TypescriptGenOptions, +} + +struct DeclPayload<'a> { + decl: &'a Decl1, + mname: &'a String, +} + +struct RttiPayload<'a> { + mname: String, + type_params: &'a Vec, +} + +impl TsGenVisitor<'_> { + pub fn gen_module(&mut self, t: &mut Tokens) -> anyhow::Result<()> { + quote_in! { *t => + $("/* @generated from adl module") $(self.module.name.clone()) $("*/") + $['\n'] + }; + self.gen_doc_comment(t, &self.module.annotations)?; + let mname = &self.module.name; + for decl in self.module.decls.iter() { + let payload = DeclPayload { + decl: decl, + mname: &mname.clone(), + }; + let r = match &decl.r#type { + DeclType::Struct(d) => self.gen_struct(t, d, payload), + DeclType::Union(d) => self.gen_union(t, d, payload), + DeclType::Newtype(d) => self.gen_newtype(t, d, payload), + DeclType::Type(d) => self.gen_type(t, d, payload), + }; + if let Err(_) = r { + return r; + } + } + lit( + t, + "export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = {\n", + ); + self.module.decls.iter().fold(false, |rest, decl| { + if rest { + lit(t, ",\n") + } + lit(t, " "); + quote_in! { *t => + $("\"")$(self.module.name.clone()).$(&decl.name)$("\"") : $(cap_opt(&decl.name, self.opts))_AST + }; + true + }); + lit(t, "\n};"); + for (_, v) in self.map.iter() { + let imp = &v.1; + quote_in! {*t => $(register (imp))} + } + Ok(()) + } +} + +impl TsGenVisitor<'_> { + fn gen_struct( + &mut self, + t: &mut Tokens, + m: &Struct1, + payload: DeclPayload<'_>, + ) -> anyhow::Result<()> { + let (decl, name) = (payload.decl, &payload.decl.name); + self.gen_doc_comment(t, &decl.annotations)?; + let te_trs: Vec> = m.fields.iter().map(|f| f.type_expr.clone()).collect(); + let mut has_make = true; + let fnames = used_type_params(&te_trs); + quote_in! { *t => + export interface $(cap_opt(name, self.opts))$(gen_type_params_(&fnames, &m.type_params)) {$['\r'] + $(for f in m.fields.iter() => + $(ref t => { + self.gen_doc_comment(t, &f.annotations)?; + let rt = self.rust_type(&f.type_expr).map_err(|s| anyhow!(s))?; + has_make = has_make && rt.0; + quote_in! { *t => + $SP$SP$(&f.name): $(rt.1);$['\r'] + } + }) + )}$['\r']$['\n'] + } + if has_make { + quote_in! { *t => + export function make$(cap_or__(name, self.opts))$(gen_type_params_(&fnames, &m.type_params))( + $(if m.fields.len() == 0 => _)input: { + $(for f in &m.fields => $(ref t => { + let rt = self.rust_type(&f.type_expr).map_err(|s| anyhow!(s))?; + let mut has_default = false; + if let Some(_) = f.default.0 { + has_default = true; + } + quote_in! { *t => $(&f.name)$(if has_default => ?): $(rt.1),$['\r']} + })) + } + ): $(cap_opt(name, self.opts))$(gen_type_params_(&fnames, &m.type_params)) { + return { + $(for f in &m.fields => $(ref t => { + if let Some(_) = f.default.0 { + quote_in! { *t => $(&f.name): input.$(&f.name) === undefined ?$[' '] } + let dvg = &mut crate::cli::tsgen::defaultval::TsDefaultValue{ + ctx: &crate::cli::tsgen::defaultval::ResolverModule { + module: self.module, + resolver: self.resolver, + }, + decl: decl, + type_map: &HashMap::new(), + // depth: Box::new(0), + }; + dvg.gen_default_value(t, &f, None)?; + quote_in! { *t => $[' ']: input.$(&f.name),$['\r'] } + } else { + quote_in! { *t => $(&f.name): input.$(&f.name),$['\r'] } + } + })) + }; + } + } + } + self.gen_rtti( + t, + decl, + &RttiPayload { + mname: payload.mname.clone(), + type_params: &m.type_params, + }, + )?; + Ok(()) + } +} + +impl TsGenVisitor<'_> { + fn gen_union( + &mut self, + t: &mut Tokens, + m: &Union1, + payload: DeclPayload<'_>, + ) -> anyhow::Result<()> { + let name = &payload.decl.name; + // lit(t, "// union \n"); + + let type_suffix = |name0: &String| { + if self.opts.capitalize_type_names || self.opts.capitalize_branch_names_in_types { + to_title(name0) + } else { + name0.clone() + } + }; + + if !crate::cli::tsgen::defaultval::is_enum(m) { + let mut opts = vec![]; + for b in m.fields.iter() { + let bname = b.name.clone(); + + let rtype = self.rust_type(&b.type_expr).map_err(|s| anyhow!(s))?; + let used = used_type_params(&vec![b.type_expr.clone()]); + + opts.push((bname.clone(), rtype.clone().1, b)); + + let is_void = match &b.type_expr.type_ref { + TypeRef::Primitive(p) => match p { + PrimitiveType::Void => true, + _ => false, + }, + _ => false, + }; + if is_void { + quote_in! { *t => + export interface $(cap_opt(name, self.opts))_$(type_suffix(&bname.clone()))$(gen_type_params_(&used, &m.type_params)) { + kind: $SQ$(bname.clone())$SQ; + }$['\r'] + } + } else { + quote_in! { *t => + export interface $(cap_opt(name, self.opts))_$(type_suffix(&bname.clone()))$(gen_type_params_(&used, &m.type_params)) { + kind: $SQ$(bname.clone())$SQ; + value: $(rtype.1.clone()); + }$['\r'] + } + } + } + let te_trs: Vec> = + m.fields.iter().map(|f| f.type_expr.clone()).collect(); + let tp_names = used_type_params(&te_trs); + quote_in! { *t => $['\n'] } + self.gen_doc_comment(t, &payload.decl.annotations)?; + quote_in! { *t => + export type $(cap_opt(name, self.opts))$(gen_type_params_(&tp_names, &m.type_params)) = $(for n in m.fields.iter().map(|b| &b.name) join ( | ) => + $(cap_opt(name, self.opts))_$(type_suffix(n))$(gen_type_params_(&tp_names, &m.type_params)) + ); + + export interface $(cap_opt(name, self.opts))Opts$(gen_type_params_(&tp_names, &m.type_params)) { + $(for opt in opts => $(ref t => { + self.gen_doc_comment(t, &opt.2.annotations)?; + quote_in! { *t => $(opt.0): $(opt.1);$['\r'] } + })) + }$['\n'] + + export function make$(cap_opt(name, self.opts))<$(gen_raw_type_params_(&tp_names, &m.type_params))K extends keyof $(cap_opt(name, self.opts))Opts$(gen_type_params_(&tp_names, &m.type_params))>(kind: K, value: $(cap_opt(name, self.opts))Opts$(gen_type_params_(&tp_names, &m.type_params))[K]) { return {kind, value}; }$['\n'] + } + } else { + let b_names: Vec<&String> = m.fields.iter().map(|f| &f.name).collect(); + quote_in! { *t => $['\n'] } + self.gen_doc_comment(t, &payload.decl.annotations)?; + // Note doc comments on enum branches is ignored by TSDoc + // see https://github.com/microsoft/tsdoc/issues/164 + quote_in! { *t => + export type $name = $(for f in &m.fields join ( | ) => $SQ$(&f.name)$SQ); + $['\r'] + } + // quote_in! { *t => + // export type $name = $(for f in &m.fields join ( | ) => $(ref t => self.gen_doc_comment(t, &f.annotations)?;)$SQ$(&f.name)$SQ); + // $['\r'] + // } + quote_in! { *t => export const values$(cap_opt(name, self.opts)) : $(cap_opt(name, self.opts))[] =$[' '] + [$(for n in b_names join (, ) => $SQ$(n)$SQ)];$['\r'] + } + } + self.gen_rtti( + t, + payload.decl, + &RttiPayload { + mname: payload.mname.clone(), + type_params: &m.type_params, + }, + )?; + Ok(()) + } + + fn gen_newtype( + &mut self, + t: &mut Tokens, + m: &NewType>, + payload: DeclPayload<'_>, + ) -> anyhow::Result<()> { + let name = &payload.decl.name; + let rtype = self.rust_type(&m.type_expr).map_err(|s| anyhow!(s))?; + + let used = used_type_params(&vec![m.type_expr.clone()]); + self.gen_doc_comment(t, &payload.decl.annotations)?; + quote_in! { *t => + export type $(cap_opt(name, self.opts))$(gen_type_params_(&used, &m.type_params)) = $(rtype.1.clone()); + } + self.gen_rtti( + t, + payload.decl, + &RttiPayload { + mname: payload.mname.clone(), + type_params: &m.type_params, + }, + )?; + quote_in! { *t => + $['\n'] + } + Ok(()) + } + + fn gen_type( + &mut self, + t: &mut Tokens, + m: &TypeDef>, + payload: DeclPayload<'_>, + ) -> anyhow::Result<()> { + let name = &payload.decl.name; + let rtype = self.rust_type(&m.type_expr).map_err(|s| anyhow!(s))?; + + let used = used_type_params(&vec![m.type_expr.clone()]); + + self.gen_doc_comment(t, &payload.decl.annotations)?; + quote_in! { *t => + export type $(cap_opt(name, self.opts))$(gen_type_params_(&used, &m.type_params)) = $(rtype.1.clone()); + } + self.gen_rtti( + t, + payload.decl, + &RttiPayload { + mname: payload.mname.clone(), + type_params: &m.type_params, + }, + )?; + quote_in! { *t => + $['\n'] + } + Ok(()) + } + + /// returns (has_make_function,ts type) + fn rust_type(&mut self, te: &TypeExpr) -> Result<(bool, String), String> { + match &te.type_ref { + TypeRef::ScopedName(n) => { + self.check_type_params_len(n, &te.parameters)?; + self.tstype_from_scoped_name(n, &te.parameters) + } + TypeRef::LocalName(n) => { + let sn = &ScopedName { + module_name: self.module.name.to_string(), + name: n.to_string(), + }; + self.check_type_params_len(sn, &te.parameters)?; + self.tstype_from_local_name(n, &te.parameters) + } + TypeRef::Primitive(n) => self.tstype_from_prim(n, &te.parameters), + TypeRef::TypeParam(n) => { + if te.parameters.len() != 0 { + return Err(format!("Type parameters take argument(s) provided. Type parameters cannot be parameterized. Type {}", n.clone())) + } + Ok((true, n.clone())) + }, + } + } + + fn check_type_params_len( + &mut self, + scoped_name: &ScopedName, + params: &Vec>, + ) -> Result<(), String> { + if let Some(decl) = self.resolver.get_decl(scoped_name) { + let type_params = get_type_params(&decl); + if type_params.len() != params.len() { + return Err(format!( + "Mismatch number of type params. Need {} received {}. For {}.{}", + type_params.len(), + params.len(), + scoped_name.module_name, + scoped_name.name + )); + } + } else { + return Err(format!( + "Can't resolve decl {}.{}", + scoped_name.module_name, scoped_name.name + )); + } + Ok(()) + } + + fn tstype_from_scoped_name( + &mut self, + scoped_name: &ScopedName, + params: &Vec>, + ) -> Result<(bool, String), String> { + let npm_pkg2 = if let Some(m2) = self.resolver.get_module(&scoped_name.module_name) { + get_npm_pkg(&m2) + } else { + None + }; + let npm_pkg = get_npm_pkg(self.module); + let imp = self.map.entry(scoped_name.clone()).or_insert_with(|| { + let path = if !self.opts.generate_transitive && npm_pkg2 != None && npm_pkg2 != npm_pkg { + npm_pkg_import(npm_pkg2.unwrap(), scoped_name.module_name.clone()) + } else { + let same_pkg = npm_pkg2 == self.npm_pkg.clone(); + + rel_import(same_pkg, &self.module.name, &scoped_name.module_name) + }; + let i_name = scoped_name + .module_name + .replace(".", "_") + .to_case(Case::Snake); + let import = js::import(path, i_name.clone()).into_wildcard(); + (i_name, import) + }); + let local_name = format!("{}.{}", imp.0.to_string(), scoped_name.name); + self.tstype_from_local_name(&local_name, params) + } + + fn tstype_from_local_name( + &mut self, + local_name: &String, + params: &Vec>, + ) -> Result<(bool, String), String> { + if params.len() > 0 { + let mut tperr = vec![]; + let tps: Vec = params + .iter() + .filter_map(|p| { + let r = self.rust_type(p); + match r { + Ok((_, t)) => Some(t), + Err(e) => { + tperr.push(e); + return None; + } + } + }) + .collect(); + if tperr.len() != 0 { + let msg = tperr.join("\n\t"); + return Err(format!("Error constructing type param: {}", msg)); + } + let tpstr = format!("{}<{}>", local_name.clone(), tps.join(", ")); + return Ok((true, tpstr)); + } + Ok((true, local_name.clone())) + } + + fn tstype_from_prim( + &mut self, + prim: &PrimitiveType, + params: &Vec>, + ) -> Result<(bool, String), String> { + match prim { + PrimitiveType::Void => Ok((true, "null".to_string())), + PrimitiveType::Bool => Ok((true, "boolean".to_string())), + PrimitiveType::Int8 => Ok((true, "number".to_string())), + PrimitiveType::Int16 => Ok((true, "number".to_string())), + PrimitiveType::Int32 => Ok((true, "number".to_string())), + PrimitiveType::Int64 => Ok((true, "number".to_string())), + PrimitiveType::Word8 => Ok((true, "number".to_string())), + PrimitiveType::Word16 => Ok((true, "number".to_string())), + PrimitiveType::Word32 => Ok((true, "number".to_string())), + PrimitiveType::Word64 => Ok((true, "number".to_string())), + PrimitiveType::Float => Ok((true, "number".to_string())), + PrimitiveType::Double => Ok((true, "number".to_string())), + PrimitiveType::Json => Ok((true, "{}|null".to_string())), + PrimitiveType::ByteVector => Ok((true, "Uint8Array".to_string())), + PrimitiveType::String => Ok((true, "string".to_string())), + _ => { + if params.len() != 1 { + return Err(format!( "Primitive parameterized type require 1 and only one param. Type {:?} provided with {}", prim, params.len() )); + } + let param_type = self.rust_type(¶ms[0])?; + match prim { + PrimitiveType::Vector => { + return Ok((param_type.0, format!("{}[]", param_type.1))); + } + PrimitiveType::StringMap => Ok(( + param_type.0, + format!("{}[key: string]: {}{}", "{", param_type.1, "}"), + )), + PrimitiveType::Nullable => { + Ok((param_type.0, format!("({}|null)", param_type.1))) + } + PrimitiveType::TypeToken => { + Ok((false, format!("ADL.ATypeExpr<{}>", param_type.1))) + } + _ => Err(format!("unknown primitive {:?}", prim)), + } + } + } + } +} + +impl TsGenVisitor<'_> { + fn gen_rtti( + &mut self, + t: &mut Tokens, + decl: &Decl1, + payload: &RttiPayload<'_>, + ) -> anyhow::Result<()> { + // Generation AST holder + let name = &decl.name; + let mname = &payload.mname; + quote_in! { *t => + $['\n'] + const $(cap_opt(name, self.opts))_AST : $(&self.adlr).ScopedDecl = + {"moduleName":$("\"")$(mname.clone())$("\""),"decl":$(ref tok => { + let mut sdg = crate::cli::tsgen::astgen::TsScopedDeclGenVisitor{module_name: &mname.clone(), t: tok}; + sdg.visit_decl(decl); + })};$['\n'] + + export const sn$(cap_or__(name, self.opts)): $(&self.adlr).ScopedName = {moduleName:$("\"")$mname$("\""), name:$("\"")$name$("\"")};$['\n'] + + export function texpr$(cap_or__(name, self.opts))$(gen_type_params(payload.type_params))($(ref t => texpr_args(t, &payload.type_params))): ADL.ATypeExpr<$(cap_opt(name, self.opts))$(gen_type_params(payload.type_params))> { + return {value:{typeRef:{kind:"reference",value:sn$(cap_or__(name, self.opts))},parameters:[$(ref t => texpr_params(t, &payload.type_params))]}}; + } + $['\n'] + } + Ok(()) + } +} + +impl TsGenVisitor<'_> { + fn gen_doc_comment( + &mut self, + t: &mut Tokens, + annotations: &Annotations, + ) -> anyhow::Result<()> { + if let Some(ds) = annotations.0.get(&docstring_scoped_name()) { + lit(t, "/**\n"); + match ds { + serde_json::Value::String(y) => { + // TODO should this be trimmed? + quote_in! { *t => $(for line in y.lines() => $[' ']* $(line.trim())$['\r'] ) }; + } + serde_json::Value::Array(array) => { + for c in array.iter() { + if let Ok(x) = serde_json::to_string(&c.clone()) { + // TODO should this be trimmed? or should the output be "*$y" ie no space + let y = x[1..x.len() - 1].trim(); + quote_in! { *t => $[' ']* $(y)$['\r'] }; + } + } + } + _ => { + let j = serde_json::to_string(ds); + return Err(anyhow!( + "error processing doc comment expect array received JSON '{}'", + j.unwrap() + )); + } + } + lit(t, " */\n"); + } + Ok(()) + } +} + +fn lit(t: &mut Tokens, s: &'static str) { + t.append(Item::Literal(ItemStr::Static(s))); +} + +fn gen_type_params<'a>(type_params: &'a Vec) -> impl FormatInto + 'a { + quote_fn! { + $(if type_params.len() > 0 => <$(for tp in type_params join (, ) => $tp)>) + } +} + +fn gen_type_params_<'a>( + used: &'a Vec, + type_params: &'a Vec, +) -> impl FormatInto + 'a { + quote_fn! { + $(if type_params.len() > 0 => <$(for tp in type_params join (, ) => $(if !used.contains(tp) => _)$tp)>) + } +} + +fn gen_raw_type_params_<'a>( + used: &'a Vec, + type_params: &'a Vec, +) -> impl FormatInto + 'a { + quote_fn! { + $(if type_params.len() > 0 => $(for tp in type_params join (, ) => $(if !used.contains(tp) => _)$tp),$[' ']) + } +} + +fn texpr_args<'a>(mut t: &mut Tokens, type_params: &'a Vec) { + type_params.iter().fold(false, |rest, p| { + if rest { + quote_in! { t => ,$[' '] }; + } + quote_in! { t => texpr$p : ADL.ATypeExpr<$p> }; + true + }); +} + +fn texpr_params<'a>(mut t: &mut Tokens, type_params: &'a Vec) { + type_params.iter().fold(false, |rest, p| { + if rest { + quote_in! { t => , }; + } + quote_in! { t => texpr$(p).value }; + true + }); +} + +fn used_type_params(te_trs: &Vec>) -> Vec { + let fnames = &mut Vec::new(); + collect_used_type_params(&te_trs, fnames); + fnames.to_vec() +} + +fn collect_used_type_params(te_trs: &Vec>, mut fnames: &mut Vec) { + te_trs.iter().for_each(|te| { + if let TypeRef::TypeParam(tp) = &te.type_ref { + fnames.push(tp.clone()); + } + collect_used_type_params(&te.parameters, &mut fnames); + }) +} + +fn cap_opt(name: &String, opts: &TypescriptGenOptions) -> String { + if opts.capitalize_type_names { + return to_title(name); + } + name.clone() +} + +pub fn cap_or__(input: &String, opts: &TypescriptGenOptions) -> String { + if opts.capitalize_type_names { + return to_title(input); + } + let mut c = input.chars(); + match c.next() { + None => String::new(), + Some(first) => { + if first.is_uppercase() { + return input.clone(); + } else { + return "_".to_string() + input; + } + } + } +} + +pub fn to_title(input: &String) -> String { + let mut c = input.chars(); + match c.next() { + None => String::new(), + Some(first) => first.to_uppercase().to_string() + &String::from(&input[1..]), + } +} diff --git a/rust/compiler/src/cli/tsgen/mod.rs b/rust/compiler/src/cli/tsgen/mod.rs new file mode 100644 index 00000000..b0ede614 --- /dev/null +++ b/rust/compiler/src/cli/tsgen/mod.rs @@ -0,0 +1,606 @@ +use regex; + +use std::io::Write as _; + +use regex::bytes::Regex; + +use std::collections::{HashMap, HashSet}; +use std::fs; +use std::ops::Deref; +use std::path::{Path, PathBuf}; + +use anyhow::anyhow; + +use genco::fmt::{self, Indentation}; +use genco::prelude::*; + +use crate::adlgen::adlc::packaging::{ + AdlPackageRefType, AdlWorkspace, ModuleSrc, NpmPackage, Payload1, TsRuntimeOpt, + TsStyle, TsWriteRuntime, TypescriptGenOptions, +}; +use crate::adlgen::sys::adlast2::Module1; +use crate::adlgen::sys::adlast2::{self as adlast}; +use crate::adlstdlib::get_file_names; +use crate::cli::tsgen::utils::{get_npm_pkg, npm_pkg_import, IndexEntry}; +use crate::processing::loader::AdlLoader; +use crate::processing::resolver::Resolver; +use crate::processing::writer::TreeWriter; + +mod astgen; +mod defaultval; +mod generate; +#[cfg(test)] +mod tests; +mod utils; +use rust_embed::RustEmbed; + +#[derive(RustEmbed)] +#[folder = "src/cli/tsgen/ts-runtime/"] +struct Asset; + +const TSC_B64: &[u8] = + b"import {fromByteArray as b64Encode, toByteArray as b64Decode} from 'base64-js'"; +const DENO_B64: &[u8] = b"import {encode as b64Encode, decode as b64Decode} from 'https://deno.land/std@0.97.0/encoding/base64.ts'"; + +fn get_modules( + opts: &TypescriptGenOptions, + wrk_root: Option, + r#ref: AdlPackageRefType, +) -> Result, anyhow::Error> { + match r#ref { + AdlPackageRefType::Dir(d) => match &opts.modules { + ModuleSrc::All => { + if wrk_root == None { + return Err(anyhow!("wrk_root needed when module src all specified")); + } + let pkg_root = wrk_root.unwrap().join(d.path.clone()).canonicalize()?; + if let Some(pkg_root_str) = pkg_root.as_os_str().to_str() { + Ok(walk_and_collect_adl_modules(pkg_root_str, &pkg_root)) + } else { + return Err(anyhow!("Could get str from pkg_root")); + } + } + ModuleSrc::Modules(ms) => Ok(ms.clone()), + }, + AdlPackageRefType::Embedded(e) => match &opts.modules { + ModuleSrc::Modules(ms) => Ok(ms.clone()), + ModuleSrc::All => Ok(get_file_names(e.alias) + .iter() + .filter(|f| { + if let Some(ext) = f.extension() { + ext == "adl" + } else { + false + } + }) + .map(|p| { + let mut p0 = p.clone(); + p0.set_extension(""); + p0.to_str().unwrap().to_string().replace("/", ".") + }) + .collect()), + }, + } +} + +fn walk_and_collect_adl_modules(pkg_root: &str, cwd: &PathBuf) -> Vec { + let mut mods = vec![]; + if let Ok(files) = fs::read_dir(cwd) { + for file in files { + if let Ok(file) = file { + let path = file.path(); + if path.is_file() { + if let Some(ext) = path.extension() { + if ext == "adl" { + if let Some(name) = path.to_str() { + let name1 = &name[(pkg_root.len() + 1)..(name.len() - 4)]; + let name2 = name1.replace("/", "."); + log::info!(" adding module {}", name2); + mods.push(name2); + } + } + } + } + if path.is_dir() { + mods.append(&mut walk_and_collect_adl_modules(pkg_root, &path)); + } + } + } + } + mods +} + +pub fn tsgen( + strip_first: bool, + packageable: bool, + loader: Box, + opts: &TypescriptGenOptions, + wrk_root: Option, + r#ref: AdlPackageRefType, + dep_adl_pkgs: Vec<&Payload1>, +) -> anyhow::Result<()> { + if opts.outputs == None { + // not gen for this pkg + return Ok(()); + } + let outputs = opts.outputs.as_ref().unwrap(); + let (manifest, outputdir) = match outputs { + crate::adlgen::adlc::packaging::OutputOpts::Gen(gen) => ( + gen.manifest.as_ref().map(|m| PathBuf::from(m)), + PathBuf::from(gen.output_dir.clone()), + ), + }; + + let mut resolver = Resolver::new(loader); + let module_names = get_modules(opts, wrk_root, r#ref)?; + for m in &module_names { + let r = resolver.add_module(m); + match r { + Ok(()) => (), + Err(e) => return Err(anyhow!("Failed to load module {}: {:?}", m, e)), + } + } + + let mut writer = TreeWriter::new(outputdir.clone(), manifest)?; + + let _parent = outputdir.file_name().unwrap().to_str().unwrap().to_string(); + + let modules: Vec = resolver + .get_module_names() + .into_iter() + .map(|mn| resolver.get_module(&mn).unwrap()) + .collect(); + + let index_map = &mut HashMap::new(); + + for m in &modules { + let does_contain = module_names.contains(&m.name); + if opts.generate_transitive || does_contain { + let path = path_from_module_name(strip_first, m.name.to_owned()); + + utils::collect_indexes(path.clone(), index_map); + + let path = path.as_path(); + // if None == path.components().next() { + // return Err(anyhow!("Output module name was empty. Potential config issue 'strip_first' might need to be false. Module: '{}'. strip_first: '{}'", m.name, strip_first)); + // } + let code = gen_ts_module(m, &resolver, opts)?; + writer + .write(path, code) + .map_err(|e| anyhow!("Error write to path {:?}. Error: {}", path, e.to_string()))?; + } + } + + { + let tokens = &mut js::Tokens::new(); + let dep_adl_resolvers = dep_adl_pkgs + .iter() + .filter_map(|d| d.p_ref.ts_opts.as_ref().map(|t| t.npm_pkg_name.clone())) + .collect(); + + if opts.include_resolver { + gen_resolver( + tokens, + opts.npm_pkg_name.clone(), + opts.generate_transitive, + &opts.runtime_opts, + &resolver, + &modules, + dep_adl_resolvers, + )?; + let config = js::Config::default(); + // let config = js::Config{ + // ..Default::default() + // }; + let mut w = fmt::IoWriter::new(Vec::::new()); + // let mut w = fmt::IoWriter::new(stdout.lock()); + let fmt = fmt::Config::from_lang::(); + let fmt = fmt::Config::with_indentation(fmt, Indentation::Space(2)); + tokens.format_file(&mut w.as_formatter(&fmt), &config)?; + let vector = w.into_inner(); + let code = std::str::from_utf8(&vector)?; + let path = PathBuf::from("resolver.ts"); + writer.write(path.as_path(), code.to_string())?; + } + } + + if let TsRuntimeOpt::Generate(_) = &opts.runtime_opts { + gen_runtime(false, false, &opts.ts_style, &mut writer)? + } + + if packageable { + let mut keys: Vec<&PathBuf> = index_map.keys().collect(); + keys.sort(); + for k in keys { + let mut out = Vec::new(); + write!(&mut out, "/* @generated - key {:?} */\n", k)?; + let vs = index_map.get(k).unwrap(); + let mut v1: Vec = vec![]; + for v in vs { + v1.push(v.to_owned()); + } + v1.sort(); + for v in &v1 { + match v { + IndexEntry::Dir(ie) => { + if ie == "_" { + write!(&mut out, "export * from './{}/index';\n", ie)?; + } else { + write!(&mut out, "export * as {} from './{}/index';\n", ie, ie)?; + } + } + IndexEntry::Leaf(ie) => { + let iep: Vec<&str> = ie.split(".").collect(); + let mut pat = String::from("/"); + pat.push_str(iep[0]); + if k.eq(&PathBuf::from("_")) + && (opts.npm_pkg_name.eq(iep[0]) + || opts.npm_pkg_name.ends_with(pat.as_str())) + { + write!(&mut out, "export * from './{}';\n", iep[0])?; + } else { + write!(&mut out, "export * as {} from './{}';\n", iep[0], iep[0])?; + } + } + } + } + let path_ind = k.join("index.ts"); + let code = std::str::from_utf8(&out)?; + writer.write(path_ind.as_path(), code.to_string())?; + } + } + Ok(()) +} + +pub fn gen_npm_package(payload: &Payload1, wrk1: &AdlWorkspace) -> anyhow::Result<()> { + let opts = payload.p_ref.ts_opts.as_ref().unwrap(); + + if opts.outputs == None { + // not gen for this pkg + return Ok(()); + } + let outputs = opts.outputs.as_ref().unwrap(); + let outputdir = match outputs { + crate::adlgen::adlc::packaging::OutputOpts::Gen(gen) => { + PathBuf::from(gen.output_dir.clone()) + } + }; + let mut writer = TreeWriter::new(outputdir.clone(), None)?; + + let mut npm_package = NpmPackage::new(opts.npm_pkg_name.clone(), opts.npm_version.clone()); + match &opts.runtime_opts { + TsRuntimeOpt::WorkspaceRef(rt) => { + npm_package + .dependencies + .insert(rt.clone(), "workspace:*".to_string()); + } + TsRuntimeOpt::PackageRef(rt) => { + npm_package + .dependencies + .insert(rt.name.clone(), rt.version.clone()); + } + TsRuntimeOpt::Generate(_) => {} + }; + for (k,v) in &opts.scripts { + npm_package.scripts.entry(k.clone()).or_insert(v.clone()); + } + + for d in &opts.extra_dependencies { + npm_package.dependencies.insert(d.0.clone(), d.1.clone()); + } + for d in &opts.extra_dev_dependencies { + npm_package + .dev_dependencies + .insert(d.0.clone(), d.1.clone()); + } + + if !opts.generate_transitive { + for r in payload.pkg.requires.iter() { + match &r.r#ref { + crate::adlgen::adlc::packaging::PkgRef::Path(p0) => { + match wrk1.r#use.iter().find(|p| p.pkg.path == *p0) { + Some(p1) => match &p1.p_ref.ts_opts { + Some(ts_opts) => { + npm_package.dependencies.insert( + ts_opts.npm_pkg_name.clone(), + "workspace:*".to_string(), + ); + } + None => { + return Err(anyhow!( + "pkg_ref::path - no ts_opts in workspace file for package '{:?}'", + p1.p_ref + )) + } + }, + None => return Err(anyhow!("no package is workspace with path '{}'", p0)), + } + } + crate::adlgen::adlc::packaging::PkgRef::Alias(a) => { + match wrk1 + .r#use + .iter() + .find(|p| p.pkg.global_alias == Some(a.to_string())) + { + Some(p1) => match &p1.p_ref.ts_opts { + Some(ts_opts) => { + npm_package.dependencies.insert( + ts_opts.npm_pkg_name.clone(), + "workspace:*".to_string(), + ); + } + None => { + return Err(anyhow!( + "pkg_ref::alias - no ts_opts in workspace file for package '{:?}'", + p1.p_ref + )) + } + }, + None => { + if *a == "sys".to_string() { + npm_package + .dependencies + .insert("@adl-lang/sys".to_string(), "1.0.0".to_string()); + } else { + return Err(anyhow!("no package is workspace with alias '{}'", a)); + } + } + } + } + }; + } + } + let content = serde_json::to_string_pretty(&npm_package)?; + writer.write(Path::new("package.json"), content)?; + log::info!("generated {:?}", outputdir.clone().join("package.json")); + + if let Some(ts_config) = &opts.tsconfig { + let content = serde_json::to_string_pretty(ts_config)?; + writer.write(Path::new("tsconfig.json"), content)?; + log::info!("generated {:?}", outputdir.clone().join("tsconfig.json")); + } + + Ok(()) +} + +fn gen_ts_module( + m: &Module1, + resolver: &Resolver, + opts: &TypescriptGenOptions, +) -> anyhow::Result { + // TODO sys.annotations::SerializedName needs to be embedded + let tokens = &mut js::Tokens::new(); + let adlr = match &opts.runtime_opts { + TsRuntimeOpt::WorkspaceRef(pkg) => js::import(pkg.clone() + "/adl", "ADL").into_wildcard(), + TsRuntimeOpt::PackageRef(pkg) => { + js::import(pkg.name.clone() + "/adl", "ADL").into_wildcard() + } + TsRuntimeOpt::Generate(_gen) => { + let src_v: Vec<&str> = m.name.split(['.']).collect(); + let src_v = &src_v[..src_v.len() - 1]; + let mut import = String::new(); + import.push_str("./"); + let mut src_i = src_v.iter().peekable(); + while src_i.next() != None { + import.push_str("../"); + } + import.push_str("runtime/adl"); + // TODO modify the import path with opts.runtime_dir + js::import(import, "ADL").into_wildcard() + } + }; + let mut mgen = generate::TsGenVisitor { + module: m, + npm_pkg: &Some(opts.npm_pkg_name.clone()), + resolver: resolver, + adlr, + map: &mut HashMap::new(), + opts, + }; + mgen.gen_module(tokens)?; + // let stdout = std::io::stdout(); + let mut w = fmt::IoWriter::new(Vec::::new()); + // let mut w = fmt::IoWriter::new(stdout.lock()); + let fmt = fmt::Config::from_lang::(); + let fmt = fmt::Config::with_indentation(fmt, Indentation::Space(2)); + + let config = js::Config::default(); + // let config = js::Config{ + // ..Default::default() + // }; + tokens.format_file(&mut w.as_formatter(&fmt), &config)?; + let vector = w.into_inner(); + let code = std::str::from_utf8(&vector)?; + Ok(code.to_string()) +} + +fn path_from_module_name(strip_first: bool, mname: adlast::ModuleName) -> PathBuf { + let mut path = PathBuf::new(); + let mut iter = mname.split(".").enumerate().peekable(); + while let Some((i, el)) = iter.next() { + if strip_first && i == 0 { + if iter.peek() == None { + // this means the adl file is at the top level. + path.push("_"); + } else { + continue; + } + } + path.push(el); + } + path.set_extension("ts"); + return path; +} + +fn gen_resolver( + t: &mut Tokens, + npm_pkg: String, + generate_transitive: bool, + runtime_opts: &TsRuntimeOpt, + resolver: &Resolver, + modules: &Vec, + adl_pkg_resolvers: HashSet, +) -> anyhow::Result<()> { + let mut local_keys = vec![]; + let m_imports: Vec = modules + .iter() + .map(|m| { + let npm_pkg2 = if let Some(m2) = resolver.get_module(&m.name) { + get_npm_pkg(&m2) + } else { + None + }; + + if let Some(npm_pkg2) = &npm_pkg2 { + if adl_pkg_resolvers.contains(npm_pkg2) { + let alias = npm_pkg2 + .replace("@", "") + .replace("-", "_") + .replace("/", "_"); + return js::import(format!("{}/resolver", npm_pkg2), "ADL_local") + .with_alias(alias); + } + } + if !generate_transitive && npm_pkg2 != None { + let npm_pkg2 = npm_pkg2.unwrap(); + if npm_pkg2 != npm_pkg.clone() { + let alias = m.name.replace(".", "_"); + local_keys.push(alias.clone()); + return js::import(npm_pkg_import(npm_pkg2, m.name.clone()), "_AST_MAP") + .with_alias(alias); + } else { + let name = rel_import_in_resolver(m); + let alias = m.name.replace(".", "_"); + local_keys.push(alias.clone()); + return js::import(format!("./{}", name), "_AST_MAP").with_alias(alias); + } + } else { + if npm_pkg2 != Some(npm_pkg.clone()) { + let alias = m.name.replace(".", "_"); + local_keys.push(alias.clone()); + return js::import(format!("./{}", m.name.replace(".", "/")), "_AST_MAP") + .with_alias(alias); + } else { + let name = rel_import_in_resolver(m); + let alias = m.name.replace(".", "_"); + local_keys.push(alias.clone()); + return js::import(format!("./{}", name), "_AST_MAP").with_alias(alias); + } + }; + }) + .collect(); + + let (adlr1, adlr2) = match runtime_opts { + TsRuntimeOpt::WorkspaceRef(pref) => ( + js::import(format!("{}/adl", pref.as_str()), "declResolver"), + js::import(format!("{}/adl", pref.as_str()), "ScopedDecl"), + ), + TsRuntimeOpt::PackageRef(pref) => ( + js::import(format!("{}/adl", pref.name.as_str()), "declResolver"), + js::import(format!("{}/adl", pref.name.as_str()), "ScopedDecl"), + ), + TsRuntimeOpt::Generate(_gen) => ( + js::import("./runtime/adl", "declResolver"), + js::import("./runtime/adl", "ScopedDecl"), + ), + }; + let gened = "/* @generated from adl */"; + + let mut dep_keys: Vec<&String> = adl_pkg_resolvers.iter().collect(); + dep_keys.sort(); + local_keys.sort(); + quote_in! { *t => + $gened$['\r'] + $(register (adlr2)) + $(register (adlr1)) + $(for m in m_imports => $(register (m))) + + + export const ADL_local: { [key: string]: ScopedDecl } = {$['\r'] + $(for m in local_keys => ...$(m),$['\r']) + };$['\r'] + + export const ADL: { [key: string]: ScopedDecl } = {$['\r'] + ...ADL_local, + $(for m in dep_keys => ...$(m.replace("@", "").replace("-", "_").replace("/", "_")),$['\r']) + };$['\r'] + + export const RESOLVER = declResolver(ADL); + } + + Ok(()) +} + +fn rel_import_in_resolver(m: &adlast::Module>) -> String { + let mut it = m.name.split(".").into_iter().peekable(); + it.next(); + let mut name = String::new(); + while let Some(n) = it.next() { + name.push_str(n); + if it.peek() != None { + name.push_str("/"); + } + } + name +} + +pub fn write_runtime(packageable: bool, rt_opts: &TsWriteRuntime) -> anyhow::Result<()> { + let mut writer = TreeWriter::new(PathBuf::from(&rt_opts.output_dir), None)?; + gen_runtime(true, packageable, &rt_opts.ts_style, &mut writer)?; + Ok(()) +} + +fn gen_runtime( + strip_first: bool, + packageable: bool, + ts_style: &TsStyle, + writer: &mut TreeWriter, +) -> anyhow::Result<()> { + log::info!("Writing Runtime to file system ..."); + let re = Regex::new(r"\$TSEXT").unwrap(); + let re2 = Regex::new(r"\$TSB64IMPORT").unwrap(); + for rt_name in Asset::iter() { + // println!(" '{}'", rt_name); + let mut file_path = PathBuf::new(); + if !strip_first { + file_path.push("./runtime"); + } + // file_path.push(&rt_gen_opts.runtime_dir); + file_path.push(rt_name.as_ref()); + if !packageable { + let is_ts = if let Some(ex) = file_path.extension() { + ex.to_os_string().eq("ts") + } else { + false + }; + if !is_ts { + log::info!("skipping file as !packageable is set. file {:?}", file_path); + continue; + } + } + let dir_path = file_path.parent().unwrap(); + std::fs::create_dir_all(dir_path)?; + + log::info!("writing {}", file_path.display()); + + let data = Asset::get(rt_name.as_ref()).unwrap(); + let content = data.data.as_ref(); + match ts_style { + TsStyle::Tsc => { + let content = re.replace_all(content, "".as_bytes()); + let content = re2.replace(&content, TSC_B64); + let x = content.deref(); + let y = String::from_utf8(x.to_vec())?; + writer.write(file_path.as_path(), y)?; + } + TsStyle::Deno => { + let content = re.replace_all(content, ".ts".as_bytes()); + let content = re2.replace(&content, DENO_B64); + let x = content.deref(); + let y = String::from_utf8(x.to_vec())?; + writer.write(file_path.as_path(), y)?; + } + } + } + Ok(()) +} diff --git a/rust/compiler/src/cli/tsgen/tests.rs b/rust/compiler/src/cli/tsgen/tests.rs new file mode 100644 index 00000000..6f0564bf --- /dev/null +++ b/rust/compiler/src/cli/tsgen/tests.rs @@ -0,0 +1,204 @@ +use std::fs::File; +use std::io::BufReader; +use std::path::PathBuf; + +use serde::Deserialize; + +use crate::{ + adlgen::adlc::{ + packaging::{GenOutput, ModuleSrc, ReferenceableScopeOption, TsGenRuntime, DirectoryRef}, + testing_table::TestFilesMetaData, + }, + processing::loader::loader_from_search_paths, cli::formatter, +}; + +use super::*; + +#[test] +fn generate_ts_from_test_files() { + let _ = env_logger::builder().is_test(true).format(formatter).filter_level(log::LevelFilter::Info).try_init(); + + let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + d.push("../../adl/tests/testing_table.json"); + + let file = File::open(d).expect(&format!( + "Failed to read file: {}", + "../../adl/tests/testing_table.json" + )); + let reader = BufReader::new(file); + + let mut de = serde_json::Deserializer::from_reader(reader); + let mut adlc_cmds = vec![]; + match TestFilesMetaData::deserialize(&mut de) { + Ok(tests) => { + for t in &tests { + if t.skip { + println!("Skipping {} {} - ts gen output;", &t.module_root, &t.title,); + continue; + } + let outdir = match &t.output_dir { + Some(dir) => dir.clone(), + None => { + let mut outdir = String::from("build/dev_adl/"); + outdir.push_str(t.module_root.as_str()); + outdir.clone() + } + }; + + let manifest = match &t.output_dir { + Some(dir) => { + let mut manifest = String::from(dir); + manifest.push_str("manifest"); + manifest + } + None => { + let mut manifest = String::from("build/dev_adl/"); + manifest.push_str(t.module_root.as_str()); + manifest.push_str("/manifest"); + manifest + } + }; + + let mut search_path = vec![]; + search_path.push(PathBuf::from("../../adl/stdlib")); + search_path.push(PathBuf::from("../../adl/adlc")); + { + let mut sp = PathBuf::from("../../adl/tests/"); + sp.push(t.module_root.clone()); + search_path.push(sp); + } + { + t.lib_paths.iter().for_each(|lib| { + let mut sp = PathBuf::from("../../adl/tests/"); + sp.push(lib); + search_path.push(sp); + }) + } + let modules = t.modules.clone(); + let ts_opts = TypescriptGenOptions { + npm_pkg_name: "testing".to_string(), + npm_version: "0.0.0".to_string(), + extra_dependencies: TypescriptGenOptions::def_extra_dependencies(), + extra_dev_dependencies: TypescriptGenOptions::def_extra_dev_dependencies(), + outputs: Some(crate::adlgen::adlc::packaging::OutputOpts::Gen(GenOutput { + referenceable: ReferenceableScopeOption::Local, + output_dir: outdir.clone(), + manifest: Some(manifest), + })), + runtime_opts: TsRuntimeOpt::Generate(TsGenRuntime {}), + generate_transitive: true, + include_resolver: true, + ts_style: crate::adlgen::adlc::packaging::TsStyle::Tsc, + modules: ModuleSrc::Modules(t.modules.clone()), + capitalize_branch_names_in_types: true, + capitalize_type_names: true, + }; + + let mut adlc_cmd = String::new(); + adlc_cmd.push_str("adlc typescript"); + search_path.iter().for_each(|p| { + adlc_cmd.push_str(" --searchdir="); + adlc_cmd.push_str(p.to_str().unwrap()); + }); + adlc_cmd.push_str(" --outputdir="); + // if let Some(dir) = &t.output_dir { + // adlc_cmd.push_str(dir.as_str()); + // } else { + adlc_cmd.push_str("build/adlc_out/"); + adlc_cmd.push_str(t.module_root.clone().as_str()); + // } + // adlc_cmd.push_str(opts.output.outdir.to_str().unwrap()); + adlc_cmd.push_str(" --generate-transitive"); + adlc_cmd.push_str(" --include-rt"); + adlc_cmd.push_str(" --include-resolver"); + adlc_cmd.push_str(" --runtime-dir=runtime"); + + adlc_cmd.push_str(" --manifest="); + // if let Some(dir) = &t.output_dir { + // adlc_cmd.push_str(dir.as_str()); + // adlc_cmd.push_str("/manifest"); + // } else { + adlc_cmd.push_str("build/adlc_out/"); + adlc_cmd.push_str(t.module_root.clone().as_str()); + adlc_cmd.push_str("/manifest"); + // } + + modules.iter().for_each(|m| { + adlc_cmd.push_str(" "); + adlc_cmd.push_str("../../adl/tests/"); + adlc_cmd.push_str(t.module_root.clone().as_str()); + adlc_cmd.push_str("/"); + adlc_cmd.push_str(m.replace(".", "/").as_str()); + adlc_cmd.push_str(".adl"); + }); + if !t.fail && !t.skip { + adlc_cmds.push(adlc_cmd.clone()); + // println!("{}", adlc_cmd); + } + + // TODO consider failed. + // t.fail + let dep_adl_pkgs = vec![]; + match tsgen(false, false, loader_from_search_paths(&search_path), &ts_opts, None, AdlPackageRefType::Dir(DirectoryRef{ path: ".".to_string() }), dep_adl_pkgs) { + Ok(_) => { + println!( + "{} {} - ts gen output; {}", + &t.module_root, + &t.title, + &t.description.join("\n "), + ); + for m in &t.modules { + println!(" build/dev_adl/{}/{}.ts", &t.module_root, m) + } + if t.fail { + assert!(false, "the above test was expected to fail, but passed.\nadlc command would be:\n\t{}\n", adlc_cmd.clone()) + } + } + Err(e) => { + if t.fail { + println!( + "{} {} - failed as expected for src; {}", + &t.module_root, + &t.title, + &t.description.join("\n\t"), + ); + for m in &t.modules { + println!(" ../../adl/tests/{}/{}.adl", &t.module_root, m) + } + println!(" error '{}'", e.to_string()); + } else { + println!( + "{} {} {} - Error '{}'", + &t.module_root, + &t.title, + &t.description.join("\n\t"), + e.to_string() + ); + for m in &t.modules { + println!(" ../../adl/tests/{}/{}.adl", &t.module_root, m) + } + assert!( + false, + "Error : '{:?}'\n{}\nadlc command would be:\n\t{}\n", + t, + e.to_string(), + adlc_cmds[adlc_cmds.len() - 1] + ); + } + } + }; + } + } + Err(err) => assert!(false, "error deserializing testing_table {}", err), + } + adlc_cmds.iter().for_each(|cmd| { + println!("{}", cmd); + }) + + // // Read the JSON contents of the file as an instance of `User`. + // let u: Result = serde_json::from_reader(reader); + // match u { + // Ok(tests) => { dbg!(tests); }, + // Err(err) => assert!(false, "error deserializing testing_table {}", err), + // } +} \ No newline at end of file diff --git a/typescript/runtime/adl.ts b/rust/compiler/src/cli/tsgen/ts-runtime/adl.ts similarity index 100% rename from typescript/runtime/adl.ts rename to rust/compiler/src/cli/tsgen/ts-runtime/adl.ts diff --git a/typescript/runtime/dynamic.ts b/rust/compiler/src/cli/tsgen/ts-runtime/dynamic.ts similarity index 100% rename from typescript/runtime/dynamic.ts rename to rust/compiler/src/cli/tsgen/ts-runtime/dynamic.ts diff --git a/typescript/runtime/json.ts b/rust/compiler/src/cli/tsgen/ts-runtime/json.ts similarity index 100% rename from typescript/runtime/json.ts rename to rust/compiler/src/cli/tsgen/ts-runtime/json.ts diff --git a/rust/compiler/src/cli/tsgen/ts-runtime/package-dist.json b/rust/compiler/src/cli/tsgen/ts-runtime/package-dist.json new file mode 100644 index 00000000..13f2dd89 --- /dev/null +++ b/rust/compiler/src/cli/tsgen/ts-runtime/package-dist.json @@ -0,0 +1,10 @@ +{ + "name": "@adl-lang/runtime", + "version": "0.0.0", + "license": "MIT", + "main": "./index.js", + "types": "./index.d.ts", + "dependencies": { + "base64-js": "^1.5.1" + } +} diff --git a/rust/compiler/src/cli/tsgen/ts-runtime/package.json b/rust/compiler/src/cli/tsgen/ts-runtime/package.json new file mode 100644 index 00000000..40592add --- /dev/null +++ b/rust/compiler/src/cli/tsgen/ts-runtime/package.json @@ -0,0 +1,18 @@ +{ + "name": "@adl-lang/runtime", + "version": "1.0.0", + "type": "commonjs", + "author": "Helix", + "license": "CLOSED", + "private": true, + "scripts": { + "tsc": "tsc" + }, + "dependencies": { + "base64-js": "^1.5.1" + }, + "devDependencies": { + "tsconfig": "workspace:*", + "typescript": "^4.9.3" + } +} diff --git a/typescript/runtime/sys/adlast.ts b/rust/compiler/src/cli/tsgen/ts-runtime/sys/adlast.ts similarity index 100% rename from typescript/runtime/sys/adlast.ts rename to rust/compiler/src/cli/tsgen/ts-runtime/sys/adlast.ts diff --git a/typescript/runtime/sys/dynamic.ts b/rust/compiler/src/cli/tsgen/ts-runtime/sys/dynamic.ts similarity index 100% rename from typescript/runtime/sys/dynamic.ts rename to rust/compiler/src/cli/tsgen/ts-runtime/sys/dynamic.ts diff --git a/typescript/runtime/sys/types.ts b/rust/compiler/src/cli/tsgen/ts-runtime/sys/types.ts similarity index 100% rename from typescript/runtime/sys/types.ts rename to rust/compiler/src/cli/tsgen/ts-runtime/sys/types.ts diff --git a/rust/compiler/src/cli/tsgen/ts-runtime/tsconfig.json b/rust/compiler/src/cli/tsgen/ts-runtime/tsconfig.json new file mode 100644 index 00000000..3367d02e --- /dev/null +++ b/rust/compiler/src/cli/tsgen/ts-runtime/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "tsconfig/base.json", + "include": ["."], + "exclude": ["dist", "build", "node_modules"], + "compilerOptions": { + "outDir": "dist", + // "target": "es2020", + // "module": "es2020", + "lib": [ + "es2020", + ] + } +} diff --git a/typescript/runtime/utils.ts b/rust/compiler/src/cli/tsgen/ts-runtime/utils.ts similarity index 100% rename from typescript/runtime/utils.ts rename to rust/compiler/src/cli/tsgen/ts-runtime/utils.ts diff --git a/rust/compiler/src/cli/tsgen/utils.rs b/rust/compiler/src/cli/tsgen/utils.rs new file mode 100644 index 00000000..73355b69 --- /dev/null +++ b/rust/compiler/src/cli/tsgen/utils.rs @@ -0,0 +1,359 @@ +use std::{collections::HashMap, path::PathBuf, vec}; + +use crate::{ + adlgen::{ + sys::adlast2::{Module1, ScopedName}, + }, +}; + + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd)] +pub enum IndexEntry { + Dir(String), + Leaf(String), +} + +impl IndexEntry { + fn to_string(&self) -> String { + match self { + IndexEntry::Leaf(i) => i.to_string(), + IndexEntry::Dir(i) => i.to_string(), + } + } +} + +impl Ord for IndexEntry { + fn cmp(&self, b: &Self) -> std::cmp::Ordering { + let a = &self; + + match a { + IndexEntry::Dir(a) => match b { + IndexEntry::Leaf(_) => std::cmp::Ordering::Less, + IndexEntry::Dir(b) => a.cmp(b), + }, + IndexEntry::Leaf(a) => match b { + IndexEntry::Leaf(b) => a.cmp(b), + IndexEntry::Dir(_) => std::cmp::Ordering::Greater, + }, + } + } +} + +pub fn collect_indexes(path: PathBuf, map: &mut HashMap>) { + let mut it = path.ancestors().peekable(); + it.next(); + let mut name = path.file_name(); + let mut first = true; + while let Some(a) = it.next() { + let e = map.entry(a.to_path_buf().clone()).or_insert(vec![]); + let n = if let Some(n) = name { + if let Some(n) = n.to_str() { + n.to_string() + } else { + "".to_string() + } + } else { + "".to_string() + }; + match e.iter().find(|x| x.to_string() == n) { + None => { + match first { + true => e.insert(0, IndexEntry::Leaf(n)), + false => e.insert(0, IndexEntry::Dir(n)), + } + first = false; + } + Some(_) => {} + } + name = a.file_name(); + } +} + +pub fn get_npm_pkg(module: &Module1) -> Option { + let npm_pkg = module.annotations.0.get(&ScopedName { + module_name: "adlc.config.typescript".to_string(), + name: "NpmPackage".to_string(), + }); + npm_pkg.map(|p| p.as_str().unwrap().to_string()) +} + +pub fn npm_pkg_import(npm_pkg2: String, module_name: String) -> String { + let mn_parts: Vec<&str> = module_name.split(".").collect(); + let npm_parts: Vec<&str> = npm_pkg2.rsplit("/").collect(); + let mut mn = mn_parts.iter().peekable(); + let mut npm = npm_parts.iter().peekable(); + while let (Some(m), Some(n)) = (&mn.peek(), &npm.peek()) { + if m != n { + break; + } + mn.next(); + npm.next(); + } + let mut path = npm_pkg2; + path.push_str("/"); + while let Some(p) = mn.next() { + path.push_str(p); + if let Some(_) = mn.peek() { + path.push_str("/"); + } + } + path +} + +pub fn rel_import(same_adl_pkg: bool, src: &String, dst: &String) -> String { + let src_v: Vec<&str> = src.split(['.']).collect(); + let src_v = &src_v[..src_v.len() - 1]; + let dst_v0: Vec<&str> = dst.split(['.']).collect(); + let last = dst_v0.last().unwrap(); + let dst_v = &dst_v0[..dst_v0.len() - 1]; + let mut src_i = src_v.iter().peekable(); + let mut dst_i = dst_v.iter().peekable(); + let mut import = String::new(); + if !same_adl_pkg { + if src_v.len() == 0 { + import.push_str("../"); + } else { + while let Some(_) = &src_i.next() { + import.push_str("../"); + } + } + while let Some(del) = &dst_i.next() { + import.push_str(del); + import.push_str("/"); + } + import.push_str(last); + return import; + } + if src_v.len() == 0 && dst_v.len() == 0 { + import.push_str("./"); + import.push_str(last); + return import; + } + if src_v.len() == 0 && dst_v.len() != 0 { + import.push_str(".."); + dst_i.next(); + while let Some(del) = &dst_i.next() { + import.push_str("/"); + import.push_str(del); + } + import.push_str("/"); + import.push_str(last); + return import; + } + import.push_str("."); + while let (Some(sel), Some(del)) = (&src_i.peek(), &dst_i.peek()) { + if sel != del { + break; + } + src_i.next(); + dst_i.next(); + } + if dst_v.len() == 0 { + src_i.next(); + } + while let Some(_) = &src_i.next() { + import.push_str("/.."); + } + while let Some(del) = &dst_i.next() { + import.push_str("/"); + import.push_str(del); + } + import.push_str("/"); + if dst_v.len() == 0 { + import.push_str("_/"); + }; + import.push_str(last); + import +} + +#[cfg(test)] +mod tests { + use super::*; + + fn make_collect_indexes( + args: &[(&[&str], &[(bool, &str)])], + ) -> HashMap> { + // fn make_collect_indexes(args: Vec<(Vec<&str>, Vec<&str>)>) -> HashMap> { + let mut map = HashMap::new(); + for arg in args { + let mut iter = arg.1.iter(); + let mut v = vec![]; + while let Some(a) = iter.next() { + match a.0 { + false => v.push(IndexEntry::Dir(a.1.to_string())), + true => v.push(IndexEntry::Leaf(a.1.to_string())), + } + } + let p: PathBuf = arg.0.iter().collect(); + // let v: Vec = arg.1.iter().map(|s| s.to_string()).collect(); + map.insert(p, v); + } + map + } + + fn make_path_bufs(args: &[&[&str]]) -> Vec { + let mut pbs = vec![]; + for arg in args { + pbs.insert(0, arg.iter().collect()); + } + pbs + } + + #[test] + fn test_collect_indexes() { + // (name, Vec, HashMap>) + let tests: Vec<( + // name + &str, + // Vec + &[&[&str]], + // HashMap> + &[(&[&str], &[(bool, &str)])], + )> = vec![ + ( + "test 00", + &[&["common.ts"]], + &[(&[""], &[(true, "common.ts")])], + ), + ( + "test 01", + &[&["common", "db.ts"]], + &[ + (&[""], &[(false, "common")]), + (&["common"], &[(true, "db.ts")]), + ], + ), + ( + "test 02", + &[&["common.ts"], &["common", "db.ts"]], + &[ + (&[""], &[(true, "common.ts"), (false, "common")]), + (&["common"], &[(true, "db.ts")]), + ], + ), + ( + "test 03", + &[&["common.ts"], &["common", "db.ts"], &["common", "ui.ts"]], + &[ + (&[""], &[(true, "common.ts"), (false, "common")]), + (&["common"], &[(true, "db.ts"), (true, "ui.ts")]), + ], + ), + ]; + + for t in tests { + let map = &mut HashMap::new(); + let exp = make_collect_indexes(t.2); + let pbs = make_path_bufs(t.1); + for p in pbs { + collect_indexes(p, map); + } + assert_eq!(*map, exp, "{}", t.0); + + println!("{:?}", map); + } + } + + #[test] + fn test_relative_import() { + let tests: Vec<(&str, bool, &str, &str, &str)> = vec![ + ("test 00", true, "abc", "def.ghi", "../ghi"), + ( + "test 00 - different packages", + false, + "abc", + "def.ghi", + "../def/ghi", + ), + ("test 00b", true, "abc", "def", "./def"), + ("test 01", true, "scopedname.def", "scopedname.abc", "./abc"), + ( + "test 01 - different packages", + false, + "scopedname.def", + "scopedname.abc", + "../scopedname/abc", + ), + ( + "test 02", + true, + "scopedname.def", + "scopedname.def.abc", + "./def/abc", + ), + ( + "test 02 - different packages", + false, + "scopedname.def", + "scopedname.def.abc", + "../scopedname/def/abc", + ), + ( + "test 03", + true, + "scopedname.def", + "runtime.adl", + "./../runtime/adl", + ), + ( + "test 04", + true, + "common.adminui.api", + "common", + "./../_/common", + ), + ( + "test 04 - different packages", + false, + "common.adminui.api", + "common", + "../../common", + ), + ("test 04b", true, "common", "common.strings", "../strings"), + ( + "test 04 - different packages", + false, + "common", + "common.strings", + "../common/strings", + ), + ( + "test 05", + true, + "common.adminui.api", + "common.db", + "./../db", + ), + ( + "test 05 - different packages", + false, + "common.adminui.api", + "common.db", + "../../common/db", + ), + ( + "test 06", + true, + "common.adminui.api", + "common.adminui", + "./../adminui", + ), + ( + "test 06 - different packages", + false, + "common.adminui.api", + "common.adminui", + "../../common/adminui", + ), + ]; + + for t in tests { + assert_eq!( + rel_import(t.1, &t.2.to_string(), &t.3.to_string()), + t.4, + "{}", + t.0 + ); + } + } +} diff --git a/rust/compiler/src/cli/verify.rs b/rust/compiler/src/cli/verify.rs new file mode 100644 index 00000000..fdf696de --- /dev/null +++ b/rust/compiler/src/cli/verify.rs @@ -0,0 +1,18 @@ +use super::VerifyOpts; + +use anyhow::anyhow; + +use crate::processing::{loader::loader_from_search_paths, resolver::Resolver}; + +pub fn verify(opts: &VerifyOpts) -> anyhow::Result<()> { + let loader = loader_from_search_paths(&opts.search.path); + let mut resolver = Resolver::new(loader); + for m in &opts.modules { + let r = resolver.add_module(m); + match r { + Ok(()) => println!("Verified module {}", m), + Err(e) => return Err(anyhow!("Failed to verify module {}: {:?}", m, e)), + } + } + Ok(()) +} diff --git a/rust/compiler/src/cli/workspace.rs b/rust/compiler/src/cli/workspace.rs new file mode 100644 index 00000000..cc66e909 --- /dev/null +++ b/rust/compiler/src/cli/workspace.rs @@ -0,0 +1,268 @@ + +use std::collections::{HashMap, BTreeSet}; +use std::path::PathBuf; +use std::{env, fs}; + +use anyhow::anyhow; + +use serde::Deserialize; + +use crate::adlgen::adlc::packaging::{ + AdlPackage, AdlPackageRefType, AdlWorkspace0, AdlWorkspace1, DirLoaderRef, InjectAnnotation, + LoaderRef, LoaderRefType, LoaderWorkspace, Payload1, EmbeddedLoaderRef, EmbeddedPkg, AdlPackageRef, PkgRef, TypescriptGenOptions, +}; +use crate::adlgen::sys::adlast2::ScopedName; +use crate::adlrt::custom::sys::types::pair::Pair; +use crate::adlstdlib::get_adl_pkg; +use crate::processing::loader::loader_from_workspace; + +use super::tsgen; + +pub(crate) fn workspace(opts: &super::GenOpts) -> Result<(), anyhow::Error> { + let pkg_defs = collect_work_and_pkg(opts)?; + let wrk1 = collection_to_workspace(pkg_defs)?; + for pkg in &wrk1.1.r#use { + let loader = loader_from_workspace(wrk1.0.clone(), wrk1_to_wld(wrk1.1.clone())?); + if let Some(opts) = &pkg.p_ref.ts_opts { + log::debug!( + "TsGen for pkg\n{:#?}\nIn workspace\n{:#?}\nOutput dir\n{:#?}", + pkg.p_ref, wrk1.0, &opts.outputs + ); + // let pkg_root = wrk1.0.join(pkg.p_ref.path.clone()).canonicalize()?; + let wrk_root = wrk1.0.canonicalize()?; + std::env::set_current_dir(&wrk1.0)?; + let dep_paths: Vec = pkg.pkg.requires.iter().filter_map(|p| if let PkgRef::Path(p1) = &p.r#ref {Some(p1.clone())} else { None } ).collect(); + let dep_alias: Vec = pkg.pkg.requires.iter().filter_map(|p| if let PkgRef::Alias(p1) = &p.r#ref {Some(p1.clone())} else { None } ).collect(); + let deps = wrk1.1.r#use.iter().filter(|p| { + if dep_paths.contains(&p.pkg.path) { + return true; + } + if let Some(a) = &p.pkg.global_alias { + return dep_alias.contains(a); + } + return false; + }).collect(); + tsgen::tsgen(true, true, loader, &opts, Some(wrk_root), pkg.p_ref.r#ref.clone(), deps)?; + tsgen::gen_npm_package(pkg, &wrk1.1)?; + } + } + for rt in &wrk1.1.runtimes { + match rt { + crate::adlgen::adlc::packaging::RuntimeOpts::TsRuntime(rt_opts) => { + tsgen::write_runtime(true, rt_opts)? + } + } + } + Ok(()) +} + +fn wrk1_to_wld(wrk1: AdlWorkspace1) -> Result { + let mut u2 = vec![]; + for u in wrk1.r#use { + u2.push(payload1_to_loader_ref(&u)?); + } + Ok(LoaderWorkspace { + adlc: wrk1.adlc, + r#use: u2, + named_options: HashMap::new(), + runtimes: wrk1.runtimes, + }) +} + +fn payload1_to_loader_ref(payload1: &Payload1) -> Result { + let mut loader_ref = LoaderRef { + r#ref: match payload1.p_ref.r#ref.clone() { + AdlPackageRefType::Dir(d) => LoaderRefType::Dir(DirLoaderRef { + path: d.path, + global_alias: payload1.pkg.global_alias.clone(), + }), + AdlPackageRefType::Embedded(_e) => LoaderRefType::Embedded(EmbeddedLoaderRef { + alias: match payload1.pkg.global_alias.clone() { + Some(s) => match s.as_str() { + "sys" => EmbeddedPkg::Sys, + "adlc" => EmbeddedPkg::Adlc, + _ => return Err(anyhow!("Embedded package not found. Must be 'sys' or 'adlc'. Provided {}", s)), + }, + None => return Err(anyhow!("Embedded package not found. Must be 'sys' or 'adlc'. Nothing Provided")), + }, + }), + }, + loader_inject_annotate: vec![], + resolver_inject_annotate: vec![], + }; + + if let Some(ts_opts) = &payload1.p_ref.ts_opts { + loader_ref + .resolver_inject_annotate + .push(InjectAnnotation::Module(Pair(( + ScopedName { + module_name: "adlc.config.typescript".to_string(), + name: "NpmPackage".to_string(), + }, + serde_json::json!(&ts_opts.npm_pkg_name), + )))); + } + + Ok(loader_ref) +} + +fn aprt_to_name(a: &AdlPackageRefType) -> String { + match a { + AdlPackageRefType::Dir(d) => d.path.clone(), + AdlPackageRefType::Embedded(e) => match e.alias { + EmbeddedPkg::Sys => "sys".to_string(), + EmbeddedPkg::Adlc => "adlc".to_string(), + }, + } +} + +fn collection_to_workspace( + pkg_defs: Vec<(PkgDef, PathBuf, &str)>, +) -> Result<(PathBuf, AdlWorkspace1), anyhow::Error> { + for porw in pkg_defs { + let porw_path = porw.1.join(porw.2); + let content = fs::read_to_string(&porw_path) + .map_err(|e| anyhow!("{:?}: {}", porw_path, e.to_string()))?; + let de = &mut serde_json::Deserializer::from_str(&content); + match porw.0 { + PkgDef::Pkg => { + // let pkg = AdlPackage::deserialize(&mut de).map_err(|e| anyhow!("{:?}: {}", porw_path, e.to_string()))?; + // println!("pkg {:?}", pkg); + } + PkgDef::Work => { + // let wrk0 = AdlWorkspace0::deserialize(de).map_err(|e| anyhow!("{:?}: {}", porw_path, e.to_string()))?; + + let mut unused = BTreeSet::new(); + let wrk0: AdlWorkspace0 = serde_ignored::deserialize(de, |path| { + unused.insert(path.to_string()); + }).map_err(|e| anyhow!("{:?}: {}", porw_path, e.to_string()))?; + if unused.len() != 0 { + return Err(anyhow!("unknown fields `{:?}` {:?}", unused, porw_path)); + } + + let named_opts = wrk0.named_options; + let mut wrk1 = AdlWorkspace1 { + adlc: wrk0.adlc.clone(), + runtimes: wrk0.runtimes, + named_options: HashMap::new(), + r#use: vec![], + }; + for p in wrk0.r#use.iter() { + let pkg = p.pkg_content(porw.1.clone())?; + let mut p2 = p.clone(); + if let Some(name) = &p.named_opts { + if let Some(opts) = named_opts.get(name) { + if let Some(tsopt) = &mut p2.ts_opts { + if let Some(rt) = &opts.ts_opts.runtime_opts { + if !tsopt.runtime_opts.eq(&TypescriptGenOptions::def_runtime_opts()) { + tsopt.runtime_opts = rt.to_owned(); + } + }; + if let Some(tsc) = &opts.ts_opts.tsconfig { + if tsopt.tsconfig == None { + tsopt.tsconfig = Some(tsc.to_owned()); + } + } + if let Some(hm) = &opts.ts_opts.dependencies { + for (k,v) in hm { + tsopt.extra_dependencies.entry(k.clone()).or_insert(v.clone()); + } + } + if let Some(hm) = &opts.ts_opts.dev_dependencies { + for (k,v) in hm { + tsopt.extra_dev_dependencies.entry(k.clone()).or_insert(v.clone()); + } + } + if let Some(hm) = &opts.ts_opts.scripts { + for (k,v) in hm { + tsopt.scripts.entry(k.clone()).or_insert(v.clone()); + } + } + p2.ts_opts = Some(tsopt.to_owned()); + } + } else { + log::warn!("Named option set specified but not found. Name: {} Package: {}", name, aprt_to_name(&p.r#ref)); + } + } + wrk1.r#use.push(Payload1::new(p2, pkg)); + } + return Ok((porw.1, wrk1)); + } + } + } + Err(anyhow!("No workspace found")) +} + +#[derive(Debug, Copy, Clone, PartialEq)] +enum PkgDef { + Pkg, + Work, +} + +fn collect_work_and_pkg( + opts: &super::GenOpts, +) -> Result, anyhow::Error> { + let mut res = vec![]; + let current_dir = env::current_dir()?; + let current_dir = current_dir.join(&opts.dir); + let mut current_dir = current_dir.canonicalize()?; + + loop { + { + let f = (&opts.workspace_filename, PkgDef::Work); + let file_path = current_dir.join(f.0); + if file_path.exists() { + res.push((f.1, current_dir.clone(), f.0.as_str())); + } + } + { + let f = (&opts.package_filenames, PkgDef::Pkg); + let file_path = current_dir.join(f.0); + if file_path.exists() { + res.push((f.1, current_dir.clone(), f.0.as_str())); + } + } + if !current_dir.pop() { + break; + } + } + Ok(res) +} + +trait AdlPackager { + fn pkg_content(&self, wrk_dir: PathBuf) -> Result; + // fn get_payload1(&self) -> &Payload1; +} + +impl AdlPackager for AdlPackageRef { + fn pkg_content(&self, wrk_dir: PathBuf) -> Result { + let (p_path, content) = match &self.r#ref { + AdlPackageRefType::Dir(p) => { + let p_path = wrk_dir.join(&p.path).join("adl.pkg.json"); + let content = fs::read_to_string(&p_path).map_err(|e| anyhow!("Can't read pkg specified in workspace.\n\tworkspace {:?}\n\t package {:?}\n\t error: {}", wrk_dir, p_path, e.to_string()))?; + (format!("{:?}", p_path), content) + } + AdlPackageRefType::Embedded(e) => { + if let Some(c) = get_adl_pkg(e.alias.clone()) { + let x = std::str::from_utf8(c.as_ref()).map_err(|err| { + anyhow!( + "Error converting adl.pkg.json from embedded pkg {:?}. err: {}", + e.alias, + err.to_string() + ) + })?; + (format!("{:?}", e.alias), String::from(x)) + } else { + return Err(anyhow!( + "Cannot file 'adl.pkg.json' in embedded pkg {:?}", + e.alias + )); + } + } + }; + let mut de = serde_json::Deserializer::from_str(&content); + let pkg = AdlPackage::deserialize(&mut de) + .map_err(|e| anyhow!("{:?}: {}", p_path, e.to_string()))?; + Ok(pkg) + } +} diff --git a/rust/compiler/src/lib.rs b/rust/compiler/src/lib.rs new file mode 100644 index 00000000..0b131d3b --- /dev/null +++ b/rust/compiler/src/lib.rs @@ -0,0 +1,9 @@ +#![warn(rust_2018_idioms)] + +pub mod adlgen; +pub mod adlrt; +pub mod cli; +pub mod parser; +pub mod processing; +pub mod utils; +pub mod adlstdlib; diff --git a/rust/compiler/src/main.rs b/rust/compiler/src/main.rs new file mode 100644 index 00000000..922fe517 --- /dev/null +++ b/rust/compiler/src/main.rs @@ -0,0 +1,9 @@ +use compiler::cli::run_cli; + +fn main() { + // // useful for recursive stack overflows + // unsafe { backtrace_on_stack_overflow::enable() }; + + let exit_code = run_cli(); + std::process::exit(exit_code); +} diff --git a/rust/compiler/src/parser/mod.rs b/rust/compiler/src/parser/mod.rs new file mode 100644 index 00000000..70e3e11d --- /dev/null +++ b/rust/compiler/src/parser/mod.rs @@ -0,0 +1,670 @@ +use crate::adlgen::sys::adlast2::Spanned; +use crate::adlgen::sys::adlast2::{self as adlast}; +use std::collections::HashMap; +use std::iter::repeat; + +use crate::adlrt::custom::sys::types::map::Map; +use crate::adlrt::custom::sys::types::maybe::Maybe; + +use nom::{ + branch::alt, + bytes::complete::tag, + character::complete::{alpha1, alphanumeric1}, + character::complete::{digit1, satisfy}, + combinator::{cut, map, opt, recognize, value}, + error::{context, ErrorKind, ParseError, VerboseError, VerboseErrorKind}, + multi::{many0, many0_count, separated_list0}, + number::complete::double, + sequence::{delimited, pair, preceded, terminated}, + *, +}; + +use nom_locate::{position, LocatedSpan}; + +#[cfg(test)] +mod tests; + +type Res = IResult>; + +type Input<'a> = LocatedSpan<&'a str>; + +type TypeExpr0 = adlast::TypeExpr; +type Module0 = adlast::Module0; +pub type RawModule = (Module0, Vec); + +pub enum DeclOrAnnotation { + DADecl(adlast::Decl0), + DAAnnotation(ExplicitAnnotation), +} + +#[derive(Eq, PartialEq, Debug)] +pub struct ExplicitAnnotation { + pub refr: ExplicitAnnotationRef, + pub scoped_name: adlast::ScopedName, + pub value: serde_json::Value, +} + +#[derive(Eq, PartialEq, Debug)] +pub enum ExplicitAnnotationRef { + Module, + Decl(String), + Field((String, String)), +} + +// Consumes whitespace and comments, but not docstrings +pub fn whitespace(i: Input<'_>) -> Res, ()> +where +{ + let mut state = 0; + let mut chars = i.char_indices(); + let mut first_slash_ci = 0; + loop { + if let Some((ci, c)) = chars.next() { + match state { + 0 => match c { + '\n' => (), + '\r' => (), + '\t' => (), + ' ' => (), + '/' => { + first_slash_ci = ci; + state = 1; + } + _ => return Ok((i.take_split(ci).0, ())), + }, + 1 => match c { + '/' => { + state = 2; + } + _ => return Ok((i.take_split(first_slash_ci).0, ())), + }, + 2 => match c { + '/' => return Ok((i.take_split(first_slash_ci).0, ())), + _ => { + state = 3; + } + }, + _ => match c { + '\n' => state = 0, + '\r' => state = 0, + _ => (), + }, + } + } else { + return Ok((i.take_split(i.len()).0, ())); + } + } +} + +pub fn docstring(i: Input<'_>) -> Res, &str> { + let (i, _) = ws(tag("///"))(i)?; + let (i, text) = i.split_at_position_complete(|item| { + let c = item.as_char(); + c == '\r' || c == '\n' + })?; + let (i, _) = i.take_split(1); // drop newline + Ok((i, &text)) +} + +/// A combinator that takes a parser `inner` and produces a parser that also consumes leading +/// returning the output of `inner`. +fn ws<'a, F: 'a, O>(inner: F) -> impl FnMut(Input<'a>) -> Res, O> +where + F: FnMut(Input<'a>) -> Res, O>, +{ + preceded(whitespace, inner) +} + +// Match a tag and preceeding whitespace +fn wtag<'a>(t: &'a str) -> impl FnMut(Input<'a>) -> Res, ()> { + move |i: Input<'a>| { + let (i, _) = whitespace(i)?; + let (i, _) = tag(t)(i)?; + Ok((i, ())) + } +} + +// Run a parser, recording the span of it's result +fn _spanned<'a, P: 'a, O>(inner: P) -> impl FnMut(Input<'a>) -> Res, adlast::Spanned> +where + P: Fn(Input<'a>) -> Res, O>, +{ + move |i: Input<'a>| { + let (i, pos1) = position(i)?; + let (i, value) = inner(i)?; + let (i, pos2) = position(i)?; + let r = Spanned::new( + value, + adlast::Span::new(pos1.location_offset() as u64, pos2.location_offset() as u64), + ); + Ok((i, r)) + } +} + +pub fn ident0(i: Input<'_>) -> Res, &str> { + let (i, id) = recognize(pair(alpha1, many0_count(alt((alphanumeric1, tag("_"))))))(i)?; + Ok((i, id.fragment())) +} + +pub fn module_name(i: Input<'_>) -> Res, adlast::ModuleName> { + let (i, m) = recognize(pair(ident0, many0(pair(satisfy(|c| c == '.'), ident0))))(i)?; + Ok((i, m.to_string())) +} + +pub fn scoped_name(i: Input<'_>) -> Res, adlast::ScopedName> { + let (i, (n0, mut ns)) = pair(ws(ident0), many0(preceded(satisfy(|c| c == '.'), ident0)))(i)?; + ns.insert(0, n0); + let ns: Vec = ns.iter().map(|n| n.to_string()).collect(); + let (name, module_name) = ns.split_last().unwrap(); + let scoped_name = adlast::ScopedName { + module_name: module_name.join("."), + name: name.clone(), + }; + Ok((i, scoped_name)) +} +pub fn raw_module(i: Input<'_>) -> Res, RawModule> { + context("module", raw_module0)(i) +} + +pub fn raw_module0(i: Input<'_>) -> Res, RawModule> { + let (i, annotations) = many0(prefix_annotation)(i)?; + let ma = merge_annotations(annotations).map_err(|emsg| custom_error(i, emsg))?; + let (i, _) = ws(tag("module"))(i)?; + let (i, name) = ws(module_name)(i)?; + let (i, (imports, decls_or_annotations)) = delimited( + wtag("{"), + pair( + many0(terminated(r#import, wtag(";"))), + many0(terminated(decl_or_annotation, wtag(";"))), + ), + wtag("}"), + )(i)?; + let mut decls: Vec = vec![]; + let mut explicit_annotations: Vec = Vec::new(); + for da in decls_or_annotations { + match da { + DeclOrAnnotation::DADecl(decl) => { + let dname = decl.name.clone(); + if let Some(_) = decls.iter().find(|d| d.name == dname) { + return Err(custom_error(i, format!("found duplicate decl: {}", dname))); + } + decls.push(decl); + } + DeclOrAnnotation::DAAnnotation(ann) => { + explicit_annotations.push(ann); + } + } + } + let module = adlast::Module::new(name, imports, decls, ma); + + Ok((i, (module, explicit_annotations))) +} + +pub fn r#import(i: Input<'_>) -> Res, adlast::Import> { + let (i, _) = wtag("import")(i)?; + let (i, import) = context( + "import", + cut(alt(( + map(wildcard_import, |mn| adlast::Import::ModuleName(mn)), + map(scoped_name, |sn| adlast::Import::ScopedName(sn)), + ))), + )(i)?; + Ok((i, import)) +} + +pub fn wildcard_import(i: Input<'_>) -> Res, adlast::ModuleName> { + let (i, m) = ws(recognize(pair( + ident0, + terminated(many0(pair(satisfy(|c| c == '.'), ident0)), tag(".*")), + )))(i)?; + Ok((i, m[..(m.len() - 2)].to_string())) +} + +pub fn decl_or_annotation(i: Input<'_>) -> Res, DeclOrAnnotation> { + alt(( + map(explicit_annotation, |a| DeclOrAnnotation::DAAnnotation(a)), + map(decl, |d| DeclOrAnnotation::DADecl(d)), + ))(i) +} + +pub fn decl(i: Input<'_>) -> Res, adlast::Decl0> { + let (i, annotations) = many0(prefix_annotation)(i)?; + let ma = merge_annotations(annotations).map_err(|emsg| custom_error(i, emsg))?; + let (i, (name, dtype)) = decl_type(i)?; + let decl = adlast::Decl { + name: name.to_owned(), + r#type: dtype, + annotations: ma, + version: Maybe::nothing(), + }; + Ok((i, decl)) +} + +pub fn prefix_annotation(i: Input<'_>) -> Res, (adlast::ScopedName, serde_json::Value)> { + alt(( + prefix_annotation_, + map(docstring, |s| { + (docstring_scoped_name(), serde_json::Value::from(s)) + }), + ))(i) +} + +pub fn prefix_annotation_(i: Input<'_>) -> Res, (adlast::ScopedName, serde_json::Value)> { + let (i, _) = wtag("@")(i)?; + let (i, sn) = scoped_name(i)?; + let (i, ojv) = opt(json)(i)?; + Ok((i, (sn, ojv.unwrap_or(serde_json::Value::Null)))) +} + +pub fn merge_annotations( + anns: Vec<(adlast::ScopedName, serde_json::Value)>, +) -> Result { + // Create a map out of the annotations, but join any doc strings as separate lines + let mut hm = HashMap::new(); + let mut ds = Vec::new(); + + for (k, v) in anns { + if k == docstring_scoped_name() { + ds.push(v.as_str().unwrap().to_owned()); + } else { + if let Some(_) = hm.insert(k.clone(), v) { + return Err(format!( + "Error duplicate annotation '{}.{}'", + &k.module_name, &k.name + )); + } + } + } + if !ds.is_empty() { + hm.insert( + docstring_scoped_name(), + serde_json::Value::from(ds.join("\n")), + ); + } + + Ok(Map(hm)) +} + +pub fn docstring_scoped_name() -> adlast::ScopedName { + adlast::ScopedName::new("sys.annotations".to_owned(), "Doc".to_owned()) + // adlast::ScopedName::new("".to_owned(), "Doc".to_owned()) +} + +pub fn serializedname_scoped_name() -> adlast::ScopedName { + // adlast::ScopedName::new("sys.annotations".to_owned(), "SerializedName".to_owned()) + adlast::ScopedName::new("".to_owned(), "SerializedName".to_owned()) +} + +pub fn decl_type(i: Input<'_>) -> Res, (&str, adlast::DeclType)> { + alt(( + context( + "struct", + map(struct_, |(name, s)| (name, adlast::DeclType::Struct(s))), + ), + context( + "union", + map(union, |(name, u)| (name, adlast::DeclType::Union(u))), + ), + context( + "type", + map(typedef, |(name, t)| (name, adlast::DeclType::Type(t))), + ), + context( + "newtype", + map(newtype, |(name, n)| (name, adlast::DeclType::Newtype(n))), + ), + ))(i) +} + +pub fn struct_(i: Input<'_>) -> Res, (&str, adlast::Struct0)> { + let (i, _) = ws(tag("struct"))(i)?; + cut(|i| { + let (i, name) = ws(ident0)(i)?; + let (i, _) = oversion(i)?; + let (i, type_params) = type_params(i)?; + let (i, fields) = delimited(wtag("{"), many0(terminated(field, wtag(";"))), wtag("}"))(i)?; + let struct_ = adlast::Struct { + fields, + type_params, + }; + Ok((i, (name, struct_))) + })(i) +} + +pub fn union(i: Input<'_>) -> Res, (&str, adlast::Union0)> { + let (i, _) = wtag("union")(i)?; + cut(|i| { + let (i, name) = ws(ident0)(i)?; + let (i, _) = oversion(i)?; + let (i, type_params) = type_params(i)?; + let (i, fields) = delimited(wtag("{"), many0(terminated(field, wtag(";"))), wtag("}"))(i)?; + let union = adlast::Union { + fields, + type_params, + }; + Ok((i, (name, union))) + })(i) +} + +pub fn typedef(i: Input<'_>) -> Res, (&str, adlast::TypeDef)> { + let (i, _) = wtag("type")(i)?; + cut(|i| { + let (i, name) = ws(ident0)(i)?; + let (i, _) = oversion(i)?; + let (i, type_params) = type_params(i)?; + let (i, type_expr) = preceded(wtag("="), type_expr)(i)?; + let typedef = adlast::TypeDef { + type_params, + type_expr, + }; + Ok((i, (name, typedef))) + })(i) +} + +pub fn newtype(i: Input<'_>) -> Res, (&str, adlast::NewType)> { + let (i, _) = ws(tag("newtype"))(i)?; + cut(|i| { + let (i, name) = ws(ident0)(i)?; + let (i, _) = oversion(i)?; + let (i, type_params) = type_params(i)?; + let (i, type_expr) = preceded(wtag("="), type_expr)(i)?; + let (i, default) = opt(preceded(wtag("="), json))(i)?; + + let newtype = adlast::NewType { + type_params, + type_expr, + default: maybe_from_option(default), + }; + Ok((i, (name, newtype))) + })(i) +} + +fn oversion(i: Input<'_>) -> Res, Option> { + opt(oversion_)(i) +} + +fn oversion_(i: Input<'_>) -> Res, u64> { + let (i, _) = ws(tag("#"))(i)?; + let (i, ds) = ws(digit1)(i)?; + Ok((i, ds.parse::().unwrap())) +} + +pub fn field(i: Input<'_>) -> Res, adlast::Field0> { + context("field", field0)(i) +} + +pub fn field0(i: Input<'_>) -> Res, adlast::Field0> { + let (i, annotations) = many0(prefix_annotation)(i)?; + let ma = merge_annotations(annotations).map_err(|emsg| custom_error(i, emsg))?; + let (i, texpr) = ws(type_expr)(i)?; + let (i, name) = ws(ident0)(i)?; + let (i, default) = opt(preceded(wtag("="), json))(i)?; + let field = adlast::Field { + name: name.to_owned(), + serialized_name: name.to_owned(), + type_expr: texpr, + default: maybe_from_option(default), + annotations: ma, + }; + Ok((i, field)) +} + +pub fn explicit_annotation(i: Input<'_>) -> Res, ExplicitAnnotation> { + preceded( + wtag("annotation"), + cut(alt(( + explicit_module_annotation, + explicit_decl_annotation, + explicit_field_annotation, + ))), + )(i) +} + +pub fn explicit_module_annotation(i: Input<'_>) -> Res, ExplicitAnnotation> { + let (i, scoped_name) = ws(scoped_name)(i)?; + let (i, value) = json(i)?; + Ok(( + i, + ExplicitAnnotation { + refr: ExplicitAnnotationRef::Module, + scoped_name, + value, + }, + )) +} + +pub fn explicit_decl_annotation(i: Input<'_>) -> Res, ExplicitAnnotation> { + let (i, decl_name) = ws(ident0)(i)?; + let (i, scoped_name) = ws(scoped_name)(i)?; + let (i, value) = json(i)?; + Ok(( + i, + ExplicitAnnotation { + refr: ExplicitAnnotationRef::Decl(decl_name.to_owned()), + scoped_name, + value, + }, + )) +} + +pub fn explicit_field_annotation(i: Input<'_>) -> Res, ExplicitAnnotation> { + let (i, decl_name) = ws(ident0)(i)?; + let (i, _) = wtag("::")(i)?; + let (i, field_name) = ws(ident0)(i)?; + let (i, scoped_name) = ws(scoped_name)(i)?; + let (i, value) = json(i)?; + + Ok(( + i, + ExplicitAnnotation { + refr: ExplicitAnnotationRef::Field((decl_name.to_owned(), field_name.to_owned())), + scoped_name, + value, + }, + )) +} + +pub fn type_params(i: Input<'_>) -> Res, Vec> { + map( + opt(delimited( + wtag("<"), + separated_list0(ws(tag(",")), map(ws(ident0), |i| i.to_string())), + wtag(">"), + )), + |idents| idents.unwrap_or_else(|| Vec::new()), + )(i) +} + +pub fn type_expr(i: Input<'_>) -> Res, TypeExpr0> { + map(pair(scoped_name, type_expr_params), |(tref, params)| { + adlast::TypeExpr::new(tref, params) + })(i) +} + +pub fn type_expr_params(i: Input<'_>) -> Res, Vec> { + map( + opt(delimited( + wtag("<"), + separated_list0(ws(tag(",")), type_expr), + wtag(">"), + )), + |texpr| texpr.unwrap_or_else(|| Vec::new()), + )(i) +} + +pub fn json(i: Input<'_>) -> Res, serde_json::Value> { + alt(( + value(serde_json::Value::Null, ws(tag("null"))), + value(serde_json::Value::Bool(true), ws(tag("true"))), + value(serde_json::Value::Bool(false), ws(tag("false"))), + json_string, + json_number, + json_object, + json_array, + ))(i) +} + +pub fn json_string(i: Input<'_>) -> Res, serde_json::Value> { + map(json_string0, |s: String| serde_json::Value::from(s))(i) +} + +pub fn json_string0(i: Input<'_>) -> Res, String> { + let mut result = String::new(); + let mut esc = false; + + let (i, _) = ws(tag("\""))(i)?; + + let mut chars = i.char_indices(); + loop { + if let Some((ci, c)) = chars.next() { + if esc { + match c { + 'b' => result.push(0x08 as char), + 'f' => result.push(0xc as char), + 'n' => result.push('\n'), + 'r' => result.push('\r'), + 't' => result.push('\t'), + // TODO: implement \uXXXX + c => result.push(c), + } + esc = false; + } else if c == '\\' { + esc = true; + } else if c == '"' { + let (i, _) = i.take_split(ci + 1); + return Ok((i, result)); + } else { + result.push(c); + } + } else { + return Err(Err::Failure(VerboseError { + errors: vec![( + i, + nom::error::VerboseErrorKind::Nom(nom::error::ErrorKind::Eof), + )], + })); + } + } +} + +pub fn json_number(i: Input<'_>) -> Res, serde_json::Value> { + map(ws(double), |v| { + if v.floor() == v { + if v >= 0.0 { + serde_json::Value::from(v as u64) + } else { + serde_json::Value::from(v as i64) + } + } else { + serde_json::Value::from(v) + } + })(i) +} + +pub fn json_object(i: Input<'_>) -> Res, serde_json::Value> { + let (i, fields) = preceded( + ws(tag("{")), + cut(terminated( + separated_list0(wtag(","), pair(terminated(json_string0, wtag(":")), json)), + wtag("}"), + )), + )(i)?; + + let mut map = serde_json::Map::new(); + for (k, v) in fields { + map.insert(k, v); + } + Ok((i, serde_json::Value::Object(map))) +} + +pub fn json_array(i: Input<'_>) -> Res, serde_json::Value> { + map( + preceded( + ws(tag("[")), + cut(terminated(separated_list0(wtag(","), json), wtag("]"))), + ), + |jv| serde_json::Value::from(jv), + )(i) +} + +pub fn maybe_from_option(v: Option) -> Maybe { + match v { + Some(v) => Maybe::just(v), + None => Maybe::nothing(), + } +} + +pub fn map_spanned(sa: Spanned, f: F) -> Spanned +where + F: Fn(A) -> B, +{ + Spanned::new(f(sa.value), sa.span) +} + +fn custom_error(i: Input<'_>, msg: String) -> nom::Err>> { + use log::error; + error!("{}", msg); + return nom::Err::Failure(VerboseError::from_error_kind(i, ErrorKind::Tag)); +} + +// Lifted from nom source, but with our custom input type. +pub fn convert_error(input: Input<'_>, e: VerboseError>) -> String { + let lines: Vec<_> = input.lines().map(String::from).collect(); + + let mut result = String::new(); + + for (i, (substring, kind)) in e.errors.iter().enumerate() { + let mut offset = input.offset(substring); + + let mut line = 0; + let mut column = 0; + + for (j, l) in lines.iter().enumerate() { + if offset <= l.len() { + line = j; + column = offset; + break; + } else { + offset = offset - l.len() - 1; + } + } + + match kind { + VerboseErrorKind::Char(c) => { + result += &format!("{}: at line {}:\n", i, line); + result += &lines[line]; + result += "\n"; + + if column > 0 { + result += &repeat(' ').take(column).collect::(); + } + result += "^\n"; + result += &format!( + "expected '{}', found {}\n\n", + c, + substring.chars().next().unwrap() + ); + } + VerboseErrorKind::Context(s) => { + result += &format!("{}: at line {}, in {}:\n", i, line, s); + result += &lines[line]; + result += "\n"; + if column > 0 { + result += &repeat(' ').take(column).collect::(); + } + result += "^\n\n"; + } + VerboseErrorKind::Nom(e) => { + result += &format!("{}: at line {}, in {:?}:\n", i, line, e); + result += &lines[line]; + result += "\n"; + if column > 0 { + result += &repeat(' ').take(column).collect::(); + } + result += "^\n\n"; + } + } + } + + result +} diff --git a/rust/compiler/src/parser/tests.rs b/rust/compiler/src/parser/tests.rs new file mode 100644 index 00000000..171ebe84 --- /dev/null +++ b/rust/compiler/src/parser/tests.rs @@ -0,0 +1,378 @@ + +use std::fs; +use std::path::PathBuf; + +use crate::utils::ast::{mk_typeexpr0, mk_scoped_name}; + +use super::*; +use nom::{ + error::{ErrorKind, VerboseError, VerboseErrorKind}, + Err as NomErr, +}; + +#[test] +fn parse_whitespace() { + assert_parse_ws(whitespace(inp("x")), "x"); + assert_parse_ws(whitespace(inp(" x")), "x"); + assert_parse_ws(whitespace(inp("\n x")), "x"); + + assert_parse_ws(whitespace(inp(" / x")), "/ x"); + assert_parse_ws(whitespace(inp(" // x")), ""); + assert_parse_ws(whitespace(inp(" // x\ny")), "y"); + assert_parse_ws(whitespace(inp("\n// a comment\n x")), "x"); + assert_parse_ws(whitespace(inp(" /// docstring \ny")), "/// docstring \ny"); +} + +fn assert_parse_ws(pr: Res, T>, remaining: &str) + where T: std::fmt::Debug+PartialEq { + if let Ok((i, _)) = pr { + assert_eq!(i.fragment(), &remaining); + } else { + panic!("Unexpected parse failure" ); + } +} + + +#[test] +fn parse_ident0() { + assert_parse_eq(ident0(inp("x")), "x"); + assert_parse_eq(ident0(inp("X")), "X"); + assert_parse_eq(ident0(inp("xy_z1")), "xy_z1"); + assert_parse_eq_2(ident0(inp("xyz.")), "xyz", "."); + + assert_eq!( + super::ident0(inp("")), + Err(NomErr::Error(VerboseError { + errors: vec![ + (inp(""), VerboseErrorKind::Nom(ErrorKind::Alpha)), + ] + })) + ); + + assert_eq!( + super::ident0(inp("7")), + Err(NomErr::Error(VerboseError { + errors: vec![ + (inp("7"), VerboseErrorKind::Nom(ErrorKind::Alpha)), + ] + })) + ); +} + + #[test] +fn parse_module_name() { + assert_parse_eq(module_name(inp("x")), "x".to_owned()); + assert_parse_eq_2(module_name(inp("x.y.z;")), "x.y.z".to_owned(), ";"); +} + +#[test] +fn parse_scoped_name() { + assert_parse_eq(scoped_name(inp("x")), adlast::ScopedName::new("".to_string(), "x".to_string())); + assert_parse_eq(scoped_name(inp("x.y.z")), adlast::ScopedName::new("x.y".to_string(), "z".to_string())); +} + +#[test] +fn parse_import() { + assert_parse_eq(r#import(inp("import x.y.z")), adlast::Import::ScopedName(mk_scoped_name("x.y", "z"))); + assert_parse_eq(r#import(inp("import x.y.*")), adlast::Import::ModuleName("x.y".to_owned())); +} + +#[test] +fn parse_type_expr() { + + assert_parse_eq( + type_expr(inp("a.X")), + mk_typeexpr0( mk_scoped_name("a", "X")) + ); + + assert_parse_eq( + type_expr(inp("a.X")), + adlast::TypeExpr{ + type_ref: mk_scoped_name("a", "X"), + parameters: vec![ + mk_typeexpr0(mk_scoped_name("y.z", "B")) + ] + } + ); + + assert_parse_eq( + type_expr(inp("a.X")), + adlast::TypeExpr{ + type_ref: mk_scoped_name("a", "X"), + parameters: vec![ + mk_typeexpr0( mk_scoped_name("y.z", "B")), + mk_typeexpr0(mk_scoped_name("", "C")), + ] + } + ); +} + +#[test] +fn parse_decl() { + + assert_parse_eq( + decl(inp("struct A { F f1; G f2; }")), + adlast::Decl{ + name: "A".to_string(), + version: Maybe::nothing(), + annotations: Map::new(Vec::new()), + r#type: adlast::DeclType::Struct(adlast::Struct{ + type_params: Vec::new(), + fields: vec![ + adlast::Field{ + name: "f1".to_string(), + annotations: Map::new(Vec::new()), + default: Maybe::nothing(), + serialized_name: "f1".to_string(), + type_expr: mk_typeexpr0(mk_scoped_name("", "F")), + }, + adlast::Field{ + name: "f2".to_string(), + annotations: Map::new(Vec::new()), + default: Maybe::nothing(), + serialized_name: "f2".to_string(), + type_expr: mk_typeexpr0(mk_scoped_name("", "G")), + } + ], + }), + }, + ) +} + +#[test] +fn parse_decl_annotations() { + + assert_parse_eq( + decl(inp("@X.Z true @Y \"xyzzy\" struct A {}")), + adlast::Decl{ + name: "A".to_string(), + version: Maybe::nothing(), + annotations: Map::from_iter(vec![ + (mk_scoped_name("", "Y"), serde_json::Value::String("xyzzy".to_owned())), + (mk_scoped_name("X", "Z"), serde_json::Value::Bool(true)), + ]), + r#type: adlast::DeclType::Struct(adlast::Struct{ + type_params: Vec::new(), + fields: vec![], + }), + }, + ) +} + +#[test] +fn parse_explicit_annotations() { + assert_parse_eq( + explicit_annotation(inp("annotation Bool false")), + ExplicitAnnotation{ + refr: ExplicitAnnotationRef::Module, + scoped_name: mk_scoped_name("", "Bool"), + value: serde_json::Value::from(false), + }, + ); + + assert_parse_eq( + explicit_annotation(inp("annotation MyStruct Bool false")), + ExplicitAnnotation{ + refr: ExplicitAnnotationRef::Decl("MyStruct".to_owned()), + scoped_name: mk_scoped_name("", "Bool"), + value: serde_json::Value::from(false), + }, + ); + + assert_parse_eq( + explicit_annotation(inp("annotation MyStruct::f1 Bool false")), + ExplicitAnnotation{ + refr: ExplicitAnnotationRef::Field(("MyStruct".to_owned(), "f1".to_owned())), + scoped_name: mk_scoped_name("", "Bool"), + value: serde_json::Value::from(false), + }, + ); +} + +#[test] +fn parse_docstring() { + assert_parse_eq(docstring(inp(" /// my doc string\n")), " my doc string"); + + assert_parse_eq( + decl(inp("/// Some doc\n struct A {}")), + adlast::Decl{ + name: "A".to_string(), + version: Maybe::nothing(), + annotations: Map::from_iter(vec![ + (docstring_scoped_name(), serde_json::Value::from(" Some doc")), + ]), + r#type: adlast::DeclType::Struct(adlast::Struct{ + type_params: Vec::new(), + fields: vec![], + }), + }, + ); + + assert_parse_eq( + decl(inp("/// Some doc\n /// with line 2\n struct A {}")), + adlast::Decl{ + name: "A".to_string(), + version: Maybe::nothing(), + annotations: Map::from_iter(vec![ + (mk_scoped_name("sys.annotations", "Doc"), serde_json::Value::from(" Some doc\n with line 2")), + ]), + r#type: adlast::DeclType::Struct(adlast::Struct{ + type_params: Vec::new(), + fields: vec![], + }), + }, + ); +} + +#[test] +fn parse_empty_module() { + let pm = raw_module(inp("module x {\n}")); + if let Ok((_i, (m, _))) = pm { + assert_eq!( m.name, "x".to_string()); + } else { + panic!("Failed to parse module" ); + } +} + +#[test] +fn parse_json() { + assert_parse_eq( json(inp("null")), serde_json::Value::Null); + + assert_parse_eq( json(inp("true")), serde_json::Value::Bool(true)); + assert_parse_eq( json(inp("false")), serde_json::Value::Bool(false)); + assert_parse_eq( json(inp("true")), serde_json::Value::Bool(true)); + + assert_parse_eq( json(inp("45")), serde_json::Value::from(45u32)); + assert_parse_eq( json(inp("+45")), serde_json::Value::from(45u32)); + assert_parse_eq( json(inp("-45")), serde_json::Value::from(-45i32)); + assert_parse_eq( json(inp("45.2")), serde_json::Value::from(45.2f64)); + assert_parse_eq( json(inp("+45.2")), serde_json::Value::from(45.2f64)); + assert_parse_eq( json(inp("-45.2")), serde_json::Value::from(-45.2f64)); + + assert_parse_eq( json(inp("\"\"")), serde_json::Value::String("".to_string())); + assert_parse_eq( json(inp("\"xyz\"")), serde_json::Value::String("xyz".to_string())); + + assert_parse_eq( json(inp("\"\\\"\"")), serde_json::Value::String("\"".to_string())); + assert_parse_eq( json(inp("\"\\\\\"")), serde_json::Value::String("\\".to_string())); + assert_parse_eq( json(inp("\"\\n\"")), serde_json::Value::String("\n".to_string())); + + assert_parse_eq( json(inp("[]")), serde_json::Value::Array(Vec::new())); + assert_parse_eq( json(inp("[ 45 ]")), serde_json::Value::Array(vec![ + serde_json::Value::from(45u32) + ])); + + assert_parse_eq( json(inp("{}")), serde_json::Value::Object(serde_json::Map::new())); + assert_parse_eq( json(inp(r#" {"f1": true, "f2": null}"#)), serde_json::Value::Object(mk_json_map(vec!( + ("f1".to_owned(), serde_json::Value::Bool(true)), + ("f2".to_owned(), serde_json::Value::Null), + )))); +} + + #[test] + fn parse_test_adl_files() { + assert_module_file_ok("../../adl/tests/test1/test1.adl"); + assert_module_file_ok("../../adl/tests/test2/test2.adl"); + assert_module_file_ok("../../adl/tests/test3/test3.adl"); + assert_module_file_ok("../../adl/tests/test4/test4.adl"); + assert_module_file_ok("../../adl/tests/test5/test5.adl"); + assert_module_file_ok("../../adl/tests/test6/test6.adl"); + assert_module_file_ok("../../adl/tests/test7/test7.adl"); + // duplicate struct name + assert_module_file_err("../../adl/tests/test8/test8.adl"); + // versions not implemented + assert_module_file_err("../../adl/tests/test9/test9.adl"); + assert_module_file_err("../../adl/tests/test10/test10.adl"); + assert_module_file_err("../../adl/tests/test11/test11.adl"); + assert_module_file_ok("../../adl/tests/test12/test12.adl"); + assert_module_file_ok("../../adl/tests/test13/test13.adl"); + assert_module_file_ok("../../adl/tests/test14/test14.adl"); + assert_module_file_ok("../../adl/tests/test15/test15.adl"); + assert_module_file_ok("../../adl/tests/test16/test16.adl"); + assert_module_file_ok("../../adl/tests/test16/test16.adl"); + assert_module_file_ok("../../adl/tests/test16/test2.adl"); + assert_module_file_ok("../../adl/tests/test17/test17.adl"); + assert_module_file_ok("../../adl/tests/test18/test18.adl"); + assert_module_file_ok("../../adl/tests/test19/test19.adl"); + assert_module_file_ok("../../adl/tests/test20/test20.adl"); + assert_module_file_ok("../../adl/tests/test21/test21.adl"); + assert_module_file_ok("../../adl/tests/test22/test22a.adl"); + assert_module_file_ok("../../adl/tests/test22/test22b.adl"); + assert_module_file_ok("../../adl/tests/test23/test23.adl"); + assert_module_file_ok("../../adl/tests/test24/test24.adl"); + assert_module_file_ok("../../adl/tests/test25/admin.adl"); + assert_module_file_ok("../../adl/tests/test26/test26.adl"); + assert_module_file_ok("../../adl/tests/test27/test27.adl"); + assert_module_file_ok("../../adl/tests/test27/test27a.adl"); + assert_module_file_ok("../../adl/tests/test28/test28.adl"); + assert_module_file_ok("../../adl/tests/test29/test29.adl"); + } + + fn inp (s: &str) -> Input<'_> { + LocatedSpan::new(s) + } + + fn assert_parse_eq(pr: Res, T>, v:T) + where T: std::fmt::Debug+PartialEq { + match pr { + Ok((i,pv)) => { + assert_eq!(pv, v); + assert!(i.is_empty()); + } + Err(e) => { + panic!("Unexpected parse failure: {}", e); + + } + } + } + + fn assert_parse_eq_2(pr: Res, T>, v:T, remaining: &str) + where T: std::fmt::Debug+PartialEq { + match pr { + Ok((i,pv)) => { + assert_eq!(pv, v); + assert_eq!(*i.fragment(), remaining); + } + Err(e) => { + panic!("Unexpected parse failure: {}", e); + + } + } +} + +fn assert_module_file_err(path: &str) { + let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + d.push(path); + let content = fs::read_to_string(d).expect(&format!("Failed to read file: {}", path) ); + let content_str: &str = &content; + let parse_result = raw_module(inp(content_str)); + match parse_result { + Ok(_) => assert!(false, "expected a parse error"), + Result::Err(_) => {}, + } +} + +fn assert_module_file_ok(path: &str) { + let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + d.push(path); + let content = fs::read_to_string(d).expect(&format!("Failed to read file: {}", path) ); + let content_str: &str = &content; + let parse_result = raw_module(inp(content_str)); + let err = parse_result.err().and_then(|e| { + match e { + Err::Error(e) => Some(e), + Err::Failure(e) => Some(e), + Err::Incomplete(_e) => None, + } + }); + + assert_eq!( err, Option::None); +} + +fn mk_json_map(vs: Vec<(String,serde_json::Value)>) -> serde_json::Map { + let mut map = serde_json::Map::new(); + for (k,jv) in vs { + map.insert(k,jv); + } + map +} + diff --git a/rust/compiler/src/processing/annotations.rs b/rust/compiler/src/processing/annotations.rs new file mode 100644 index 00000000..8d7b8bb2 --- /dev/null +++ b/rust/compiler/src/processing/annotations.rs @@ -0,0 +1,298 @@ +use std::fmt; + +use crate::adlgen::sys::adlast2::{self as adlast, Module0}; +use crate::parser::{serializedname_scoped_name, ExplicitAnnotationRef, RawModule}; + +fn apply_serialized_name(m0: &mut Module0) { + for decl in m0.decls.iter_mut() { + // if the match variable isn't '&mut' the the branches need '(ref mut dt)' + //eg adlast::DeclType::Struct(ref mut dt) + match &mut decl.r#type { + adlast::DeclType::Struct(dt) => { + for f in dt.fields.iter_mut() { + if let Some(ser_value) = f.annotations.0.remove(&serializedname_scoped_name()) { + // currently there is a bug where a local_name SerializedName can get confussed with sys.annotation.SerializedName + // this is to mitigate this + match ser_value.as_str() { + Some(ser_name) => { + f.serialized_name = String::from(ser_name); + } + None => { + // TODO print warning? + } + } + } + } + } + adlast::DeclType::Union(dt) => { + for f in dt.fields.iter_mut() { + if let Some(ser_value) = f.annotations.0.remove(&serializedname_scoped_name()) { + // currently there is a bug where a local_name SerializedName can get confussed with sys.annotation.SerializedName + // this is to mitigate this + match ser_value.as_str() { + Some(ser_name) => { + f.serialized_name = String::from(ser_name); + } + None => { + // TODO print warning? + } + } + } + } + } + _ => {} + } + } +} + +/// Attach explicit annotations to the appropriate nodes in the AST. On failure, returns +/// the nodes that could not be attached. +pub fn apply_explicit_annotations_and_serialized_name( + raw_module: RawModule, +) -> Result { + let (mut module0, explicit_annotations) = raw_module; + let mut unresolved = Vec::new(); + + for ea in explicit_annotations { + let aref = find_annotations_ref(&ea.refr, &mut module0); + match aref { + Some(aref) => { + if let Some(_) = aref.0.get(&ea.scoped_name) { + return Err(AnnotationError::Override(format!( + "explicit annotations can't override prefix annotation. Target '{}.{}'", + module0.name, + // ea.scoped_name.module_name, + ea.scoped_name.name + ))); + } else { + aref.0.insert(ea.scoped_name, ea.value); + } + } + None => { + unresolved.push(ea.refr); + } + } + } + + if unresolved.is_empty() { + apply_serialized_name(&mut module0); + Ok(module0) + } else { + Err(AnnotationError::Unresolved(UnresolvedExplicitAnnotations { + unresolved, + })) + } +} + +/// Find the referenced annotations hashmap +fn find_annotations_ref<'a>( + ear: &ExplicitAnnotationRef, + module0: &'a mut Module0, +) -> Option<&'a mut adlast::Annotations> { + match ear { + ExplicitAnnotationRef::Module => Some(&mut module0.annotations), + ExplicitAnnotationRef::Decl(decl_name) => { + if let Some(decl) = module0.decls.iter_mut().find(|d| d.name == *decl_name) { + return Some(&mut decl.annotations); + } + None + } + ExplicitAnnotationRef::Field((decl_name, field_name)) => { + if let Some(decl) = module0.decls.iter_mut().find(|d| d.name == *decl_name) { + let ofields = match &mut decl.r#type { + adlast::DeclType::Struct(s) => Some(&mut s.fields), + adlast::DeclType::Union(u) => Some(&mut u.fields), + _ => None, + }; + if let Some(fields) = ofields { + let ofield = fields.iter_mut().find(|f| f.name == *field_name); + if let Some(field) = ofield { + return Some(&mut field.annotations); + } + } + } + None + } + } +} + +#[derive(Debug)] +pub enum AnnotationError { + Unresolved(UnresolvedExplicitAnnotations), + Override(String), +} + +impl std::error::Error for AnnotationError {} + +impl fmt::Display for AnnotationError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + AnnotationError::Unresolved(urefs) => { + urefs.fmt(f)?; + // Ok(()) + } + AnnotationError::Override(o) => { + write!(f, "Forbidden override: {}", o)?; + // Ok(()) + } + } + Ok(()) + } +} + +#[derive(Debug)] +pub struct UnresolvedExplicitAnnotations { + pub unresolved: Vec, +} + +impl std::error::Error for UnresolvedExplicitAnnotations {} + +impl fmt::Display for UnresolvedExplicitAnnotations { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "Unresolved explicit annotations: ")?; + for uref in &self.unresolved { + match uref { + ExplicitAnnotationRef::Module => write!(f, "")?, + ExplicitAnnotationRef::Decl(d) => write!(f, "{}", d)?, + ExplicitAnnotationRef::Field((d, df)) => write!(f, "{}::{}", d, df)?, + } + } + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use crate::adlgen::sys::adlast2 as adlast; + use crate::{parser::raw_module, utils::ast::mk_scoped_name}; + use nom_locate::LocatedSpan; + + #[test] + fn explicit_annotations_ok() { + let rm = raw_module(LocatedSpan::new(OK_ADL)).unwrap().1; + + // We should have 3 explicit annotations to attach + assert_eq!(rm.1.len(), 3); + + let m0 = super::apply_explicit_annotations_and_serialized_name(rm).unwrap(); + assert_eq!( + m0.annotations.0.get(&mk_scoped_name("", "A")), + Some(&serde_json::Value::from(1i32)) + ); + assert_eq!( + m0.annotations.0.get(&mk_scoped_name("", "E")), + Some(&serde_json::Value::from(6i32)) + ); + + let decl = m0.decls.iter().find(|d| d.name == "Y").unwrap(); + assert_eq!( + decl.annotations.0.get(&mk_scoped_name("", "B")), + Some(&serde_json::Value::from(2i32)) + ); + assert_eq!( + decl.annotations.0.get(&mk_scoped_name("", "F")), + Some(&serde_json::Value::from(7i32)) + ); + + let field = if let adlast::DeclType::Struct(s) = &decl.r#type { + s.fields.iter().find(|f| f.name == "z") + } else { + None + } + .unwrap(); + assert_eq!( + field.annotations.0.get(&mk_scoped_name("", "C")), + Some(&serde_json::Value::from(3i32)) + ); + assert_eq!( + field.annotations.0.get(&mk_scoped_name("", "G")), + Some(&serde_json::Value::from(8i32)) + ); + } + + const OK_ADL: &str = " +@A 1 +module X { + @B 2 + struct Y { + @C 3 + Word64 z; + }; + + annotation E 6; + annotation Y F 7; + annotation Y::z G 8; +} + +"; + + #[test] + fn test_serialized_name() { + let rm = raw_module(LocatedSpan::new(SER_ADL)).unwrap().1; + + assert_eq!(rm.1.len(), 1); + + let mut m1 = super::apply_explicit_annotations_and_serialized_name(rm).unwrap(); + + super::apply_serialized_name(&mut m1); + + let decl = m1.decls.iter().find(|d| d.name == "Y").unwrap(); + + let field_z = if let adlast::DeclType::Struct(s) = &decl.r#type { + s.fields.iter().find(|f| f.name == "z") + } else { + None + } + .unwrap(); + assert_eq!(field_z.serialized_name, "a"); + + let field_y = if let adlast::DeclType::Struct(s) = &decl.r#type { + s.fields.iter().find(|f| f.name == "y") + } else { + None + } + .unwrap(); + assert_eq!(field_y.serialized_name, "b"); + } + + const SER_ADL: &str = " +module X { + struct Y { + @SerializedName \"a\" + Word64 z; + Int64 y; + }; + + annotation Y::y SerializedName \"b\"; +} + +"; + + #[test] + fn explicit_annotations_bad() { + let rm = raw_module(LocatedSpan::new(BAD_ADL)).unwrap().1; + + // We should have 3 explicit annotations to attach + assert_eq!(rm.1.len(), 3); + + let err = super::apply_explicit_annotations_and_serialized_name(rm).unwrap_err(); + + // All of which should have failed + match err { + super::AnnotationError::Unresolved(err) => assert_eq!(err.unresolved.len(), 3), + _ => assert!(false), + } + } + + const BAD_ADL: &str = " +module X { + struct Y { + Word64 z; + }; + + annotation A F 7; + annotation A::z G 8; + annotation Y::q G 9; +} +"; +} diff --git a/rust/compiler/src/processing/checks.rs b/rust/compiler/src/processing/checks.rs new file mode 100644 index 00000000..dcad0323 --- /dev/null +++ b/rust/compiler/src/processing/checks.rs @@ -0,0 +1,48 @@ +use std::collections::HashMap; + +use crate::adlgen::sys::adlast2 as adlast; +use crate::utils::ast::{get_fields, get_type_params}; + +use super::ErrorConsumer; + +pub mod check_duplicates { + use super::*; + + pub fn module(m: &adlast::Module>, ec: &mut dyn ErrorConsumer) { + for d in &m.decls { + decl(&m.name, d, ec); + } + } + + pub fn decl(mname: &str, d: &adlast::Decl>, ec: &mut dyn ErrorConsumer) { + if let Some(fs) = get_fields(d) { + let dnames = find_duplicates(fs.iter().map(|f| f.name.clone()).collect()); + for dname in dnames { + ec.consume_error(format!( + "decl {}.{} has duplicated field {}", + mname, d.name, dname + )); + } + } + let dnames = find_duplicates(get_type_params(d).clone()); + for dname in dnames { + ec.consume_error(format!( + "decl {}.{} has duplicated type parameter {}", + mname, d.name, dname + )); + } + } + + fn find_duplicates(strings: Vec) -> Vec { + let mut hm = HashMap::new(); + for s in strings { + *hm.entry(s).or_insert(0) += 1; + } + let duplicates = hm + .into_iter() + .filter(|(_, n)| n > &1) + .map(|(s, _)| s) + .collect(); + duplicates + } +} diff --git a/rust/compiler/src/processing/loader.rs b/rust/compiler/src/processing/loader.rs new file mode 100644 index 00000000..492ec4f4 --- /dev/null +++ b/rust/compiler/src/processing/loader.rs @@ -0,0 +1,255 @@ +use anyhow::anyhow; +use nom::Finish; +use nom_locate::LocatedSpan; +use std::collections::HashMap; +use std::fs; +use std::io::ErrorKind; +use std::path::PathBuf; + +use crate::adlgen::adlc::packaging::{ + EmbeddedPkg, InjectAnnotation, InjectAnnotations, LoaderRefType, LoaderWorkspace, +}; +use crate::adlgen::sys::adlast2::{self as adlast, Module0}; +use crate::parser::{convert_error, raw_module}; +use crate::processing::annotations::apply_explicit_annotations_and_serialized_name; + +pub fn loader_from_workspace(root: PathBuf, workspace: LoaderWorkspace) -> Box { + Box::new(WorkspaceLoader { + root, + workspace, + loaders: HashMap::new(), + }) +} + +pub fn loader_from_search_paths(paths: &Vec) -> Box { + let loaders = paths.iter().map(loader_from_dir_tree).collect(); + Box::new(MultiLoader::new(loaders)) +} + +pub fn loader_from_dir_tree(path: &PathBuf) -> Box { + Box::new(DirTreeLoader::new(path.clone())) +} + +pub trait AdlLoader { + /// Find and load the specified ADL module + fn load( + &mut self, + module_name: &adlast::ModuleName, + ) -> Result)>, anyhow::Error>; + fn debug(&self); +} + +pub struct WorkspaceLoader { + root: PathBuf, + workspace: LoaderWorkspace, + loaders: HashMap>, +} + +impl AdlLoader for WorkspaceLoader { + fn debug(&self) { + println!("!!!! WorkspaceLoader {:?} {:?}", self.root, self.workspace); + let keys: &Vec<&String> = &self.loaders.keys().collect(); + // let &mut keys: &mut Vec<&String> = &self.loaders.keys().collect(); + // keys.sort(); + for k in keys.iter() { + self.loaders.get(k.clone()).unwrap().debug(); + } + } + + fn load( + &mut self, + module_name: &adlast::ModuleName, + ) -> Result)>, anyhow::Error> { + // if let Some(embedded_sys_loader_ref) = &self.workspace.embedded_sys_loader.0 { + // if let Some(mut module) = self.embedded.load(module_name)? { + // if module_name != "sys.annotations" { + // for an in &embedded_sys_loader_ref.loader_inject_annotate { + // match an { + // InjectAnnotation::Module(man) => { + // module + // .0 + // .annotations + // .0 + // .insert(man.0 .0.clone(), man.0 .1.clone()); + // } + // } + // } + // } + // module.1 = Some(embedded_sys_loader_ref.resolver_inject_annotate.clone()); + // return Ok(Some(module)); + // } + // } + for pkg in &self.workspace.r#use { + let loader = match pkg.r#ref.clone() { + LoaderRefType::Dir(d) => { + let pkg_path = d.path.as_str(); + // println!(" looking for {} in {} or {:?}", module_name, pkg_path, pkg.0.1.global_alias.clone()); + let pkg_name = if module_name.starts_with(pkg_path) { + Some(d.path.clone()) + } else if let Some(alias) = d.global_alias.clone() { + if module_name.starts_with(alias.as_str()) { + Some(alias) + } else { + None + } + } else { + None + }; + if pkg_name == None { + continue; + } + let name = pkg_name.unwrap(); + let loader = self + .loaders + .entry(name.clone()) + .or_insert(Box::new(DirTreeLoader::new(self.root.join(&d.path)))); + loader + }, + LoaderRefType::Embedded(e) => { + self + .loaders + .entry(format!("{:?}", e.alias)) + .or_insert(Box::new(EmbeddedStdlibLoader { pkg: e.alias })) + }, + }; + let module0 = loader.load(module_name); + match module0 { + Ok(module2) => { + if let Some((mut module1, _)) = module2.clone() { + for an in &pkg.loader_inject_annotate { + match an { + InjectAnnotation::Module(man) => { + if *module_name != "sys.annotations".to_string() { + if man.0 .0.module_name == *module_name { + module1.annotations.0.insert( + adlast::ScopedName { + module_name: "".to_string(), + name: man.0 .0.name.clone(), + }, + man.0 .1.clone(), + ); + } else { + module1 + .annotations + .0 + .insert(man.0 .0.clone(), man.0 .1.clone()); + } + } + } + } + } + return Ok(Some((module1, Some(pkg.resolver_inject_annotate.clone())))); + } else { + // return Ok(None); + // return Err(anyhow!("Module not found '{}'", module_name)); + } + } + Err(_) => return module0, + } + } + Ok(None) + } +} + +/// Combines a bunch of loaders +pub struct MultiLoader { + loaders: Vec>, +} + +impl MultiLoader { + pub fn new(loaders: Vec>) -> Self { + MultiLoader { loaders } + } +} + +impl AdlLoader for MultiLoader { + fn debug(&self) { + println!("!!!! MultiLoader"); + for l in &self.loaders { + l.debug(); + } + } + + fn load( + &mut self, + module_name: &adlast::ModuleName, + ) -> Result)>, anyhow::Error> { + for loader in &mut self.loaders { + if let Some(module) = loader.load(module_name)? { + return Ok(Some(module)); + } + } + Ok(None) + } +} + +pub struct EmbeddedStdlibLoader { + pkg: EmbeddedPkg, +} + +impl AdlLoader for EmbeddedStdlibLoader { + fn debug(&self) { + println!("!!! EmbeddedStdlibLoader {:?}", self.pkg); + } + + fn load( + &mut self, + module_name: &adlast::ModuleName, + ) -> Result)>, anyhow::Error> { + match crate::adlstdlib::get_stdlib(self.pkg.clone(), module_name, "") { + Some(data) => match std::str::from_utf8(data.as_ref()) { + Ok(content) => return parse(&content).map(|m| Some((m, None))), + Err(err) => return Err(anyhow::Error::from(err)), + }, + None => return Ok(None), + } + } +} + +pub struct DirTreeLoader { + root: PathBuf, +} + +impl DirTreeLoader { + pub fn new(root: PathBuf) -> Self { + DirTreeLoader { root } + } +} + +impl AdlLoader for DirTreeLoader { + fn debug(&self) { + println!("!!!! DirTreeLoader {:?}", self.root); + } + + fn load( + &mut self, + module_name: &adlast::ModuleName, + ) -> Result)>, anyhow::Error> { + let mut path = self.root.clone(); + for mp in module_name.split(".") { + path.push(mp); + } + path.set_extension("adl"); + let econtent = fs::read_to_string(path.clone()); + let content = match econtent { + Err(err) => match err.kind() { + ErrorKind::NotFound => return Ok(None), + _ => return Err(anyhow::Error::from(err)), + }, + Ok(content) => content, + }; + log::info!("loaded {} from {}", module_name, path.display()); + parse(&content).map(|m| Some((m, None))) + } +} + +fn parse(content: &str) -> Result { + let inp = LocatedSpan::new(content); + let (_, raw_module) = raw_module(inp) + .finish() + .map_err(|e| anyhow!(convert_error(inp, e)))?; + match apply_explicit_annotations_and_serialized_name(raw_module) { + Ok(module0) => Ok(module0), + Err(err) => Err(anyhow::Error::from(err)), + } +} diff --git a/rust/compiler/src/processing/mod.rs b/rust/compiler/src/processing/mod.rs new file mode 100644 index 00000000..505425f6 --- /dev/null +++ b/rust/compiler/src/processing/mod.rs @@ -0,0 +1,32 @@ +use crate::adlgen::sys::adlast2 as adlast; + +pub mod annotations; +pub mod checks; +pub mod loader; +pub mod primitives; +pub mod resolver; +pub mod writer; + +pub type TypeExpr0 = adlast::TypeExpr; +pub type Module0 = adlast::Module; + +pub trait ErrorConsumer { + fn consume_error(&mut self, error: String) -> (); +} + +pub struct ErrorLogger { + pub failed: bool, +} + +impl ErrorLogger { + pub fn new() -> Self { + ErrorLogger { failed: false } + } +} + +impl ErrorConsumer for ErrorLogger { + fn consume_error(&mut self, error: String) { + log::error!("{}", error); + self.failed = true; + } +} diff --git a/rust/compiler/src/processing/primitives.rs b/rust/compiler/src/processing/primitives.rs new file mode 100644 index 00000000..e92c10f7 --- /dev/null +++ b/rust/compiler/src/processing/primitives.rs @@ -0,0 +1,50 @@ +use crate::adlgen::sys::adlast2::PrimitiveType; + +pub fn str_from_prim(prim: PrimitiveType) -> &'static str { + match prim { + PrimitiveType::Void => "Void", + PrimitiveType::Bool => "Bool", + PrimitiveType::Int8 => "Int8", + PrimitiveType::Int16 => "Int16", + PrimitiveType::Int32 => "Int32", + PrimitiveType::Int64 => "Int64", + PrimitiveType::Word8 => "Word8", + PrimitiveType::Word16 => "Word16", + PrimitiveType::Word32 => "Word32", + PrimitiveType::Word64 => "Word64", + PrimitiveType::Float => "Float", + PrimitiveType::Double => "Double", + PrimitiveType::Json => "Json", + PrimitiveType::ByteVector => "Bytes", + PrimitiveType::String => "String", + PrimitiveType::Vector => "Vector", + PrimitiveType::StringMap => "StringMap", + PrimitiveType::Nullable => "Nullable", + PrimitiveType::TypeToken => "TypeToken", + } +} + +pub fn prim_from_str(s: &str) -> Option { + match s { + "Void" => Some(PrimitiveType::Void), + "Bool" => Some(PrimitiveType::Bool), + "Int8" => Some(PrimitiveType::Int8), + "Int16" => Some(PrimitiveType::Int16), + "Int32" => Some(PrimitiveType::Int32), + "Int64" => Some(PrimitiveType::Int64), + "Word8" => Some(PrimitiveType::Word8), + "Word16" => Some(PrimitiveType::Word16), + "Word32" => Some(PrimitiveType::Word32), + "Word64" => Some(PrimitiveType::Word64), + "Float" => Some(PrimitiveType::Float), + "Double" => Some(PrimitiveType::Double), + "Json" => Some(PrimitiveType::Json), + "Bytes" => Some(PrimitiveType::ByteVector), + "String" => Some(PrimitiveType::String), + "Vector" => Some(PrimitiveType::Vector), + "StringMap" => Some(PrimitiveType::StringMap), + "Nullable" => Some(PrimitiveType::Nullable), + "TypeToken" => Some(PrimitiveType::TypeToken), + _ => None, + } +} diff --git a/rust/compiler/src/processing/resolver.rs b/rust/compiler/src/processing/resolver.rs new file mode 100644 index 00000000..9efc84f7 --- /dev/null +++ b/rust/compiler/src/processing/resolver.rs @@ -0,0 +1,484 @@ +use anyhow::anyhow; +use std::collections::HashMap; +use std::collections::HashSet; + +use crate::adlgen::adlc::packaging::InjectAnnotation; +use crate::adlgen::adlc::packaging::InjectAnnotations; +use crate::adlgen::sys::adlast2::{self as adlast, ScopedName}; +use crate::adlrt::custom::sys::types::map::Map; + +use super::loader::AdlLoader; +use super::primitives::prim_from_str; +use super::{Module0, TypeExpr0}; + +type Result = anyhow::Result; + +pub type TypeRef = adlast::TypeRef; +pub type TypeExpr1 = adlast::TypeExpr1; +pub type Decl1 = adlast::Decl1; +pub type Module1 = adlast::Module1; +pub type ModuleName = adlast::ModuleName; + +pub struct Resolver { + loader: Box, + modules: HashMap, +} + +#[derive(Debug)] +pub struct ResolvedModule { + module1: Module1, + inject_annotions: Option, + decls: HashMap, +} + +impl Resolver { + pub fn new(loader: Box) -> Self { + Self { + loader, + modules: HashMap::new(), + } + } + + pub fn add_module(&mut self, module_name: &ModuleName) -> Result<()> { + let mut in_progress = HashSet::new(); + self.add_module_impl(&mut in_progress, module_name) + } + + pub fn get_module_names(&self) -> Vec { + self.modules.keys().cloned().collect() + } + + fn get_rmodule(&self, module_name: &ModuleName) -> Option<&ResolvedModule> { + self.modules.get(module_name) + } + + pub fn get_module(&self, module_name: &ModuleName) -> Option { + let rm0 = self.modules.get(module_name); + if let Some(rm1) = rm0 { + let inject_annotions = &rm1.inject_annotions; + if let Some(inj) = &inject_annotions { + if inj.len() > 0 { + let mut module1 = rm1.module1.clone(); + let mut ann = module1.annotations.0.clone(); + for an in inj { + match an { + InjectAnnotation::Module(man) => { + ann.insert(man.0.0.clone(), man.0.1.clone()); + }, + } + } + module1.annotations = Map(ann); + return Some(module1); + } + } + return Some(rm1.module1.to_owned()); + } else { + return None; + } + } + + pub fn get_decl(&self, scoped_name: &adlast::ScopedName) -> Option<&Decl1> { + match self.modules.get(&scoped_name.module_name) { + None => None, + Some(rmodule) => return rmodule.decls.get(&scoped_name.name), + } + } + + fn add_module_impl( + &mut self, + in_progress: &mut HashSet, + module_name: &ModuleName, + ) -> Result<()> { + if self.modules.contains_key(module_name) { + return Ok(()); + } + + if in_progress.contains(module_name) { + for inp in in_progress.iter() { + let inp1 = self.loader.load(inp).unwrap().unwrap().0; + eprintln!("IN PROGRESS {} IMPORTS {:?}", inp, inp1); + } + return Err(anyhow!("Circular reference loop including module_name: '{}' in_progress: {:?}", module_name, in_progress)); + } + + in_progress.insert(module_name.clone()); + + let mut module0 = self + .loader + .load(module_name)? + .ok_or_else(|| { + self.loader.debug(); + anyhow!("Module {} not found", module_name) + })?; + self.add_default_imports(&mut module0.0); + + let module_refs = find_module_refs(&module0.0); + for m in &module_refs { + self.add_module_impl(in_progress, m)?; + } + + let type_params = HashSet::new(); + let expanded_imports = self.get_expanded_imports(&module0.0); + let local_names = module0.0.decls.iter().map(|d| &(d.name) as &str).collect(); + let mut ctx = ResolveCtx { + resolver: self, + module0: &module0.0, + local_names: &local_names, + expanded_imports: &expanded_imports, + type_params, + }; + let module1 = resolve_module(&mut ctx, &module0.0)?; + check_module(&module1)?; + let decls: HashMap = module1 + .decls + .iter() + .map(|d| (d.name.clone(), d.clone())) + .collect(); + + let rmodule = ResolvedModule { + module1, + inject_annotions: module0.1, + decls, + }; + self.modules.insert(module_name.clone(), rmodule); + + in_progress.remove(module_name); + + Ok(()) + } + + fn add_default_imports(&self, module: &mut Module0) { + // sys.annotations does not need to be in default imports since Doc and SerializedName are processed in a way that does not require it. + // let default_imports = vec!["sys.annotations"]; + let default_imports: Vec<&str> = vec![]; + for din in default_imports { + let di = adlast::Import::ModuleName(din.to_owned()); + if module.name != din && !module.imports.contains(&di) { + module.imports.push(di); + } + } + } + + fn get_expanded_imports(&self, module: &Module0) -> HashMap { + let mut result = HashMap::new(); + for i in &module.imports { + match i { + adlast::Import::ScopedName(sn) => { + result.insert(sn.name.clone(), sn.clone()); + } + adlast::Import::ModuleName(mn) => { + if let Some(m) = self.get_module(&mn) { + for decl_name in m.decls.iter().map(|d| &d.name) { + result.insert( + decl_name.clone(), + adlast::ScopedName { + module_name: m.name.clone(), + name: decl_name.clone(), + }, + ); + } + } + } + } + } + result + } +} + +pub fn check_module(m: &Module1) -> Result<()> { + let mut elog = super::ErrorLogger::new(); + super::checks::check_duplicates::module(m, &mut elog); + if elog.failed { + Err(anyhow!("checks failed")) + } else { + Ok(()) + } +} + +fn resolve_module(ctx: &mut ResolveCtx<'_>, module0: &Module0) -> Result { + let decls1 = module0 + .decls + .iter() + .map(|decl0| { + let decl1 = resolve_decl(ctx, &decl0)?; + Ok(decl1) + }) + .collect::>>()?; + let annotations1 = resolve_annotations(ctx, &module0.annotations)?; + let module1 = adlast::Module::new( + module0.name.clone(), + module0.imports.clone(), + decls1, + annotations1, + ); + Ok(module1) +} + +fn resolve_decl( + ctx: &mut ResolveCtx<'_>, + decl0: &adlast::Decl, +) -> Result> { + let dtype = match &decl0.r#type { + adlast::DeclType::Struct(s) => resolve_struct(ctx, &s)?, + adlast::DeclType::Union(u) => resolve_union(ctx, &u)?, + adlast::DeclType::Type(t) => resolve_type_alias(ctx, &t)?, + adlast::DeclType::Newtype(n) => resolve_newtype(ctx, &n)?, + }; + let annotations = resolve_annotations(ctx, &decl0.annotations)?; + let decl = adlast::Decl::new( + decl0.name.clone(), + decl0.version.clone(), + dtype, + annotations, + ); + Ok(decl) +} + +fn resolve_struct<'a>( + ctx0: &mut ResolveCtx<'a>, + struct0: &adlast::Struct, +) -> Result> { + let ctx = with_type_params(ctx0, &struct0.type_params); + let fields = resolve_fields(&ctx, &struct0.fields)?; + let struct1 = adlast::Struct::new(struct0.type_params.clone(), fields); + Ok(adlast::DeclType::Struct(struct1)) +} + +fn resolve_union( + ctx0: &mut ResolveCtx<'_>, + union0: &adlast::Union, +) -> Result> { + let ctx = with_type_params(ctx0, &union0.type_params); + let fields = resolve_fields(&ctx, &union0.fields)?; + let union1 = adlast::Union::new(union0.type_params.clone(), fields); + Ok(adlast::DeclType::Union(union1)) +} + +fn resolve_type_alias( + ctx0: &mut ResolveCtx<'_>, + type0: &adlast::TypeDef, +) -> Result> { + let ctx = with_type_params(ctx0, &type0.type_params); + let type_expr1 = resolve_type_expr(&ctx, &type0.type_expr)?; + let type1 = adlast::TypeDef::new(type0.type_params.clone(), type_expr1); + Ok(adlast::DeclType::Type(type1)) +} + +fn resolve_newtype( + ctx0: &mut ResolveCtx<'_>, + newtype0: &adlast::NewType, +) -> Result> { + let ctx = with_type_params(ctx0, &newtype0.type_params); + let type_expr1 = resolve_type_expr(&ctx, &newtype0.type_expr)?; + let newtype1 = adlast::NewType::new( + newtype0.type_params.clone(), + type_expr1, + newtype0.default.clone(), + ); + Ok(adlast::DeclType::Newtype(newtype1)) +} + +fn resolve_fields( + ctx: &ResolveCtx<'_>, + fields0: &Vec>, +) -> Result>> { + fields0 + .iter() + .map(|f| resolve_field(ctx, f)) + .collect::>>() +} + +fn resolve_field( + ctx: &ResolveCtx<'_>, + field0: &adlast::Field, +) -> Result> { + let field1 = adlast::Field::new( + field0.name.clone(), + field0.serialized_name.clone(), + resolve_type_expr(ctx, &field0.type_expr)?, + field0.default.clone(), + resolve_annotations(ctx, &field0.annotations)?, + ); + Ok(field1) +} + +/// This function checks that each annotation refers to an actual declaration +fn resolve_annotations( + ctx: &ResolveCtx<'_>, + annotations0: &adlast::Annotations, +) -> Result { + let hm1 = annotations0 + .0 + .iter() + .map(|(sn0, jv)| { + let tr1 = ctx.resolve_type_ref(sn0)?; + match tr1 { + TypeRef::ScopedName(sn1) => Ok((sn1, jv.clone())), + TypeRef::LocalName(ln1) => Ok(( + ScopedName { + module_name: ctx.module0.name.clone(), + name: ln1, + }, + jv.clone(), + )), + TypeRef::Primitive(_) => Err(anyhow!("primitives can't be annotations")), + TypeRef::TypeParam(_) => Err(anyhow!("typeparams can't be annotations")), + } + }) + .collect::>>()?; + Ok(Map(hm1)) +} + +fn resolve_type_expr(ctx: &ResolveCtx<'_>, typeexpr0: &TypeExpr0) -> Result { + let type_ref = ctx.resolve_type_ref(&typeexpr0.type_ref)?; + let parameters = typeexpr0 + .parameters + .iter() + .map(|p| resolve_type_expr(ctx, p)) + .collect::>>()?; + let type_expr = adlast::TypeExpr::new(type_ref, parameters); + Ok(type_expr) +} + +pub struct ResolveCtx<'a> { + resolver: &'a mut Resolver, + module0: &'a Module0, + local_names: &'a HashSet<&'a str>, + expanded_imports: &'a HashMap, + type_params: HashSet, +} + +impl<'a> ResolveCtx<'a> { + fn resolve_type_ref(&self, scoped_name0: &adlast::ScopedName) -> Result { + if scoped_name0.module_name.is_empty() { + let name = &scoped_name0.name; + if self.type_params.contains(name.as_str()) { + return Ok(TypeRef::TypeParam(name.clone())); + } + if let Some(ptype) = prim_from_str(&name) { + return Ok(TypeRef::Primitive(ptype)); + } + if self.local_names.contains(&name as &str) { + return Ok(TypeRef::LocalName(name.clone())); + } + if let Some(scoped_name) = self.expanded_imports.get(name) { + return Ok(TypeRef::ScopedName(scoped_name.clone())); + } + Err(anyhow!("Local type {} not found", name)) + } else { + match self.resolver.get_rmodule(&scoped_name0.module_name) { + None => return Err(anyhow!("module {} not found", scoped_name0.module_name)), + Some(rmodule) => match rmodule.decls.get(&scoped_name0.name) { + None => { + return Err(anyhow!( + "type {}.{} not found", + scoped_name0.module_name, + scoped_name0.name + )) + } + Some(_) => return Ok(TypeRef::ScopedName(scoped_name0.clone())), + }, + } + } + } +} + +fn with_type_params<'a>( + ctx0: &'a mut ResolveCtx<'_>, + type_params: &'a Vec, +) -> ResolveCtx<'a> { + ResolveCtx { + resolver: ctx0.resolver, + module0: ctx0.module0, + local_names: ctx0.local_names, + expanded_imports: ctx0.expanded_imports, + type_params: type_params_set(type_params), + } +} + +fn type_params_set(type_params: &Vec) -> HashSet { + type_params + .iter() + .map(|i| i.clone()) + .collect::>() +} + +fn find_module_refs(module: &Module0) -> HashSet { + struct C { + refs: HashSet, + } + impl AstConsumer for C { + fn consume_typeref(&mut self, sn: adlast::ScopedName) -> () { + self.consume_scoped_name(sn) + } + fn consume_scoped_name(&mut self, sn: adlast::ScopedName) { + if sn.module_name != "" { + self.refs.insert(sn.module_name); + } + } + } + let mut ac = C { + refs: HashSet::new(), + }; + consume::module(module, &mut ac); + for i in &module.imports { + match i { + adlast::Import::ModuleName(mn) => ac.refs.insert(mn.clone()), + adlast::Import::ScopedName(sn) => ac.refs.insert(sn.module_name.clone()), + }; + } + ac.refs +} + +mod consume { + use super::*; + + pub fn module(m: &adlast::Module>, ac: &mut dyn AstConsumer) { + annotations(&m.annotations, ac); + for d in &m.decls { + decl(d, ac); + } + } + + pub fn decl(d: &adlast::Decl>, ac: &mut dyn AstConsumer) { + annotations(&d.annotations, ac); + match &d.r#type { + adlast::DeclType::Struct(s) => fields(&s.fields, ac), + adlast::DeclType::Union(u) => fields(&u.fields, ac), + adlast::DeclType::Type(t) => type_expr(&t.type_expr, ac), + adlast::DeclType::Newtype(n) => type_expr(&n.type_expr, ac), + } + } + + pub fn fields( + fs: &Vec>>, + ac: &mut dyn AstConsumer, + ) { + for f in fs { + field(f, ac); + } + } + + pub fn field(f: &adlast::Field>, ac: &mut dyn AstConsumer) { + annotations(&f.annotations, ac); + type_expr(&f.type_expr, ac); + } + + pub fn annotations(annotations: &adlast::Annotations, ac: &mut dyn AstConsumer) { + for a in annotations.0.keys() { + ac.consume_scoped_name(a.clone()); + } + } + + pub fn type_expr(te: &adlast::TypeExpr, ac: &mut dyn AstConsumer) { + ac.consume_typeref(te.type_ref.clone()); + for p in &te.parameters { + type_expr(p, ac); + } + } +} + +pub trait AstConsumer { + fn consume_typeref(&mut self, t: TR) -> (); + fn consume_scoped_name(&mut self, sn: adlast::ScopedName) -> (); +} diff --git a/rust/compiler/src/processing/writer.rs b/rust/compiler/src/processing/writer.rs new file mode 100644 index 00000000..887dd2b9 --- /dev/null +++ b/rust/compiler/src/processing/writer.rs @@ -0,0 +1,97 @@ +use std::{path::{Path, PathBuf}, collections::HashSet}; +use std::{fs,io}; +use std::io::{Write,BufRead}; + +pub struct TreeWriter { + pub root_dir: PathBuf, + pub manifest_file: Option, + pub manifest: Manifest, +} + +impl TreeWriter { + pub fn new(root_dir: PathBuf, manifest_file: Option) -> io::Result { + + let manifest = HashSet::new(); + Ok(TreeWriter { root_dir, manifest_file, manifest}) + } + + /// Write a file to the specifed path, creating parent directories as required + pub fn write(&mut self, path: &Path, content: String) -> io::Result<()> { + let mut file_path = self.root_dir.clone(); + file_path.push(path); + log::info!("writing {}", file_path.display()); + let dir_path = file_path.parent().unwrap(); + std::fs::create_dir_all(dir_path)?; + std::fs::write(file_path, &content)?; + + self.manifest.insert(path.to_owned()); + Ok(()) + } + + pub fn close(&self) -> io::Result<()> { + + if let Some(to_file) = &self.manifest_file { + + // Read old manifest + let old_manifest = + if to_file.exists() { + TreeWriter::read_manifest(to_file)? + } else { + HashSet::new() + }; + + // Write the new one + log::info!("writing manifest {}", to_file.display()); + TreeWriter::write_manifest(to_file, &self.manifest)?; + + // Remove any files left from the old manifest + for f in old_manifest.difference(&self.manifest) { + let mut file_path = self.root_dir.clone(); + file_path.push(f); + log::info!("removing {}", file_path.display()); + } + } + Ok(()) + } + + fn read_manifest(from_file: &Path) -> io::Result { + let file = fs::File::open(from_file)?; + let lines = io::BufReader::new(file).lines(); + let mut manifest : Manifest = HashSet::new(); + for line in lines { + let s = line?; + let s = s.trim(); + if ! s.starts_with("#") { + manifest.insert(PathBuf::from(s)); + } + } + Ok(manifest) + } + + fn write_manifest(to_file: &Path, manifest: &Manifest) -> io::Result<()> { + let dir_path = to_file.parent().unwrap(); + fs::create_dir_all(dir_path)?; + let mut file = fs::OpenOptions::new() + .write(true) + .create(true) + .open(to_file)?; + file.write(b"# manifest @generated by the adl compiler\n")?; + let mut manifest: Vec<&PathBuf> = manifest.into_iter().collect(); + manifest.sort(); + for m in manifest { + file.write(m.to_str().unwrap().as_bytes())?; + file.write(b"\n")?; + } + Ok(()) + } +} + +impl Drop for TreeWriter { + fn drop(&mut self) { + self.close().unwrap(); + } +} + + +type Manifest = HashSet; + diff --git a/rust/compiler/src/utils/ast.rs b/rust/compiler/src/utils/ast.rs new file mode 100644 index 00000000..00e150c0 --- /dev/null +++ b/rust/compiler/src/utils/ast.rs @@ -0,0 +1,30 @@ +use crate::adlgen::sys::adlast2 as adlast; + +pub fn mk_scoped_name(mname: &str, name: &str) -> adlast::ScopedName { + adlast::ScopedName::new(mname.to_string(), name.to_string()) +} + +pub fn mk_typeexpr0(type_ref: adlast::ScopedName) -> adlast::TypeExpr { + adlast::TypeExpr { + type_ref, + parameters: vec![], + } +} + +pub fn get_fields(d: &adlast::Decl) -> Option<&Vec>> { + match &d.r#type { + adlast::DeclType::Struct(s) => Some(&s.fields), + adlast::DeclType::Union(u) => Some(&u.fields), + adlast::DeclType::Type(_) => None, + adlast::DeclType::Newtype(_) => None, + } +} + +pub fn get_type_params(d: &adlast::Decl) -> &Vec { + match &d.r#type { + adlast::DeclType::Struct(s) => &s.type_params, + adlast::DeclType::Union(u) => &u.type_params, + adlast::DeclType::Type(t) => &t.type_params, + adlast::DeclType::Newtype(n) => &n.type_params, + } +} diff --git a/rust/compiler/src/utils/mod.rs b/rust/compiler/src/utils/mod.rs new file mode 100644 index 00000000..1333fbfb --- /dev/null +++ b/rust/compiler/src/utils/mod.rs @@ -0,0 +1 @@ +pub mod ast; \ No newline at end of file diff --git a/rust/runtime/custom/sys/types/map.rs b/rust/runtime/custom/sys/types/map.rs index 27812baf..a1c93ca8 100644 --- a/rust/runtime/custom/sys/types/map.rs +++ b/rust/runtime/custom/sys/types/map.rs @@ -1,13 +1,14 @@ use serde::{Deserialize, Deserializer}; use serde::{Serialize, Serializer}; use std::collections::HashMap; +use std::iter::FromIterator; use std::hash::Hash; use std::result; use super::mapentry::MapEntry; -#[derive(Clone,Eq,PartialEq)] -pub struct Map(HashMap); +#[derive(Clone,Eq,PartialEq, Debug)] +pub struct Map(pub HashMap); impl Map { pub fn new(v: Vec>) -> Map @@ -20,6 +21,20 @@ impl Map { } } +impl FromIterator<(K,V)> for Map +where + K: Eq + Hash, +{ + fn from_iter>(iter: T) -> Map { + let mut hm = HashMap::new(); + for (k,v) in iter { + hm.insert(k,v); + } + Map(hm) + } + +} + impl Serialize for Map where K: Serialize + Eq + Hash, diff --git a/rust/runtime/custom/sys/types/mapentry.rs b/rust/runtime/custom/sys/types/mapentry.rs index cb168fec..d143415f 100644 --- a/rust/runtime/custom/sys/types/mapentry.rs +++ b/rust/runtime/custom/sys/types/mapentry.rs @@ -1,7 +1,7 @@ use serde::{Deserialize}; use serde::{Serialize}; -#[derive(Clone,Deserialize,Eq,Hash,PartialEq,Serialize)] +#[derive(Clone,Debug,Deserialize,Eq,Hash,PartialEq,Serialize)] pub struct MapEntry { #[serde(rename="k")] pub key: K, diff --git a/rust/runtime/custom/sys/types/maybe.rs b/rust/runtime/custom/sys/types/maybe.rs index f6faded6..252b228d 100644 --- a/rust/runtime/custom/sys/types/maybe.rs +++ b/rust/runtime/custom/sys/types/maybe.rs @@ -5,8 +5,8 @@ use std::result; // Maybe is a custom mapping to Option, // with ADL compatible serialization -#[derive(Clone,Eq,Hash,PartialEq)] -pub struct Maybe (Option); +#[derive(Clone,Debug,Eq,Hash,PartialEq)] +pub struct Maybe (pub Option); impl Maybe { pub fn nothing() -> Maybe { diff --git a/rust/runtime/custom/sys/types/pair.rs b/rust/runtime/custom/sys/types/pair.rs index aa41a129..9a058b10 100644 --- a/rust/runtime/custom/sys/types/pair.rs +++ b/rust/runtime/custom/sys/types/pair.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Deserializer}; use serde::{Serialize, Serializer}; use std::result; -#[derive(Clone,Eq,Hash,PartialEq)] +#[derive(Clone,Debug,Eq,Hash,PartialEq)] pub struct Pair (pub (A,B)); impl Pair { diff --git a/rust/runtime/custom/sys/types/result.rs b/rust/runtime/custom/sys/types/result.rs index fa52edc8..2b10b851 100644 --- a/rust/runtime/custom/sys/types/result.rs +++ b/rust/runtime/custom/sys/types/result.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Deserializer}; use serde::{Serialize, Serializer}; -#[derive(Clone,Eq,Hash,PartialEq)] +#[derive(Clone,Debug,Eq,Hash,PartialEq)] pub struct Result(pub std::result::Result); impl Result { diff --git a/typescript/cli/runtime/adl.ts b/typescript/cli/runtime/adl.ts new file mode 100644 index 00000000..f7ab32b1 --- /dev/null +++ b/typescript/cli/runtime/adl.ts @@ -0,0 +1,84 @@ +import * as AST from './sys/adlast$TSEXT'; + +export type ScopedName = AST.ScopedName; +export type ScopedDecl = AST.ScopedDecl; +export type ATypeRef<_T> = {value: AST.TypeRef}; +export type ATypeExpr<_T> = {value : AST.TypeExpr}; + +/** + * A function to obtain details on a declared type. + */ +export interface DeclResolver { + (decl : AST.ScopedName): AST.ScopedDecl; +}; + +export function declResolver(...astMaps : ({[key:string] : AST.ScopedDecl})[]) { + const astMap : {[key:string] : AST.ScopedDecl} = {}; + for (let map of astMaps) { + for (let scopedName in map) { + astMap[scopedName] = map[scopedName]; + } + } + + function resolver(scopedName : AST.ScopedName) : AST.ScopedDecl { + const scopedNameStr = scopedName.moduleName + "." + scopedName.name; + const result = astMap[scopedNameStr]; + if (result === undefined) { + throw new Error("Unable to resolve ADL type " + scopedNameStr); + } + return result; + } + + return resolver; +} + +type Unknown = {} | null; +type Json = {} | null; + +/* Type expressions for primitive types */ + +function texprPrimitive(ptype: string): ATypeExpr { + return { + value: { + typeRef: { kind: "primitive", value: ptype }, + parameters: [] + } + }; +}; + +function texprPrimitive1(ptype: string, etype: ATypeExpr): ATypeExpr { + return { + value: { + typeRef: { kind: "primitive", value: ptype }, + parameters: [etype.value] + } + }; +}; + +export function texprVoid() : ATypeExpr {return texprPrimitive("Void");} +export function texprBool() : ATypeExpr {return texprPrimitive("Bool");} +export function texprInt8() : ATypeExpr {return texprPrimitive("Int8");} +export function texprInt16() : ATypeExpr {return texprPrimitive("Int16");} +export function texprInt32() : ATypeExpr {return texprPrimitive("Int32");} +export function texprInt64() : ATypeExpr {return texprPrimitive("Int64");} +export function texprWord8() : ATypeExpr {return texprPrimitive("Word8");} +export function texprWord16() : ATypeExpr {return texprPrimitive("Word16");} +export function texprWord32() : ATypeExpr {return texprPrimitive("Word32");} +export function texprWord64() : ATypeExpr {return texprPrimitive("Word64");} +export function texprFloat() : ATypeExpr {return texprPrimitive("Float");} +export function texprDouble() : ATypeExpr {return texprPrimitive("Double");} +export function texprJson() : ATypeExpr {return texprPrimitive("Json");} +export function texprByteVector() : ATypeExpr {return texprPrimitive("ByteVector");} +export function texprString() : ATypeExpr {return texprPrimitive("String");} + +export function texprVector(etype: ATypeExpr) : ATypeExpr { + return texprPrimitive1("Vector", etype); +} + +export function texprStringMap(etype: ATypeExpr) : ATypeExpr<{[key:string]:T}> { + return texprPrimitive1("StringMap", etype); +} + +export function texprNullable(etype: ATypeExpr) : ATypeExpr { + return texprPrimitive1("Nullable", etype); +} diff --git a/typescript/cli/runtime/dynamic.ts b/typescript/cli/runtime/dynamic.ts new file mode 100644 index 00000000..8eb392ca --- /dev/null +++ b/typescript/cli/runtime/dynamic.ts @@ -0,0 +1,20 @@ +import {typeExprsEqual} from './utils$TSEXT'; +import {JsonBinding} from './json$TSEXT'; +import {Dynamic} from './sys/dynamic$TSEXT'; + +/** + * Convert an ADL value to a dynamically typed value + */ +export function toDynamic(jsonBinding : JsonBinding, value : T) : Dynamic { + return {typeExpr: jsonBinding.typeExpr, value : jsonBinding.toJson(value)}; +} + +/** + * Convert an ADL value to a dynamically typed value + */ +export function fromDynamic(jsonBinding : JsonBinding, dynamic : Dynamic) : (T|null) { + if (typeExprsEqual(jsonBinding.typeExpr, dynamic.typeExpr)) { + return jsonBinding.fromJson(dynamic.value); + } + return null; +} diff --git a/typescript/cli/runtime/json.ts b/typescript/cli/runtime/json.ts new file mode 100644 index 00000000..b870db22 --- /dev/null +++ b/typescript/cli/runtime/json.ts @@ -0,0 +1,514 @@ +import {DeclResolver,ATypeExpr} from './adl$TSEXT'; +import * as AST from './sys/adlast$TSEXT'; +$TSB64IMPORT; +import {isVoid, isEnum, scopedNamesEqual} from './utils$TSEXT'; + +/** A type for json serialised values */ + +export type Json = JsonObject | JsonArray | JsonValue; +export type JsonArray = Json[]; +export type JsonValue = string | number | JsonObject | JsonArray | boolean | null; +export interface JsonObject { + [key: string]: Json +}; + +function asJsonObject(jv: Json): JsonObject | undefined { + if (jv instanceof Object && !(jv instanceof Array)) { + return jv as JsonObject; + } + return undefined; +} + +function asJsonArray(jv: Json): JsonArray | undefined{ + if(jv instanceof Array) { + return jv as JsonArray; + } + return undefined; +} + +/** + * A JsonBinding is a de/serialiser for a give ADL type + */ +export interface JsonBinding { + typeExpr : AST.TypeExpr; + + // Convert a value of type T to Json + toJson (t : T): Json; + + // Parse a json blob into a value of type T. Throws + // JsonParseExceptions on failure. + fromJson(json : Json) : T; + + // Variant of fromJson that throws Errors on failure + fromJsonE(json : Json) : T; +}; + +/** + * Construct a JsonBinding for an arbitrary type expression + */ +export function createJsonBinding(dresolver : DeclResolver, texpr : ATypeExpr) : JsonBinding { + const jb0 = buildJsonBinding(dresolver, texpr.value, {}); + function fromJsonE(json :Json): T { + try { + return jb0.fromJson(json); + } catch (e) { + throw mapJsonException(e); + } + } + return {typeExpr : texpr.value, toJson:jb0.toJson, fromJson:jb0.fromJson, fromJsonE}; +}; + +/** + * Interface for json parsing exceptions. + * Any implementation should properly show the parse error tree. + * + * @interface JsonParseException + */ +export interface JsonParseException { + kind: 'JsonParseException'; + getMessage(): string; + pushField(fieldName: string): void; + pushIndex(index: number): void; + toString(): string; +} + +// Map a JsonException to an Error value +export function mapJsonException(exception:unknown): unknown { + if (exception && (exception as {kind:string})['kind'] == "JsonParseException") { + const jserr: JsonParseException = exception as JsonParseException; + return new Error(jserr.getMessage()); + } else { + return exception; + } +} + +/** Convenience function for generating a json parse exception. + * @param {string} message - Exception message. + */ +export function jsonParseException(message: string): JsonParseException { + const context: string[] = []; + let createContextString: () => string = () => { + const rcontext: string[] = context.slice(0); + rcontext.push('$'); + rcontext.reverse(); + return rcontext.join('.'); + }; + return { + kind: 'JsonParseException', + getMessage(): string { + return message + ' at ' + createContextString(); + }, + pushField(fieldName: string): void { + context.push(fieldName); + }, + pushIndex(index: number): void { + context.push('[' + index + ']'); + }, + toString(): string { + return this.getMessage(); + } + }; +} + +/** + * Check if a javascript error is of the json parse exception type. + * @param exception The exception to check. + */ +export function isJsonParseException(exception: unknown): exception is JsonParseException { + return ( exception).kind === 'JsonParseException'; +} + +interface JsonBinding0 { + toJson (t : T): Json; + fromJson(json : Json) : T; +}; + +interface BoundTypeParams { + [key: string]: JsonBinding0; +} + +function buildJsonBinding0(dresolver : DeclResolver, texpr : AST.TypeExpr, boundTypeParams : BoundTypeParams) : JsonBinding0 { + if (texpr.typeRef.kind === "primitive") { + return primitiveJsonBinding(dresolver, texpr.typeRef.value, texpr.parameters, boundTypeParams); + } else if (texpr.typeRef.kind === "reference") { + const ast = dresolver(texpr.typeRef.value); + if (ast.decl.type_.kind === "struct_") { + return structJsonBinding(dresolver, ast.decl.type_.value, texpr.parameters, boundTypeParams); + } else if (ast.decl.type_.kind === "union_") { + const union = ast.decl.type_.value; + if (isEnum(union)) { + return enumJsonBinding(dresolver, union, texpr.parameters, boundTypeParams); + } else { + return unionJsonBinding(dresolver, union, texpr.parameters, boundTypeParams); + } + } else if (ast.decl.type_.kind === "newtype_") { + return newtypeJsonBinding(dresolver, ast.decl.type_.value, texpr.parameters, boundTypeParams); + } else if (ast.decl.type_.kind === "type_") { + return typedefJsonBinding(dresolver, ast.decl.type_.value, texpr.parameters, boundTypeParams); + } + } else if (texpr.typeRef.kind === "typeParam") { + return boundTypeParams[texpr.typeRef.value]; + } + throw new Error("buildJsonBinding : unimplemented ADL type"); +}; + +function buildJsonBinding(dresolver : DeclResolver, texpr : AST.TypeExpr, boundTypeParams : BoundTypeParams) : JsonBinding0 { + const jb0 = buildJsonBinding0(dresolver, texpr, boundTypeParams); + return jb0 as JsonBinding0; +}; + +function primitiveJsonBinding(dresolver : DeclResolver, ptype : string, params : AST.TypeExpr[], boundTypeParams : BoundTypeParams ) : JsonBinding0 { + if (ptype === "String") { return identityJsonBinding("a string", (v) => typeof(v) === 'string'); } + else if (ptype === "Int8") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Void") { return identityJsonBinding("a null", (v) => v === null); } + else if (ptype === "Bool") { return identityJsonBinding("a bool", (v) => typeof(v) === 'boolean'); } + else if (ptype === "Int8") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Int16") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Int32") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Int64") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Word8") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Word16") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Word32") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Word64") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Float") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Double") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Json") { return identityJsonBinding("a json value", (_v) => true); } + else if (ptype === "Bytes") { return bytesJsonBinding(); } + else if (ptype === "Vector") { return vectorJsonBinding(dresolver, params[0], boundTypeParams); } + else if (ptype === "StringMap") { return stringMapJsonBinding(dresolver, params[0], boundTypeParams); } + else if (ptype === "Nullable") { return nullableJsonBinding(dresolver, params[0], boundTypeParams); } + else throw new Error("Unimplemented json binding for primitive " + ptype); +}; + +function identityJsonBinding(expected : string, predicate : (json : Json) => boolean) : JsonBinding0{ + + function toJson(v : T) : Json { + return (v as unknown as Json); + } + + function fromJson(json : Json) : T { + if( !predicate(json)) { + throw jsonParseException("expected " + expected); + } + return json as unknown as T; + } + + return {toJson, fromJson}; +} + +function bytesJsonBinding() : JsonBinding0 { + function toJson(v : Uint8Array) : Json { + return b64Encode(v); + } + + function fromJson(json : Json) : Uint8Array { + if (typeof(json) != 'string') { + throw jsonParseException('expected a string'); + } + return b64Decode(json); + } + + return {toJson, fromJson}; +} + +function vectorJsonBinding(dresolver : DeclResolver, texpr : AST.TypeExpr, boundTypeParams : BoundTypeParams) : JsonBinding0 { + const elementBinding = once(() => buildJsonBinding(dresolver, texpr, boundTypeParams)); + + function toJson(v : T[]) : Json { + return v.map(elementBinding().toJson); + } + + function fromJson(json : Json) : T[] { + const jarr = asJsonArray(json); + if (jarr == undefined) { + throw jsonParseException('expected an array'); + } + let result : T[] = []; + jarr.forEach( (eljson:Json,i:number) => { + try { + result.push(elementBinding().fromJson(eljson)); + } catch(e) { + if (isJsonParseException(e)) { + e.pushIndex(i); + } + throw e; + } + }); + return result; + } + + return {toJson, fromJson}; +} + +type StringMap = {[key:string]: T}; +function stringMapJsonBinding(dresolver : DeclResolver, texpr : AST.TypeExpr, boundTypeParams : BoundTypeParams) : JsonBinding0> { + const elementBinding = once(() => buildJsonBinding(dresolver, texpr, boundTypeParams)); + + function toJson(v : StringMap) : Json { + const result: JsonObject = {}; + for (let k in v) { + result[k] = elementBinding().toJson(v[k]); + } + return result; + } + + function fromJson(json : Json) : StringMap { + const jobj = asJsonObject(json); + if (!jobj) { + throw jsonParseException('expected an object'); + } + let result: Record = {}; + for (let k in jobj) { + try { + result[k] = elementBinding().fromJson(jobj[k]); + } catch(e) { + if (isJsonParseException(e)) { + e.pushField(k); + } + throw e; + } + } + return result; + } + + return {toJson, fromJson}; +} + +function nullableJsonBinding(dresolver : DeclResolver, texpr : AST.TypeExpr, boundTypeParams : BoundTypeParams) : JsonBinding0 { + const elementBinding = once(() => buildJsonBinding(dresolver, texpr, boundTypeParams)); + + function toJson(v : T|null) : Json { + if (v === null) { + return null; + } + return elementBinding().toJson(v); + } + + function fromJson(json : Json) : T|null { + if (json === null) { + return null; + } + return elementBinding().fromJson(json); + } + + return {toJson,fromJson}; +} + +interface StructFieldDetails { + field : AST.Field, + jsonBinding : () => JsonBinding0, + buildDefault : () => { value : unknown } | null +}; + +function structJsonBinding>(dresolver : DeclResolver, struct : AST.Struct, params : AST.TypeExpr[], boundTypeParams : BoundTypeParams ) : JsonBinding0 { + const newBoundTypeParams = createBoundTypeParams(dresolver, struct.typeParams, params, boundTypeParams); + const fieldDetails : StructFieldDetails[] = []; + struct.fields.forEach( (field) => { + let buildDefault = once( () => { + if (field.default.kind === "just") { + const json = field.default.value; + return { 'value' : buildJsonBinding(dresolver, field.typeExpr, newBoundTypeParams).fromJson(json)}; + } else { + return null; + } + }); + + fieldDetails.push( { + field : field, + jsonBinding : once(() => buildJsonBinding(dresolver, field.typeExpr, newBoundTypeParams)), + buildDefault : buildDefault, + }); + }); + + function toJson(v0: unknown) : Json { + const v = v0 as {[key:string]:unknown}; + const json: JsonObject = {}; + fieldDetails.forEach( (fd) => { + json[fd.field.serializedName] = fd.jsonBinding().toJson(v && v[fd.field.name]); + }); + return json; + } + + function fromJson(json: Json): T { + const jobj = asJsonObject(json); + if (!jobj) { + throw jsonParseException("expected an object"); + } + + const v = {} as T; + fieldDetails.forEach( (fd) => { + const name = fd.field.name as keyof T; + + if (jobj[fd.field.serializedName] === undefined) { + const defaultv = fd.buildDefault(); + if (defaultv === null) { + throw jsonParseException("missing struct field " + fd.field.serializedName ); + } else { + const value = defaultv.value as T[keyof T]; + v[name] = value; + } + } else { + try { + const value = fd.jsonBinding().fromJson(jobj[fd.field.serializedName]) as T[keyof T]; + v[name] = value; + } catch(e) { + if (isJsonParseException(e)) { + e.pushField(fd.field.serializedName); + } + throw e; + } + } + }); + return v; + } + + return {toJson, fromJson}; +} + +function enumJsonBinding(_dresolver : DeclResolver, union : AST.Union, _params : AST.TypeExpr[], _boundTypeParams : BoundTypeParams ) : JsonBinding0 { + const toSerialized: {[key:string]:string} = {}; + const fromSerialized: {[key:string]:string} = {}; + union.fields.forEach( field => { + toSerialized[field.name] = field.serializedName; + fromSerialized[field.serializedName] = field.name; + }); + + function toJson(v :unknown) : Json { + return toSerialized[v as string]; + } + + function fromJson(json : Json) : unknown { + if (typeof(json) !== 'string') { + throw jsonParseException("expected a string for enum"); + } + const result = fromSerialized[json as string]; + if (result === undefined) { + throw jsonParseException("invalid string for enum: " + json); + } + return result; + } + + return {toJson, fromJson}; +} + +interface FieldDetails { + field : AST.Field; + isVoid : boolean; + jsonBinding : () => JsonBinding0; +}; + +function unionJsonBinding(dresolver : DeclResolver, union : AST.Union, params : AST.TypeExpr[], boundTypeParams : BoundTypeParams ) : JsonBinding0 { + + const newBoundTypeParams = createBoundTypeParams(dresolver, union.typeParams, params, boundTypeParams); + const detailsByName : {[key: string]: FieldDetails} = {}; + const detailsBySerializedName : {[key: string]: FieldDetails} = {}; + union.fields.forEach( (field) => { + const details = { + field : field, + isVoid : isVoid(field.typeExpr), + jsonBinding : once(() => buildJsonBinding(dresolver, field.typeExpr, newBoundTypeParams)) + }; + detailsByName[field.name] = details; + detailsBySerializedName[field.serializedName] = details; + }); + + function toJson(v0 : unknown) : Json { + const v = v0 as {kind:string, value:unknown}; + const details = detailsByName[v.kind]; + if (details.isVoid) { + return details.field.serializedName; + } else { + const result: JsonObject = {}; + result[details.field.serializedName] = details.jsonBinding().toJson(v.value); + return result; + } + } + + function lookupDetails(serializedName : string) { + let details = detailsBySerializedName[serializedName]; + if (details === undefined) { + throw jsonParseException("invalid union field " + serializedName); + } + return details; + } + + function fromJson(json : Json) : unknown { + if (typeof(json) === "string") { + let details = lookupDetails(json); + if (!details.isVoid) { + throw jsonParseException("union field " + json + "needs an associated value"); + } + return { kind : details.field.name }; + } + const jobj = asJsonObject(json); + if (jobj) { + for (let k in jobj) { + let details = lookupDetails(k); + try { + return { + kind : details.field.name, + value : details.jsonBinding().fromJson(jobj[k]) + } + } catch(e) { + if (isJsonParseException(e)) { + e.pushField(k); + } + throw e; + } + } + throw jsonParseException("union without a property"); + } else { + throw jsonParseException("expected an object or string"); + } + } + + return {toJson, fromJson}; +} + +function newtypeJsonBinding(dresolver : DeclResolver, newtype : AST.NewType, params : AST.TypeExpr[], boundTypeParams : BoundTypeParams ) : JsonBinding0 { + const newBoundTypeParams = createBoundTypeParams(dresolver, newtype.typeParams, params, boundTypeParams); + return buildJsonBinding(dresolver, newtype.typeExpr, newBoundTypeParams); +} + +function typedefJsonBinding(dresolver : DeclResolver, typedef : AST.TypeDef, params : AST.TypeExpr[], boundTypeParams : BoundTypeParams ) : JsonBinding0 { + const newBoundTypeParams = createBoundTypeParams(dresolver, typedef.typeParams, params, boundTypeParams); + return buildJsonBinding(dresolver, typedef.typeExpr, newBoundTypeParams); +} + +function createBoundTypeParams(dresolver : DeclResolver, paramNames : string[], paramTypes : AST.TypeExpr[], boundTypeParams : BoundTypeParams) : BoundTypeParams +{ + let result : BoundTypeParams = {}; + paramNames.forEach( (paramName,i) => { + result[paramName] = buildJsonBinding(dresolver,paramTypes[i], boundTypeParams); + }); + return result; +} + +/** + * Helper function that takes a thunk, and evaluates it only on the first call. Subsequent + * calls return the previous value + */ +function once(run : () => T) : () => T { + let result : T | null = null; + return () => { + if(result === null) { + result = run(); + } + return result; + }; +} + +/** + * Get the value of an annotation of type T + */ +export function getAnnotation(jb: JsonBinding, annotations: AST.Annotations): T | undefined { + if (jb.typeExpr.typeRef.kind != 'reference') { + return undefined; + } + const annScopedName :AST.ScopedName = jb.typeExpr.typeRef.value; + const ann = annotations.find(el => scopedNamesEqual(el.key, annScopedName)); + if (ann === undefined) { + return undefined; + } + return jb.fromJsonE(ann.value); +} diff --git a/typescript/cli/runtime/sys/adlast.ts b/typescript/cli/runtime/sys/adlast.ts new file mode 100644 index 00000000..39ac2496 --- /dev/null +++ b/typescript/cli/runtime/sys/adlast.ts @@ -0,0 +1,274 @@ +/* @generated from adl module sys.adlast */ + +import * as sys_types from './types$TSEXT'; + +export type ModuleName = string; + +export type Ident = string; + +export type Annotations = sys_types.Map; + +export interface ScopedName { + moduleName: ModuleName; + name: Ident; +} + +export function makeScopedName( + input: { + moduleName: ModuleName, + name: Ident, + } +): ScopedName { + return { + moduleName: input.moduleName, + name: input.name, + }; +} + +export interface TypeRef_Primitive { + kind: 'primitive'; + value: Ident; +} +export interface TypeRef_TypeParam { + kind: 'typeParam'; + value: Ident; +} +export interface TypeRef_Reference { + kind: 'reference'; + value: ScopedName; +} + +export type TypeRef = TypeRef_Primitive | TypeRef_TypeParam | TypeRef_Reference; + +export interface TypeRefOpts { + primitive: Ident; + typeParam: Ident; + reference: ScopedName; +} + +export function makeTypeRef(kind: K, value: TypeRefOpts[K]) { return {kind, value}; } + +export interface TypeExpr { + typeRef: TypeRef; + parameters: TypeExpr[]; +} + +export function makeTypeExpr( + input: { + typeRef: TypeRef, + parameters: TypeExpr[], + } +): TypeExpr { + return { + typeRef: input.typeRef, + parameters: input.parameters, + }; +} + +export interface Field { + name: Ident; + serializedName: Ident; + typeExpr: TypeExpr; + default: sys_types.Maybe<{}|null>; + annotations: Annotations; +} + +export function makeField( + input: { + name: Ident, + serializedName: Ident, + typeExpr: TypeExpr, + default: sys_types.Maybe<{}|null>, + annotations: Annotations, + } +): Field { + return { + name: input.name, + serializedName: input.serializedName, + typeExpr: input.typeExpr, + default: input.default, + annotations: input.annotations, + }; +} + +export interface Struct { + typeParams: Ident[]; + fields: Field[]; +} + +export function makeStruct( + input: { + typeParams: Ident[], + fields: Field[], + } +): Struct { + return { + typeParams: input.typeParams, + fields: input.fields, + }; +} + +export interface Union { + typeParams: Ident[]; + fields: Field[]; +} + +export function makeUnion( + input: { + typeParams: Ident[], + fields: Field[], + } +): Union { + return { + typeParams: input.typeParams, + fields: input.fields, + }; +} + +export interface TypeDef { + typeParams: Ident[]; + typeExpr: TypeExpr; +} + +export function makeTypeDef( + input: { + typeParams: Ident[], + typeExpr: TypeExpr, + } +): TypeDef { + return { + typeParams: input.typeParams, + typeExpr: input.typeExpr, + }; +} + +export interface NewType { + typeParams: Ident[]; + typeExpr: TypeExpr; + default: sys_types.Maybe<{}|null>; +} + +export function makeNewType( + input: { + typeParams: Ident[], + typeExpr: TypeExpr, + default: sys_types.Maybe<{}|null>, + } +): NewType { + return { + typeParams: input.typeParams, + typeExpr: input.typeExpr, + default: input.default, + }; +} + +export interface DeclType_Struct_ { + kind: 'struct_'; + value: Struct; +} +export interface DeclType_Union_ { + kind: 'union_'; + value: Union; +} +export interface DeclType_Type_ { + kind: 'type_'; + value: TypeDef; +} +export interface DeclType_Newtype_ { + kind: 'newtype_'; + value: NewType; +} + +export type DeclType = DeclType_Struct_ | DeclType_Union_ | DeclType_Type_ | DeclType_Newtype_; + +export interface DeclTypeOpts { + struct_: Struct; + union_: Union; + type_: TypeDef; + newtype_: NewType; +} + +export function makeDeclType(kind: K, value: DeclTypeOpts[K]) { return {kind, value}; } + +export interface Decl { + name: Ident; + version: sys_types.Maybe; + type_: DeclType; + annotations: Annotations; +} + +export function makeDecl( + input: { + name: Ident, + version: sys_types.Maybe, + type_: DeclType, + annotations: Annotations, + } +): Decl { + return { + name: input.name, + version: input.version, + type_: input.type_, + annotations: input.annotations, + }; +} + +export interface ScopedDecl { + moduleName: ModuleName; + decl: Decl; +} + +export function makeScopedDecl( + input: { + moduleName: ModuleName, + decl: Decl, + } +): ScopedDecl { + return { + moduleName: input.moduleName, + decl: input.decl, + }; +} + +export type DeclVersions = Decl[]; + +export interface Import_ModuleName { + kind: 'moduleName'; + value: ModuleName; +} +export interface Import_ScopedName { + kind: 'scopedName'; + value: ScopedName; +} + +export type Import = Import_ModuleName | Import_ScopedName; + +export interface ImportOpts { + moduleName: ModuleName; + scopedName: ScopedName; +} + +export function makeImport(kind: K, value: ImportOpts[K]) { return {kind, value}; } + +export interface Module { + name: ModuleName; + imports: Import[]; + decls: {[key: string]: Decl}; + annotations: Annotations; +} + +export function makeModule( + input: { + name: ModuleName, + imports: Import[], + decls: {[key: string]: Decl}, + annotations: Annotations, + } +): Module { + return { + name: input.name, + imports: input.imports, + decls: input.decls, + annotations: input.annotations, + }; +} diff --git a/typescript/cli/runtime/sys/dynamic.ts b/typescript/cli/runtime/sys/dynamic.ts new file mode 100644 index 00000000..1493a277 --- /dev/null +++ b/typescript/cli/runtime/sys/dynamic.ts @@ -0,0 +1,23 @@ +/* @generated from adl module sys.dynamic */ + +import * as sys_adlast from './adlast$TSEXT'; + +/** + * A serialised value along with its type + */ +export interface Dynamic { + typeExpr: sys_adlast.TypeExpr; + value: {}|null; +} + +export function makeDynamic( + input: { + typeExpr: sys_adlast.TypeExpr, + value: {}|null, + } +): Dynamic { + return { + typeExpr: input.typeExpr, + value: input.value, + }; +} diff --git a/typescript/cli/runtime/sys/types.ts b/typescript/cli/runtime/sys/types.ts new file mode 100644 index 00000000..aa9735c1 --- /dev/null +++ b/typescript/cli/runtime/sys/types.ts @@ -0,0 +1,93 @@ +/* @generated from adl module sys.types */ + + +export interface Pair { + v1: T1; + v2: T2; +} + +export function makePair( + input: { + v1: T1, + v2: T2, + } +): Pair { + return { + v1: input.v1, + v2: input.v2, + }; +} + +export interface Either_Left { + kind: 'left'; + value: T1; +} +export interface Either_Right<_T1, T2> { + kind: 'right'; + value: T2; +} + +export type Either = Either_Left | Either_Right; + +export interface EitherOpts { + left: T1; + right: T2; +} + +export function makeEither>(kind: K, value: EitherOpts[K]) { return {kind, value}; } + +export interface Maybe_Nothing<_T> { + kind: 'nothing'; +} +export interface Maybe_Just { + kind: 'just'; + value: T; +} + +export type Maybe = Maybe_Nothing | Maybe_Just; + +export interface MaybeOpts { + nothing: null; + just: T; +} + +export function makeMaybe>(kind: K, value: MaybeOpts[K]) { return {kind, value}; } + +export interface Result_Ok { + kind: 'ok'; + value: T; +} +export interface Result_Error<_T, E> { + kind: 'error'; + value: E; +} + +export type Result = Result_Ok | Result_Error; + +export interface ResultOpts { + ok: T; + error: E; +} + +export function makeResult>(kind: K, value: ResultOpts[K]) { return {kind, value}; } + +export interface MapEntry { + key: K; + value: V; +} + +export function makeMapEntry( + input: { + key: K, + value: V, + } +): MapEntry { + return { + key: input.key, + value: input.value, + }; +} + +export type Map = MapEntry[]; + +export type Set = T[]; diff --git a/typescript/cli/runtime/utils.ts b/typescript/cli/runtime/utils.ts new file mode 100644 index 00000000..b358aee7 --- /dev/null +++ b/typescript/cli/runtime/utils.ts @@ -0,0 +1,77 @@ +import * as AST from './sys/adlast$TSEXT'; + +export function isEnum(union : AST.Union) : boolean { + for (let field of union.fields) { + if (!isVoid(field.typeExpr)) { + return false; + } + } + return true; +} + +export function isVoid(texpr : AST.TypeExpr) : boolean { + if (texpr.typeRef.kind === "primitive") { + return texpr.typeRef.value === "Void"; + } + return false; +} + +export function typeExprsEqual(texpr1 : AST.TypeExpr, texpr2 : AST.TypeExpr) : boolean { + if (!typeRefsEqual(texpr1.typeRef, texpr2.typeRef)) { + return false; + } + if (texpr1.parameters.length != texpr2.parameters.length) { + return false; + } + for (let i = 0; i < texpr1.parameters.length; i++) { + if(!typeExprsEqual(texpr1.parameters[i], texpr2.parameters[i])) { + return false; + } + } + return true; +} + +export function typeRefsEqual(tref1 : AST.TypeRef, tref2 : AST.TypeRef) : boolean { + if (tref1.kind === "primitive" && tref2.kind === "primitive") { + return tref1.value === tref2.value; + } else if (tref1.kind === "typeParam" && tref2.kind === "typeParam") { + return tref1.value === tref2.value; + } else if (tref1.kind === "reference" && tref2.kind === "reference") { + return scopedNamesEqual(tref1.value, tref2.value); + } + return false; +} + +export function scopedNamesEqual(sn1: AST.ScopedName, sn2: AST.ScopedName): boolean { + return sn1.moduleName === sn2.moduleName && sn1.name === sn2.name; +} + +function typeExprToStringImpl(te: AST.TypeExpr, withScopedNames: boolean) : string { + let result = ""; + if (te.typeRef.kind == "primitive") { + result = te.typeRef.value; + } else if (te.typeRef.kind == "typeParam") { + result = te.typeRef.value; + } else if (te.typeRef.kind == "reference") { + result = withScopedNames + ? te.typeRef.value.moduleName + "." + te.typeRef.value.name + : te.typeRef.value.name; + } + if (te.parameters.length > 0) { + result = result + "<" + te.parameters.map(p => typeExprToStringImpl(p, withScopedNames)) + ">"; + } + return result; +} + +/* Convert a type expression to a string, with fully scoped names */ + +export function typeExprToString(te: AST.TypeExpr) : string { + return typeExprToStringImpl(te, true); +} + +/* Convert a type expression to a string, with unscoped names */ + +export function typeExprToStringUnscoped(te: AST.TypeExpr) : string { + return typeExprToStringImpl(te, false); +} + diff --git a/typescript/tests/deno-1.10.2/.gitignore b/typescript/cli/tests/deno-1.10.2/.gitignore similarity index 100% rename from typescript/tests/deno-1.10.2/.gitignore rename to typescript/cli/tests/deno-1.10.2/.gitignore diff --git a/typescript/tests/deno-1.10.2/example.tests.ts b/typescript/cli/tests/deno-1.10.2/example.tests.ts similarity index 100% rename from typescript/tests/deno-1.10.2/example.tests.ts rename to typescript/cli/tests/deno-1.10.2/example.tests.ts diff --git a/typescript/tests/example.adl b/typescript/cli/tests/example.adl similarity index 100% rename from typescript/tests/example.adl rename to typescript/cli/tests/example.adl diff --git a/typescript/tests/run-tests.sh b/typescript/cli/tests/run-tests.sh similarity index 100% rename from typescript/tests/run-tests.sh rename to typescript/cli/tests/run-tests.sh diff --git a/typescript/tests/ts-3.5.2/.gitignore b/typescript/cli/tests/ts-3.5.2/.gitignore similarity index 100% rename from typescript/tests/ts-3.5.2/.gitignore rename to typescript/cli/tests/ts-3.5.2/.gitignore diff --git a/typescript/tests/ts-3.5.2/example.spec.ts b/typescript/cli/tests/ts-3.5.2/example.spec.ts similarity index 100% rename from typescript/tests/ts-3.5.2/example.spec.ts rename to typescript/cli/tests/ts-3.5.2/example.spec.ts diff --git a/typescript/tests/ts-3.5.2/package.json b/typescript/cli/tests/ts-3.5.2/package.json similarity index 100% rename from typescript/tests/ts-3.5.2/package.json rename to typescript/cli/tests/ts-3.5.2/package.json diff --git a/typescript/tests/ts-3.5.2/tsconfig.json b/typescript/cli/tests/ts-3.5.2/tsconfig.json similarity index 100% rename from typescript/tests/ts-3.5.2/tsconfig.json rename to typescript/cli/tests/ts-3.5.2/tsconfig.json diff --git a/typescript/tests/ts-3.5.2/tslint.json b/typescript/cli/tests/ts-3.5.2/tslint.json similarity index 100% rename from typescript/tests/ts-3.5.2/tslint.json rename to typescript/cli/tests/ts-3.5.2/tslint.json diff --git a/typescript/tests/ts-3.5.2/yarn.lock b/typescript/cli/tests/ts-3.5.2/yarn.lock similarity index 100% rename from typescript/tests/ts-3.5.2/yarn.lock rename to typescript/cli/tests/ts-3.5.2/yarn.lock diff --git a/typescript/tests/ts-3.8.3/.gitignore b/typescript/cli/tests/ts-3.8.3/.gitignore similarity index 100% rename from typescript/tests/ts-3.8.3/.gitignore rename to typescript/cli/tests/ts-3.8.3/.gitignore diff --git a/typescript/tests/ts-3.8.3/example.spec.ts b/typescript/cli/tests/ts-3.8.3/example.spec.ts similarity index 100% rename from typescript/tests/ts-3.8.3/example.spec.ts rename to typescript/cli/tests/ts-3.8.3/example.spec.ts diff --git a/typescript/tests/ts-3.8.3/package.json b/typescript/cli/tests/ts-3.8.3/package.json similarity index 100% rename from typescript/tests/ts-3.8.3/package.json rename to typescript/cli/tests/ts-3.8.3/package.json diff --git a/typescript/tests/ts-3.8.3/tsconfig.json b/typescript/cli/tests/ts-3.8.3/tsconfig.json similarity index 100% rename from typescript/tests/ts-3.8.3/tsconfig.json rename to typescript/cli/tests/ts-3.8.3/tsconfig.json diff --git a/typescript/tests/ts-3.8.3/tslint.json b/typescript/cli/tests/ts-3.8.3/tslint.json similarity index 100% rename from typescript/tests/ts-3.8.3/tslint.json rename to typescript/cli/tests/ts-3.8.3/tslint.json diff --git a/typescript/tests/ts-3.8.3/yarn.lock b/typescript/cli/tests/ts-3.8.3/yarn.lock similarity index 100% rename from typescript/tests/ts-3.8.3/yarn.lock rename to typescript/cli/tests/ts-3.8.3/yarn.lock diff --git a/typescript/tests/ts-4.2.4/.gitignore b/typescript/cli/tests/ts-4.2.4/.gitignore similarity index 100% rename from typescript/tests/ts-4.2.4/.gitignore rename to typescript/cli/tests/ts-4.2.4/.gitignore diff --git a/typescript/tests/ts-4.2.4/example.spec.ts b/typescript/cli/tests/ts-4.2.4/example.spec.ts similarity index 100% rename from typescript/tests/ts-4.2.4/example.spec.ts rename to typescript/cli/tests/ts-4.2.4/example.spec.ts diff --git a/typescript/tests/ts-4.2.4/package.json b/typescript/cli/tests/ts-4.2.4/package.json similarity index 100% rename from typescript/tests/ts-4.2.4/package.json rename to typescript/cli/tests/ts-4.2.4/package.json diff --git a/typescript/tests/ts-4.2.4/tsconfig.json b/typescript/cli/tests/ts-4.2.4/tsconfig.json similarity index 100% rename from typescript/tests/ts-4.2.4/tsconfig.json rename to typescript/cli/tests/ts-4.2.4/tsconfig.json diff --git a/typescript/tests/ts-4.2.4/tslint.json b/typescript/cli/tests/ts-4.2.4/tslint.json similarity index 100% rename from typescript/tests/ts-4.2.4/tslint.json rename to typescript/cli/tests/ts-4.2.4/tslint.json diff --git a/typescript/tests/ts-4.2.4/yarn.lock b/typescript/cli/tests/ts-4.2.4/yarn.lock similarity index 100% rename from typescript/tests/ts-4.2.4/yarn.lock rename to typescript/cli/tests/ts-4.2.4/yarn.lock diff --git a/typescript/tests/ts-4.6.3/.gitignore b/typescript/cli/tests/ts-4.6.3/.gitignore similarity index 100% rename from typescript/tests/ts-4.6.3/.gitignore rename to typescript/cli/tests/ts-4.6.3/.gitignore diff --git a/typescript/tests/ts-4.6.3/example.spec.ts b/typescript/cli/tests/ts-4.6.3/example.spec.ts similarity index 100% rename from typescript/tests/ts-4.6.3/example.spec.ts rename to typescript/cli/tests/ts-4.6.3/example.spec.ts diff --git a/typescript/tests/ts-4.6.3/package.json b/typescript/cli/tests/ts-4.6.3/package.json similarity index 100% rename from typescript/tests/ts-4.6.3/package.json rename to typescript/cli/tests/ts-4.6.3/package.json diff --git a/typescript/tests/ts-4.6.3/tsconfig.json b/typescript/cli/tests/ts-4.6.3/tsconfig.json similarity index 100% rename from typescript/tests/ts-4.6.3/tsconfig.json rename to typescript/cli/tests/ts-4.6.3/tsconfig.json diff --git a/typescript/tests/ts-4.6.3/tslint.json b/typescript/cli/tests/ts-4.6.3/tslint.json similarity index 100% rename from typescript/tests/ts-4.6.3/tslint.json rename to typescript/cli/tests/ts-4.6.3/tslint.json diff --git a/typescript/tests/ts-4.6.3/yarn.lock b/typescript/cli/tests/ts-4.6.3/yarn.lock similarity index 100% rename from typescript/tests/ts-4.6.3/yarn.lock rename to typescript/cli/tests/ts-4.6.3/yarn.lock diff --git a/typescript/workspace/.gitignore b/typescript/workspace/.gitignore new file mode 100644 index 00000000..b9470778 --- /dev/null +++ b/typescript/workspace/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +dist/ diff --git a/typescript/workspace/adl.work.json b/typescript/workspace/adl.work.json new file mode 100644 index 00000000..1de86e06 --- /dev/null +++ b/typescript/workspace/adl.work.json @@ -0,0 +1,109 @@ +{ + "adlc": "0.0.0", + "named_options": { + "base": { + "ts_opts": { + "runtime_opts": { + "workspace_ref": "@adl-lang/runtime" + }, + "dev_dependencies": { + "tsconfig": "workspace:*", + "typescript": "^4.9.3" + }, + "scripts": { + "tsc": "tsc", + "clean": "rm -rf dist && rm -rf node_modules" + }, + "tsconfig": { + "extends": "tsconfig/base.json", + "include": [ + "." + ], + "exclude": [ + "dist", + "build", + "node_modules" + ], + "compilerOptions": { + "outDir": "dist", + "lib": [ + "es2020" + ] + } + } + } + } + }, + "runtimes": [ + { + "ts_runtime": { + "output_dir": "./generated/runtime", + "npm_pkg_name": "@adl-lang/runtime" + } + } + ], + "use": [ + { + "named_opts": "base", + "ref": { + "embedded": { + "alias": "sys" + } + }, + "ts_opts": { + "npm_pkg_name": "@adl-lang/sys", + "npm_version": "1.0.0", + "extra_dependencies": { + "base64-js": "^1.5.1" + }, + "outputs": { + "gen": { + "output_dir": "./generated/sys", + "manifest": "./generated/sys/.adl-manifest" + } + }, + "include_resolver": true + } + }, + { + "named_opts": "base", + "ref": { + "dir": { + "path": "./adl/lib" + } + }, + "ts_opts": { + "npm_pkg_name": "@adl-lang/common", + "outputs": { + "gen": { + "output_dir": "./generated/common", + "manifest": "./generated/common/.adl-manifest" + } + }, + "include_resolver": true + } + }, + { + "named_opts": "base", + "ref": { + "dir": { + "path": "./adl/proj" + } + }, + "ts_opts": { + "npm_pkg_name": "@adl-lang/protoclient", + "generate_transitive": false, + "extra_dependencies": { + "base64-js": "^1.5.1" + }, + "outputs": { + "gen": { + "output_dir": "./generated/protoclient", + "manifest": "./generated/protoclient/.adl-manifest" + } + }, + "include_resolver": true + } + } + ] +} \ No newline at end of file diff --git a/typescript/workspace/adl/lib/adl.pkg.json b/typescript/workspace/adl/lib/adl.pkg.json new file mode 100644 index 00000000..627e1999 --- /dev/null +++ b/typescript/workspace/adl/lib/adl.pkg.json @@ -0,0 +1,12 @@ +{ + "path" : "github.com/adl-lang/adl/typescript/workspace/adl/lib", + "global_alias": "common", + "adlc": "0.0.0", + "requires": [ + { + "ref": { + "alias": "sys" + } + } + ] +} \ No newline at end of file diff --git a/typescript/workspace/adl/lib/common.adl b/typescript/workspace/adl/lib/common.adl new file mode 100644 index 00000000..d8c48a78 --- /dev/null +++ b/typescript/workspace/adl/lib/common.adl @@ -0,0 +1,94 @@ +module common { + +import common.strings.StringNE; +import common.db.DbColumnType; + +/// A instant in time, represented as milliseconds from +/// the epoch of "1970-01-01T00:00:00Z +newtype Instant = Int64; + +/// A date in ISO8601 format +newtype LocalDate = String = "1970-01-01"; + +/// A time in ISO8601 format +newtype LocalTime = String = "00:00:00"; + +/// A datetime in ISO8601 format +newtype LocalDateTime = String = "1970-01-01T00:00:00"; + +/// The day of the week +union DayOfWeek { + Void monday; + Void tuesday; + Void wednesday; + Void thursday; + Void friday; + Void saturday; + Void sunday; +}; + +/// A duration in ISO8601 format +@DbColumnType "interval" +newtype Duration = String = "P1D"; + +/// An IANA timezone +newtype Timezone = StringNE; + +/// A holder for paginated results +struct Paginated { + + /// The paginated items + Vector items; + + /// The offset used for this query + Int64 current_offset; + + /// The size of the entire date set + Int64 total_size; +}; + +/// Empty Struct (Used mostly for Void RPC responses) +struct Unit {}; + +/// Phantom type to capture a StringMap with a named string key type: +type StringKeyMap = StringMap; + +/// Naming aid for strings used as keys +type Key = String; + +/// A value of type T along with the Key +struct WithKey { + Key key; + T value; +}; + +/// Postgres array of strings type that is serialized in to a list of Strings +@DbColumnType "text[]" +newtype StringList = Vector; + +// Postgres tsvector type for plain text searching +@DbColumnType "tsvector" +newtype TSVector = String; + +/// Postgres Geography type that is serialized using GeoJson +// Maps to postgres database as 'geography' column +// See https://postgis.net/workshops/postgis-intro/geography.html#casting-to-geometry +@DbColumnType "geography" +newtype GeographyGeoJson = String; + +/// Postgres Geometry type +// Maps to postgres database as 'geometry' column +// Serialise to/from WKT (Well Known Text) in the string +@DbColumnType "geometry" +newtype GeometryWKT = String; + + +/// A floating point decimal value +// +// In principle, the json format allows numbers with arbitrary decimal precision. However +// support for this is dependent on individual client libraries, and crucially the +// JSON.parse() function in browsers converts json numbers to a binary floating point +// double representation. Hence we take the safe option and serialize as JSON strings. +@DbColumnType "numeric" +newtype BigDecimal = String; +}; diff --git a/typescript/workspace/adl/lib/common.adl-java b/typescript/workspace/adl/lib/common.adl-java new file mode 100644 index 00000000..4b922fc2 --- /dev/null +++ b/typescript/workspace/adl/lib/common.adl-java @@ -0,0 +1,82 @@ +module common +{ +import adlc.config.java.*; +import common.db.JavaDbCustomType; +import sys.types.Set; + +annotation JavaPackage "au.com.helixta.adl.common"; + +annotation Instant JavaCustomType { + "javaname" : "java.time.Instant", + "helpers" : "au.com.helixta.adl.custom.InstantHelpers" +}; + +annotation LocalDate JavaCustomType { + "javaname" : "java.time.LocalDate", + "helpers" : "au.com.helixta.adl.custom.LocalDateHelpers" +}; + +annotation LocalTime JavaCustomType { + "javaname" : "java.time.LocalTime", + "helpers" : "au.com.helixta.adl.custom.LocalTimeHelpers" +}; + +annotation LocalDateTime JavaCustomType { + "javaname" : "java.time.LocalDateTime", + "helpers" : "au.com.helixta.adl.custom.LocalDateTimeHelpers" +}; + +annotation DayOfWeek JavaCustomType { + "javaname" : "java.time.DayOfWeek", + "helpers" : "au.com.helixta.adl.custom.DayOfWeekHelpers" +}; + +annotation GeographyGeoJson JavaCustomType { + "javaname" : "org.postgis.PGgeometry", + "helpers": "au.com.helixta.adl.custom.PGgeometryHelpers" +}; + +annotation GeographyGeoJson JavaDbCustomType { + "javaDbType": "org.postgis.PGgeometry", + "helpers": "au.com.helixta.adl.custom.PGgeometryHelpers" +}; + +annotation GeometryWKT JavaCustomType { + "javaname" : "org.postgis.PGgeometry", + "helpers": "au.com.helixta.adl.custom.PGgeometryWKTHelpers" +}; + +annotation GeometryWKT JavaDbCustomType { + "javaDbType" : "org.postgis.PGgeometry", + "helpers": "au.com.helixta.adl.custom.PGgeometryWKTHelpers" +}; + +annotation TSVector JavaDbCustomType { + "javaDbType" : "String", + "helpers": "au.com.helixta.adl.custom.TSVectorHelpers" +}; + +annotation StringList JavaDbCustomType { + "javaDbType" : "au.com.helixta.nofrills.sql.StringList", + "helpers": "au.com.helixta.adl.custom.StringListHelpers" +}; + +annotation StringList JavaCustomType { + "javaname" : "au.com.helixta.nofrills.sql.StringList", + "helpers": "au.com.helixta.adl.custom.StringListHelpers" +}; + +annotation BigDecimal JavaCustomType { + "javaname" : "java.math.BigDecimal", + "helpers": "au.com.helixta.adl.custom.BigDecimalHelpers" +}; + +annotation BigDecimal JavaDbCustomType { + "javaDbType" : "java.math.BigDecimal", + "helpers": "au.com.helixta.adl.custom.BigDecimalHelpers" +}; + +/// Force adlc java runtime to include HashSetHelpers.java +newtype SetStrings = Set; + +}; diff --git a/typescript/workspace/adl/lib/common/adminui/api.adl b/typescript/workspace/adl/lib/common/adminui/api.adl new file mode 100644 index 00000000..a9217501 --- /dev/null +++ b/typescript/workspace/adl/lib/common/adminui/api.adl @@ -0,0 +1,168 @@ +module common.adminui.api { + +import sys.adlast.TypeExpr; +import sys.adlast.ModuleName; +import sys.adlast.ScopedName; +import sys.types.Maybe; +import common.Unit; +import common.db.DbKey; +import common.db.WithDbId; +import common.Paginated; +import common.tabular.TableQuery; +import common.http.HttpPost; +import common.adminui.db.MetaAdlDecl; + +import common.flyway.api.FlywayReq; +import common.flyway.api.FlywayResp; + +// An adl value serialised via the standard schema +type AdlValue = Json; + +// A Row in a table is a map of Adl values +type DbRow = StringMap; +type DbId = DbKey; + +/// Endpoints supporting CRUD for the Admin UI, +/// along with metadata access. +struct AdminApiRequests { + + /// Query the tables available for admin access + HttpPost> queryTables = { + "path" : "/admin/meta/tables", + "security" : {"tokenWithRole": "admin"} + }; + + /// Query the ADL declarations used in the column + /// type declarations + HttpPost> queryDecls = { + "path" : "/admin/meta/decls", + "security" : {"tokenWithRole": "admin"} + }; + + /// Query rows from a table, specifying pagination, + /// filtering and sorting. As per it's return type, this method + /// can only be used for tables with a string primary key + /// called `id`. + HttpPost>> query = { + "path" : "/admin/query", + "security" : {"tokenWithRole": "admin"} + }; + + /// Query rows from a table without requiring a primary key, specifying pagination, + /// filtering and sorting. + HttpPost> queryWithoutIds = { + "path" : "/admin/query-without-ids", + "security" : {"tokenWithRole": "admin"} + }; + + /// Create a new row in a table + HttpPost> create = { + "path" : "/admin/create", + "security" : {"tokenWithRole": "admin"} + }; + + /// Update a single existing row in a table + HttpPost> update = { + "path" : "/admin/update", + "security" : {"tokenWithRole": "admin"} + }; + + /// Delete a single existing row in a table + HttpPost> delete = { + "path" : "/admin/delete", + "security" : {"tokenWithRole": "admin"} + }; + + /// Fetch descriptive strings for db keys + HttpPost,Vector> dbKeyLabels = { + "path" : "/admin/dbkeylabels", + "security" : {"tokenWithRole": "admin"} + }; + + /// Flyway migration handled by adminui + HttpPost flyway = { + "path" : "/admin/flyway", + "security" : {"tokenWithRole": "admin"} + }; +}; + +struct QueryReq { + String table; + + /// The columns to be included in the result. If empty, all + /// columns will be included. + Vector columns; + + TableQuery query; +}; + +struct Table { + String name; + String label; + String description; + Bool hasIdPrimaryKey; + + /// If true, the current user is allowed to query existingRows + Bool allowQuery; + + /// If true, the current user is allowed to insert new rows + Bool allowInsert; + + /// If true, the current user is allowed to delete rows + Bool allowDelete; + + /// If true, the current user is allowed to update rows + Bool allowUpdate; + + Vector columns; + ModuleName declModuleName; + String declName; +}; + +union Access { + Void readOnly; + Void readWrite; +}; + +struct TableColumn { + String name; + String label; + String description; + TypeExpr typeExpr; + Maybe defaultValue; + Bool generated; + Access access; +}; + +struct CreateReq { + String table; + DbRow values; +}; + +struct UpdateReq { + String table; + WithDbId values; +}; + +struct DeleteReq { + String table; + DbId id; +}; + +union DbResult { + T ok; + String dbError; +}; + +struct DbKeyLabelReq { + ScopedName scopedName; + String id; +}; + +struct DbKeyLabelResp { + ScopedName scopedName; + String id; + String label; +}; + +}; diff --git a/typescript/workspace/adl/lib/common/adminui/api.adl-java b/typescript/workspace/adl/lib/common/adminui/api.adl-java new file mode 100644 index 00000000..106a2ff7 --- /dev/null +++ b/typescript/workspace/adl/lib/common/adminui/api.adl-java @@ -0,0 +1,6 @@ +module common.adminui.api +{ +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.adminui.api"; +}; diff --git a/typescript/workspace/adl/lib/common/adminui/config.adl b/typescript/workspace/adl/lib/common/adminui/config.adl new file mode 100644 index 00000000..dfc90669 --- /dev/null +++ b/typescript/workspace/adl/lib/common/adminui/config.adl @@ -0,0 +1,35 @@ +module common.adminui.config { + +import common.config.frontend.ThreadPoolConfig; +import common.config.log.LogConfig; +import common.config.log.ClientLogConfig; +import common.config.db.PostgreSqlConfig; + +/// Configuration for the adminui server +struct ServerConfig { + /// Port to listen for requests + Int16 port; + + /// Environment name, e.g. dev, uat, prod + String environment; + + /// Name of the release / code version + String releaseName; + + /// Secret used to sign JWT tokens + String jwtSecret; + + /// Database config + PostgreSqlConfig db; + + /// Server-side logging config + LogConfig logging; + + /// Frontend threadpool configuration + ThreadPoolConfig threadPool; + + // DB Migration config, if null flyway is not available. + Nullable flyway = null; +}; + +}; diff --git a/typescript/workspace/adl/lib/common/adminui/db.adl b/typescript/workspace/adl/lib/common/adminui/db.adl new file mode 100644 index 00000000..27132a7e --- /dev/null +++ b/typescript/workspace/adl/lib/common/adminui/db.adl @@ -0,0 +1,40 @@ +module common.adminui.db { + +import sys.adlast.Decl; +import sys.adlast.ModuleName; +import common.db.DbTable; +import common.db.DbColumnName; +import common.Instant; + +struct MetaTable { + String name; + String description; + ModuleName declModuleName; + String declName; +}; + +annotation MetaTable DbTable { + "withPrimaryKey": [ + "name" + ], + "uniquenessConstraints": [ + ["name"] + ] +}; + +struct MetaAdlDecl { + ModuleName moduleName; + String name; + Decl decl; +}; + +annotation MetaAdlDecl DbTable { + "withPrimaryKey": [ + "moduleName", "name" + ], + "uniquenessConstraints": [ + ["moduleName", "name"] + ] +}; + +}; diff --git a/typescript/workspace/adl/lib/common/adminui/db.adl-java b/typescript/workspace/adl/lib/common/adminui/db.adl-java new file mode 100644 index 00000000..472873e2 --- /dev/null +++ b/typescript/workspace/adl/lib/common/adminui/db.adl-java @@ -0,0 +1,6 @@ +module common.adminui.db +{ +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.adminui.db"; +}; diff --git a/typescript/workspace/adl/lib/common/config/aws.adl b/typescript/workspace/adl/lib/common/config/aws.adl new file mode 100644 index 00000000..075a970e --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/aws.adl @@ -0,0 +1,46 @@ +module common.config.aws +{ + +struct AwsCredentials { + String accessKey; + String secretKey; +}; + +/// The methods available to obtain AWS credentials +union AwsCredentialsProvider { + Void useEnvVariables; + Void useInstanceProfile; + AwsCredentials value; +}; + +/// The methods available to determine the AWS region +union AwsRegionProvider { + Void fromInstance; + String value; +}; + +struct S3Location { + /// The name on of an S3 bucket + String s3Bucket; + + /// The S3 path prefix for the storage + String s3Prefix; +}; + +/// Description of an AWS SQS queue +struct QueueDetails { + /// The amount of time to keep the connection open while waiting for queue messages. + Int32 waitTimeSeconds = 10; + String queueUrl = ""; +}; + + +/// Configuration of an S3 client +struct S3ClientConfig { + S3Location location; + AwsRegionProvider region; + AwsCredentialsProvider credentials; +}; + + +}; diff --git a/typescript/workspace/adl/lib/common/config/aws.adl-java b/typescript/workspace/adl/lib/common/config/aws.adl-java new file mode 100644 index 00000000..0ffa32cf --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/aws.adl-java @@ -0,0 +1,7 @@ +module common.config.aws +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.config.aws"; +}; diff --git a/typescript/workspace/adl/lib/common/config/azure.adl b/typescript/workspace/adl/lib/common/config/azure.adl new file mode 100644 index 00000000..8d07e641 --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/azure.adl @@ -0,0 +1,15 @@ +module common.config.azure { + + /// Methods available to obtain Azure credentials + union AzureCredentialsProvider { + /// A shared access signature string + String sharedAccessSignature; + }; + + /// Config parameters for an Azure Blob Client + struct AzureBlobClientConfig { + String blobstoreUri; + AzureCredentialsProvider credentials; + String container; + }; +}; diff --git a/typescript/workspace/adl/lib/common/config/db.adl b/typescript/workspace/adl/lib/common/config/db.adl new file mode 100644 index 00000000..34a5adf6 --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/db.adl @@ -0,0 +1,67 @@ +module common.config.db +{ + +// Connection details for a postgres server +struct PostgreSqlConfig +{ + String host; + Int32 port; + + // the database name + String dbname; + + // login parameters + String user; + String password; + + // The size of the connection pool + Int32 poolSize = 5; + + // true to enable the postgis extensions + Bool postgisEnabled = false; + + /// The amount of time to wait before refreshing a connection + Int32 minRefreshDelayMillis = 60000; + + /// The amount of time to wait for a free connection before timing out + Int32 connectionWaitMillis = 5000; + + /// The root cert to be used for ssl connections + Nullable sslRootCert = null; + + /// The ssl connection mode + PostgresqlSslMode sslMode = "prefer"; +}; + +union PostgresqlSslMode { + Void disable; + Void allow; + Void prefer; + Void require; + + @SerializedName "verify-ca" + Void verifyCa; + + @SerializedName "verify-full" + Void verifyFull; +}; + + +// Connection details for a microsoft SQL server +struct SqlServerConfig +{ + String host; + Int32 port; + + // the database name + String dbname; + + // login parameters + String user; + String password; + + // The size of the connection pool + Int32 poolSize = 5; +}; + +}; diff --git a/typescript/workspace/adl/lib/common/config/db.adl-java b/typescript/workspace/adl/lib/common/config/db.adl-java new file mode 100644 index 00000000..ad45d24e --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/db.adl-java @@ -0,0 +1,7 @@ +module common.config.db +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.config.db"; +}; diff --git a/typescript/workspace/adl/lib/common/config/emailer.adl b/typescript/workspace/adl/lib/common/config/emailer.adl new file mode 100644 index 00000000..f662a8d8 --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/emailer.adl @@ -0,0 +1,22 @@ +module common.config.emailer +{ +import common.config.aws.AwsCredentialsProvider; +import common.config.aws.AwsRegionProvider; + +/// Configuration for the emailer used +union EmailerConfig { + /// Fake emailer, just prints outgoing email info to stdout + Void fake; + + /// SES emailer implementation + SesConfig ses; + +}; + +/// Configuration for AWS SES emailer implementation +struct SesConfig { + AwsCredentialsProvider credentials; + AwsRegionProvider region; +}; + +}; diff --git a/typescript/workspace/adl/lib/common/config/emailer.adl-java b/typescript/workspace/adl/lib/common/config/emailer.adl-java new file mode 100644 index 00000000..0982d4ce --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/emailer.adl-java @@ -0,0 +1,7 @@ +module common.config.emailer +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.config.emailer"; +}; diff --git a/typescript/workspace/adl/lib/common/config/frontend.adl b/typescript/workspace/adl/lib/common/config/frontend.adl new file mode 100644 index 00000000..f194854f --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/frontend.adl @@ -0,0 +1,22 @@ +module common.config.frontend { + +/// Configuration for a consumer which processes work from a queue with a bounded thread pool. +/// +/// e.g. Useful for configuring jetty's request thread pool. +/// +// TODO: Java custom type to map this to au.com.helixta.util.concurrent.ThreadPoolConfig +struct ThreadPoolConfig { + /// Maximum number of threads that can be spawned to handle requests + Int32 maxThreads; + + /// Minimum number of threads ready for jetty to handle requests + Int32 minThreads; + + /// How long a thread can be idle before it is candidate to be stopped + Int32 idleTimeoutMillis; + + /// Maximum number of pending requests before new ones are dropped + Int32 queueSize; +}; + +}; diff --git a/typescript/workspace/adl/lib/common/config/frontend.adl-java b/typescript/workspace/adl/lib/common/config/frontend.adl-java new file mode 100644 index 00000000..1e7586a7 --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/frontend.adl-java @@ -0,0 +1,8 @@ +module common.config.frontend +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.config.frontend"; +}; + diff --git a/typescript/workspace/adl/lib/common/config/google.adl b/typescript/workspace/adl/lib/common/config/google.adl new file mode 100644 index 00000000..6aeb3bf4 --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/google.adl @@ -0,0 +1,12 @@ +module common.config.google +{ + +/// Connection parameters for google services +struct GoogleConfig { + String clientId; + String clientSecret; + String accessToken; + String refreshToken; +}; + +}; diff --git a/typescript/workspace/adl/lib/common/config/google.adl-java b/typescript/workspace/adl/lib/common/config/google.adl-java new file mode 100644 index 00000000..b134c62c --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/google.adl-java @@ -0,0 +1,8 @@ +module common.config.google +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.config.google"; +}; + diff --git a/typescript/workspace/adl/lib/common/config/jwt.adl b/typescript/workspace/adl/lib/common/config/jwt.adl new file mode 100644 index 00000000..86ba18b6 --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/jwt.adl @@ -0,0 +1,10 @@ +module common.config.jwt +{ + +/// Secret and expiry of the JWT token +struct JwtConfig { + String secret; + Double expiryInMinutes; +}; + +}; diff --git a/typescript/workspace/adl/lib/common/config/jwt.adl-java b/typescript/workspace/adl/lib/common/config/jwt.adl-java new file mode 100644 index 00000000..c9ece9b4 --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/jwt.adl-java @@ -0,0 +1,7 @@ +module common.config.jwt +{ + import adlc.config.java.*; + + annotation JavaPackage "au.com.helixta.adl.common.config.jwt"; + +}; diff --git a/typescript/workspace/adl/lib/common/config/log.adl b/typescript/workspace/adl/lib/common/config/log.adl new file mode 100644 index 00000000..f91dbc62 --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/log.adl @@ -0,0 +1,69 @@ +module common.config.log +{ + +import common.config.aws.AwsCredentialsProvider; +import common.config.aws.AwsRegionProvider; + +// Configuration for logging +union LogLevel { + Void DEBUG; + Void INFO; + Void WARN; + Void ERROR; + Void NONE; + Void TRACE; +}; + +struct StdoutConfig { + LogLevel level; +}; + +struct FluentdConfig { + LogLevel level; + String hostname; + Int32 port; + String tag; +}; + +/// Server side Rollbar config +/// NOTE: Name is `ServerRollbarConfig` due to being named prior to adding +/// `ClientRollbarConfig` +struct RollbarConfig { + LogLevel level; + String serverToken; + String env = ""; +}; + +/// Server side logging, i.e. reporting errors originating from the server +/// NOTE: Name is not `ServerLogConfig` due to being named prior to adding +/// `ClientLogConfig` +struct LogConfig { + Nullable stdout = {"level" : "INFO"}; + Nullable fluentd = null; + Nullable rollbar = null; + Nullable cloudwatch = null; +}; + +/// Client side Rollbar config, i.e. from Rollbar JS +struct ClientRollbarConfig { + String accessToken; + String env = ""; +}; + +/// Client side logging, i.e. reporting errors originating from the client +struct ClientLogConfig { + Nullable rollbar = null; +}; + +/// Logging of metrics to cloudwatch +struct CloudWatchMetricLogConfig { + AwsCredentialsProvider credentials; + AwsRegionProvider region; + String env; + String namespace; + /// A whitelist of metrics that should be sent to CloudWatch. Users should be + /// aware that making this list too big can quickly cause costs to increase + Vector metricsToSend; +}; + +}; diff --git a/typescript/workspace/adl/lib/common/config/log.adl-java b/typescript/workspace/adl/lib/common/config/log.adl-java new file mode 100644 index 00000000..3daf592d --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/log.adl-java @@ -0,0 +1,12 @@ +module common.config.log +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.config.log"; + +annotation LogLevel JavaCustomType { + "javaname" : "au.com.helixta.log.Log.Level", + "helpers" : "au.com.helixta.adl.custom.LogLevelHelpers" +}; +}; diff --git a/typescript/workspace/adl/lib/common/config/okta.adl b/typescript/workspace/adl/lib/common/config/okta.adl new file mode 100644 index 00000000..92c073d4 --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/okta.adl @@ -0,0 +1,32 @@ +module common.config.okta +{ +import sys.types.Maybe; + +/// Config parameters for setting up open ID authentication using Okta +struct OktaConfig { + + // NOTE(Barry): The following parameters are sufficient to use for the + // majority of our applications; however, the Okta implementation was written + // for Sydney Airport which has many other features that are bespoke to that + // application. The Java binding for this ADL type ignores all of the extra + // config parameters that are not necessary (i.e. sets them to empty + // strings). + + /// ID of the client application + String clientId; + /// Secret of the client application + String clientSecret; + /// Hostname of the okta instance + String clientHost; + /// Endpoint which users should be redirected to to complete authorization + String authorizeEndpoint; + /// The URL supplied to okta to redirect the user to after authorization is + /// complete + String redirectUrl; + /// API key used for performing actions in okta, not required if the app does + /// not use this functionality + Maybe apiKey; +}; + + +}; diff --git a/typescript/workspace/adl/lib/common/config/okta.adl-java b/typescript/workspace/adl/lib/common/config/okta.adl-java new file mode 100644 index 00000000..b8474fbf --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/okta.adl-java @@ -0,0 +1,12 @@ +module common.config.okta +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.config.okta"; + +annotation OktaConfig JavaCustomType { + "javaname" : "au.com.helixta.service.auth.OktaCfg", + "helpers" : "au.com.helixta.adl.custom.OktaConfigHelpers" +}; +}; diff --git a/typescript/workspace/adl/lib/common/config/sms.adl b/typescript/workspace/adl/lib/common/config/sms.adl new file mode 100644 index 00000000..95af4094 --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/sms.adl @@ -0,0 +1,32 @@ +module common.config.sms +{ +import common.config.aws.AwsCredentialsProvider; +import common.config.aws.AwsRegionProvider; +import common.strings.StringNE; + +/// Configuration for the sms provider used +union SmsConfig { + /// Fake sms, just prints outgoing message info to stdout + Void fake; + + /// Twilio implementation + TwilioConfig twilio; + + /// AWS SNS implementation + AwsSnsConfig sns; + +}; + +/// Configuration for twilio +struct TwilioConfig { + StringNE accountSid; + StringNE authToken; +}; + +/// Configuration for AWS SMS implementation +struct AwsSnsConfig { + AwsCredentialsProvider credentials; + AwsRegionProvider region; +}; + +}; diff --git a/typescript/workspace/adl/lib/common/config/sms.adl-java b/typescript/workspace/adl/lib/common/config/sms.adl-java new file mode 100644 index 00000000..d614f75c --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/sms.adl-java @@ -0,0 +1,7 @@ +module common.config.sms +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.config.sms"; +}; diff --git a/typescript/workspace/adl/lib/common/config/storage.adl b/typescript/workspace/adl/lib/common/config/storage.adl new file mode 100644 index 00000000..5b3b7b6f --- /dev/null +++ b/typescript/workspace/adl/lib/common/config/storage.adl @@ -0,0 +1,30 @@ +module common.config.storage { + + struct LocalBlobstoreConfig { + /// The directory in which the blobstore files will be stored + String directory; + + /// The host of the server to be used for serving public files, e.g. "http://localhost" + String publicHost; + + /// The path on which blobstore objects are publically accessible e.g. "/files" + String publicPath; + }; + + struct LocalFileStoreConfig { + /// The directory in which the blobstore files will be stored + String directory; + + /// The host of the server to be used for serving public files, e.g. "http://localhost" + String publicHost; + + /// The path on which blobstore objects are publically accessible e.g. "/files" + String publicPath; + + /// False if the data in the FileStore is to be immutable + Bool allowOverwrite; + }; + + + +}; diff --git a/typescript/workspace/adl/lib/common/db.adl b/typescript/workspace/adl/lib/common/db.adl new file mode 100644 index 00000000..c5af92c7 --- /dev/null +++ b/typescript/workspace/adl/lib/common/db.adl @@ -0,0 +1,78 @@ +module common.db { + +// Annotation to indicate that an ADL struct is to be +// mapped to a database table +struct DbTable +{ + // If non empty, specifies the table name in the + // database. Otherwise it will be derived from the + // name of the adl struct + String tableName = ""; + + // If true, the generated db table will containing + // a text column `id`, which will be the primary key. + Bool withIdPrimaryKey = false; + + // If provided, use the given fields as the table's primary key + Vector withPrimaryKey = []; + + // Indexes for the table + Vector> indexes = []; + + // Uniqueness constraints over the table + Vector> uniquenessConstraints = []; + + // Additional SQL to be run after all tables have been + // created + Vector extraSql = []; + + // The textual columns used to assemble a label for the row + // (to be shown in UIs alongside the id) + Vector label = []; +}; + +// Annotation to indicate that an ADL struct is to be +// mapped to a database view. +struct DbView { + + // If non empty, specifies the view name in the + // database. Otherwise it will be derived from the + // name of the adl struct + String viewName = ""; + + // If true, the view will containing + // a text column `id`, which will be the primary key. + Bool withIdPrimaryKey = false; + + // If non empty the sql required to create the view. + // If empty, then it's assumed that the view corresponding + // is created by some other means + Vector viewSql = []; +}; + + +/// Field level annotation to override the name of the +/// database column. +type DbColumnName = String; + +/// Field or type level annotation to override the type of the +/// database column. +type DbColumnType = String; + +/// Field level annotation to indicate that a column value +/// is generated, and hence need not be requested from or edited +/// by a user. +type DbColumnGenerated = Void; + +/// A reference for a database stored value, referenced by a +/// string primary key. +newtype DbKey = String; + +/// A value of type T along with a unique db identifier +struct WithDbId +{ + DbKey id; + T value; +}; + +}; diff --git a/typescript/workspace/adl/lib/common/db.adl-java b/typescript/workspace/adl/lib/common/db.adl-java new file mode 100644 index 00000000..a16294b9 --- /dev/null +++ b/typescript/workspace/adl/lib/common/db.adl-java @@ -0,0 +1,32 @@ +module common.db +{ +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.db"; + +/// Annotation to control how java custom types are mapped to the +/// database +struct JavaDbCustomType { + /// The type returned from a db query + String javaDbType; + + /// The class in which to look for fromDb and toDb static functions + String helpers; +}; + +/// Annotation to control which format of java db table class is emitted +union JavaDbTableVersion { + Void v1; + Void v2; +}; + + +// Use a custom type for DbKey, primarily so that we can override the +// toString implementation +annotation DbKey JavaCustomType { + "javaname" : "au.com.helixta.adl.custom.DbKey", + "helpers": "au.com.helixta.adl.custom.DbKeyHelpers" +}; + +}; + diff --git a/typescript/workspace/adl/lib/common/flyway/api.adl b/typescript/workspace/adl/lib/common/flyway/api.adl new file mode 100644 index 00000000..d1ad8c40 --- /dev/null +++ b/typescript/workspace/adl/lib/common/flyway/api.adl @@ -0,0 +1,119 @@ +module common.flyway.api { + +import common.flyway.internals.FlywayAction; +import common.flyway.internals.FlywayContext; +import common.http.HttpPost; + +type FlywayApi = HttpPost; + +union FlywayReq { + /// Show pending migrations + Void plan; + /// Apply pending migrations + Void apply; + /// Something customized + AdvancedFlywayReq advanced; +}; + +/// Information passed when access via API +struct AdvancedFlywayReq { + FlywayReqContextOpt context = "application"; + FlywayAction action; +}; + +union FlywayReqContextOpt { + /// Derive the context from the app config + /// Throw exception if it app is not configured with a flyway context + Void application; + /// The first ctx in bootstrapable->bootstrap. + /// Throw exception if it doesn't exist + Void bootstrap; + /// Overide the application flyway config + FlywayContext customCtx; +}; + +union FlywayResp { + String error; + String msg; + FlywayCleanResult clean; + FlywayInfo info; + FlywayMigrateResult migrationResult; + FlywayBaselineResult baselineResult; + Vector sequence; +}; + +struct FlywayInfo { + String schemaVersion; + Vector migrations; +}; + +struct FlywayMigrationInfo { + String category; + String version; + String description; + String type_; + String installed_on; + String state; +}; + +struct FlywayMigrateResult { + String message; + // OperationResultBase + String flywayVersion; + String database; + Vector warnings; + String operation; + // MigrateResult + Nullable initialSchemaVersion; + Nullable targetSchemaVersion; + Nullable schemaName; + Vector migrations; + Nullable migrationsExecuted; +}; + +struct FlywayBaselineResult { + // OperationResultBase + String flywayVersion; + String database; + Vector warnings; + String operation; + // BaselineResult + Bool successfullyBaselined; + Nullable baselineVersion; +}; + +struct FlywayCleanResult { + // OperationResultBase + String flywayVersion; + String database; + Vector warnings; + String operation; + // BaselineResult + Vector schemasCleaned; + Vector schemasDropped; +}; + +struct FlywayMigrateOutput { + String category; + String version; + String description; + String type_; + String filepath; + Int32 executionTime; +}; + +// struct FlywaySchemaHistory { +// Int32 installed_rank; // | integer | not null +// Nullable version; // | character varying(50) | +// String description; // | character varying(200) | not null +// String type_; // | character varying(20) | not null +// String script; // | character varying(1000) | not null +// Nullable checksum; // | integer | +// String installed_by; // | character varying(100) | not null +// Instant installed_on; // | timestamp without time zone | not null default now() +// Int32 execution_time; // | integer | not null +// Bool success; // | boolean | not null +// }; + + +}; diff --git a/typescript/workspace/adl/lib/common/flyway/api.adl-java b/typescript/workspace/adl/lib/common/flyway/api.adl-java new file mode 100644 index 00000000..9c2b227f --- /dev/null +++ b/typescript/workspace/adl/lib/common/flyway/api.adl-java @@ -0,0 +1,7 @@ +module common.flyway.api { + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.flyway.api"; + +}; diff --git a/typescript/workspace/adl/lib/common/flyway/example_patterns.adl b/typescript/workspace/adl/lib/common/flyway/example_patterns.adl new file mode 100644 index 00000000..9a7ba433 --- /dev/null +++ b/typescript/workspace/adl/lib/common/flyway/example_patterns.adl @@ -0,0 +1,103 @@ +// These are example configs which in a project would likely be constructed in code +// and used when calling FlywayUtils +module common.flyway.example_patterns { + +import common.flyway.internals.FlywayCommand; + + +// Example application config. +union FlywayConfig { + // bootstraps by applying "create migrations" & baseline existing migrations + // startup applies new migrations. + Void mixed_mode_latest; + // bootstraps by applying "create migrations" & baseline existing migrations + // startup does not apply migrations. Migrations can be applied via adminui. + Void mixed_mode_manual; + // bootstraps by applying all migrations from scratch. + // startup applies new migrations. + Void migration_mode_latest; + // customize the flyway app startup + FlywayCommand advanced; +}; + + +type ExampleFlywayCommand = StringMap; + +annotation ExampleFlywayCommand { +// Tim's preferred model for fastdev, which works the same, but runs +// any pending migrations when the server is started + "mixedmode_latest": + { + "ctx": { + "sqlMigrationDir": "/app/sql/migrations", + "javaMigrationPackage": "app/java/migrations" + }, + "bootstrap": [ + { + "withContext": { + "ctx": { + "schemaHistoryTable": "flyway_bootstrap_schema_history", + "sqlMigrationDir": "/app/sql/create", + "javaMigrationPackage": "app/java/createmigrations" + }, + "action": { + "sequence": [ + "baseline_zero", + "migrate" + ] + } + } + }, + "baseline_latest", + "migrate" + ], + "action": "migrate" + } +, +// Tim's preferred model for prod, which bootstraps a new db from create scripts +// and baselines to the last migration. Subsequent migrations are run from the adminui + "mixedmode_manual": + { + "ctx": { + "sqlMigrationDir": "/app/sql/migrations", + "javaMigrationPackage": "app/java/migrations" + }, + "bootstrap": [ + { + "withContext": { + "ctx": { + "schemaHistoryTable": "flyway_bootstrap_schema_history", + "sqlMigrationDir": "/app/sql/create", + "javaMigrationPackage": "app/java/createmigrations" + }, + "action": { + "sequence": [ + "baseline_zero", + "migrate" + ] + } + } + }, + "baseline_latest", + "migrate" + ], + "action": null + } +, +// Paul's preferred model for prod (I think) which bootstraps +// by applying all migrations from scratch + "migration_mode_latest": + { + "ctx": { + "sqlMigrationDir": "/app/sql/migrations", + "javaMigrationPackage": "app/java/migrations" + }, + "bootstrap": [ + "baseline_zero", + "migrate" + ], + "action": "migrate" + } +}; + +}; diff --git a/typescript/workspace/adl/lib/common/flyway/example_patterns.adl-java b/typescript/workspace/adl/lib/common/flyway/example_patterns.adl-java new file mode 100644 index 00000000..6fd24eb1 --- /dev/null +++ b/typescript/workspace/adl/lib/common/flyway/example_patterns.adl-java @@ -0,0 +1,7 @@ +module common.flyway.example_patterns { + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.flyway.example_patterns"; + +}; diff --git a/typescript/workspace/adl/lib/common/flyway/internals.adl b/typescript/workspace/adl/lib/common/flyway/internals.adl new file mode 100644 index 00000000..64d13279 --- /dev/null +++ b/typescript/workspace/adl/lib/common/flyway/internals.adl @@ -0,0 +1,112 @@ +module common.flyway.internals { + +struct FlywayCommand { + FlywayContext ctx; + /// The action to take on application startup + Vector bootstrap = []; + Nullable action; +}; + +/// Contextual information required to run flyway +struct FlywayContext { + /// The name of the flyway history table. + /// Useful to override for bootstraping. + String schemaHistoryTable = "flyway_schema_history"; + /// The location from which db migrations are loaded + String sqlMigrationDir = "/app/sql/migrations"; + /// The package from which java based db migrations are loaded + Nullable javaMigrationPackage = "app/java/migrations"; + /// DB connection retries, with 1 second between retries + Int32 connect_retries = 3; +}; + +union FlywayAction { + /// Get migration info, the a combintation of the flyway schema history and future migrations. + Void info; + // Baseline actions + Void baseline_zero; + Void baseline_one; + Void baseline_latest; + String baseline_version; + // Migration actions + /// Migrate to lastest with default options + Void migrate; + MigrateLatestAction migrate_latest; + MigrateAction migrate_to_version; + // other + Vector sequence; + FlywayCtxAction withContext; +}; + +struct FlywayCtxAction { + /// The context in normal (non-bootstrap) mode + FlywayContext ctx; + /// Array of actions to run on bootstrap + FlywayAction action; +}; + +struct MigrateLatestAction { + /// migration options + MigrateOptionsOptions options = "defaults"; +}; + +struct MigrateAction { + /// migration options + MigrateOptionsOptions options = "defaults"; + String version; +}; + +union MigrateOptionsOptions { + Void defaults; + Void ignoreMissingMigrations; + Void ignoreIgnoredMigrations; + Void outOfOrder; + Void dontValidateOnMigrate; + MigrateOptions custom = {}; +}; + +struct MigrateOptions { + /// Ignore missing migrations when reading the schema history table. These are migrations that were performed by an + /// older deployment of the application that are no longer available in this version. + // Not the Flyway default + Bool ignoreMissingMigrations = true; + /// Ignore ignored migrations when reading the schema history table. These are migrations that were added in between + /// already migrated migrations in this version. + // Not the Flyway default + Bool ignoreIgnoredMigrations= true; + /// Ignore pending migrations when reading the schema history table. These are migrations that are available on the + /// classpath but have not yet been performed by an application deployment. + /// This can be useful for verifying that in-development migration changes don't contain any validation-breaking changes + /// of migrations that have already been applied to a production environment, e.g. as part of a CI/CD process, without + /// failing because of the existence of new migration versions. + Bool ignorePendingMigrations = false; + /// Ignore future migrations when reading the schema history table. These are migrations that were performed by a + /// newer deployment of the application that are not yet available in this version. For example: we have migrations + /// available on the classpath up to version 3.0. The schema history table indicates that a migration to version 4.0 + /// (unknown to us) has already been applied. Instead of bombing out (fail fast) with an exception, a + /// warning is logged and Flyway continues normally. This is useful for situations where one must be able to redeploy + /// an older version of the application after the database has been migrated by a newer one. + Bool ignoreFutureMigrations = true; + /// Whether to validate migrations and callbacks whose scripts do not obey the correct naming convention. A failure can be + /// useful to check that errors such as case sensitivity in migration prefixes have been corrected. + Bool validateMigrationNaming = false; + /// Whether to automatically call validate or not when running migrate. (default: {@code true}) + Bool validateOnMigrate = true; + /// Whether to automatically call clean or not when a validation error occurs. (default: {@code false}) + ///

This is exclusively intended as a convenience for development. even though we + /// strongly recommend not to change migration scripts once they have been checked into SCM and run, this provides a + /// way of dealing with this case in a smooth manner. The database will be wiped clean automatically, ensuring that + /// the next migration will bring you back to the state checked into SCM.

+ ///

Warning ! Do not enable in production !

+ Bool cleanOnValidationError = false; + /// Whether to disable clean. (default: {@code false}) + ///

This is especially useful for production environments where running clean can be quite a career limiting move.

+ Bool cleanDisabled = false; + /// Allows migrations to be run "out of order". + ///

If you already have versions 1 and 3 applied, and now a version 2 is found, + /// it will be applied too instead of being ignored.

+ Bool outOfOrder = false; +}; + + +}; diff --git a/typescript/workspace/adl/lib/common/flyway/internals.adl-java b/typescript/workspace/adl/lib/common/flyway/internals.adl-java new file mode 100644 index 00000000..c17b1343 --- /dev/null +++ b/typescript/workspace/adl/lib/common/flyway/internals.adl-java @@ -0,0 +1,7 @@ +module common.flyway.internals { + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.flyway.internals"; + +}; diff --git a/typescript/workspace/adl/lib/common/http.adl b/typescript/workspace/adl/lib/common/http.adl new file mode 100644 index 00000000..ce930b76 --- /dev/null +++ b/typescript/workspace/adl/lib/common/http.adl @@ -0,0 +1,152 @@ +module common.http { + +import sys.types.Set; + +/// A marker type to associate the output response +/// type for an http Get request. +type Get = Void; + +/// A marker type to associate the input request and output response +/// types for an http put request. +type Put = Void; + +/// A marker type to associate the input request and output response +/// types for an http post request. +type Post = Void; + +/// An annotation indicating the URL path for a request +type Path = String; + +/// An annotation indicating that a request requires an Authorization http header +type AuthHeader = Void; + +/// An annotation indicating that a request is idemponent, and can hence be safely +/// retried on failure. +type Idempotent = Void; + +/// An annotation indicating that a request can be made idempotent if the caller +/// provides an Idempotency-Key header with a unique value. +type IdempotentWithKey = Void; + +/// The standard message body for errors +struct PublicErrorData { + String publicMessage; +}; + +/// New request types + +struct HttpGet { + String path; + HttpSecurity security; + Nullable rateLimit = null; + TypeToken respType = null; +}; + +struct HttpGetStream { + String path; + HttpSecurity security; + TypeToken respItemType = null; +}; + +struct HttpGet2 { + String path; + HttpSecurity security; + Nullable rateLimit = null; + TypeToken

paramsType = null; + TypeToken respType = null; +}; + +struct HttpPut { + String path; + HttpSecurity security; + Nullable rateLimit = null; + TypeToken reqType = null; + TypeToken respType = null; +}; + +struct HttpPost { + String path; + HttpSecurity security; + Nullable rateLimit = null; + TypeToken reqType = null; + TypeToken respType = null; +}; + +struct HttpPost2 { + String path; + HttpSecurity security; + Nullable rateLimit = null; + TypeToken

paramsType = null; + TypeToken reqType = null; + TypeToken respType = null; +}; + +struct HttpDelete { + String path; + HttpSecurity security; + TypeToken

paramsType = null; + TypeToken respType = null; +}; + +union HttpSecurity { + // The endpoint is publically accessible + Void public; + + // A token is required to access the endpoint + Void token; + + // A token containing the specified role is required + // for access + String tokenWithRole; +}; + + +struct HttpRateLimit { + Word32 maxRequests; + RateLimitTimeUnit perTimeUnit; +}; + +union RateLimitTimeUnit { + Void second; + Void minute; + Void hour; +}; + +/// API decl or request annotation to specify +/// the non-success response codes we want +/// included in the generated open API. The +/// Json should have exactly the structure of +/// the OpenApi responses map +type OpenApiOtherResponses = Json; + + +/// API annotation to specify the available +/// server endpoints. The Json should have +/// exactly the structure of the OpenApi +/// servers map +type OpenApiServers = Json; + +/// Marker annotation to indicate that an endpoint +/// or (defaulted) field should be left out of the +/// generated openapi +type OpenApiExclude = Bool; + +/// API annotation to specify additional api +/// information. The Json should have +/// exactly the structure of the OpenApi +/// info map +type OpenApiInfo = Json; + +/// API decl annotation to specify +/// the security schema in use +union SecurityScheme { + Void httpBearer; + HeaderApiKeyScheme apiKey; +}; + +struct HeaderApiKeyScheme { + String headerName; +}; + +}; + diff --git a/typescript/workspace/adl/lib/common/http.adl-java b/typescript/workspace/adl/lib/common/http.adl-java new file mode 100644 index 00000000..79db148e --- /dev/null +++ b/typescript/workspace/adl/lib/common/http.adl-java @@ -0,0 +1,7 @@ +module common.http +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.http"; +}; diff --git a/typescript/workspace/adl/lib/common/strings.adl b/typescript/workspace/adl/lib/common/strings.adl new file mode 100644 index 00000000..e080e8ce --- /dev/null +++ b/typescript/workspace/adl/lib/common/strings.adl @@ -0,0 +1,46 @@ +/// Some string type aliases, with attributes to derive UI validation +module common.strings +{ + +import common.ui.ValidRegex; + +/// A string that isn't empty, and isn't only whitespace. +type StringNE = String; + +annotation StringNE ValidRegex { + "regex" : "^.*\\S+.*$", + "description" : "non empty", + "returnGroup" : 0 +}; + +/// An alphanumeric string, with hyphens for separation. +type StringANH = String; + +/// A multi line, free-form text string +type StringML = String; + +annotation StringANH ValidRegex { + "regex" : "^[A-Za-z][A-Za-z0-9-]*$", + "description" : "alphanumeric", + "returnGroup" : 0 +}; + +/// An email address +type EmailAddress = String; + +// see https://stackoverflow.com/questions/201323/how-to-validate-an-email-address-using-a-regular-expression +// The regex below allows whitespace before and after the email address, but the first match group excludes these. +annotation EmailAddress ValidRegex { + "regex" : "^\\s*((?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\]))\\s*$", + "description" : "an email address", + "returnGroup" : 1 +}; + +/// A markdown text string +type StringMD = String; + +/// A password, which cannot be empty. Other constraints +/// are application specific. +type Password = String; + +}; diff --git a/typescript/workspace/adl/lib/common/tabular.adl b/typescript/workspace/adl/lib/common/tabular.adl new file mode 100644 index 00000000..1f8ca5a3 --- /dev/null +++ b/typescript/workspace/adl/lib/common/tabular.adl @@ -0,0 +1,83 @@ +/// Common definitions for querying tabular data +module common.tabular +{ + +import common.strings.StringNE; +import common.Instant; +import common.LocalDate; + +type FieldName = StringNE; + +struct ExprLike { Expr expr; String pattern; Bool caseSensitive = true; }; +struct ExprIn { Expr expr; Vector exprs; }; +struct ExprComparison { Expr expr1; Expr expr2; }; + +union FieldPredicate { + ExprComparison equalTo; + ExprIn in; + ExprLike like; + Expr isnull; + FieldPredicate not; + ExprComparison greaterThan; + ExprComparison lessThan; + Vector and; + Vector or; + Bool literal; +}; + +union Expr { + String string; + Int32 int; + Bool bool; + LocalDate date; + Instant instant; + + FieldName field; + Void currentDate; + Vector concat; +}; + +union SortDirection { + Void ascending; + Void descending; +}; + +struct SortField { FieldName field; SortDirection direction; }; + + +// A view of a table +struct TableView +{ + // The columns to show + Vector columns; + + // A filter controlling which rows to show + FieldPredicate filter = {"literal":true}; + + // How the results should be sorted + Vector sorting = []; +}; + +// The structure we pass to specify a page of values to be +// loaded. +struct TableQuery { + // By default we match all rows + FieldPredicate filter = {"literal":true}; + + // Sorting order + Vector sorting = []; + + // Pagination offset + Int32 offset = 0; + + // Number of items to return (-1 => all) + Int32 count = -1; +}; + +// A trivial single element struct, to enable non-struct +// values to be shown in tables +struct SingleField { + T value; +}; + +}; diff --git a/typescript/workspace/adl/lib/common/tabular.adl-java b/typescript/workspace/adl/lib/common/tabular.adl-java new file mode 100644 index 00000000..ec8c810b --- /dev/null +++ b/typescript/workspace/adl/lib/common/tabular.adl-java @@ -0,0 +1,8 @@ +module common.tabular +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.tabular"; + +}; diff --git a/typescript/workspace/adl/lib/common/ui.adl b/typescript/workspace/adl/lib/common/ui.adl new file mode 100644 index 00000000..82331de5 --- /dev/null +++ b/typescript/workspace/adl/lib/common/ui.adl @@ -0,0 +1,51 @@ +module common.ui +{ + +import sys.types.Pair; + +// UI Annotations + +// field annotation specifying the label to be shown on forms and +// table headings +type FormLabel = String; + +// field annotation allocating a field to a display group. An empty +// group key means that the field is to be shown ungrouped. +type FormGroupKey = String; + +// struct annotation for groups +struct FormGroups { + // The default group for unannotated fields + FormGroupKey defaultKey; + + // The text labels for each group + Vector> labels; +}; + +/// An field/type alias annotation to constrain the +/// values allowed by a string to the enumerated values +struct ValidValues { + /// The allowed values + Vector values; + + /// A (short) user readable string describing the + /// expected text. + String description; +}; + +/// An field/type alias annotation to constrain the +/// values allowed by a string to a regular expression +struct ValidRegex { + /// The regexp that must be matched + String regex; + + /// A (short) user readable string describing the + /// expected text. + String description; + + /// The regex group index to return if matches + /// 0 is the entire string + Int8 returnGroup = 0; +}; + +}; diff --git a/typescript/workspace/adl/lib/common/ui.adl-java b/typescript/workspace/adl/lib/common/ui.adl-java new file mode 100644 index 00000000..0b9567be --- /dev/null +++ b/typescript/workspace/adl/lib/common/ui.adl-java @@ -0,0 +1,7 @@ +module common.ui +{ + +import adlc.config.java.*; + +annotation JavaPackage "au.com.helixta.adl.common.ui"; +}; diff --git a/typescript/workspace/adl/proj/adl.pkg.json b/typescript/workspace/adl/proj/adl.pkg.json new file mode 100644 index 00000000..1f3a7352 --- /dev/null +++ b/typescript/workspace/adl/proj/adl.pkg.json @@ -0,0 +1,17 @@ +{ + "path" : "github.com/adl-lang/adl/typescript/workspace/adl/proj", + "global_alias": "protoclient", + "adlc": "0.0.0", + "requires": [ + { + "ref": { + "alias": "sys" + } + }, + { + "ref": { + "alias": "common" + } + } + ] +} \ No newline at end of file diff --git a/typescript/workspace/adl/proj/protoclient/protoapp/api.adl b/typescript/workspace/adl/proj/protoclient/protoapp/api.adl new file mode 100644 index 00000000..966fe5f2 --- /dev/null +++ b/typescript/workspace/adl/proj/protoclient/protoapp/api.adl @@ -0,0 +1,149 @@ +module protoclient.protoapp.api { + +import sys.types.Map; + +import common.Instant; +import common.db.WithDbId; +import common.config.log.LogLevel; +import common.tabular.TableQuery; +import common.Paginated; +import common.Unit; +import common.http.HttpPost; +import common.http.HttpGet; +import common.strings.Password; +import common.strings.StringML; +import common.strings.StringNE; + +import protoclient.protoapp.db.AppUser; +import protoclient.protoapp.db.AppUserId; +import protoclient.protoapp.db.MessageId; + +struct X { + +}; + +/// The app API +struct ApiRequests { + X x; + // Vector y; + Map imamap; + /// Login a user + HttpPost>> with_prim = { + "path": "/login", + "security" : "public" + }; + + /// Login a user + HttpPost login = { + "path": "/login", + "security" : "public" + }; + + /// Post a message to the noticeboard + HttpPost newMessage = { + "path": "/messages/new", + "security" : "token" + }; + + /// Get recent noticeboard messages + HttpPost > recentMessages = { + "path": "/messages/recent", + "security" : "token" + }; + + /// Gets the logged in user details + // NOTE: Fails with 401 if the token is invalid or user does not exist + HttpGet whoAmI = { + "path": "/whoami", + "security" : "token" + }; + + /// Create a new user + HttpPost createUser = { + "path": "/users/create", + "security" : {"tokenWithRole": "admin"} + }; + + /// Update an existing user + HttpPost, Unit> updateUser = { + "path": "/users/update", + "security" : {"tokenWithRole": "admin"} + }; + + /// Delete an existing user + HttpPost deleteUser = { + "path": "/users/delete", + "security" : {"tokenWithRole": "admin"} + }; + + /// Query existing users sorted and filters according to the + /// TableQuery request. + HttpPost>> queryUsers = { + "path": "/users/query", + "security" : {"tokenWithRole": "admin"} + }; + + /// Logs an error from the client app without user information, i.e. when the + /// user has not logged in + HttpPost logClientErrorPublic = { + "path": "/client/log/public", + "security": "public", + "rateLimit": { "maxRequests": 6, "perTimeUnit": "minute" } + }; + + /// Logs an error from the client app and includes user information + HttpPost logClientErrorUser = { + "path": "/client/log/user", + "security": "token" + }; +}; + +struct UserProfile { + AppUserId id; + String fullname; + String email; + Bool isAdmin; +}; + +/// Details for a user +struct UserReq { + String fullname; + String email; + Password password; +}; + +struct LoginReq { + StringNE email; + Password password; +}; + +union LoginResp { + StringNE accessToken; + Void invalidCredentials; +}; + +struct NewMessageReq { + StringML message; +}; + +struct RecentMessagesReq { + // Pagination offset + Int32 offset = 0; + + // Number of items to return + Int32 count = 20; +}; + +struct Message { + MessageId id; + Instant postedAt; + String userFullName; + StringML message; +}; + +struct ClientLogReq { + LogLevel level; + String error; + Nullable stacktrace; +}; +}; diff --git a/typescript/workspace/adl/proj/protoclient/protoapp/config.adl b/typescript/workspace/adl/proj/protoclient/protoapp/config.adl new file mode 100644 index 00000000..481975ff --- /dev/null +++ b/typescript/workspace/adl/proj/protoclient/protoapp/config.adl @@ -0,0 +1,51 @@ +module protoclient.protoapp.config { + +import common.config.frontend.ThreadPoolConfig; +import common.config.log.LogConfig; +import common.config.log.FluentdConfig; +import common.config.db.PostgreSqlConfig; + +/// Configuration for the server +struct ServerConfig { + /// Port to listen for requests + Int16 port; + + /// Environment name, e.g. dev, uat, prod + String environment; + + /// Name of the release / code version + String releaseName; + + /// The shared secret that will be present on requests + /// made by the cron webhook system. + String cronSharedSecret; + + /// Secret used to sign JWT tokens + String jwtSecret; + + /// Database config + PostgreSqlConfig db; + + /// Server-side logging config + LogConfig logging; + + /// Client-side logging config + /// If not provided all client logs will appear in the server logs + Nullable clientLogging = null; + + /// Frontend threadpool configuration + ThreadPoolConfig threadPool; + + // If set, apply automatic migrations on startup + Nullable flyway = null; +}; + +type ClientLogConfig = FluentdConfig; + +union LocalFlywayConfig { + Void fastdev; + Void deployed; + common.flyway.internals.FlywayCommand advanced; +}; + +}; diff --git a/typescript/workspace/adl/proj/protoclient/protoapp/db.adl b/typescript/workspace/adl/proj/protoclient/protoapp/db.adl new file mode 100644 index 00000000..2445717f --- /dev/null +++ b/typescript/workspace/adl/proj/protoclient/protoapp/db.adl @@ -0,0 +1,57 @@ +module protoclient.protoapp.db { + +import common.strings.StringML; +import common.strings.StringNE; +import common.db.DbTable; +import common.db.DbKey; +import common.Instant; + + +struct Trade { + Vector commodities; + Instant date; +}; + +annotation Trade DbTable { + "withIdPrimaryKey" : true +}; + + +struct Commodity { + String code; +}; + +/// Details for a user +struct AppUser { + StringNE fullname; + StringNE email; + Bool isAdmin; + StringNE hashedPassword = ""; +}; + +// Annotation to specify that there is a db table for user, +// with an id primary key, and a index over username. +annotation AppUser DbTable { + "withIdPrimaryKey" : true, + "indexes" : [["email"]], + "label" : ["fullname"] +}; + +type AppUserId = DbKey; + +/// messages posted on the noticeboard +struct Message { + Instant postedAt; + DbKey postedBy; + StringML message; +}; + +annotation Message DbTable { + "withIdPrimaryKey" : true, + "indexes" : [["posted_at"]] +}; + +type MessageId = DbKey; + + +}; diff --git a/typescript/workspace/adl/proj/protoclient/protoapp/uiconfig.adl b/typescript/workspace/adl/proj/protoclient/protoapp/uiconfig.adl new file mode 100644 index 00000000..aa62bfb2 --- /dev/null +++ b/typescript/workspace/adl/proj/protoclient/protoapp/uiconfig.adl @@ -0,0 +1,17 @@ +module protoclient.protoapp.uiconfig { + +import common.config.log.ClientRollbarConfig; + +/// Configuration for the web frontend. +struct UiConfig { + /// Application title + String title = ""; + + /// Environment name, e.g. dev, uat, prod + String environment; + + /// Name of the release / code version + String releaseName; +}; + +}; diff --git a/typescript/workspace/generated/common/.adl-manifest b/typescript/workspace/generated/common/.adl-manifest new file mode 100644 index 00000000..52927eef --- /dev/null +++ b/typescript/workspace/generated/common/.adl-manifest @@ -0,0 +1,30 @@ +# manifest @generated by the adl compiler +_/common.ts +_/index.ts +adminui/api.ts +adminui/config.ts +adminui/db.ts +adminui/index.ts +config/aws.ts +config/azure.ts +config/db.ts +config/emailer.ts +config/frontend.ts +config/google.ts +config/index.ts +config/jwt.ts +config/log.ts +config/okta.ts +config/sms.ts +config/storage.ts +db.ts +flyway/api.ts +flyway/example_patterns.ts +flyway/index.ts +flyway/internals.ts +http.ts +index.ts +resolver.ts +strings.ts +tabular.ts +ui.ts diff --git a/typescript/workspace/generated/common/_/common.ts b/typescript/workspace/generated/common/_/common.ts new file mode 100644 index 00000000..e81265e4 --- /dev/null +++ b/typescript/workspace/generated/common/_/common.ts @@ -0,0 +1,310 @@ +import * as common_strings from "../strings"; +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common */ + +/** + * A instant in time, represented as milliseconds from + * the epoch of "1970-01-01T00:00:00Z + */ +export type Instant = number; + +const Instant_AST : ADL.ScopedDecl = + {"moduleName":"common","decl":{"annotations":[],"type_":{"kind":"newtype_","value":{"typeParams":[],"default":{"kind":"nothing"},"typeExpr":{"typeRef":{"kind":"primitive","value":"Int64"},"parameters":[]}}},"name":"Instant","version":{"kind":"nothing"}}}; + +export const snInstant: ADL.ScopedName = {moduleName:"common", name:"Instant"}; + +export function texprInstant(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snInstant},parameters:[]}}; +} + +/** + * A date in ISO8601 format + */ +export type LocalDate = string; + +const LocalDate_AST : ADL.ScopedDecl = + {"moduleName":"common","decl":{"annotations":[],"type_":{"kind":"newtype_","value":{"typeParams":[],"default":{"kind":"just","value":"1970-01-01"},"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"LocalDate","version":{"kind":"nothing"}}}; + +export const snLocalDate: ADL.ScopedName = {moduleName:"common", name:"LocalDate"}; + +export function texprLocalDate(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snLocalDate},parameters:[]}}; +} + +/** + * A time in ISO8601 format + */ +export type LocalTime = string; + +const LocalTime_AST : ADL.ScopedDecl = + {"moduleName":"common","decl":{"annotations":[],"type_":{"kind":"newtype_","value":{"typeParams":[],"default":{"kind":"just","value":"00:00:00"},"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"LocalTime","version":{"kind":"nothing"}}}; + +export const snLocalTime: ADL.ScopedName = {moduleName:"common", name:"LocalTime"}; + +export function texprLocalTime(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snLocalTime},parameters:[]}}; +} + +/** + * A datetime in ISO8601 format + */ +export type LocalDateTime = string; + +const LocalDateTime_AST : ADL.ScopedDecl = + {"moduleName":"common","decl":{"annotations":[],"type_":{"kind":"newtype_","value":{"typeParams":[],"default":{"kind":"just","value":"1970-01-01T00:00:00"},"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"LocalDateTime","version":{"kind":"nothing"}}}; + +export const snLocalDateTime: ADL.ScopedName = {moduleName:"common", name:"LocalDateTime"}; + +export function texprLocalDateTime(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snLocalDateTime},parameters:[]}}; +} + +/** + * The day of the week + */ +export type DayOfWeek = 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday' | 'sunday'; +export const valuesDayOfWeek : DayOfWeek[] = ['monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday', 'sunday']; + +const DayOfWeek_AST : ADL.ScopedDecl = + {"moduleName":"common","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"monday","default":{"kind":"nothing"},"name":"monday","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"tuesday","default":{"kind":"nothing"},"name":"tuesday","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"wednesday","default":{"kind":"nothing"},"name":"wednesday","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"thursday","default":{"kind":"nothing"},"name":"thursday","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"friday","default":{"kind":"nothing"},"name":"friday","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"saturday","default":{"kind":"nothing"},"name":"saturday","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"sunday","default":{"kind":"nothing"},"name":"sunday","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}}]}},"name":"DayOfWeek","version":{"kind":"nothing"}}}; + +export const snDayOfWeek: ADL.ScopedName = {moduleName:"common", name:"DayOfWeek"}; + +export function texprDayOfWeek(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDayOfWeek},parameters:[]}}; +} + +/** + * A duration in ISO8601 format + */ +export type Duration = string; + +const Duration_AST : ADL.ScopedDecl = + {"moduleName":"common","decl":{"annotations":[{"value":"interval","key":{"moduleName":"common.db","name":"DbColumnType"}}],"type_":{"kind":"newtype_","value":{"typeParams":[],"default":{"kind":"just","value":"P1D"},"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"Duration","version":{"kind":"nothing"}}}; + +export const snDuration: ADL.ScopedName = {moduleName:"common", name:"Duration"}; + +export function texprDuration(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDuration},parameters:[]}}; +} + +/** + * An IANA timezone + */ +export type Timezone = common_strings.StringNE; + +const Timezone_AST : ADL.ScopedDecl = + {"moduleName":"common","decl":{"annotations":[],"type_":{"kind":"newtype_","value":{"typeParams":[],"default":{"kind":"nothing"},"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.strings","name":"StringNE"}},"parameters":[]}}},"name":"Timezone","version":{"kind":"nothing"}}}; + +export const snTimezone: ADL.ScopedName = {moduleName:"common", name:"Timezone"}; + +export function texprTimezone(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snTimezone},parameters:[]}}; +} + +/** + * A holder for paginated results + */ +export interface Paginated { +/** + * The paginated items + */ + items: T[]; +/** + * The offset used for this query + */ + current_offset: number; +/** + * The size of the entire date set + */ + total_size: number; +} + +export function makePaginated( + input: { + items: T[], + current_offset: number, + total_size: number, + } +): Paginated { + return { + items: input.items, + current_offset: input.current_offset, + total_size: input.total_size, + }; +} + +const Paginated_AST : ADL.ScopedDecl = + {"moduleName":"common","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["T"],"fields":[{"annotations":[],"serializedName":"items","default":{"kind":"nothing"},"name":"items","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"typeParam","value":"T"},"parameters":[]}]}},{"annotations":[],"serializedName":"current_offset","default":{"kind":"nothing"},"name":"current_offset","typeExpr":{"typeRef":{"kind":"primitive","value":"Int64"},"parameters":[]}},{"annotations":[],"serializedName":"total_size","default":{"kind":"nothing"},"name":"total_size","typeExpr":{"typeRef":{"kind":"primitive","value":"Int64"},"parameters":[]}}]}},"name":"Paginated","version":{"kind":"nothing"}}}; + +export const snPaginated: ADL.ScopedName = {moduleName:"common", name:"Paginated"}; + +export function texprPaginated(texprT : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snPaginated},parameters:[texprT.value]}}; +} + +/** + * Empty Struct (Used mostly for Void RPC responses) + */ +export interface Unit { +} + +export function makeUnit( + _input: {} +): Unit { + return {}; +} + +const Unit_AST : ADL.ScopedDecl = + {"moduleName":"common","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[]}},"name":"Unit","version":{"kind":"nothing"}}}; + +export const snUnit: ADL.ScopedName = {moduleName:"common", name:"Unit"}; + +export function texprUnit(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snUnit},parameters:[]}}; +} + +/** + * Phantom type to capture a StringMap with a named string key type: + */ +export type StringKeyMap<_K, V> = {[key: string]: V}; + +const StringKeyMap_AST : ADL.ScopedDecl = + {"moduleName":"common","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":["K","V"],"typeExpr":{"typeRef":{"kind":"primitive","value":"StringMap"},"parameters":[{"typeRef":{"kind":"typeParam","value":"V"},"parameters":[]}]}}},"name":"StringKeyMap","version":{"kind":"nothing"}}}; + +export const snStringKeyMap: ADL.ScopedName = {moduleName:"common", name:"StringKeyMap"}; + +export function texprStringKeyMap(texprK : ADL.ATypeExpr, texprV : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snStringKeyMap},parameters:[texprK.value,texprV.value]}}; +} + +/** + * Naming aid for strings used as keys + */ +export type Key<_T> = string; + +const Key_AST : ADL.ScopedDecl = + {"moduleName":"common","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":["T"],"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"Key","version":{"kind":"nothing"}}}; + +export const snKey: ADL.ScopedName = {moduleName:"common", name:"Key"}; + +export function texprKey(texprT : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snKey},parameters:[texprT.value]}}; +} + +/** + * A value of type T along with the Key + */ +export interface WithKey { + key: Key; + value: T; +} + +export function makeWithKey( + input: { + key: Key, + value: T, + } +): WithKey { + return { + key: input.key, + value: input.value, + }; +} + +const WithKey_AST : ADL.ScopedDecl = + {"moduleName":"common","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["T"],"fields":[{"annotations":[],"serializedName":"key","default":{"kind":"nothing"},"name":"key","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"Key"}},"parameters":[{"typeRef":{"kind":"typeParam","value":"T"},"parameters":[]}]}},{"annotations":[],"serializedName":"value","default":{"kind":"nothing"},"name":"value","typeExpr":{"typeRef":{"kind":"typeParam","value":"T"},"parameters":[]}}]}},"name":"WithKey","version":{"kind":"nothing"}}}; + +export const snWithKey: ADL.ScopedName = {moduleName:"common", name:"WithKey"}; + +export function texprWithKey(texprT : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snWithKey},parameters:[texprT.value]}}; +} + +/** + * Postgres array of strings type that is serialized in to a list of Strings + */ +export type StringList = string[]; + +const StringList_AST : ADL.ScopedDecl = + {"moduleName":"common","decl":{"annotations":[{"value":"text[]","key":{"moduleName":"common.db","name":"DbColumnType"}}],"type_":{"kind":"newtype_","value":{"typeParams":[],"default":{"kind":"nothing"},"typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}}},"name":"StringList","version":{"kind":"nothing"}}}; + +export const snStringList: ADL.ScopedName = {moduleName:"common", name:"StringList"}; + +export function texprStringList(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snStringList},parameters:[]}}; +} + +export type TSVector = string; + +const TSVector_AST : ADL.ScopedDecl = + {"moduleName":"common","decl":{"annotations":[{"value":"tsvector","key":{"moduleName":"common.db","name":"DbColumnType"}}],"type_":{"kind":"newtype_","value":{"typeParams":[],"default":{"kind":"nothing"},"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"TSVector","version":{"kind":"nothing"}}}; + +export const snTSVector: ADL.ScopedName = {moduleName:"common", name:"TSVector"}; + +export function texprTSVector(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snTSVector},parameters:[]}}; +} + +/** + * Postgres Geography type that is serialized using GeoJson + */ +export type GeographyGeoJson = string; + +const GeographyGeoJson_AST : ADL.ScopedDecl = + {"moduleName":"common","decl":{"annotations":[{"value":"geography","key":{"moduleName":"common.db","name":"DbColumnType"}}],"type_":{"kind":"newtype_","value":{"typeParams":[],"default":{"kind":"nothing"},"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"GeographyGeoJson","version":{"kind":"nothing"}}}; + +export const snGeographyGeoJson: ADL.ScopedName = {moduleName:"common", name:"GeographyGeoJson"}; + +export function texprGeographyGeoJson(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snGeographyGeoJson},parameters:[]}}; +} + +/** + * Postgres Geometry type + */ +export type GeometryWKT = string; + +const GeometryWKT_AST : ADL.ScopedDecl = + {"moduleName":"common","decl":{"annotations":[{"value":"geometry","key":{"moduleName":"common.db","name":"DbColumnType"}}],"type_":{"kind":"newtype_","value":{"typeParams":[],"default":{"kind":"nothing"},"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"GeometryWKT","version":{"kind":"nothing"}}}; + +export const snGeometryWKT: ADL.ScopedName = {moduleName:"common", name:"GeometryWKT"}; + +export function texprGeometryWKT(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snGeometryWKT},parameters:[]}}; +} + +/** + * A floating point decimal value + */ +export type BigDecimal = string; + +const BigDecimal_AST : ADL.ScopedDecl = + {"moduleName":"common","decl":{"annotations":[{"value":"numeric","key":{"moduleName":"common.db","name":"DbColumnType"}}],"type_":{"kind":"newtype_","value":{"typeParams":[],"default":{"kind":"nothing"},"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"BigDecimal","version":{"kind":"nothing"}}}; + +export const snBigDecimal: ADL.ScopedName = {moduleName:"common", name:"BigDecimal"}; + +export function texprBigDecimal(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snBigDecimal},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.Instant" : Instant_AST, + "common.LocalDate" : LocalDate_AST, + "common.LocalTime" : LocalTime_AST, + "common.LocalDateTime" : LocalDateTime_AST, + "common.DayOfWeek" : DayOfWeek_AST, + "common.Duration" : Duration_AST, + "common.Timezone" : Timezone_AST, + "common.Paginated" : Paginated_AST, + "common.Unit" : Unit_AST, + "common.StringKeyMap" : StringKeyMap_AST, + "common.Key" : Key_AST, + "common.WithKey" : WithKey_AST, + "common.StringList" : StringList_AST, + "common.TSVector" : TSVector_AST, + "common.GeographyGeoJson" : GeographyGeoJson_AST, + "common.GeometryWKT" : GeometryWKT_AST, + "common.BigDecimal" : BigDecimal_AST +}; diff --git a/typescript/workspace/generated/common/_/index.ts b/typescript/workspace/generated/common/_/index.ts new file mode 100644 index 00000000..1ce952e9 --- /dev/null +++ b/typescript/workspace/generated/common/_/index.ts @@ -0,0 +1,2 @@ +/* @generated - key "_" */ +export * from './common'; diff --git a/typescript/workspace/generated/common/adminui/api.ts b/typescript/workspace/generated/common/adminui/api.ts new file mode 100644 index 00000000..4848fcdf --- /dev/null +++ b/typescript/workspace/generated/common/adminui/api.ts @@ -0,0 +1,455 @@ +import * as common from "./../_/common"; +import * as common_db from "./../db"; +import * as common_flyway_api from "./../flyway/api"; +import * as common_http from "./../http"; +import * as common_tabular from "./../tabular"; +import * as common_adminui_db from "./db"; +import * as ADL from "@adl-lang/runtime/adl"; +import * as sys_adlast from "@adl-lang/sys/adlast"; +import * as sys_types from "@adl-lang/sys/types"; + +/* @generated from adl module common.adminui.api */ + +export type AdlValue = {}|null; + +const AdlValue_AST : ADL.ScopedDecl = + {"moduleName":"common.adminui.api","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"Json"},"parameters":[]}}},"name":"AdlValue","version":{"kind":"nothing"}}}; + +export const snAdlValue: ADL.ScopedName = {moduleName:"common.adminui.api", name:"AdlValue"}; + +export function texprAdlValue(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snAdlValue},parameters:[]}}; +} + +export type DbRow = {[key: string]: AdlValue}; + +const DbRow_AST : ADL.ScopedDecl = + {"moduleName":"common.adminui.api","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"StringMap"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"AdlValue"}},"parameters":[]}]}}},"name":"DbRow","version":{"kind":"nothing"}}}; + +export const snDbRow: ADL.ScopedName = {moduleName:"common.adminui.api", name:"DbRow"}; + +export function texprDbRow(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDbRow},parameters:[]}}; +} + +export type DbId = common_db.DbKey; + +const DbId_AST : ADL.ScopedDecl = + {"moduleName":"common.adminui.api","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.db","name":"DbKey"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"DbRow"}},"parameters":[]}]}}},"name":"DbId","version":{"kind":"nothing"}}}; + +export const snDbId: ADL.ScopedName = {moduleName:"common.adminui.api", name:"DbId"}; + +export function texprDbId(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDbId},parameters:[]}}; +} + +/** + * Endpoints supporting CRUD for the Admin UI, + * along with metadata access. + */ +export interface AdminApiRequests { +/** + * Query the tables available for admin access + */ + queryTables: common_http.HttpPost>; +/** + * Query the ADL declarations used in the column + * type declarations + */ + queryDecls: common_http.HttpPost>; +/** + * Query rows from a table, specifying pagination, + * filtering and sorting. As per it's return type, this method + * can only be used for tables with a string primary key + * called `id`. + */ + query: common_http.HttpPost>>; +/** + * Query rows from a table without requiring a primary key, specifying pagination, + * filtering and sorting. + */ + queryWithoutIds: common_http.HttpPost>; +/** + * Create a new row in a table + */ + create: common_http.HttpPost>; +/** + * Update a single existing row in a table + */ + update: common_http.HttpPost>; +/** + * Delete a single existing row in a table + */ + delete: common_http.HttpPost>; +/** + * Fetch descriptive strings for db keys + */ + dbKeyLabels: common_http.HttpPost; +/** + * Flyway migration handled by adminui + */ + flyway: common_http.HttpPost; +} + +export function makeAdminApiRequests( + input: { + queryTables?: common_http.HttpPost>, + queryDecls?: common_http.HttpPost>, + query?: common_http.HttpPost>>, + queryWithoutIds?: common_http.HttpPost>, + create?: common_http.HttpPost>, + update?: common_http.HttpPost>, + delete?: common_http.HttpPost>, + dbKeyLabels?: common_http.HttpPost, + flyway?: common_http.HttpPost, + } +): AdminApiRequests { + return { + queryTables: input.queryTables === undefined ? {path : "/admin/meta/tables", security : {kind : "tokenWithRole", value : "admin"}, rateLimit : null, reqType : common_tabular.texprTableQuery(), respType : common.texprPaginated(texprTable())} : input.queryTables, + queryDecls: input.queryDecls === undefined ? {path : "/admin/meta/decls", security : {kind : "tokenWithRole", value : "admin"}, rateLimit : null, reqType : common_tabular.texprTableQuery(), respType : common.texprPaginated(common_adminui_db.texprMetaAdlDecl())} : input.queryDecls, + query: input.query === undefined ? {path : "/admin/query", security : {kind : "tokenWithRole", value : "admin"}, rateLimit : null, reqType : texprQueryReq(), respType : common.texprPaginated(common_db.texprWithDbId(texprDbRow()))} : input.query, + queryWithoutIds: input.queryWithoutIds === undefined ? {path : "/admin/query-without-ids", security : {kind : "tokenWithRole", value : "admin"}, rateLimit : null, reqType : texprQueryReq(), respType : common.texprPaginated(texprDbRow())} : input.queryWithoutIds, + create: input.create === undefined ? {path : "/admin/create", security : {kind : "tokenWithRole", value : "admin"}, rateLimit : null, reqType : texprCreateReq(), respType : texprDbResult(texprDbId())} : input.create, + update: input.update === undefined ? {path : "/admin/update", security : {kind : "tokenWithRole", value : "admin"}, rateLimit : null, reqType : texprUpdateReq(), respType : texprDbResult(common.texprUnit())} : input.update, + delete: input.delete === undefined ? {path : "/admin/delete", security : {kind : "tokenWithRole", value : "admin"}, rateLimit : null, reqType : texprDeleteReq(), respType : texprDbResult(common.texprUnit())} : input.delete, + dbKeyLabels: input.dbKeyLabels === undefined ? {path : "/admin/dbkeylabels", security : {kind : "tokenWithRole", value : "admin"}, rateLimit : null, reqType : ADL.texprVector(texprDbKeyLabelReq()), respType : ADL.texprVector(texprDbKeyLabelResp())} : input.dbKeyLabels, + flyway: input.flyway === undefined ? {path : "/admin/flyway", security : {kind : "tokenWithRole", value : "admin"}, rateLimit : null, reqType : common_flyway_api.texprFlywayReq(), respType : common_flyway_api.texprFlywayResp()} : input.flyway, + }; +} + +const AdminApiRequests_AST : ADL.ScopedDecl = + {"moduleName":"common.adminui.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"queryTables","default":{"kind":"just","value":{"path":"/admin/meta/tables","security":{"tokenWithRole":"admin"}}},"name":"queryTables","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"TableQuery"}},"parameters":[]},{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"Paginated"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"Table"}},"parameters":[]}]}]}},{"annotations":[],"serializedName":"queryDecls","default":{"kind":"just","value":{"path":"/admin/meta/decls","security":{"tokenWithRole":"admin"}}},"name":"queryDecls","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"TableQuery"}},"parameters":[]},{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"Paginated"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.db","name":"MetaAdlDecl"}},"parameters":[]}]}]}},{"annotations":[],"serializedName":"query","default":{"kind":"just","value":{"path":"/admin/query","security":{"tokenWithRole":"admin"}}},"name":"query","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"QueryReq"}},"parameters":[]},{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"Paginated"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.db","name":"WithDbId"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"DbRow"}},"parameters":[]}]}]}]}},{"annotations":[],"serializedName":"queryWithoutIds","default":{"kind":"just","value":{"path":"/admin/query-without-ids","security":{"tokenWithRole":"admin"}}},"name":"queryWithoutIds","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"QueryReq"}},"parameters":[]},{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"Paginated"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"DbRow"}},"parameters":[]}]}]}},{"annotations":[],"serializedName":"create","default":{"kind":"just","value":{"path":"/admin/create","security":{"tokenWithRole":"admin"}}},"name":"create","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"CreateReq"}},"parameters":[]},{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"DbResult"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"DbId"}},"parameters":[]}]}]}},{"annotations":[],"serializedName":"update","default":{"kind":"just","value":{"path":"/admin/update","security":{"tokenWithRole":"admin"}}},"name":"update","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"UpdateReq"}},"parameters":[]},{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"DbResult"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"Unit"}},"parameters":[]}]}]}},{"annotations":[],"serializedName":"delete","default":{"kind":"just","value":{"path":"/admin/delete","security":{"tokenWithRole":"admin"}}},"name":"delete","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"DeleteReq"}},"parameters":[]},{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"DbResult"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"Unit"}},"parameters":[]}]}]}},{"annotations":[],"serializedName":"dbKeyLabels","default":{"kind":"just","value":{"path":"/admin/dbkeylabels","security":{"tokenWithRole":"admin"}}},"name":"dbKeyLabels","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"DbKeyLabelReq"}},"parameters":[]}]},{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"DbKeyLabelResp"}},"parameters":[]}]}]}},{"annotations":[],"serializedName":"flyway","default":{"kind":"just","value":{"path":"/admin/flyway","security":{"tokenWithRole":"admin"}}},"name":"flyway","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.api","name":"FlywayReq"}},"parameters":[]},{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.api","name":"FlywayResp"}},"parameters":[]}]}}]}},"name":"AdminApiRequests","version":{"kind":"nothing"}}}; + +export const snAdminApiRequests: ADL.ScopedName = {moduleName:"common.adminui.api", name:"AdminApiRequests"}; + +export function texprAdminApiRequests(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snAdminApiRequests},parameters:[]}}; +} + +export interface QueryReq { + table: string; +/** + * The columns to be included in the result. If empty, all + * columns will be included. + */ + columns: string[]; + query: common_tabular.TableQuery; +} + +export function makeQueryReq( + input: { + table: string, + columns: string[], + query: common_tabular.TableQuery, + } +): QueryReq { + return { + table: input.table, + columns: input.columns, + query: input.query, + }; +} + +const QueryReq_AST : ADL.ScopedDecl = + {"moduleName":"common.adminui.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"table","default":{"kind":"nothing"},"name":"table","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"columns","default":{"kind":"nothing"},"name":"columns","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}},{"annotations":[],"serializedName":"query","default":{"kind":"nothing"},"name":"query","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"TableQuery"}},"parameters":[]}}]}},"name":"QueryReq","version":{"kind":"nothing"}}}; + +export const snQueryReq: ADL.ScopedName = {moduleName:"common.adminui.api", name:"QueryReq"}; + +export function texprQueryReq(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snQueryReq},parameters:[]}}; +} + +export interface Table { + name: string; + label: string; + description: string; + hasIdPrimaryKey: boolean; +/** + * If true, the current user is allowed to query existingRows + */ + allowQuery: boolean; +/** + * If true, the current user is allowed to insert new rows + */ + allowInsert: boolean; +/** + * If true, the current user is allowed to delete rows + */ + allowDelete: boolean; +/** + * If true, the current user is allowed to update rows + */ + allowUpdate: boolean; + columns: TableColumn[]; + declModuleName: sys_adlast.ModuleName; + declName: string; +} + +export function makeTable( + input: { + name: string, + label: string, + description: string, + hasIdPrimaryKey: boolean, + allowQuery: boolean, + allowInsert: boolean, + allowDelete: boolean, + allowUpdate: boolean, + columns: TableColumn[], + declModuleName: sys_adlast.ModuleName, + declName: string, + } +): Table { + return { + name: input.name, + label: input.label, + description: input.description, + hasIdPrimaryKey: input.hasIdPrimaryKey, + allowQuery: input.allowQuery, + allowInsert: input.allowInsert, + allowDelete: input.allowDelete, + allowUpdate: input.allowUpdate, + columns: input.columns, + declModuleName: input.declModuleName, + declName: input.declName, + }; +} + +const Table_AST : ADL.ScopedDecl = + {"moduleName":"common.adminui.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"name","default":{"kind":"nothing"},"name":"name","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"label","default":{"kind":"nothing"},"name":"label","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"description","default":{"kind":"nothing"},"name":"description","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"hasIdPrimaryKey","default":{"kind":"nothing"},"name":"hasIdPrimaryKey","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"allowQuery","default":{"kind":"nothing"},"name":"allowQuery","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"allowInsert","default":{"kind":"nothing"},"name":"allowInsert","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"allowDelete","default":{"kind":"nothing"},"name":"allowDelete","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"allowUpdate","default":{"kind":"nothing"},"name":"allowUpdate","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"columns","default":{"kind":"nothing"},"name":"columns","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"TableColumn"}},"parameters":[]}]}},{"annotations":[],"serializedName":"declModuleName","default":{"kind":"nothing"},"name":"declModuleName","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"ModuleName"}},"parameters":[]}},{"annotations":[],"serializedName":"declName","default":{"kind":"nothing"},"name":"declName","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"Table","version":{"kind":"nothing"}}}; + +export const snTable: ADL.ScopedName = {moduleName:"common.adminui.api", name:"Table"}; + +export function texprTable(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snTable},parameters:[]}}; +} + +export type Access = 'readOnly' | 'readWrite'; +export const valuesAccess : Access[] = ['readOnly', 'readWrite']; + +const Access_AST : ADL.ScopedDecl = + {"moduleName":"common.adminui.api","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"readOnly","default":{"kind":"nothing"},"name":"readOnly","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"readWrite","default":{"kind":"nothing"},"name":"readWrite","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}}]}},"name":"Access","version":{"kind":"nothing"}}}; + +export const snAccess: ADL.ScopedName = {moduleName:"common.adminui.api", name:"Access"}; + +export function texprAccess(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snAccess},parameters:[]}}; +} + +export interface TableColumn { + name: string; + label: string; + description: string; + typeExpr: sys_adlast.TypeExpr; + defaultValue: sys_types.Maybe<{}|null>; + generated: boolean; + access: Access; +} + +export function makeTableColumn( + input: { + name: string, + label: string, + description: string, + typeExpr: sys_adlast.TypeExpr, + defaultValue: sys_types.Maybe<{}|null>, + generated: boolean, + access: Access, + } +): TableColumn { + return { + name: input.name, + label: input.label, + description: input.description, + typeExpr: input.typeExpr, + defaultValue: input.defaultValue, + generated: input.generated, + access: input.access, + }; +} + +const TableColumn_AST : ADL.ScopedDecl = + {"moduleName":"common.adminui.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"name","default":{"kind":"nothing"},"name":"name","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"label","default":{"kind":"nothing"},"name":"label","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"description","default":{"kind":"nothing"},"name":"description","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"typeExpr","default":{"kind":"nothing"},"name":"typeExpr","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"TypeExpr"}},"parameters":[]}},{"annotations":[],"serializedName":"defaultValue","default":{"kind":"nothing"},"name":"defaultValue","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.types","name":"Maybe"}},"parameters":[{"typeRef":{"kind":"primitive","value":"Json"},"parameters":[]}]}},{"annotations":[],"serializedName":"generated","default":{"kind":"nothing"},"name":"generated","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"access","default":{"kind":"nothing"},"name":"access","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"Access"}},"parameters":[]}}]}},"name":"TableColumn","version":{"kind":"nothing"}}}; + +export const snTableColumn: ADL.ScopedName = {moduleName:"common.adminui.api", name:"TableColumn"}; + +export function texprTableColumn(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snTableColumn},parameters:[]}}; +} + +export interface CreateReq { + table: string; + values: DbRow; +} + +export function makeCreateReq( + input: { + table: string, + values: DbRow, + } +): CreateReq { + return { + table: input.table, + values: input.values, + }; +} + +const CreateReq_AST : ADL.ScopedDecl = + {"moduleName":"common.adminui.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"table","default":{"kind":"nothing"},"name":"table","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"values","default":{"kind":"nothing"},"name":"values","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"DbRow"}},"parameters":[]}}]}},"name":"CreateReq","version":{"kind":"nothing"}}}; + +export const snCreateReq: ADL.ScopedName = {moduleName:"common.adminui.api", name:"CreateReq"}; + +export function texprCreateReq(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snCreateReq},parameters:[]}}; +} + +export interface UpdateReq { + table: string; + values: common_db.WithDbId; +} + +export function makeUpdateReq( + input: { + table: string, + values: common_db.WithDbId, + } +): UpdateReq { + return { + table: input.table, + values: input.values, + }; +} + +const UpdateReq_AST : ADL.ScopedDecl = + {"moduleName":"common.adminui.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"table","default":{"kind":"nothing"},"name":"table","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"values","default":{"kind":"nothing"},"name":"values","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.db","name":"WithDbId"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"DbRow"}},"parameters":[]}]}}]}},"name":"UpdateReq","version":{"kind":"nothing"}}}; + +export const snUpdateReq: ADL.ScopedName = {moduleName:"common.adminui.api", name:"UpdateReq"}; + +export function texprUpdateReq(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snUpdateReq},parameters:[]}}; +} + +export interface DeleteReq { + table: string; + id: DbId; +} + +export function makeDeleteReq( + input: { + table: string, + id: DbId, + } +): DeleteReq { + return { + table: input.table, + id: input.id, + }; +} + +const DeleteReq_AST : ADL.ScopedDecl = + {"moduleName":"common.adminui.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"table","default":{"kind":"nothing"},"name":"table","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"id","default":{"kind":"nothing"},"name":"id","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.adminui.api","name":"DbId"}},"parameters":[]}}]}},"name":"DeleteReq","version":{"kind":"nothing"}}}; + +export const snDeleteReq: ADL.ScopedName = {moduleName:"common.adminui.api", name:"DeleteReq"}; + +export function texprDeleteReq(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDeleteReq},parameters:[]}}; +} + +export interface DbResult_Ok { + kind: 'ok'; + value: T; +} +export interface DbResult_DbError<_T> { + kind: 'dbError'; + value: string; +} + +export type DbResult = DbResult_Ok | DbResult_DbError; + +export interface DbResultOpts { + ok: T; + dbError: string; +} + +export function makeDbResult>(kind: K, value: DbResultOpts[K]) { return {kind, value}; } + +const DbResult_AST : ADL.ScopedDecl = + {"moduleName":"common.adminui.api","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":["T"],"fields":[{"annotations":[],"serializedName":"ok","default":{"kind":"nothing"},"name":"ok","typeExpr":{"typeRef":{"kind":"typeParam","value":"T"},"parameters":[]}},{"annotations":[],"serializedName":"dbError","default":{"kind":"nothing"},"name":"dbError","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"DbResult","version":{"kind":"nothing"}}}; + +export const snDbResult: ADL.ScopedName = {moduleName:"common.adminui.api", name:"DbResult"}; + +export function texprDbResult(texprT : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snDbResult},parameters:[texprT.value]}}; +} + +export interface DbKeyLabelReq { + scopedName: sys_adlast.ScopedName; + id: string; +} + +export function makeDbKeyLabelReq( + input: { + scopedName: sys_adlast.ScopedName, + id: string, + } +): DbKeyLabelReq { + return { + scopedName: input.scopedName, + id: input.id, + }; +} + +const DbKeyLabelReq_AST : ADL.ScopedDecl = + {"moduleName":"common.adminui.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"scopedName","default":{"kind":"nothing"},"name":"scopedName","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"ScopedName"}},"parameters":[]}},{"annotations":[],"serializedName":"id","default":{"kind":"nothing"},"name":"id","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"DbKeyLabelReq","version":{"kind":"nothing"}}}; + +export const snDbKeyLabelReq: ADL.ScopedName = {moduleName:"common.adminui.api", name:"DbKeyLabelReq"}; + +export function texprDbKeyLabelReq(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDbKeyLabelReq},parameters:[]}}; +} + +export interface DbKeyLabelResp { + scopedName: sys_adlast.ScopedName; + id: string; + label: string; +} + +export function makeDbKeyLabelResp( + input: { + scopedName: sys_adlast.ScopedName, + id: string, + label: string, + } +): DbKeyLabelResp { + return { + scopedName: input.scopedName, + id: input.id, + label: input.label, + }; +} + +const DbKeyLabelResp_AST : ADL.ScopedDecl = + {"moduleName":"common.adminui.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"scopedName","default":{"kind":"nothing"},"name":"scopedName","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"ScopedName"}},"parameters":[]}},{"annotations":[],"serializedName":"id","default":{"kind":"nothing"},"name":"id","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"label","default":{"kind":"nothing"},"name":"label","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"DbKeyLabelResp","version":{"kind":"nothing"}}}; + +export const snDbKeyLabelResp: ADL.ScopedName = {moduleName:"common.adminui.api", name:"DbKeyLabelResp"}; + +export function texprDbKeyLabelResp(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDbKeyLabelResp},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.adminui.api.AdlValue" : AdlValue_AST, + "common.adminui.api.DbRow" : DbRow_AST, + "common.adminui.api.DbId" : DbId_AST, + "common.adminui.api.AdminApiRequests" : AdminApiRequests_AST, + "common.adminui.api.QueryReq" : QueryReq_AST, + "common.adminui.api.Table" : Table_AST, + "common.adminui.api.Access" : Access_AST, + "common.adminui.api.TableColumn" : TableColumn_AST, + "common.adminui.api.CreateReq" : CreateReq_AST, + "common.adminui.api.UpdateReq" : UpdateReq_AST, + "common.adminui.api.DeleteReq" : DeleteReq_AST, + "common.adminui.api.DbResult" : DbResult_AST, + "common.adminui.api.DbKeyLabelReq" : DbKeyLabelReq_AST, + "common.adminui.api.DbKeyLabelResp" : DbKeyLabelResp_AST +}; diff --git a/typescript/workspace/generated/common/adminui/config.ts b/typescript/workspace/generated/common/adminui/config.ts new file mode 100644 index 00000000..4c44aede --- /dev/null +++ b/typescript/workspace/generated/common/adminui/config.ts @@ -0,0 +1,79 @@ +import * as common_config_db from "./../config/db"; +import * as common_config_frontend from "./../config/frontend"; +import * as common_config_log from "./../config/log"; +import * as common_flyway_example_patterns from "./../flyway/example_patterns"; +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common.adminui.config */ + +/** + * Configuration for the adminui server + */ +export interface ServerConfig { +/** + * Port to listen for requests + */ + port: number; +/** + * Environment name, e.g. dev, uat, prod + */ + environment: string; +/** + * Name of the release / code version + */ + releaseName: string; +/** + * Secret used to sign JWT tokens + */ + jwtSecret: string; +/** + * Database config + */ + db: common_config_db.PostgreSqlConfig; +/** + * Server-side logging config + */ + logging: common_config_log.LogConfig; +/** + * Frontend threadpool configuration + */ + threadPool: common_config_frontend.ThreadPoolConfig; + flyway: (common_flyway_example_patterns.FlywayConfig|null); +} + +export function makeServerConfig( + input: { + port: number, + environment: string, + releaseName: string, + jwtSecret: string, + db: common_config_db.PostgreSqlConfig, + logging: common_config_log.LogConfig, + threadPool: common_config_frontend.ThreadPoolConfig, + flyway?: (common_flyway_example_patterns.FlywayConfig|null), + } +): ServerConfig { + return { + port: input.port, + environment: input.environment, + releaseName: input.releaseName, + jwtSecret: input.jwtSecret, + db: input.db, + logging: input.logging, + threadPool: input.threadPool, + flyway: input.flyway === undefined ? null : input.flyway, + }; +} + +const ServerConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.adminui.config","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"port","default":{"kind":"nothing"},"name":"port","typeExpr":{"typeRef":{"kind":"primitive","value":"Int16"},"parameters":[]}},{"annotations":[],"serializedName":"environment","default":{"kind":"nothing"},"name":"environment","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"releaseName","default":{"kind":"nothing"},"name":"releaseName","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"jwtSecret","default":{"kind":"nothing"},"name":"jwtSecret","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"db","default":{"kind":"nothing"},"name":"db","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.db","name":"PostgreSqlConfig"}},"parameters":[]}},{"annotations":[],"serializedName":"logging","default":{"kind":"nothing"},"name":"logging","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.log","name":"LogConfig"}},"parameters":[]}},{"annotations":[],"serializedName":"threadPool","default":{"kind":"nothing"},"name":"threadPool","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.frontend","name":"ThreadPoolConfig"}},"parameters":[]}},{"annotations":[],"serializedName":"flyway","default":{"kind":"just","value":null},"name":"flyway","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.example_patterns","name":"FlywayConfig"}},"parameters":[]}]}}]}},"name":"ServerConfig","version":{"kind":"nothing"}}}; + +export const snServerConfig: ADL.ScopedName = {moduleName:"common.adminui.config", name:"ServerConfig"}; + +export function texprServerConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snServerConfig},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.adminui.config.ServerConfig" : ServerConfig_AST +}; diff --git a/typescript/workspace/generated/common/adminui/db.ts b/typescript/workspace/generated/common/adminui/db.ts new file mode 100644 index 00000000..ce12c142 --- /dev/null +++ b/typescript/workspace/generated/common/adminui/db.ts @@ -0,0 +1,70 @@ +import * as ADL from "@adl-lang/runtime/adl"; +import * as sys_adlast from "@adl-lang/sys/adlast"; + +/* @generated from adl module common.adminui.db */ + +export interface MetaTable { + name: string; + description: string; + declModuleName: sys_adlast.ModuleName; + declName: string; +} + +export function makeMetaTable( + input: { + name: string, + description: string, + declModuleName: sys_adlast.ModuleName, + declName: string, + } +): MetaTable { + return { + name: input.name, + description: input.description, + declModuleName: input.declModuleName, + declName: input.declName, + }; +} + +const MetaTable_AST : ADL.ScopedDecl = + {"moduleName":"common.adminui.db","decl":{"annotations":[{"value":{"uniquenessConstraints":[["name"]],"withPrimaryKey":["name"]},"key":{"moduleName":"common.db","name":"DbTable"}}],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"name","default":{"kind":"nothing"},"name":"name","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"description","default":{"kind":"nothing"},"name":"description","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"declModuleName","default":{"kind":"nothing"},"name":"declModuleName","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"ModuleName"}},"parameters":[]}},{"annotations":[],"serializedName":"declName","default":{"kind":"nothing"},"name":"declName","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"MetaTable","version":{"kind":"nothing"}}}; + +export const snMetaTable: ADL.ScopedName = {moduleName:"common.adminui.db", name:"MetaTable"}; + +export function texprMetaTable(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snMetaTable},parameters:[]}}; +} + +export interface MetaAdlDecl { + moduleName: sys_adlast.ModuleName; + name: string; + decl: sys_adlast.Decl; +} + +export function makeMetaAdlDecl( + input: { + moduleName: sys_adlast.ModuleName, + name: string, + decl: sys_adlast.Decl, + } +): MetaAdlDecl { + return { + moduleName: input.moduleName, + name: input.name, + decl: input.decl, + }; +} + +const MetaAdlDecl_AST : ADL.ScopedDecl = + {"moduleName":"common.adminui.db","decl":{"annotations":[{"value":{"uniquenessConstraints":[["moduleName","name"]],"withPrimaryKey":["moduleName","name"]},"key":{"moduleName":"common.db","name":"DbTable"}}],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"moduleName","default":{"kind":"nothing"},"name":"moduleName","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"ModuleName"}},"parameters":[]}},{"annotations":[],"serializedName":"name","default":{"kind":"nothing"},"name":"name","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"decl","default":{"kind":"nothing"},"name":"decl","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Decl"}},"parameters":[]}}]}},"name":"MetaAdlDecl","version":{"kind":"nothing"}}}; + +export const snMetaAdlDecl: ADL.ScopedName = {moduleName:"common.adminui.db", name:"MetaAdlDecl"}; + +export function texprMetaAdlDecl(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snMetaAdlDecl},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.adminui.db.MetaTable" : MetaTable_AST, + "common.adminui.db.MetaAdlDecl" : MetaAdlDecl_AST +}; diff --git a/typescript/workspace/generated/common/adminui/index.ts b/typescript/workspace/generated/common/adminui/index.ts new file mode 100644 index 00000000..29abf502 --- /dev/null +++ b/typescript/workspace/generated/common/adminui/index.ts @@ -0,0 +1,4 @@ +/* @generated - key "adminui" */ +export * as api from './api'; +export * as config from './config'; +export * as db from './db'; diff --git a/typescript/workspace/generated/common/config/aws.ts b/typescript/workspace/generated/common/config/aws.ts new file mode 100644 index 00000000..f94362ef --- /dev/null +++ b/typescript/workspace/generated/common/config/aws.ts @@ -0,0 +1,196 @@ +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common.config.aws */ + +export interface AwsCredentials { + accessKey: string; + secretKey: string; +} + +export function makeAwsCredentials( + input: { + accessKey: string, + secretKey: string, + } +): AwsCredentials { + return { + accessKey: input.accessKey, + secretKey: input.secretKey, + }; +} + +const AwsCredentials_AST : ADL.ScopedDecl = + {"moduleName":"common.config.aws","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"accessKey","default":{"kind":"nothing"},"name":"accessKey","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"secretKey","default":{"kind":"nothing"},"name":"secretKey","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"AwsCredentials","version":{"kind":"nothing"}}}; + +export const snAwsCredentials: ADL.ScopedName = {moduleName:"common.config.aws", name:"AwsCredentials"}; + +export function texprAwsCredentials(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snAwsCredentials},parameters:[]}}; +} + +export interface AwsCredentialsProvider_UseEnvVariables { + kind: 'useEnvVariables'; +} +export interface AwsCredentialsProvider_UseInstanceProfile { + kind: 'useInstanceProfile'; +} +export interface AwsCredentialsProvider_Value { + kind: 'value'; + value: AwsCredentials; +} + +/** + * The methods available to obtain AWS credentials + */ +export type AwsCredentialsProvider = AwsCredentialsProvider_UseEnvVariables | AwsCredentialsProvider_UseInstanceProfile | AwsCredentialsProvider_Value; + +export interface AwsCredentialsProviderOpts { + useEnvVariables: null; + useInstanceProfile: null; + value: AwsCredentials; +} + +export function makeAwsCredentialsProvider(kind: K, value: AwsCredentialsProviderOpts[K]) { return {kind, value}; } + +const AwsCredentialsProvider_AST : ADL.ScopedDecl = + {"moduleName":"common.config.aws","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"useEnvVariables","default":{"kind":"nothing"},"name":"useEnvVariables","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"useInstanceProfile","default":{"kind":"nothing"},"name":"useInstanceProfile","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"value","default":{"kind":"nothing"},"name":"value","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.aws","name":"AwsCredentials"}},"parameters":[]}}]}},"name":"AwsCredentialsProvider","version":{"kind":"nothing"}}}; + +export const snAwsCredentialsProvider: ADL.ScopedName = {moduleName:"common.config.aws", name:"AwsCredentialsProvider"}; + +export function texprAwsCredentialsProvider(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snAwsCredentialsProvider},parameters:[]}}; +} + +export interface AwsRegionProvider_FromInstance { + kind: 'fromInstance'; +} +export interface AwsRegionProvider_Value { + kind: 'value'; + value: string; +} + +/** + * The methods available to determine the AWS region + */ +export type AwsRegionProvider = AwsRegionProvider_FromInstance | AwsRegionProvider_Value; + +export interface AwsRegionProviderOpts { + fromInstance: null; + value: string; +} + +export function makeAwsRegionProvider(kind: K, value: AwsRegionProviderOpts[K]) { return {kind, value}; } + +const AwsRegionProvider_AST : ADL.ScopedDecl = + {"moduleName":"common.config.aws","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"fromInstance","default":{"kind":"nothing"},"name":"fromInstance","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"value","default":{"kind":"nothing"},"name":"value","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"AwsRegionProvider","version":{"kind":"nothing"}}}; + +export const snAwsRegionProvider: ADL.ScopedName = {moduleName:"common.config.aws", name:"AwsRegionProvider"}; + +export function texprAwsRegionProvider(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snAwsRegionProvider},parameters:[]}}; +} + +export interface S3Location { +/** + * The name on of an S3 bucket + */ + s3Bucket: string; +/** + * The S3 path prefix for the storage + */ + s3Prefix: string; +} + +export function makeS3Location( + input: { + s3Bucket: string, + s3Prefix: string, + } +): S3Location { + return { + s3Bucket: input.s3Bucket, + s3Prefix: input.s3Prefix, + }; +} + +const S3Location_AST : ADL.ScopedDecl = + {"moduleName":"common.config.aws","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"s3Bucket","default":{"kind":"nothing"},"name":"s3Bucket","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"s3Prefix","default":{"kind":"nothing"},"name":"s3Prefix","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"S3Location","version":{"kind":"nothing"}}}; + +export const snS3Location: ADL.ScopedName = {moduleName:"common.config.aws", name:"S3Location"}; + +export function texprS3Location(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snS3Location},parameters:[]}}; +} + +/** + * Description of an AWS SQS queue + */ +export interface QueueDetails { +/** + * The amount of time to keep the connection open while waiting for queue messages. + */ + waitTimeSeconds: number; + queueUrl: string; +} + +export function makeQueueDetails( + input: { + waitTimeSeconds?: number, + queueUrl?: string, + } +): QueueDetails { + return { + waitTimeSeconds: input.waitTimeSeconds === undefined ? 10 : input.waitTimeSeconds, + queueUrl: input.queueUrl === undefined ? "" : input.queueUrl, + }; +} + +const QueueDetails_AST : ADL.ScopedDecl = + {"moduleName":"common.config.aws","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"waitTimeSeconds","default":{"kind":"just","value":10},"name":"waitTimeSeconds","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}},{"annotations":[],"serializedName":"queueUrl","default":{"kind":"just","value":""},"name":"queueUrl","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"QueueDetails","version":{"kind":"nothing"}}}; + +export const snQueueDetails: ADL.ScopedName = {moduleName:"common.config.aws", name:"QueueDetails"}; + +export function texprQueueDetails(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snQueueDetails},parameters:[]}}; +} + +/** + * Configuration of an S3 client + */ +export interface S3ClientConfig { + location: S3Location; + region: AwsRegionProvider; + credentials: AwsCredentialsProvider; +} + +export function makeS3ClientConfig( + input: { + location: S3Location, + region: AwsRegionProvider, + credentials: AwsCredentialsProvider, + } +): S3ClientConfig { + return { + location: input.location, + region: input.region, + credentials: input.credentials, + }; +} + +const S3ClientConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.aws","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"location","default":{"kind":"nothing"},"name":"location","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.aws","name":"S3Location"}},"parameters":[]}},{"annotations":[],"serializedName":"region","default":{"kind":"nothing"},"name":"region","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.aws","name":"AwsRegionProvider"}},"parameters":[]}},{"annotations":[],"serializedName":"credentials","default":{"kind":"nothing"},"name":"credentials","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.aws","name":"AwsCredentialsProvider"}},"parameters":[]}}]}},"name":"S3ClientConfig","version":{"kind":"nothing"}}}; + +export const snS3ClientConfig: ADL.ScopedName = {moduleName:"common.config.aws", name:"S3ClientConfig"}; + +export function texprS3ClientConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snS3ClientConfig},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.config.aws.AwsCredentials" : AwsCredentials_AST, + "common.config.aws.AwsCredentialsProvider" : AwsCredentialsProvider_AST, + "common.config.aws.AwsRegionProvider" : AwsRegionProvider_AST, + "common.config.aws.S3Location" : S3Location_AST, + "common.config.aws.QueueDetails" : QueueDetails_AST, + "common.config.aws.S3ClientConfig" : S3ClientConfig_AST +}; diff --git a/typescript/workspace/generated/common/config/azure.ts b/typescript/workspace/generated/common/config/azure.ts new file mode 100644 index 00000000..73868fc8 --- /dev/null +++ b/typescript/workspace/generated/common/config/azure.ts @@ -0,0 +1,68 @@ +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common.config.azure */ + +export interface AzureCredentialsProvider_SharedAccessSignature { + kind: 'sharedAccessSignature'; + value: string; +} + +/** + * Methods available to obtain Azure credentials + */ +export type AzureCredentialsProvider = AzureCredentialsProvider_SharedAccessSignature; + +export interface AzureCredentialsProviderOpts { + /** + * A shared access signature string + */ +sharedAccessSignature: string; +} + +export function makeAzureCredentialsProvider(kind: K, value: AzureCredentialsProviderOpts[K]) { return {kind, value}; } + +const AzureCredentialsProvider_AST : ADL.ScopedDecl = + {"moduleName":"common.config.azure","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"sharedAccessSignature","default":{"kind":"nothing"},"name":"sharedAccessSignature","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"AzureCredentialsProvider","version":{"kind":"nothing"}}}; + +export const snAzureCredentialsProvider: ADL.ScopedName = {moduleName:"common.config.azure", name:"AzureCredentialsProvider"}; + +export function texprAzureCredentialsProvider(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snAzureCredentialsProvider},parameters:[]}}; +} + +/** + * Config parameters for an Azure Blob Client + */ +export interface AzureBlobClientConfig { + blobstoreUri: string; + credentials: AzureCredentialsProvider; + container: string; +} + +export function makeAzureBlobClientConfig( + input: { + blobstoreUri: string, + credentials: AzureCredentialsProvider, + container: string, + } +): AzureBlobClientConfig { + return { + blobstoreUri: input.blobstoreUri, + credentials: input.credentials, + container: input.container, + }; +} + +const AzureBlobClientConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.azure","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"blobstoreUri","default":{"kind":"nothing"},"name":"blobstoreUri","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"credentials","default":{"kind":"nothing"},"name":"credentials","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.azure","name":"AzureCredentialsProvider"}},"parameters":[]}},{"annotations":[],"serializedName":"container","default":{"kind":"nothing"},"name":"container","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"AzureBlobClientConfig","version":{"kind":"nothing"}}}; + +export const snAzureBlobClientConfig: ADL.ScopedName = {moduleName:"common.config.azure", name:"AzureBlobClientConfig"}; + +export function texprAzureBlobClientConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snAzureBlobClientConfig},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.config.azure.AzureCredentialsProvider" : AzureCredentialsProvider_AST, + "common.config.azure.AzureBlobClientConfig" : AzureBlobClientConfig_AST +}; diff --git a/typescript/workspace/generated/common/config/db.ts b/typescript/workspace/generated/common/config/db.ts new file mode 100644 index 00000000..8a92988a --- /dev/null +++ b/typescript/workspace/generated/common/config/db.ts @@ -0,0 +1,124 @@ +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common.config.db */ + +export interface PostgreSqlConfig { + host: string; + port: number; + dbname: string; + user: string; + password: string; + poolSize: number; + postgisEnabled: boolean; +/** + * The amount of time to wait before refreshing a connection + */ + minRefreshDelayMillis: number; +/** + * The amount of time to wait for a free connection before timing out + */ + connectionWaitMillis: number; +/** + * The root cert to be used for ssl connections + */ + sslRootCert: (string|null); +/** + * The ssl connection mode + */ + sslMode: PostgresqlSslMode; +} + +export function makePostgreSqlConfig( + input: { + host: string, + port: number, + dbname: string, + user: string, + password: string, + poolSize?: number, + postgisEnabled?: boolean, + minRefreshDelayMillis?: number, + connectionWaitMillis?: number, + sslRootCert?: (string|null), + sslMode?: PostgresqlSslMode, + } +): PostgreSqlConfig { + return { + host: input.host, + port: input.port, + dbname: input.dbname, + user: input.user, + password: input.password, + poolSize: input.poolSize === undefined ? 5 : input.poolSize, + postgisEnabled: input.postgisEnabled === undefined ? false : input.postgisEnabled, + minRefreshDelayMillis: input.minRefreshDelayMillis === undefined ? 60000 : input.minRefreshDelayMillis, + connectionWaitMillis: input.connectionWaitMillis === undefined ? 5000 : input.connectionWaitMillis, + sslRootCert: input.sslRootCert === undefined ? null : input.sslRootCert, + sslMode: input.sslMode === undefined ? "prefer" : input.sslMode, + }; +} + +const PostgreSqlConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.db","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"host","default":{"kind":"nothing"},"name":"host","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"port","default":{"kind":"nothing"},"name":"port","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}},{"annotations":[],"serializedName":"dbname","default":{"kind":"nothing"},"name":"dbname","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"user","default":{"kind":"nothing"},"name":"user","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"password","default":{"kind":"nothing"},"name":"password","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"poolSize","default":{"kind":"just","value":5},"name":"poolSize","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}},{"annotations":[],"serializedName":"postgisEnabled","default":{"kind":"just","value":false},"name":"postgisEnabled","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"minRefreshDelayMillis","default":{"kind":"just","value":60000},"name":"minRefreshDelayMillis","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}},{"annotations":[],"serializedName":"connectionWaitMillis","default":{"kind":"just","value":5000},"name":"connectionWaitMillis","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}},{"annotations":[],"serializedName":"sslRootCert","default":{"kind":"just","value":null},"name":"sslRootCert","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}},{"annotations":[],"serializedName":"sslMode","default":{"kind":"just","value":"prefer"},"name":"sslMode","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.db","name":"PostgresqlSslMode"}},"parameters":[]}}]}},"name":"PostgreSqlConfig","version":{"kind":"nothing"}}}; + +export const snPostgreSqlConfig: ADL.ScopedName = {moduleName:"common.config.db", name:"PostgreSqlConfig"}; + +export function texprPostgreSqlConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snPostgreSqlConfig},parameters:[]}}; +} + +export type PostgresqlSslMode = 'disable' | 'allow' | 'prefer' | 'require' | 'verifyCa' | 'verifyFull'; +export const valuesPostgresqlSslMode : PostgresqlSslMode[] = ['disable', 'allow', 'prefer', 'require', 'verifyCa', 'verifyFull']; + +const PostgresqlSslMode_AST : ADL.ScopedDecl = + {"moduleName":"common.config.db","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"disable","default":{"kind":"nothing"},"name":"disable","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"allow","default":{"kind":"nothing"},"name":"allow","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"prefer","default":{"kind":"nothing"},"name":"prefer","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"require","default":{"kind":"nothing"},"name":"require","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"verify-ca","default":{"kind":"nothing"},"name":"verifyCa","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"verify-full","default":{"kind":"nothing"},"name":"verifyFull","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}}]}},"name":"PostgresqlSslMode","version":{"kind":"nothing"}}}; + +export const snPostgresqlSslMode: ADL.ScopedName = {moduleName:"common.config.db", name:"PostgresqlSslMode"}; + +export function texprPostgresqlSslMode(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snPostgresqlSslMode},parameters:[]}}; +} + +export interface SqlServerConfig { + host: string; + port: number; + dbname: string; + user: string; + password: string; + poolSize: number; +} + +export function makeSqlServerConfig( + input: { + host: string, + port: number, + dbname: string, + user: string, + password: string, + poolSize?: number, + } +): SqlServerConfig { + return { + host: input.host, + port: input.port, + dbname: input.dbname, + user: input.user, + password: input.password, + poolSize: input.poolSize === undefined ? 5 : input.poolSize, + }; +} + +const SqlServerConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.db","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"host","default":{"kind":"nothing"},"name":"host","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"port","default":{"kind":"nothing"},"name":"port","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}},{"annotations":[],"serializedName":"dbname","default":{"kind":"nothing"},"name":"dbname","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"user","default":{"kind":"nothing"},"name":"user","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"password","default":{"kind":"nothing"},"name":"password","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"poolSize","default":{"kind":"just","value":5},"name":"poolSize","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}}]}},"name":"SqlServerConfig","version":{"kind":"nothing"}}}; + +export const snSqlServerConfig: ADL.ScopedName = {moduleName:"common.config.db", name:"SqlServerConfig"}; + +export function texprSqlServerConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snSqlServerConfig},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.config.db.PostgreSqlConfig" : PostgreSqlConfig_AST, + "common.config.db.PostgresqlSslMode" : PostgresqlSslMode_AST, + "common.config.db.SqlServerConfig" : SqlServerConfig_AST +}; diff --git a/typescript/workspace/generated/common/config/emailer.ts b/typescript/workspace/generated/common/config/emailer.ts new file mode 100644 index 00000000..2387e536 --- /dev/null +++ b/typescript/workspace/generated/common/config/emailer.ts @@ -0,0 +1,73 @@ +import * as common_config_aws from "./aws"; +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common.config.emailer */ + +export interface EmailerConfig_Fake { + kind: 'fake'; +} +export interface EmailerConfig_Ses { + kind: 'ses'; + value: SesConfig; +} + +/** + * Configuration for the emailer used + */ +export type EmailerConfig = EmailerConfig_Fake | EmailerConfig_Ses; + +export interface EmailerConfigOpts { + /** + * Fake emailer, just prints outgoing email info to stdout + */ +fake: null; + /** + * SES emailer implementation + */ +ses: SesConfig; +} + +export function makeEmailerConfig(kind: K, value: EmailerConfigOpts[K]) { return {kind, value}; } + +const EmailerConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.emailer","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"fake","default":{"kind":"nothing"},"name":"fake","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"ses","default":{"kind":"nothing"},"name":"ses","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.emailer","name":"SesConfig"}},"parameters":[]}}]}},"name":"EmailerConfig","version":{"kind":"nothing"}}}; + +export const snEmailerConfig: ADL.ScopedName = {moduleName:"common.config.emailer", name:"EmailerConfig"}; + +export function texprEmailerConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snEmailerConfig},parameters:[]}}; +} + +/** + * Configuration for AWS SES emailer implementation + */ +export interface SesConfig { + credentials: common_config_aws.AwsCredentialsProvider; + region: common_config_aws.AwsRegionProvider; +} + +export function makeSesConfig( + input: { + credentials: common_config_aws.AwsCredentialsProvider, + region: common_config_aws.AwsRegionProvider, + } +): SesConfig { + return { + credentials: input.credentials, + region: input.region, + }; +} + +const SesConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.emailer","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"credentials","default":{"kind":"nothing"},"name":"credentials","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.aws","name":"AwsCredentialsProvider"}},"parameters":[]}},{"annotations":[],"serializedName":"region","default":{"kind":"nothing"},"name":"region","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.aws","name":"AwsRegionProvider"}},"parameters":[]}}]}},"name":"SesConfig","version":{"kind":"nothing"}}}; + +export const snSesConfig: ADL.ScopedName = {moduleName:"common.config.emailer", name:"SesConfig"}; + +export function texprSesConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snSesConfig},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.config.emailer.EmailerConfig" : EmailerConfig_AST, + "common.config.emailer.SesConfig" : SesConfig_AST +}; diff --git a/typescript/workspace/generated/common/config/frontend.ts b/typescript/workspace/generated/common/config/frontend.ts new file mode 100644 index 00000000..6091a561 --- /dev/null +++ b/typescript/workspace/generated/common/config/frontend.ts @@ -0,0 +1,56 @@ +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common.config.frontend */ + +/** + * Configuration for a consumer which processes work from a queue with a bounded thread pool. + * + * e.g. Useful for configuring jetty's request thread pool. + */ +export interface ThreadPoolConfig { +/** + * Maximum number of threads that can be spawned to handle requests + */ + maxThreads: number; +/** + * Minimum number of threads ready for jetty to handle requests + */ + minThreads: number; +/** + * How long a thread can be idle before it is candidate to be stopped + */ + idleTimeoutMillis: number; +/** + * Maximum number of pending requests before new ones are dropped + */ + queueSize: number; +} + +export function makeThreadPoolConfig( + input: { + maxThreads: number, + minThreads: number, + idleTimeoutMillis: number, + queueSize: number, + } +): ThreadPoolConfig { + return { + maxThreads: input.maxThreads, + minThreads: input.minThreads, + idleTimeoutMillis: input.idleTimeoutMillis, + queueSize: input.queueSize, + }; +} + +const ThreadPoolConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.frontend","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"maxThreads","default":{"kind":"nothing"},"name":"maxThreads","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}},{"annotations":[],"serializedName":"minThreads","default":{"kind":"nothing"},"name":"minThreads","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}},{"annotations":[],"serializedName":"idleTimeoutMillis","default":{"kind":"nothing"},"name":"idleTimeoutMillis","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}},{"annotations":[],"serializedName":"queueSize","default":{"kind":"nothing"},"name":"queueSize","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}}]}},"name":"ThreadPoolConfig","version":{"kind":"nothing"}}}; + +export const snThreadPoolConfig: ADL.ScopedName = {moduleName:"common.config.frontend", name:"ThreadPoolConfig"}; + +export function texprThreadPoolConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snThreadPoolConfig},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.config.frontend.ThreadPoolConfig" : ThreadPoolConfig_AST +}; diff --git a/typescript/workspace/generated/common/config/google.ts b/typescript/workspace/generated/common/config/google.ts new file mode 100644 index 00000000..17516b23 --- /dev/null +++ b/typescript/workspace/generated/common/config/google.ts @@ -0,0 +1,42 @@ +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common.config.google */ + +/** + * Connection parameters for google services + */ +export interface GoogleConfig { + clientId: string; + clientSecret: string; + accessToken: string; + refreshToken: string; +} + +export function makeGoogleConfig( + input: { + clientId: string, + clientSecret: string, + accessToken: string, + refreshToken: string, + } +): GoogleConfig { + return { + clientId: input.clientId, + clientSecret: input.clientSecret, + accessToken: input.accessToken, + refreshToken: input.refreshToken, + }; +} + +const GoogleConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.google","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"clientId","default":{"kind":"nothing"},"name":"clientId","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"clientSecret","default":{"kind":"nothing"},"name":"clientSecret","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"accessToken","default":{"kind":"nothing"},"name":"accessToken","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"refreshToken","default":{"kind":"nothing"},"name":"refreshToken","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"GoogleConfig","version":{"kind":"nothing"}}}; + +export const snGoogleConfig: ADL.ScopedName = {moduleName:"common.config.google", name:"GoogleConfig"}; + +export function texprGoogleConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snGoogleConfig},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.config.google.GoogleConfig" : GoogleConfig_AST +}; diff --git a/typescript/workspace/generated/common/config/index.ts b/typescript/workspace/generated/common/config/index.ts new file mode 100644 index 00000000..eaa93b2e --- /dev/null +++ b/typescript/workspace/generated/common/config/index.ts @@ -0,0 +1,12 @@ +/* @generated - key "config" */ +export * as aws from './aws'; +export * as azure from './azure'; +export * as db from './db'; +export * as emailer from './emailer'; +export * as frontend from './frontend'; +export * as google from './google'; +export * as jwt from './jwt'; +export * as log from './log'; +export * as okta from './okta'; +export * as sms from './sms'; +export * as storage from './storage'; diff --git a/typescript/workspace/generated/common/config/jwt.ts b/typescript/workspace/generated/common/config/jwt.ts new file mode 100644 index 00000000..18e513ce --- /dev/null +++ b/typescript/workspace/generated/common/config/jwt.ts @@ -0,0 +1,36 @@ +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common.config.jwt */ + +/** + * Secret and expiry of the JWT token + */ +export interface JwtConfig { + secret: string; + expiryInMinutes: number; +} + +export function makeJwtConfig( + input: { + secret: string, + expiryInMinutes: number, + } +): JwtConfig { + return { + secret: input.secret, + expiryInMinutes: input.expiryInMinutes, + }; +} + +const JwtConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.jwt","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"secret","default":{"kind":"nothing"},"name":"secret","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"expiryInMinutes","default":{"kind":"nothing"},"name":"expiryInMinutes","typeExpr":{"typeRef":{"kind":"primitive","value":"Double"},"parameters":[]}}]}},"name":"JwtConfig","version":{"kind":"nothing"}}}; + +export const snJwtConfig: ADL.ScopedName = {moduleName:"common.config.jwt", name:"JwtConfig"}; + +export function texprJwtConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snJwtConfig},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.config.jwt.JwtConfig" : JwtConfig_AST +}; diff --git a/typescript/workspace/generated/common/config/log.ts b/typescript/workspace/generated/common/config/log.ts new file mode 100644 index 00000000..7170e7c1 --- /dev/null +++ b/typescript/workspace/generated/common/config/log.ts @@ -0,0 +1,250 @@ +import * as common_config_aws from "./aws"; +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common.config.log */ + +export type LogLevel = 'DEBUG' | 'INFO' | 'WARN' | 'ERROR' | 'NONE' | 'TRACE'; +export const valuesLogLevel : LogLevel[] = ['DEBUG', 'INFO', 'WARN', 'ERROR', 'NONE', 'TRACE']; + +const LogLevel_AST : ADL.ScopedDecl = + {"moduleName":"common.config.log","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"DEBUG","default":{"kind":"nothing"},"name":"DEBUG","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"INFO","default":{"kind":"nothing"},"name":"INFO","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"WARN","default":{"kind":"nothing"},"name":"WARN","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"ERROR","default":{"kind":"nothing"},"name":"ERROR","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"NONE","default":{"kind":"nothing"},"name":"NONE","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"TRACE","default":{"kind":"nothing"},"name":"TRACE","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}}]}},"name":"LogLevel","version":{"kind":"nothing"}}}; + +export const snLogLevel: ADL.ScopedName = {moduleName:"common.config.log", name:"LogLevel"}; + +export function texprLogLevel(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snLogLevel},parameters:[]}}; +} + +export interface StdoutConfig { + level: LogLevel; +} + +export function makeStdoutConfig( + input: { + level: LogLevel, + } +): StdoutConfig { + return { + level: input.level, + }; +} + +const StdoutConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.log","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"level","default":{"kind":"nothing"},"name":"level","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.log","name":"LogLevel"}},"parameters":[]}}]}},"name":"StdoutConfig","version":{"kind":"nothing"}}}; + +export const snStdoutConfig: ADL.ScopedName = {moduleName:"common.config.log", name:"StdoutConfig"}; + +export function texprStdoutConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snStdoutConfig},parameters:[]}}; +} + +export interface FluentdConfig { + level: LogLevel; + hostname: string; + port: number; + tag: string; +} + +export function makeFluentdConfig( + input: { + level: LogLevel, + hostname: string, + port: number, + tag: string, + } +): FluentdConfig { + return { + level: input.level, + hostname: input.hostname, + port: input.port, + tag: input.tag, + }; +} + +const FluentdConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.log","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"level","default":{"kind":"nothing"},"name":"level","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.log","name":"LogLevel"}},"parameters":[]}},{"annotations":[],"serializedName":"hostname","default":{"kind":"nothing"},"name":"hostname","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"port","default":{"kind":"nothing"},"name":"port","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}},{"annotations":[],"serializedName":"tag","default":{"kind":"nothing"},"name":"tag","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"FluentdConfig","version":{"kind":"nothing"}}}; + +export const snFluentdConfig: ADL.ScopedName = {moduleName:"common.config.log", name:"FluentdConfig"}; + +export function texprFluentdConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFluentdConfig},parameters:[]}}; +} + +/** + * Server side Rollbar config + * NOTE: Name is `ServerRollbarConfig` due to being named prior to adding + * `ClientRollbarConfig` + */ +export interface RollbarConfig { + level: LogLevel; + serverToken: string; + env: string; +} + +export function makeRollbarConfig( + input: { + level: LogLevel, + serverToken: string, + env?: string, + } +): RollbarConfig { + return { + level: input.level, + serverToken: input.serverToken, + env: input.env === undefined ? "" : input.env, + }; +} + +const RollbarConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.log","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"level","default":{"kind":"nothing"},"name":"level","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.log","name":"LogLevel"}},"parameters":[]}},{"annotations":[],"serializedName":"serverToken","default":{"kind":"nothing"},"name":"serverToken","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"env","default":{"kind":"just","value":""},"name":"env","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"RollbarConfig","version":{"kind":"nothing"}}}; + +export const snRollbarConfig: ADL.ScopedName = {moduleName:"common.config.log", name:"RollbarConfig"}; + +export function texprRollbarConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snRollbarConfig},parameters:[]}}; +} + +/** + * Server side logging, i.e. reporting errors originating from the server + * NOTE: Name is not `ServerLogConfig` due to being named prior to adding + * `ClientLogConfig` + */ +export interface LogConfig { + stdout: (StdoutConfig|null); + fluentd: (FluentdConfig|null); + rollbar: (RollbarConfig|null); + cloudwatch: (CloudWatchMetricLogConfig|null); +} + +export function makeLogConfig( + input: { + stdout?: (StdoutConfig|null), + fluentd?: (FluentdConfig|null), + rollbar?: (RollbarConfig|null), + cloudwatch?: (CloudWatchMetricLogConfig|null), + } +): LogConfig { + return { + stdout: input.stdout === undefined ? {level : "INFO"} : input.stdout, + fluentd: input.fluentd === undefined ? null : input.fluentd, + rollbar: input.rollbar === undefined ? null : input.rollbar, + cloudwatch: input.cloudwatch === undefined ? null : input.cloudwatch, + }; +} + +const LogConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.log","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"stdout","default":{"kind":"just","value":{"level":"INFO"}},"name":"stdout","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.log","name":"StdoutConfig"}},"parameters":[]}]}},{"annotations":[],"serializedName":"fluentd","default":{"kind":"just","value":null},"name":"fluentd","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.log","name":"FluentdConfig"}},"parameters":[]}]}},{"annotations":[],"serializedName":"rollbar","default":{"kind":"just","value":null},"name":"rollbar","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.log","name":"RollbarConfig"}},"parameters":[]}]}},{"annotations":[],"serializedName":"cloudwatch","default":{"kind":"just","value":null},"name":"cloudwatch","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.log","name":"CloudWatchMetricLogConfig"}},"parameters":[]}]}}]}},"name":"LogConfig","version":{"kind":"nothing"}}}; + +export const snLogConfig: ADL.ScopedName = {moduleName:"common.config.log", name:"LogConfig"}; + +export function texprLogConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snLogConfig},parameters:[]}}; +} + +/** + * Client side Rollbar config, i.e. from Rollbar JS + */ +export interface ClientRollbarConfig { + accessToken: string; + env: string; +} + +export function makeClientRollbarConfig( + input: { + accessToken: string, + env?: string, + } +): ClientRollbarConfig { + return { + accessToken: input.accessToken, + env: input.env === undefined ? "" : input.env, + }; +} + +const ClientRollbarConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.log","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"accessToken","default":{"kind":"nothing"},"name":"accessToken","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"env","default":{"kind":"just","value":""},"name":"env","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"ClientRollbarConfig","version":{"kind":"nothing"}}}; + +export const snClientRollbarConfig: ADL.ScopedName = {moduleName:"common.config.log", name:"ClientRollbarConfig"}; + +export function texprClientRollbarConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snClientRollbarConfig},parameters:[]}}; +} + +/** + * Client side logging, i.e. reporting errors originating from the client + */ +export interface ClientLogConfig { + rollbar: (ClientRollbarConfig|null); +} + +export function makeClientLogConfig( + input: { + rollbar?: (ClientRollbarConfig|null), + } +): ClientLogConfig { + return { + rollbar: input.rollbar === undefined ? null : input.rollbar, + }; +} + +const ClientLogConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.log","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"rollbar","default":{"kind":"just","value":null},"name":"rollbar","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.log","name":"ClientRollbarConfig"}},"parameters":[]}]}}]}},"name":"ClientLogConfig","version":{"kind":"nothing"}}}; + +export const snClientLogConfig: ADL.ScopedName = {moduleName:"common.config.log", name:"ClientLogConfig"}; + +export function texprClientLogConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snClientLogConfig},parameters:[]}}; +} + +/** + * Logging of metrics to cloudwatch + */ +export interface CloudWatchMetricLogConfig { + credentials: common_config_aws.AwsCredentialsProvider; + region: common_config_aws.AwsRegionProvider; + env: string; + namespace: string; +/** + * A whitelist of metrics that should be sent to CloudWatch. Users should be + * aware that making this list too big can quickly cause costs to increase + */ + metricsToSend: string[]; +} + +export function makeCloudWatchMetricLogConfig( + input: { + credentials: common_config_aws.AwsCredentialsProvider, + region: common_config_aws.AwsRegionProvider, + env: string, + namespace: string, + metricsToSend: string[], + } +): CloudWatchMetricLogConfig { + return { + credentials: input.credentials, + region: input.region, + env: input.env, + namespace: input.namespace, + metricsToSend: input.metricsToSend, + }; +} + +const CloudWatchMetricLogConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.log","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"credentials","default":{"kind":"nothing"},"name":"credentials","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.aws","name":"AwsCredentialsProvider"}},"parameters":[]}},{"annotations":[],"serializedName":"region","default":{"kind":"nothing"},"name":"region","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.aws","name":"AwsRegionProvider"}},"parameters":[]}},{"annotations":[],"serializedName":"env","default":{"kind":"nothing"},"name":"env","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"namespace","default":{"kind":"nothing"},"name":"namespace","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"metricsToSend","default":{"kind":"nothing"},"name":"metricsToSend","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}}]}},"name":"CloudWatchMetricLogConfig","version":{"kind":"nothing"}}}; + +export const snCloudWatchMetricLogConfig: ADL.ScopedName = {moduleName:"common.config.log", name:"CloudWatchMetricLogConfig"}; + +export function texprCloudWatchMetricLogConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snCloudWatchMetricLogConfig},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.config.log.LogLevel" : LogLevel_AST, + "common.config.log.StdoutConfig" : StdoutConfig_AST, + "common.config.log.FluentdConfig" : FluentdConfig_AST, + "common.config.log.RollbarConfig" : RollbarConfig_AST, + "common.config.log.LogConfig" : LogConfig_AST, + "common.config.log.ClientRollbarConfig" : ClientRollbarConfig_AST, + "common.config.log.ClientLogConfig" : ClientLogConfig_AST, + "common.config.log.CloudWatchMetricLogConfig" : CloudWatchMetricLogConfig_AST +}; diff --git a/typescript/workspace/generated/common/config/okta.ts b/typescript/workspace/generated/common/config/okta.ts new file mode 100644 index 00000000..523d6e81 --- /dev/null +++ b/typescript/workspace/generated/common/config/okta.ts @@ -0,0 +1,69 @@ +import * as ADL from "@adl-lang/runtime/adl"; +import * as sys_types from "@adl-lang/sys/types"; + +/* @generated from adl module common.config.okta */ + +/** + * Config parameters for setting up open ID authentication using Okta + */ +export interface OktaConfig { +/** + * ID of the client application + */ + clientId: string; +/** + * Secret of the client application + */ + clientSecret: string; +/** + * Hostname of the okta instance + */ + clientHost: string; +/** + * Endpoint which users should be redirected to to complete authorization + */ + authorizeEndpoint: string; +/** + * The URL supplied to okta to redirect the user to after authorization is + * complete + */ + redirectUrl: string; +/** + * API key used for performing actions in okta, not required if the app does + * not use this functionality + */ + apiKey: sys_types.Maybe; +} + +export function makeOktaConfig( + input: { + clientId: string, + clientSecret: string, + clientHost: string, + authorizeEndpoint: string, + redirectUrl: string, + apiKey: sys_types.Maybe, + } +): OktaConfig { + return { + clientId: input.clientId, + clientSecret: input.clientSecret, + clientHost: input.clientHost, + authorizeEndpoint: input.authorizeEndpoint, + redirectUrl: input.redirectUrl, + apiKey: input.apiKey, + }; +} + +const OktaConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.okta","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"clientId","default":{"kind":"nothing"},"name":"clientId","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"clientSecret","default":{"kind":"nothing"},"name":"clientSecret","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"clientHost","default":{"kind":"nothing"},"name":"clientHost","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"authorizeEndpoint","default":{"kind":"nothing"},"name":"authorizeEndpoint","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"redirectUrl","default":{"kind":"nothing"},"name":"redirectUrl","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"apiKey","default":{"kind":"nothing"},"name":"apiKey","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.types","name":"Maybe"}},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}}]}},"name":"OktaConfig","version":{"kind":"nothing"}}}; + +export const snOktaConfig: ADL.ScopedName = {moduleName:"common.config.okta", name:"OktaConfig"}; + +export function texprOktaConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snOktaConfig},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.config.okta.OktaConfig" : OktaConfig_AST +}; diff --git a/typescript/workspace/generated/common/config/sms.ts b/typescript/workspace/generated/common/config/sms.ts new file mode 100644 index 00000000..b8498d56 --- /dev/null +++ b/typescript/workspace/generated/common/config/sms.ts @@ -0,0 +1,112 @@ +import * as common_strings from "./../strings"; +import * as common_config_aws from "./aws"; +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common.config.sms */ + +export interface SmsConfig_Fake { + kind: 'fake'; +} +export interface SmsConfig_Twilio { + kind: 'twilio'; + value: TwilioConfig; +} +export interface SmsConfig_Sns { + kind: 'sns'; + value: AwsSnsConfig; +} + +/** + * Configuration for the sms provider used + */ +export type SmsConfig = SmsConfig_Fake | SmsConfig_Twilio | SmsConfig_Sns; + +export interface SmsConfigOpts { + /** + * Fake sms, just prints outgoing message info to stdout + */ +fake: null; + /** + * Twilio implementation + */ +twilio: TwilioConfig; + /** + * AWS SNS implementation + */ +sns: AwsSnsConfig; +} + +export function makeSmsConfig(kind: K, value: SmsConfigOpts[K]) { return {kind, value}; } + +const SmsConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.sms","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"fake","default":{"kind":"nothing"},"name":"fake","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"twilio","default":{"kind":"nothing"},"name":"twilio","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.sms","name":"TwilioConfig"}},"parameters":[]}},{"annotations":[],"serializedName":"sns","default":{"kind":"nothing"},"name":"sns","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.sms","name":"AwsSnsConfig"}},"parameters":[]}}]}},"name":"SmsConfig","version":{"kind":"nothing"}}}; + +export const snSmsConfig: ADL.ScopedName = {moduleName:"common.config.sms", name:"SmsConfig"}; + +export function texprSmsConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snSmsConfig},parameters:[]}}; +} + +/** + * Configuration for twilio + */ +export interface TwilioConfig { + accountSid: common_strings.StringNE; + authToken: common_strings.StringNE; +} + +export function makeTwilioConfig( + input: { + accountSid: common_strings.StringNE, + authToken: common_strings.StringNE, + } +): TwilioConfig { + return { + accountSid: input.accountSid, + authToken: input.authToken, + }; +} + +const TwilioConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.sms","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"accountSid","default":{"kind":"nothing"},"name":"accountSid","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.strings","name":"StringNE"}},"parameters":[]}},{"annotations":[],"serializedName":"authToken","default":{"kind":"nothing"},"name":"authToken","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.strings","name":"StringNE"}},"parameters":[]}}]}},"name":"TwilioConfig","version":{"kind":"nothing"}}}; + +export const snTwilioConfig: ADL.ScopedName = {moduleName:"common.config.sms", name:"TwilioConfig"}; + +export function texprTwilioConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snTwilioConfig},parameters:[]}}; +} + +/** + * Configuration for AWS SMS implementation + */ +export interface AwsSnsConfig { + credentials: common_config_aws.AwsCredentialsProvider; + region: common_config_aws.AwsRegionProvider; +} + +export function makeAwsSnsConfig( + input: { + credentials: common_config_aws.AwsCredentialsProvider, + region: common_config_aws.AwsRegionProvider, + } +): AwsSnsConfig { + return { + credentials: input.credentials, + region: input.region, + }; +} + +const AwsSnsConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.sms","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"credentials","default":{"kind":"nothing"},"name":"credentials","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.aws","name":"AwsCredentialsProvider"}},"parameters":[]}},{"annotations":[],"serializedName":"region","default":{"kind":"nothing"},"name":"region","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.aws","name":"AwsRegionProvider"}},"parameters":[]}}]}},"name":"AwsSnsConfig","version":{"kind":"nothing"}}}; + +export const snAwsSnsConfig: ADL.ScopedName = {moduleName:"common.config.sms", name:"AwsSnsConfig"}; + +export function texprAwsSnsConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snAwsSnsConfig},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.config.sms.SmsConfig" : SmsConfig_AST, + "common.config.sms.TwilioConfig" : TwilioConfig_AST, + "common.config.sms.AwsSnsConfig" : AwsSnsConfig_AST +}; diff --git a/typescript/workspace/generated/common/config/storage.ts b/typescript/workspace/generated/common/config/storage.ts new file mode 100644 index 00000000..2c185cd1 --- /dev/null +++ b/typescript/workspace/generated/common/config/storage.ts @@ -0,0 +1,90 @@ +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common.config.storage */ + +export interface LocalBlobstoreConfig { +/** + * The directory in which the blobstore files will be stored + */ + directory: string; +/** + * The host of the server to be used for serving public files, e.g. "http://localhost" + */ + publicHost: string; +/** + * The path on which blobstore objects are publically accessible e.g. "/files" + */ + publicPath: string; +} + +export function makeLocalBlobstoreConfig( + input: { + directory: string, + publicHost: string, + publicPath: string, + } +): LocalBlobstoreConfig { + return { + directory: input.directory, + publicHost: input.publicHost, + publicPath: input.publicPath, + }; +} + +const LocalBlobstoreConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.storage","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"directory","default":{"kind":"nothing"},"name":"directory","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"publicHost","default":{"kind":"nothing"},"name":"publicHost","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"publicPath","default":{"kind":"nothing"},"name":"publicPath","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"LocalBlobstoreConfig","version":{"kind":"nothing"}}}; + +export const snLocalBlobstoreConfig: ADL.ScopedName = {moduleName:"common.config.storage", name:"LocalBlobstoreConfig"}; + +export function texprLocalBlobstoreConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snLocalBlobstoreConfig},parameters:[]}}; +} + +export interface LocalFileStoreConfig { +/** + * The directory in which the blobstore files will be stored + */ + directory: string; +/** + * The host of the server to be used for serving public files, e.g. "http://localhost" + */ + publicHost: string; +/** + * The path on which blobstore objects are publically accessible e.g. "/files" + */ + publicPath: string; +/** + * False if the data in the FileStore is to be immutable + */ + allowOverwrite: boolean; +} + +export function makeLocalFileStoreConfig( + input: { + directory: string, + publicHost: string, + publicPath: string, + allowOverwrite: boolean, + } +): LocalFileStoreConfig { + return { + directory: input.directory, + publicHost: input.publicHost, + publicPath: input.publicPath, + allowOverwrite: input.allowOverwrite, + }; +} + +const LocalFileStoreConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.config.storage","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"directory","default":{"kind":"nothing"},"name":"directory","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"publicHost","default":{"kind":"nothing"},"name":"publicHost","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"publicPath","default":{"kind":"nothing"},"name":"publicPath","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"allowOverwrite","default":{"kind":"nothing"},"name":"allowOverwrite","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}}]}},"name":"LocalFileStoreConfig","version":{"kind":"nothing"}}}; + +export const snLocalFileStoreConfig: ADL.ScopedName = {moduleName:"common.config.storage", name:"LocalFileStoreConfig"}; + +export function texprLocalFileStoreConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snLocalFileStoreConfig},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.config.storage.LocalBlobstoreConfig" : LocalBlobstoreConfig_AST, + "common.config.storage.LocalFileStoreConfig" : LocalFileStoreConfig_AST +}; diff --git a/typescript/workspace/generated/common/db.ts b/typescript/workspace/generated/common/db.ts new file mode 100644 index 00000000..9372a6f6 --- /dev/null +++ b/typescript/workspace/generated/common/db.ts @@ -0,0 +1,173 @@ +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common.db */ + +export interface DbTable { + tableName: string; + withIdPrimaryKey: boolean; + withPrimaryKey: string[]; + indexes: string[][]; + uniquenessConstraints: string[][]; + extraSql: string[]; + label: string[]; +} + +export function makeDbTable( + input: { + tableName?: string, + withIdPrimaryKey?: boolean, + withPrimaryKey?: string[], + indexes?: string[][], + uniquenessConstraints?: string[][], + extraSql?: string[], + label?: string[], + } +): DbTable { + return { + tableName: input.tableName === undefined ? "" : input.tableName, + withIdPrimaryKey: input.withIdPrimaryKey === undefined ? false : input.withIdPrimaryKey, + withPrimaryKey: input.withPrimaryKey === undefined ? [] : input.withPrimaryKey, + indexes: input.indexes === undefined ? [] : input.indexes, + uniquenessConstraints: input.uniquenessConstraints === undefined ? [] : input.uniquenessConstraints, + extraSql: input.extraSql === undefined ? [] : input.extraSql, + label: input.label === undefined ? [] : input.label, + }; +} + +const DbTable_AST : ADL.ScopedDecl = + {"moduleName":"common.db","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"tableName","default":{"kind":"just","value":""},"name":"tableName","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"withIdPrimaryKey","default":{"kind":"just","value":false},"name":"withIdPrimaryKey","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"withPrimaryKey","default":{"kind":"just","value":[]},"name":"withPrimaryKey","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}},{"annotations":[],"serializedName":"indexes","default":{"kind":"just","value":[]},"name":"indexes","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}]}},{"annotations":[],"serializedName":"uniquenessConstraints","default":{"kind":"just","value":[]},"name":"uniquenessConstraints","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}]}},{"annotations":[],"serializedName":"extraSql","default":{"kind":"just","value":[]},"name":"extraSql","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}},{"annotations":[],"serializedName":"label","default":{"kind":"just","value":[]},"name":"label","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}}]}},"name":"DbTable","version":{"kind":"nothing"}}}; + +export const snDbTable: ADL.ScopedName = {moduleName:"common.db", name:"DbTable"}; + +export function texprDbTable(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDbTable},parameters:[]}}; +} + +export interface DbView { + viewName: string; + withIdPrimaryKey: boolean; + viewSql: string[]; +} + +export function makeDbView( + input: { + viewName?: string, + withIdPrimaryKey?: boolean, + viewSql?: string[], + } +): DbView { + return { + viewName: input.viewName === undefined ? "" : input.viewName, + withIdPrimaryKey: input.withIdPrimaryKey === undefined ? false : input.withIdPrimaryKey, + viewSql: input.viewSql === undefined ? [] : input.viewSql, + }; +} + +const DbView_AST : ADL.ScopedDecl = + {"moduleName":"common.db","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"viewName","default":{"kind":"just","value":""},"name":"viewName","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"withIdPrimaryKey","default":{"kind":"just","value":false},"name":"withIdPrimaryKey","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"viewSql","default":{"kind":"just","value":[]},"name":"viewSql","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}}]}},"name":"DbView","version":{"kind":"nothing"}}}; + +export const snDbView: ADL.ScopedName = {moduleName:"common.db", name:"DbView"}; + +export function texprDbView(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDbView},parameters:[]}}; +} + +/** + * Field level annotation to override the name of the + * database column. + */ +export type DbColumnName = string; + +const DbColumnName_AST : ADL.ScopedDecl = + {"moduleName":"common.db","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"DbColumnName","version":{"kind":"nothing"}}}; + +export const snDbColumnName: ADL.ScopedName = {moduleName:"common.db", name:"DbColumnName"}; + +export function texprDbColumnName(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDbColumnName},parameters:[]}}; +} + +/** + * Field or type level annotation to override the type of the + * database column. + */ +export type DbColumnType = string; + +const DbColumnType_AST : ADL.ScopedDecl = + {"moduleName":"common.db","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"DbColumnType","version":{"kind":"nothing"}}}; + +export const snDbColumnType: ADL.ScopedName = {moduleName:"common.db", name:"DbColumnType"}; + +export function texprDbColumnType(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDbColumnType},parameters:[]}}; +} + +/** + * Field level annotation to indicate that a column value + * is generated, and hence need not be requested from or edited + * by a user. + */ +export type DbColumnGenerated = null; + +const DbColumnGenerated_AST : ADL.ScopedDecl = + {"moduleName":"common.db","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}}},"name":"DbColumnGenerated","version":{"kind":"nothing"}}}; + +export const snDbColumnGenerated: ADL.ScopedName = {moduleName:"common.db", name:"DbColumnGenerated"}; + +export function texprDbColumnGenerated(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDbColumnGenerated},parameters:[]}}; +} + +/** + * A reference for a database stored value, referenced by a + * string primary key. + */ +export type DbKey<_T> = string; + +const DbKey_AST : ADL.ScopedDecl = + {"moduleName":"common.db","decl":{"annotations":[],"type_":{"kind":"newtype_","value":{"typeParams":["T"],"default":{"kind":"nothing"},"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"DbKey","version":{"kind":"nothing"}}}; + +export const snDbKey: ADL.ScopedName = {moduleName:"common.db", name:"DbKey"}; + +export function texprDbKey(texprT : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snDbKey},parameters:[texprT.value]}}; +} + +/** + * A value of type T along with a unique db identifier + */ +export interface WithDbId { + id: DbKey; + value: T; +} + +export function makeWithDbId( + input: { + id: DbKey, + value: T, + } +): WithDbId { + return { + id: input.id, + value: input.value, + }; +} + +const WithDbId_AST : ADL.ScopedDecl = + {"moduleName":"common.db","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["T"],"fields":[{"annotations":[],"serializedName":"id","default":{"kind":"nothing"},"name":"id","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.db","name":"DbKey"}},"parameters":[{"typeRef":{"kind":"typeParam","value":"T"},"parameters":[]}]}},{"annotations":[],"serializedName":"value","default":{"kind":"nothing"},"name":"value","typeExpr":{"typeRef":{"kind":"typeParam","value":"T"},"parameters":[]}}]}},"name":"WithDbId","version":{"kind":"nothing"}}}; + +export const snWithDbId: ADL.ScopedName = {moduleName:"common.db", name:"WithDbId"}; + +export function texprWithDbId(texprT : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snWithDbId},parameters:[texprT.value]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.db.DbTable" : DbTable_AST, + "common.db.DbView" : DbView_AST, + "common.db.DbColumnName" : DbColumnName_AST, + "common.db.DbColumnType" : DbColumnType_AST, + "common.db.DbColumnGenerated" : DbColumnGenerated_AST, + "common.db.DbKey" : DbKey_AST, + "common.db.WithDbId" : WithDbId_AST +}; diff --git a/typescript/workspace/generated/common/flyway/api.ts b/typescript/workspace/generated/common/flyway/api.ts new file mode 100644 index 00000000..059af413 --- /dev/null +++ b/typescript/workspace/generated/common/flyway/api.ts @@ -0,0 +1,419 @@ +import * as common_http from "./../http"; +import * as common_flyway_internals from "./internals"; +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common.flyway.api */ + +export type FlywayApi = common_http.HttpPost; + +const FlywayApi_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.api","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.api","name":"FlywayReq"}},"parameters":[]},{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.api","name":"FlywayResp"}},"parameters":[]}]}}},"name":"FlywayApi","version":{"kind":"nothing"}}}; + +export const snFlywayApi: ADL.ScopedName = {moduleName:"common.flyway.api", name:"FlywayApi"}; + +export function texprFlywayApi(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFlywayApi},parameters:[]}}; +} + +export interface FlywayReq_Plan { + kind: 'plan'; +} +export interface FlywayReq_Apply { + kind: 'apply'; +} +export interface FlywayReq_Advanced { + kind: 'advanced'; + value: AdvancedFlywayReq; +} + +export type FlywayReq = FlywayReq_Plan | FlywayReq_Apply | FlywayReq_Advanced; + +export interface FlywayReqOpts { + /** + * Show pending migrations + */ +plan: null; + /** + * Apply pending migrations + */ +apply: null; + /** + * Something customized + */ +advanced: AdvancedFlywayReq; +} + +export function makeFlywayReq(kind: K, value: FlywayReqOpts[K]) { return {kind, value}; } + +const FlywayReq_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.api","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"plan","default":{"kind":"nothing"},"name":"plan","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"apply","default":{"kind":"nothing"},"name":"apply","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"advanced","default":{"kind":"nothing"},"name":"advanced","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.api","name":"AdvancedFlywayReq"}},"parameters":[]}}]}},"name":"FlywayReq","version":{"kind":"nothing"}}}; + +export const snFlywayReq: ADL.ScopedName = {moduleName:"common.flyway.api", name:"FlywayReq"}; + +export function texprFlywayReq(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFlywayReq},parameters:[]}}; +} + +/** + * Information passed when access via API + */ +export interface AdvancedFlywayReq { + context: FlywayReqContextOpt; + action: common_flyway_internals.FlywayAction; +} + +export function makeAdvancedFlywayReq( + input: { + context?: FlywayReqContextOpt, + action: common_flyway_internals.FlywayAction, + } +): AdvancedFlywayReq { + return { + context: input.context === undefined ? {kind : "application"} : input.context, + action: input.action, + }; +} + +const AdvancedFlywayReq_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"context","default":{"kind":"just","value":"application"},"name":"context","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.api","name":"FlywayReqContextOpt"}},"parameters":[]}},{"annotations":[],"serializedName":"action","default":{"kind":"nothing"},"name":"action","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.internals","name":"FlywayAction"}},"parameters":[]}}]}},"name":"AdvancedFlywayReq","version":{"kind":"nothing"}}}; + +export const snAdvancedFlywayReq: ADL.ScopedName = {moduleName:"common.flyway.api", name:"AdvancedFlywayReq"}; + +export function texprAdvancedFlywayReq(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snAdvancedFlywayReq},parameters:[]}}; +} + +export interface FlywayReqContextOpt_Application { + kind: 'application'; +} +export interface FlywayReqContextOpt_Bootstrap { + kind: 'bootstrap'; +} +export interface FlywayReqContextOpt_CustomCtx { + kind: 'customCtx'; + value: common_flyway_internals.FlywayContext; +} + +export type FlywayReqContextOpt = FlywayReqContextOpt_Application | FlywayReqContextOpt_Bootstrap | FlywayReqContextOpt_CustomCtx; + +export interface FlywayReqContextOptOpts { + /** + * Derive the context from the app config + * Throw exception if it app is not configured with a flyway context + */ +application: null; + /** + * The first ctx in bootstrapable->bootstrap. + * Throw exception if it doesn't exist + */ +bootstrap: null; + /** + * Overide the application flyway config + */ +customCtx: common_flyway_internals.FlywayContext; +} + +export function makeFlywayReqContextOpt(kind: K, value: FlywayReqContextOptOpts[K]) { return {kind, value}; } + +const FlywayReqContextOpt_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.api","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"application","default":{"kind":"nothing"},"name":"application","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"bootstrap","default":{"kind":"nothing"},"name":"bootstrap","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"customCtx","default":{"kind":"nothing"},"name":"customCtx","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.internals","name":"FlywayContext"}},"parameters":[]}}]}},"name":"FlywayReqContextOpt","version":{"kind":"nothing"}}}; + +export const snFlywayReqContextOpt: ADL.ScopedName = {moduleName:"common.flyway.api", name:"FlywayReqContextOpt"}; + +export function texprFlywayReqContextOpt(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFlywayReqContextOpt},parameters:[]}}; +} + +export interface FlywayResp_Error { + kind: 'error'; + value: string; +} +export interface FlywayResp_Msg { + kind: 'msg'; + value: string; +} +export interface FlywayResp_Clean { + kind: 'clean'; + value: FlywayCleanResult; +} +export interface FlywayResp_Info { + kind: 'info'; + value: FlywayInfo; +} +export interface FlywayResp_MigrationResult { + kind: 'migrationResult'; + value: FlywayMigrateResult; +} +export interface FlywayResp_BaselineResult { + kind: 'baselineResult'; + value: FlywayBaselineResult; +} +export interface FlywayResp_Sequence { + kind: 'sequence'; + value: FlywayResp[]; +} + +export type FlywayResp = FlywayResp_Error | FlywayResp_Msg | FlywayResp_Clean | FlywayResp_Info | FlywayResp_MigrationResult | FlywayResp_BaselineResult | FlywayResp_Sequence; + +export interface FlywayRespOpts { + error: string; + msg: string; + clean: FlywayCleanResult; + info: FlywayInfo; + migrationResult: FlywayMigrateResult; + baselineResult: FlywayBaselineResult; + sequence: FlywayResp[]; +} + +export function makeFlywayResp(kind: K, value: FlywayRespOpts[K]) { return {kind, value}; } + +const FlywayResp_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.api","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"error","default":{"kind":"nothing"},"name":"error","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"msg","default":{"kind":"nothing"},"name":"msg","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"clean","default":{"kind":"nothing"},"name":"clean","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.api","name":"FlywayCleanResult"}},"parameters":[]}},{"annotations":[],"serializedName":"info","default":{"kind":"nothing"},"name":"info","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.api","name":"FlywayInfo"}},"parameters":[]}},{"annotations":[],"serializedName":"migrationResult","default":{"kind":"nothing"},"name":"migrationResult","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.api","name":"FlywayMigrateResult"}},"parameters":[]}},{"annotations":[],"serializedName":"baselineResult","default":{"kind":"nothing"},"name":"baselineResult","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.api","name":"FlywayBaselineResult"}},"parameters":[]}},{"annotations":[],"serializedName":"sequence","default":{"kind":"nothing"},"name":"sequence","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.api","name":"FlywayResp"}},"parameters":[]}]}}]}},"name":"FlywayResp","version":{"kind":"nothing"}}}; + +export const snFlywayResp: ADL.ScopedName = {moduleName:"common.flyway.api", name:"FlywayResp"}; + +export function texprFlywayResp(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFlywayResp},parameters:[]}}; +} + +export interface FlywayInfo { + schemaVersion: string; + migrations: FlywayMigrationInfo[]; +} + +export function makeFlywayInfo( + input: { + schemaVersion: string, + migrations: FlywayMigrationInfo[], + } +): FlywayInfo { + return { + schemaVersion: input.schemaVersion, + migrations: input.migrations, + }; +} + +const FlywayInfo_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"schemaVersion","default":{"kind":"nothing"},"name":"schemaVersion","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"migrations","default":{"kind":"nothing"},"name":"migrations","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.api","name":"FlywayMigrationInfo"}},"parameters":[]}]}}]}},"name":"FlywayInfo","version":{"kind":"nothing"}}}; + +export const snFlywayInfo: ADL.ScopedName = {moduleName:"common.flyway.api", name:"FlywayInfo"}; + +export function texprFlywayInfo(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFlywayInfo},parameters:[]}}; +} + +export interface FlywayMigrationInfo { + category: string; + version: string; + description: string; + type_: string; + installed_on: string; + state: string; +} + +export function makeFlywayMigrationInfo( + input: { + category: string, + version: string, + description: string, + type_: string, + installed_on: string, + state: string, + } +): FlywayMigrationInfo { + return { + category: input.category, + version: input.version, + description: input.description, + type_: input.type_, + installed_on: input.installed_on, + state: input.state, + }; +} + +const FlywayMigrationInfo_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"category","default":{"kind":"nothing"},"name":"category","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"version","default":{"kind":"nothing"},"name":"version","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"description","default":{"kind":"nothing"},"name":"description","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"type_","default":{"kind":"nothing"},"name":"type_","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"installed_on","default":{"kind":"nothing"},"name":"installed_on","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"state","default":{"kind":"nothing"},"name":"state","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"FlywayMigrationInfo","version":{"kind":"nothing"}}}; + +export const snFlywayMigrationInfo: ADL.ScopedName = {moduleName:"common.flyway.api", name:"FlywayMigrationInfo"}; + +export function texprFlywayMigrationInfo(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFlywayMigrationInfo},parameters:[]}}; +} + +export interface FlywayMigrateResult { + message: string; + flywayVersion: string; + database: string; + warnings: string[]; + operation: string; + initialSchemaVersion: (string|null); + targetSchemaVersion: (string|null); + schemaName: (string|null); + migrations: FlywayMigrateOutput[]; + migrationsExecuted: (number|null); +} + +export function makeFlywayMigrateResult( + input: { + message: string, + flywayVersion: string, + database: string, + warnings: string[], + operation: string, + initialSchemaVersion: (string|null), + targetSchemaVersion: (string|null), + schemaName: (string|null), + migrations: FlywayMigrateOutput[], + migrationsExecuted: (number|null), + } +): FlywayMigrateResult { + return { + message: input.message, + flywayVersion: input.flywayVersion, + database: input.database, + warnings: input.warnings, + operation: input.operation, + initialSchemaVersion: input.initialSchemaVersion, + targetSchemaVersion: input.targetSchemaVersion, + schemaName: input.schemaName, + migrations: input.migrations, + migrationsExecuted: input.migrationsExecuted, + }; +} + +const FlywayMigrateResult_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"message","default":{"kind":"nothing"},"name":"message","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"flywayVersion","default":{"kind":"nothing"},"name":"flywayVersion","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"database","default":{"kind":"nothing"},"name":"database","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"warnings","default":{"kind":"nothing"},"name":"warnings","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}},{"annotations":[],"serializedName":"operation","default":{"kind":"nothing"},"name":"operation","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"initialSchemaVersion","default":{"kind":"nothing"},"name":"initialSchemaVersion","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}},{"annotations":[],"serializedName":"targetSchemaVersion","default":{"kind":"nothing"},"name":"targetSchemaVersion","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}},{"annotations":[],"serializedName":"schemaName","default":{"kind":"nothing"},"name":"schemaName","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}},{"annotations":[],"serializedName":"migrations","default":{"kind":"nothing"},"name":"migrations","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.api","name":"FlywayMigrateOutput"}},"parameters":[]}]}},{"annotations":[],"serializedName":"migrationsExecuted","default":{"kind":"nothing"},"name":"migrationsExecuted","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}]}}]}},"name":"FlywayMigrateResult","version":{"kind":"nothing"}}}; + +export const snFlywayMigrateResult: ADL.ScopedName = {moduleName:"common.flyway.api", name:"FlywayMigrateResult"}; + +export function texprFlywayMigrateResult(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFlywayMigrateResult},parameters:[]}}; +} + +export interface FlywayBaselineResult { + flywayVersion: string; + database: string; + warnings: string[]; + operation: string; + successfullyBaselined: boolean; + baselineVersion: (string|null); +} + +export function makeFlywayBaselineResult( + input: { + flywayVersion: string, + database: string, + warnings: string[], + operation: string, + successfullyBaselined: boolean, + baselineVersion: (string|null), + } +): FlywayBaselineResult { + return { + flywayVersion: input.flywayVersion, + database: input.database, + warnings: input.warnings, + operation: input.operation, + successfullyBaselined: input.successfullyBaselined, + baselineVersion: input.baselineVersion, + }; +} + +const FlywayBaselineResult_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"flywayVersion","default":{"kind":"nothing"},"name":"flywayVersion","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"database","default":{"kind":"nothing"},"name":"database","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"warnings","default":{"kind":"nothing"},"name":"warnings","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}},{"annotations":[],"serializedName":"operation","default":{"kind":"nothing"},"name":"operation","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"successfullyBaselined","default":{"kind":"nothing"},"name":"successfullyBaselined","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"baselineVersion","default":{"kind":"nothing"},"name":"baselineVersion","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}}]}},"name":"FlywayBaselineResult","version":{"kind":"nothing"}}}; + +export const snFlywayBaselineResult: ADL.ScopedName = {moduleName:"common.flyway.api", name:"FlywayBaselineResult"}; + +export function texprFlywayBaselineResult(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFlywayBaselineResult},parameters:[]}}; +} + +export interface FlywayCleanResult { + flywayVersion: string; + database: string; + warnings: string[]; + operation: string; + schemasCleaned: string[]; + schemasDropped: string[]; +} + +export function makeFlywayCleanResult( + input: { + flywayVersion: string, + database: string, + warnings: string[], + operation: string, + schemasCleaned: string[], + schemasDropped: string[], + } +): FlywayCleanResult { + return { + flywayVersion: input.flywayVersion, + database: input.database, + warnings: input.warnings, + operation: input.operation, + schemasCleaned: input.schemasCleaned, + schemasDropped: input.schemasDropped, + }; +} + +const FlywayCleanResult_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"flywayVersion","default":{"kind":"nothing"},"name":"flywayVersion","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"database","default":{"kind":"nothing"},"name":"database","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"warnings","default":{"kind":"nothing"},"name":"warnings","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}},{"annotations":[],"serializedName":"operation","default":{"kind":"nothing"},"name":"operation","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"schemasCleaned","default":{"kind":"nothing"},"name":"schemasCleaned","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}},{"annotations":[],"serializedName":"schemasDropped","default":{"kind":"nothing"},"name":"schemasDropped","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}}]}},"name":"FlywayCleanResult","version":{"kind":"nothing"}}}; + +export const snFlywayCleanResult: ADL.ScopedName = {moduleName:"common.flyway.api", name:"FlywayCleanResult"}; + +export function texprFlywayCleanResult(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFlywayCleanResult},parameters:[]}}; +} + +export interface FlywayMigrateOutput { + category: string; + version: string; + description: string; + type_: string; + filepath: string; + executionTime: number; +} + +export function makeFlywayMigrateOutput( + input: { + category: string, + version: string, + description: string, + type_: string, + filepath: string, + executionTime: number, + } +): FlywayMigrateOutput { + return { + category: input.category, + version: input.version, + description: input.description, + type_: input.type_, + filepath: input.filepath, + executionTime: input.executionTime, + }; +} + +const FlywayMigrateOutput_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"category","default":{"kind":"nothing"},"name":"category","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"version","default":{"kind":"nothing"},"name":"version","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"description","default":{"kind":"nothing"},"name":"description","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"type_","default":{"kind":"nothing"},"name":"type_","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"filepath","default":{"kind":"nothing"},"name":"filepath","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"executionTime","default":{"kind":"nothing"},"name":"executionTime","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}}]}},"name":"FlywayMigrateOutput","version":{"kind":"nothing"}}}; + +export const snFlywayMigrateOutput: ADL.ScopedName = {moduleName:"common.flyway.api", name:"FlywayMigrateOutput"}; + +export function texprFlywayMigrateOutput(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFlywayMigrateOutput},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.flyway.api.FlywayApi" : FlywayApi_AST, + "common.flyway.api.FlywayReq" : FlywayReq_AST, + "common.flyway.api.AdvancedFlywayReq" : AdvancedFlywayReq_AST, + "common.flyway.api.FlywayReqContextOpt" : FlywayReqContextOpt_AST, + "common.flyway.api.FlywayResp" : FlywayResp_AST, + "common.flyway.api.FlywayInfo" : FlywayInfo_AST, + "common.flyway.api.FlywayMigrationInfo" : FlywayMigrationInfo_AST, + "common.flyway.api.FlywayMigrateResult" : FlywayMigrateResult_AST, + "common.flyway.api.FlywayBaselineResult" : FlywayBaselineResult_AST, + "common.flyway.api.FlywayCleanResult" : FlywayCleanResult_AST, + "common.flyway.api.FlywayMigrateOutput" : FlywayMigrateOutput_AST +}; diff --git a/typescript/workspace/generated/common/flyway/example_patterns.ts b/typescript/workspace/generated/common/flyway/example_patterns.ts new file mode 100644 index 00000000..796ff23a --- /dev/null +++ b/typescript/workspace/generated/common/flyway/example_patterns.ts @@ -0,0 +1,54 @@ +import * as common_flyway_internals from "./internals"; +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common.flyway.example_patterns */ + +export interface FlywayConfig_Mixed_mode_latest { + kind: 'mixed_mode_latest'; +} +export interface FlywayConfig_Mixed_mode_manual { + kind: 'mixed_mode_manual'; +} +export interface FlywayConfig_Migration_mode_latest { + kind: 'migration_mode_latest'; +} +export interface FlywayConfig_Advanced { + kind: 'advanced'; + value: common_flyway_internals.FlywayCommand; +} + +export type FlywayConfig = FlywayConfig_Mixed_mode_latest | FlywayConfig_Mixed_mode_manual | FlywayConfig_Migration_mode_latest | FlywayConfig_Advanced; + +export interface FlywayConfigOpts { + mixed_mode_latest: null; + mixed_mode_manual: null; + migration_mode_latest: null; + advanced: common_flyway_internals.FlywayCommand; +} + +export function makeFlywayConfig(kind: K, value: FlywayConfigOpts[K]) { return {kind, value}; } + +const FlywayConfig_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.example_patterns","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"mixed_mode_latest","default":{"kind":"nothing"},"name":"mixed_mode_latest","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"mixed_mode_manual","default":{"kind":"nothing"},"name":"mixed_mode_manual","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"migration_mode_latest","default":{"kind":"nothing"},"name":"migration_mode_latest","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"advanced","default":{"kind":"nothing"},"name":"advanced","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.internals","name":"FlywayCommand"}},"parameters":[]}}]}},"name":"FlywayConfig","version":{"kind":"nothing"}}}; + +export const snFlywayConfig: ADL.ScopedName = {moduleName:"common.flyway.example_patterns", name:"FlywayConfig"}; + +export function texprFlywayConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFlywayConfig},parameters:[]}}; +} + +export type ExampleFlywayCommand = {[key: string]: common_flyway_internals.FlywayCommand}; + +const ExampleFlywayCommand_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.example_patterns","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"StringMap"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.internals","name":"FlywayCommand"}},"parameters":[]}]}}},"name":"ExampleFlywayCommand","version":{"kind":"nothing"}}}; + +export const snExampleFlywayCommand: ADL.ScopedName = {moduleName:"common.flyway.example_patterns", name:"ExampleFlywayCommand"}; + +export function texprExampleFlywayCommand(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snExampleFlywayCommand},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.flyway.example_patterns.FlywayConfig" : FlywayConfig_AST, + "common.flyway.example_patterns.ExampleFlywayCommand" : ExampleFlywayCommand_AST +}; diff --git a/typescript/workspace/generated/common/flyway/index.ts b/typescript/workspace/generated/common/flyway/index.ts new file mode 100644 index 00000000..1c040f5c --- /dev/null +++ b/typescript/workspace/generated/common/flyway/index.ts @@ -0,0 +1,4 @@ +/* @generated - key "flyway" */ +export * as api from './api'; +export * as example_patterns from './example_patterns'; +export * as internals from './internals'; diff --git a/typescript/workspace/generated/common/flyway/internals.ts b/typescript/workspace/generated/common/flyway/internals.ts new file mode 100644 index 00000000..4d3f6eb7 --- /dev/null +++ b/typescript/workspace/generated/common/flyway/internals.ts @@ -0,0 +1,385 @@ +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common.flyway.internals */ + +export interface FlywayCommand { + ctx: FlywayContext; +/** + * The action to take on application startup + */ + bootstrap: FlywayAction[]; + action: (FlywayAction|null); +} + +export function makeFlywayCommand( + input: { + ctx: FlywayContext, + bootstrap?: FlywayAction[], + action: (FlywayAction|null), + } +): FlywayCommand { + return { + ctx: input.ctx, + bootstrap: input.bootstrap === undefined ? [] : input.bootstrap, + action: input.action, + }; +} + +const FlywayCommand_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.internals","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"ctx","default":{"kind":"nothing"},"name":"ctx","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.internals","name":"FlywayContext"}},"parameters":[]}},{"annotations":[],"serializedName":"bootstrap","default":{"kind":"just","value":[]},"name":"bootstrap","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.internals","name":"FlywayAction"}},"parameters":[]}]}},{"annotations":[],"serializedName":"action","default":{"kind":"nothing"},"name":"action","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.internals","name":"FlywayAction"}},"parameters":[]}]}}]}},"name":"FlywayCommand","version":{"kind":"nothing"}}}; + +export const snFlywayCommand: ADL.ScopedName = {moduleName:"common.flyway.internals", name:"FlywayCommand"}; + +export function texprFlywayCommand(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFlywayCommand},parameters:[]}}; +} + +/** + * Contextual information required to run flyway + */ +export interface FlywayContext { +/** + * The name of the flyway history table. + * Useful to override for bootstraping. + */ + schemaHistoryTable: string; +/** + * The location from which db migrations are loaded + */ + sqlMigrationDir: string; +/** + * The package from which java based db migrations are loaded + */ + javaMigrationPackage: (string|null); +/** + * DB connection retries, with 1 second between retries + */ + connect_retries: number; +} + +export function makeFlywayContext( + input: { + schemaHistoryTable?: string, + sqlMigrationDir?: string, + javaMigrationPackage?: (string|null), + connect_retries?: number, + } +): FlywayContext { + return { + schemaHistoryTable: input.schemaHistoryTable === undefined ? "flyway_schema_history" : input.schemaHistoryTable, + sqlMigrationDir: input.sqlMigrationDir === undefined ? "/app/sql/migrations" : input.sqlMigrationDir, + javaMigrationPackage: input.javaMigrationPackage === undefined ? "app/java/migrations" : input.javaMigrationPackage, + connect_retries: input.connect_retries === undefined ? 3 : input.connect_retries, + }; +} + +const FlywayContext_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.internals","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"schemaHistoryTable","default":{"kind":"just","value":"flyway_schema_history"},"name":"schemaHistoryTable","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"sqlMigrationDir","default":{"kind":"just","value":"/app/sql/migrations"},"name":"sqlMigrationDir","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"javaMigrationPackage","default":{"kind":"just","value":"app/java/migrations"},"name":"javaMigrationPackage","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}},{"annotations":[],"serializedName":"connect_retries","default":{"kind":"just","value":3},"name":"connect_retries","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}}]}},"name":"FlywayContext","version":{"kind":"nothing"}}}; + +export const snFlywayContext: ADL.ScopedName = {moduleName:"common.flyway.internals", name:"FlywayContext"}; + +export function texprFlywayContext(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFlywayContext},parameters:[]}}; +} + +export interface FlywayAction_Info { + kind: 'info'; +} +export interface FlywayAction_Baseline_zero { + kind: 'baseline_zero'; +} +export interface FlywayAction_Baseline_one { + kind: 'baseline_one'; +} +export interface FlywayAction_Baseline_latest { + kind: 'baseline_latest'; +} +export interface FlywayAction_Baseline_version { + kind: 'baseline_version'; + value: string; +} +export interface FlywayAction_Migrate { + kind: 'migrate'; +} +export interface FlywayAction_Migrate_latest { + kind: 'migrate_latest'; + value: MigrateLatestAction; +} +export interface FlywayAction_Migrate_to_version { + kind: 'migrate_to_version'; + value: MigrateAction; +} +export interface FlywayAction_Sequence { + kind: 'sequence'; + value: FlywayAction[]; +} +export interface FlywayAction_WithContext { + kind: 'withContext'; + value: FlywayCtxAction; +} + +export type FlywayAction = FlywayAction_Info | FlywayAction_Baseline_zero | FlywayAction_Baseline_one | FlywayAction_Baseline_latest | FlywayAction_Baseline_version | FlywayAction_Migrate | FlywayAction_Migrate_latest | FlywayAction_Migrate_to_version | FlywayAction_Sequence | FlywayAction_WithContext; + +export interface FlywayActionOpts { + /** + * Get migration info, the a combintation of the flyway schema history and future migrations. + */ +info: null; + baseline_zero: null; + baseline_one: null; + baseline_latest: null; + baseline_version: string; + /** + * Migrate to lastest with default options + */ +migrate: null; + migrate_latest: MigrateLatestAction; + migrate_to_version: MigrateAction; + sequence: FlywayAction[]; + withContext: FlywayCtxAction; +} + +export function makeFlywayAction(kind: K, value: FlywayActionOpts[K]) { return {kind, value}; } + +const FlywayAction_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.internals","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"info","default":{"kind":"nothing"},"name":"info","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"baseline_zero","default":{"kind":"nothing"},"name":"baseline_zero","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"baseline_one","default":{"kind":"nothing"},"name":"baseline_one","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"baseline_latest","default":{"kind":"nothing"},"name":"baseline_latest","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"baseline_version","default":{"kind":"nothing"},"name":"baseline_version","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"migrate","default":{"kind":"nothing"},"name":"migrate","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"migrate_latest","default":{"kind":"nothing"},"name":"migrate_latest","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.internals","name":"MigrateLatestAction"}},"parameters":[]}},{"annotations":[],"serializedName":"migrate_to_version","default":{"kind":"nothing"},"name":"migrate_to_version","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.internals","name":"MigrateAction"}},"parameters":[]}},{"annotations":[],"serializedName":"sequence","default":{"kind":"nothing"},"name":"sequence","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.internals","name":"FlywayAction"}},"parameters":[]}]}},{"annotations":[],"serializedName":"withContext","default":{"kind":"nothing"},"name":"withContext","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.internals","name":"FlywayCtxAction"}},"parameters":[]}}]}},"name":"FlywayAction","version":{"kind":"nothing"}}}; + +export const snFlywayAction: ADL.ScopedName = {moduleName:"common.flyway.internals", name:"FlywayAction"}; + +export function texprFlywayAction(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFlywayAction},parameters:[]}}; +} + +export interface FlywayCtxAction { +/** + * The context in normal (non-bootstrap) mode + */ + ctx: FlywayContext; +/** + * Array of actions to run on bootstrap + */ + action: FlywayAction; +} + +export function makeFlywayCtxAction( + input: { + ctx: FlywayContext, + action: FlywayAction, + } +): FlywayCtxAction { + return { + ctx: input.ctx, + action: input.action, + }; +} + +const FlywayCtxAction_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.internals","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"ctx","default":{"kind":"nothing"},"name":"ctx","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.internals","name":"FlywayContext"}},"parameters":[]}},{"annotations":[],"serializedName":"action","default":{"kind":"nothing"},"name":"action","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.internals","name":"FlywayAction"}},"parameters":[]}}]}},"name":"FlywayCtxAction","version":{"kind":"nothing"}}}; + +export const snFlywayCtxAction: ADL.ScopedName = {moduleName:"common.flyway.internals", name:"FlywayCtxAction"}; + +export function texprFlywayCtxAction(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFlywayCtxAction},parameters:[]}}; +} + +export interface MigrateLatestAction { +/** + * migration options + */ + options: MigrateOptionsOptions; +} + +export function makeMigrateLatestAction( + input: { + options?: MigrateOptionsOptions, + } +): MigrateLatestAction { + return { + options: input.options === undefined ? {kind : "defaults"} : input.options, + }; +} + +const MigrateLatestAction_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.internals","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"options","default":{"kind":"just","value":"defaults"},"name":"options","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.internals","name":"MigrateOptionsOptions"}},"parameters":[]}}]}},"name":"MigrateLatestAction","version":{"kind":"nothing"}}}; + +export const snMigrateLatestAction: ADL.ScopedName = {moduleName:"common.flyway.internals", name:"MigrateLatestAction"}; + +export function texprMigrateLatestAction(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snMigrateLatestAction},parameters:[]}}; +} + +export interface MigrateAction { +/** + * migration options + */ + options: MigrateOptionsOptions; + version: string; +} + +export function makeMigrateAction( + input: { + options?: MigrateOptionsOptions, + version: string, + } +): MigrateAction { + return { + options: input.options === undefined ? {kind : "defaults"} : input.options, + version: input.version, + }; +} + +const MigrateAction_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.internals","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"options","default":{"kind":"just","value":"defaults"},"name":"options","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.internals","name":"MigrateOptionsOptions"}},"parameters":[]}},{"annotations":[],"serializedName":"version","default":{"kind":"nothing"},"name":"version","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"MigrateAction","version":{"kind":"nothing"}}}; + +export const snMigrateAction: ADL.ScopedName = {moduleName:"common.flyway.internals", name:"MigrateAction"}; + +export function texprMigrateAction(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snMigrateAction},parameters:[]}}; +} + +export interface MigrateOptionsOptions_Defaults { + kind: 'defaults'; +} +export interface MigrateOptionsOptions_IgnoreMissingMigrations { + kind: 'ignoreMissingMigrations'; +} +export interface MigrateOptionsOptions_IgnoreIgnoredMigrations { + kind: 'ignoreIgnoredMigrations'; +} +export interface MigrateOptionsOptions_OutOfOrder { + kind: 'outOfOrder'; +} +export interface MigrateOptionsOptions_DontValidateOnMigrate { + kind: 'dontValidateOnMigrate'; +} +export interface MigrateOptionsOptions_Custom { + kind: 'custom'; + value: MigrateOptions; +} + +export type MigrateOptionsOptions = MigrateOptionsOptions_Defaults | MigrateOptionsOptions_IgnoreMissingMigrations | MigrateOptionsOptions_IgnoreIgnoredMigrations | MigrateOptionsOptions_OutOfOrder | MigrateOptionsOptions_DontValidateOnMigrate | MigrateOptionsOptions_Custom; + +export interface MigrateOptionsOptionsOpts { + defaults: null; + ignoreMissingMigrations: null; + ignoreIgnoredMigrations: null; + outOfOrder: null; + dontValidateOnMigrate: null; + custom: MigrateOptions; +} + +export function makeMigrateOptionsOptions(kind: K, value: MigrateOptionsOptionsOpts[K]) { return {kind, value}; } + +const MigrateOptionsOptions_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.internals","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"defaults","default":{"kind":"nothing"},"name":"defaults","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"ignoreMissingMigrations","default":{"kind":"nothing"},"name":"ignoreMissingMigrations","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"ignoreIgnoredMigrations","default":{"kind":"nothing"},"name":"ignoreIgnoredMigrations","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"outOfOrder","default":{"kind":"nothing"},"name":"outOfOrder","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"dontValidateOnMigrate","default":{"kind":"nothing"},"name":"dontValidateOnMigrate","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"custom","default":{"kind":"just","value":{}},"name":"custom","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.internals","name":"MigrateOptions"}},"parameters":[]}}]}},"name":"MigrateOptionsOptions","version":{"kind":"nothing"}}}; + +export const snMigrateOptionsOptions: ADL.ScopedName = {moduleName:"common.flyway.internals", name:"MigrateOptionsOptions"}; + +export function texprMigrateOptionsOptions(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snMigrateOptionsOptions},parameters:[]}}; +} + +export interface MigrateOptions { +/** + * Ignore missing migrations when reading the schema history table. These are migrations that were performed by an + * older deployment of the application that are no longer available in this version. + */ + ignoreMissingMigrations: boolean; +/** + * Ignore ignored migrations when reading the schema history table. These are migrations that were added in between + * already migrated migrations in this version. + */ + ignoreIgnoredMigrations: boolean; +/** + * Ignore pending migrations when reading the schema history table. These are migrations that are available on the + * classpath but have not yet been performed by an application deployment. + * This can be useful for verifying that in-development migration changes don't contain any validation-breaking changes + * of migrations that have already been applied to a production environment, e.g. as part of a CI/CD process, without + * failing because of the existence of new migration versions. + */ + ignorePendingMigrations: boolean; +/** + * Ignore future migrations when reading the schema history table. These are migrations that were performed by a + * newer deployment of the application that are not yet available in this version. For example: we have migrations + * available on the classpath up to version 3.0. The schema history table indicates that a migration to version 4.0 + * (unknown to us) has already been applied. Instead of bombing out (fail fast) with an exception, a + * warning is logged and Flyway continues normally. This is useful for situations where one must be able to redeploy + * an older version of the application after the database has been migrated by a newer one. + */ + ignoreFutureMigrations: boolean; +/** + * Whether to validate migrations and callbacks whose scripts do not obey the correct naming convention. A failure can be + * useful to check that errors such as case sensitivity in migration prefixes have been corrected. + */ + validateMigrationNaming: boolean; +/** + * Whether to automatically call validate or not when running migrate. (default: {@code true}) + */ + validateOnMigrate: boolean; +/** + * Whether to automatically call clean or not when a validation error occurs. (default: {@code false}) + *

This is exclusively intended as a convenience for development. even though we + * strongly recommend not to change migration scripts once they have been checked into SCM and run, this provides a + * way of dealing with this case in a smooth manner. The database will be wiped clean automatically, ensuring that + * the next migration will bring you back to the state checked into SCM.

+ *

Warning ! Do not enable in production !

+ */ + cleanOnValidationError: boolean; +/** + * Whether to disable clean. (default: {@code false}) + *

This is especially useful for production environments where running clean can be quite a career limiting move.

+ */ + cleanDisabled: boolean; +/** + * Allows migrations to be run "out of order". + *

If you already have versions 1 and 3 applied, and now a version 2 is found, + * it will be applied too instead of being ignored.

+ */ + outOfOrder: boolean; +} + +export function makeMigrateOptions( + input: { + ignoreMissingMigrations?: boolean, + ignoreIgnoredMigrations?: boolean, + ignorePendingMigrations?: boolean, + ignoreFutureMigrations?: boolean, + validateMigrationNaming?: boolean, + validateOnMigrate?: boolean, + cleanOnValidationError?: boolean, + cleanDisabled?: boolean, + outOfOrder?: boolean, + } +): MigrateOptions { + return { + ignoreMissingMigrations: input.ignoreMissingMigrations === undefined ? true : input.ignoreMissingMigrations, + ignoreIgnoredMigrations: input.ignoreIgnoredMigrations === undefined ? true : input.ignoreIgnoredMigrations, + ignorePendingMigrations: input.ignorePendingMigrations === undefined ? false : input.ignorePendingMigrations, + ignoreFutureMigrations: input.ignoreFutureMigrations === undefined ? true : input.ignoreFutureMigrations, + validateMigrationNaming: input.validateMigrationNaming === undefined ? false : input.validateMigrationNaming, + validateOnMigrate: input.validateOnMigrate === undefined ? true : input.validateOnMigrate, + cleanOnValidationError: input.cleanOnValidationError === undefined ? false : input.cleanOnValidationError, + cleanDisabled: input.cleanDisabled === undefined ? false : input.cleanDisabled, + outOfOrder: input.outOfOrder === undefined ? false : input.outOfOrder, + }; +} + +const MigrateOptions_AST : ADL.ScopedDecl = + {"moduleName":"common.flyway.internals","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"ignoreMissingMigrations","default":{"kind":"just","value":true},"name":"ignoreMissingMigrations","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"ignoreIgnoredMigrations","default":{"kind":"just","value":true},"name":"ignoreIgnoredMigrations","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"ignorePendingMigrations","default":{"kind":"just","value":false},"name":"ignorePendingMigrations","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"ignoreFutureMigrations","default":{"kind":"just","value":true},"name":"ignoreFutureMigrations","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"validateMigrationNaming","default":{"kind":"just","value":false},"name":"validateMigrationNaming","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"validateOnMigrate","default":{"kind":"just","value":true},"name":"validateOnMigrate","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"cleanOnValidationError","default":{"kind":"just","value":false},"name":"cleanOnValidationError","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"cleanDisabled","default":{"kind":"just","value":false},"name":"cleanDisabled","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"outOfOrder","default":{"kind":"just","value":false},"name":"outOfOrder","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}}]}},"name":"MigrateOptions","version":{"kind":"nothing"}}}; + +export const snMigrateOptions: ADL.ScopedName = {moduleName:"common.flyway.internals", name:"MigrateOptions"}; + +export function texprMigrateOptions(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snMigrateOptions},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.flyway.internals.FlywayCommand" : FlywayCommand_AST, + "common.flyway.internals.FlywayContext" : FlywayContext_AST, + "common.flyway.internals.FlywayAction" : FlywayAction_AST, + "common.flyway.internals.FlywayCtxAction" : FlywayCtxAction_AST, + "common.flyway.internals.MigrateLatestAction" : MigrateLatestAction_AST, + "common.flyway.internals.MigrateAction" : MigrateAction_AST, + "common.flyway.internals.MigrateOptionsOptions" : MigrateOptionsOptions_AST, + "common.flyway.internals.MigrateOptions" : MigrateOptions_AST +}; diff --git a/typescript/workspace/generated/common/http.ts b/typescript/workspace/generated/common/http.ts new file mode 100644 index 00000000..1ad1232c --- /dev/null +++ b/typescript/workspace/generated/common/http.ts @@ -0,0 +1,467 @@ +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common.http */ + +/** + * A marker type to associate the output response + * type for an http Get request. + */ +export type Get<_I> = null; + +const Get_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":["I"],"typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}}},"name":"Get","version":{"kind":"nothing"}}}; + +export const snGet: ADL.ScopedName = {moduleName:"common.http", name:"Get"}; + +export function texprGet(texprI : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snGet},parameters:[texprI.value]}}; +} + +/** + * A marker type to associate the input request and output response + * types for an http put request. + */ +export type Put<_I, _O> = null; + +const Put_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":["I","O"],"typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}}},"name":"Put","version":{"kind":"nothing"}}}; + +export const snPut: ADL.ScopedName = {moduleName:"common.http", name:"Put"}; + +export function texprPut(texprI : ADL.ATypeExpr, texprO : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snPut},parameters:[texprI.value,texprO.value]}}; +} + +/** + * A marker type to associate the input request and output response + * types for an http post request. + */ +export type Post<_I, _O> = null; + +const Post_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":["I","O"],"typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}}},"name":"Post","version":{"kind":"nothing"}}}; + +export const snPost: ADL.ScopedName = {moduleName:"common.http", name:"Post"}; + +export function texprPost(texprI : ADL.ATypeExpr, texprO : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snPost},parameters:[texprI.value,texprO.value]}}; +} + +/** + * An annotation indicating the URL path for a request + */ +export type Path = string; + +const Path_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"Path","version":{"kind":"nothing"}}}; + +export const snPath: ADL.ScopedName = {moduleName:"common.http", name:"Path"}; + +export function texprPath(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snPath},parameters:[]}}; +} + +/** + * An annotation indicating that a request requires an Authorization http header + */ +export type AuthHeader = null; + +const AuthHeader_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}}},"name":"AuthHeader","version":{"kind":"nothing"}}}; + +export const snAuthHeader: ADL.ScopedName = {moduleName:"common.http", name:"AuthHeader"}; + +export function texprAuthHeader(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snAuthHeader},parameters:[]}}; +} + +/** + * An annotation indicating that a request is idemponent, and can hence be safely + * retried on failure. + */ +export type Idempotent = null; + +const Idempotent_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}}},"name":"Idempotent","version":{"kind":"nothing"}}}; + +export const snIdempotent: ADL.ScopedName = {moduleName:"common.http", name:"Idempotent"}; + +export function texprIdempotent(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snIdempotent},parameters:[]}}; +} + +/** + * An annotation indicating that a request can be made idempotent if the caller + * provides an Idempotency-Key header with a unique value. + */ +export type IdempotentWithKey = null; + +const IdempotentWithKey_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}}},"name":"IdempotentWithKey","version":{"kind":"nothing"}}}; + +export const snIdempotentWithKey: ADL.ScopedName = {moduleName:"common.http", name:"IdempotentWithKey"}; + +export function texprIdempotentWithKey(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snIdempotentWithKey},parameters:[]}}; +} + +/** + * The standard message body for errors + */ +export interface PublicErrorData { + publicMessage: string; +} + +export function makePublicErrorData( + input: { + publicMessage: string, + } +): PublicErrorData { + return { + publicMessage: input.publicMessage, + }; +} + +const PublicErrorData_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"publicMessage","default":{"kind":"nothing"},"name":"publicMessage","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"PublicErrorData","version":{"kind":"nothing"}}}; + +export const snPublicErrorData: ADL.ScopedName = {moduleName:"common.http", name:"PublicErrorData"}; + +export function texprPublicErrorData(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snPublicErrorData},parameters:[]}}; +} + +/** + * New request types + */ +export interface HttpGet { + path: string; + security: HttpSecurity; + rateLimit: (HttpRateLimit|null); + respType: ADL.ATypeExpr; +} + +const HttpGet_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["O"],"fields":[{"annotations":[],"serializedName":"path","default":{"kind":"nothing"},"name":"path","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"security","default":{"kind":"nothing"},"name":"security","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpSecurity"}},"parameters":[]}},{"annotations":[],"serializedName":"rateLimit","default":{"kind":"just","value":null},"name":"rateLimit","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpRateLimit"}},"parameters":[]}]}},{"annotations":[],"serializedName":"respType","default":{"kind":"just","value":null},"name":"respType","typeExpr":{"typeRef":{"kind":"primitive","value":"TypeToken"},"parameters":[{"typeRef":{"kind":"typeParam","value":"O"},"parameters":[]}]}}]}},"name":"HttpGet","version":{"kind":"nothing"}}}; + +export const snHttpGet: ADL.ScopedName = {moduleName:"common.http", name:"HttpGet"}; + +export function texprHttpGet(texprO : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snHttpGet},parameters:[texprO.value]}}; +} + +export interface HttpGetStream { + path: string; + security: HttpSecurity; + respItemType: ADL.ATypeExpr; +} + +const HttpGetStream_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["O"],"fields":[{"annotations":[],"serializedName":"path","default":{"kind":"nothing"},"name":"path","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"security","default":{"kind":"nothing"},"name":"security","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpSecurity"}},"parameters":[]}},{"annotations":[],"serializedName":"respItemType","default":{"kind":"just","value":null},"name":"respItemType","typeExpr":{"typeRef":{"kind":"primitive","value":"TypeToken"},"parameters":[{"typeRef":{"kind":"typeParam","value":"O"},"parameters":[]}]}}]}},"name":"HttpGetStream","version":{"kind":"nothing"}}}; + +export const snHttpGetStream: ADL.ScopedName = {moduleName:"common.http", name:"HttpGetStream"}; + +export function texprHttpGetStream(texprO : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snHttpGetStream},parameters:[texprO.value]}}; +} + +export interface HttpGet2 { + path: string; + security: HttpSecurity; + rateLimit: (HttpRateLimit|null); + paramsType: ADL.ATypeExpr

; + respType: ADL.ATypeExpr; +} + +const HttpGet2_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["P","O"],"fields":[{"annotations":[],"serializedName":"path","default":{"kind":"nothing"},"name":"path","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"security","default":{"kind":"nothing"},"name":"security","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpSecurity"}},"parameters":[]}},{"annotations":[],"serializedName":"rateLimit","default":{"kind":"just","value":null},"name":"rateLimit","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpRateLimit"}},"parameters":[]}]}},{"annotations":[],"serializedName":"paramsType","default":{"kind":"just","value":null},"name":"paramsType","typeExpr":{"typeRef":{"kind":"primitive","value":"TypeToken"},"parameters":[{"typeRef":{"kind":"typeParam","value":"P"},"parameters":[]}]}},{"annotations":[],"serializedName":"respType","default":{"kind":"just","value":null},"name":"respType","typeExpr":{"typeRef":{"kind":"primitive","value":"TypeToken"},"parameters":[{"typeRef":{"kind":"typeParam","value":"O"},"parameters":[]}]}}]}},"name":"HttpGet2","version":{"kind":"nothing"}}}; + +export const snHttpGet2: ADL.ScopedName = {moduleName:"common.http", name:"HttpGet2"}; + +export function texprHttpGet2(texprP : ADL.ATypeExpr

, texprO : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snHttpGet2},parameters:[texprP.value,texprO.value]}}; +} + +export interface HttpPut { + path: string; + security: HttpSecurity; + rateLimit: (HttpRateLimit|null); + reqType: ADL.ATypeExpr; + respType: ADL.ATypeExpr; +} + +const HttpPut_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["I","O"],"fields":[{"annotations":[],"serializedName":"path","default":{"kind":"nothing"},"name":"path","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"security","default":{"kind":"nothing"},"name":"security","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpSecurity"}},"parameters":[]}},{"annotations":[],"serializedName":"rateLimit","default":{"kind":"just","value":null},"name":"rateLimit","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpRateLimit"}},"parameters":[]}]}},{"annotations":[],"serializedName":"reqType","default":{"kind":"just","value":null},"name":"reqType","typeExpr":{"typeRef":{"kind":"primitive","value":"TypeToken"},"parameters":[{"typeRef":{"kind":"typeParam","value":"I"},"parameters":[]}]}},{"annotations":[],"serializedName":"respType","default":{"kind":"just","value":null},"name":"respType","typeExpr":{"typeRef":{"kind":"primitive","value":"TypeToken"},"parameters":[{"typeRef":{"kind":"typeParam","value":"O"},"parameters":[]}]}}]}},"name":"HttpPut","version":{"kind":"nothing"}}}; + +export const snHttpPut: ADL.ScopedName = {moduleName:"common.http", name:"HttpPut"}; + +export function texprHttpPut(texprI : ADL.ATypeExpr, texprO : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snHttpPut},parameters:[texprI.value,texprO.value]}}; +} + +export interface HttpPost { + path: string; + security: HttpSecurity; + rateLimit: (HttpRateLimit|null); + reqType: ADL.ATypeExpr; + respType: ADL.ATypeExpr; +} + +const HttpPost_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["I","O"],"fields":[{"annotations":[],"serializedName":"path","default":{"kind":"nothing"},"name":"path","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"security","default":{"kind":"nothing"},"name":"security","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpSecurity"}},"parameters":[]}},{"annotations":[],"serializedName":"rateLimit","default":{"kind":"just","value":null},"name":"rateLimit","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpRateLimit"}},"parameters":[]}]}},{"annotations":[],"serializedName":"reqType","default":{"kind":"just","value":null},"name":"reqType","typeExpr":{"typeRef":{"kind":"primitive","value":"TypeToken"},"parameters":[{"typeRef":{"kind":"typeParam","value":"I"},"parameters":[]}]}},{"annotations":[],"serializedName":"respType","default":{"kind":"just","value":null},"name":"respType","typeExpr":{"typeRef":{"kind":"primitive","value":"TypeToken"},"parameters":[{"typeRef":{"kind":"typeParam","value":"O"},"parameters":[]}]}}]}},"name":"HttpPost","version":{"kind":"nothing"}}}; + +export const snHttpPost: ADL.ScopedName = {moduleName:"common.http", name:"HttpPost"}; + +export function texprHttpPost(texprI : ADL.ATypeExpr, texprO : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snHttpPost},parameters:[texprI.value,texprO.value]}}; +} + +export interface HttpPost2 { + path: string; + security: HttpSecurity; + rateLimit: (HttpRateLimit|null); + paramsType: ADL.ATypeExpr

; + reqType: ADL.ATypeExpr; + respType: ADL.ATypeExpr; +} + +const HttpPost2_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["P","I","O"],"fields":[{"annotations":[],"serializedName":"path","default":{"kind":"nothing"},"name":"path","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"security","default":{"kind":"nothing"},"name":"security","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpSecurity"}},"parameters":[]}},{"annotations":[],"serializedName":"rateLimit","default":{"kind":"just","value":null},"name":"rateLimit","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpRateLimit"}},"parameters":[]}]}},{"annotations":[],"serializedName":"paramsType","default":{"kind":"just","value":null},"name":"paramsType","typeExpr":{"typeRef":{"kind":"primitive","value":"TypeToken"},"parameters":[{"typeRef":{"kind":"typeParam","value":"P"},"parameters":[]}]}},{"annotations":[],"serializedName":"reqType","default":{"kind":"just","value":null},"name":"reqType","typeExpr":{"typeRef":{"kind":"primitive","value":"TypeToken"},"parameters":[{"typeRef":{"kind":"typeParam","value":"I"},"parameters":[]}]}},{"annotations":[],"serializedName":"respType","default":{"kind":"just","value":null},"name":"respType","typeExpr":{"typeRef":{"kind":"primitive","value":"TypeToken"},"parameters":[{"typeRef":{"kind":"typeParam","value":"O"},"parameters":[]}]}}]}},"name":"HttpPost2","version":{"kind":"nothing"}}}; + +export const snHttpPost2: ADL.ScopedName = {moduleName:"common.http", name:"HttpPost2"}; + +export function texprHttpPost2(texprP : ADL.ATypeExpr

, texprI : ADL.ATypeExpr, texprO : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snHttpPost2},parameters:[texprP.value,texprI.value,texprO.value]}}; +} + +export interface HttpDelete { + path: string; + security: HttpSecurity; + paramsType: ADL.ATypeExpr

; + respType: ADL.ATypeExpr; +} + +const HttpDelete_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["P","O"],"fields":[{"annotations":[],"serializedName":"path","default":{"kind":"nothing"},"name":"path","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"security","default":{"kind":"nothing"},"name":"security","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpSecurity"}},"parameters":[]}},{"annotations":[],"serializedName":"paramsType","default":{"kind":"just","value":null},"name":"paramsType","typeExpr":{"typeRef":{"kind":"primitive","value":"TypeToken"},"parameters":[{"typeRef":{"kind":"typeParam","value":"P"},"parameters":[]}]}},{"annotations":[],"serializedName":"respType","default":{"kind":"just","value":null},"name":"respType","typeExpr":{"typeRef":{"kind":"primitive","value":"TypeToken"},"parameters":[{"typeRef":{"kind":"typeParam","value":"O"},"parameters":[]}]}}]}},"name":"HttpDelete","version":{"kind":"nothing"}}}; + +export const snHttpDelete: ADL.ScopedName = {moduleName:"common.http", name:"HttpDelete"}; + +export function texprHttpDelete(texprP : ADL.ATypeExpr

, texprO : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snHttpDelete},parameters:[texprP.value,texprO.value]}}; +} + +export interface HttpSecurity_Public { + kind: 'public'; +} +export interface HttpSecurity_Token { + kind: 'token'; +} +export interface HttpSecurity_TokenWithRole { + kind: 'tokenWithRole'; + value: string; +} + +export type HttpSecurity = HttpSecurity_Public | HttpSecurity_Token | HttpSecurity_TokenWithRole; + +export interface HttpSecurityOpts { + public: null; + token: null; + tokenWithRole: string; +} + +export function makeHttpSecurity(kind: K, value: HttpSecurityOpts[K]) { return {kind, value}; } + +const HttpSecurity_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"public","default":{"kind":"nothing"},"name":"public","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"token","default":{"kind":"nothing"},"name":"token","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"tokenWithRole","default":{"kind":"nothing"},"name":"tokenWithRole","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"HttpSecurity","version":{"kind":"nothing"}}}; + +export const snHttpSecurity: ADL.ScopedName = {moduleName:"common.http", name:"HttpSecurity"}; + +export function texprHttpSecurity(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snHttpSecurity},parameters:[]}}; +} + +export interface HttpRateLimit { + maxRequests: number; + perTimeUnit: RateLimitTimeUnit; +} + +export function makeHttpRateLimit( + input: { + maxRequests: number, + perTimeUnit: RateLimitTimeUnit, + } +): HttpRateLimit { + return { + maxRequests: input.maxRequests, + perTimeUnit: input.perTimeUnit, + }; +} + +const HttpRateLimit_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"maxRequests","default":{"kind":"nothing"},"name":"maxRequests","typeExpr":{"typeRef":{"kind":"primitive","value":"Word32"},"parameters":[]}},{"annotations":[],"serializedName":"perTimeUnit","default":{"kind":"nothing"},"name":"perTimeUnit","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"RateLimitTimeUnit"}},"parameters":[]}}]}},"name":"HttpRateLimit","version":{"kind":"nothing"}}}; + +export const snHttpRateLimit: ADL.ScopedName = {moduleName:"common.http", name:"HttpRateLimit"}; + +export function texprHttpRateLimit(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snHttpRateLimit},parameters:[]}}; +} + +export type RateLimitTimeUnit = 'second' | 'minute' | 'hour'; +export const valuesRateLimitTimeUnit : RateLimitTimeUnit[] = ['second', 'minute', 'hour']; + +const RateLimitTimeUnit_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"second","default":{"kind":"nothing"},"name":"second","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"minute","default":{"kind":"nothing"},"name":"minute","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"hour","default":{"kind":"nothing"},"name":"hour","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}}]}},"name":"RateLimitTimeUnit","version":{"kind":"nothing"}}}; + +export const snRateLimitTimeUnit: ADL.ScopedName = {moduleName:"common.http", name:"RateLimitTimeUnit"}; + +export function texprRateLimitTimeUnit(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snRateLimitTimeUnit},parameters:[]}}; +} + +/** + * API decl or request annotation to specify + * the non-success response codes we want + * included in the generated open API. The + * Json should have exactly the structure of + * the OpenApi responses map + */ +export type OpenApiOtherResponses = {}|null; + +const OpenApiOtherResponses_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"Json"},"parameters":[]}}},"name":"OpenApiOtherResponses","version":{"kind":"nothing"}}}; + +export const snOpenApiOtherResponses: ADL.ScopedName = {moduleName:"common.http", name:"OpenApiOtherResponses"}; + +export function texprOpenApiOtherResponses(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snOpenApiOtherResponses},parameters:[]}}; +} + +/** + * API annotation to specify the available + * server endpoints. The Json should have + * exactly the structure of the OpenApi + * servers map + */ +export type OpenApiServers = {}|null; + +const OpenApiServers_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"Json"},"parameters":[]}}},"name":"OpenApiServers","version":{"kind":"nothing"}}}; + +export const snOpenApiServers: ADL.ScopedName = {moduleName:"common.http", name:"OpenApiServers"}; + +export function texprOpenApiServers(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snOpenApiServers},parameters:[]}}; +} + +/** + * Marker annotation to indicate that an endpoint + * or (defaulted) field should be left out of the + * generated openapi + */ +export type OpenApiExclude = boolean; + +const OpenApiExclude_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}}},"name":"OpenApiExclude","version":{"kind":"nothing"}}}; + +export const snOpenApiExclude: ADL.ScopedName = {moduleName:"common.http", name:"OpenApiExclude"}; + +export function texprOpenApiExclude(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snOpenApiExclude},parameters:[]}}; +} + +/** + * API annotation to specify additional api + * information. The Json should have + * exactly the structure of the OpenApi + * info map + */ +export type OpenApiInfo = {}|null; + +const OpenApiInfo_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"Json"},"parameters":[]}}},"name":"OpenApiInfo","version":{"kind":"nothing"}}}; + +export const snOpenApiInfo: ADL.ScopedName = {moduleName:"common.http", name:"OpenApiInfo"}; + +export function texprOpenApiInfo(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snOpenApiInfo},parameters:[]}}; +} + +export interface SecurityScheme_HttpBearer { + kind: 'httpBearer'; +} +export interface SecurityScheme_ApiKey { + kind: 'apiKey'; + value: HeaderApiKeyScheme; +} + +/** + * API decl annotation to specify + * the security schema in use + */ +export type SecurityScheme = SecurityScheme_HttpBearer | SecurityScheme_ApiKey; + +export interface SecuritySchemeOpts { + httpBearer: null; + apiKey: HeaderApiKeyScheme; +} + +export function makeSecurityScheme(kind: K, value: SecuritySchemeOpts[K]) { return {kind, value}; } + +const SecurityScheme_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"httpBearer","default":{"kind":"nothing"},"name":"httpBearer","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"apiKey","default":{"kind":"nothing"},"name":"apiKey","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HeaderApiKeyScheme"}},"parameters":[]}}]}},"name":"SecurityScheme","version":{"kind":"nothing"}}}; + +export const snSecurityScheme: ADL.ScopedName = {moduleName:"common.http", name:"SecurityScheme"}; + +export function texprSecurityScheme(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snSecurityScheme},parameters:[]}}; +} + +export interface HeaderApiKeyScheme { + headerName: string; +} + +export function makeHeaderApiKeyScheme( + input: { + headerName: string, + } +): HeaderApiKeyScheme { + return { + headerName: input.headerName, + }; +} + +const HeaderApiKeyScheme_AST : ADL.ScopedDecl = + {"moduleName":"common.http","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"headerName","default":{"kind":"nothing"},"name":"headerName","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"HeaderApiKeyScheme","version":{"kind":"nothing"}}}; + +export const snHeaderApiKeyScheme: ADL.ScopedName = {moduleName:"common.http", name:"HeaderApiKeyScheme"}; + +export function texprHeaderApiKeyScheme(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snHeaderApiKeyScheme},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.http.Get" : Get_AST, + "common.http.Put" : Put_AST, + "common.http.Post" : Post_AST, + "common.http.Path" : Path_AST, + "common.http.AuthHeader" : AuthHeader_AST, + "common.http.Idempotent" : Idempotent_AST, + "common.http.IdempotentWithKey" : IdempotentWithKey_AST, + "common.http.PublicErrorData" : PublicErrorData_AST, + "common.http.HttpGet" : HttpGet_AST, + "common.http.HttpGetStream" : HttpGetStream_AST, + "common.http.HttpGet2" : HttpGet2_AST, + "common.http.HttpPut" : HttpPut_AST, + "common.http.HttpPost" : HttpPost_AST, + "common.http.HttpPost2" : HttpPost2_AST, + "common.http.HttpDelete" : HttpDelete_AST, + "common.http.HttpSecurity" : HttpSecurity_AST, + "common.http.HttpRateLimit" : HttpRateLimit_AST, + "common.http.RateLimitTimeUnit" : RateLimitTimeUnit_AST, + "common.http.OpenApiOtherResponses" : OpenApiOtherResponses_AST, + "common.http.OpenApiServers" : OpenApiServers_AST, + "common.http.OpenApiExclude" : OpenApiExclude_AST, + "common.http.OpenApiInfo" : OpenApiInfo_AST, + "common.http.SecurityScheme" : SecurityScheme_AST, + "common.http.HeaderApiKeyScheme" : HeaderApiKeyScheme_AST +}; diff --git a/typescript/workspace/generated/common/index.ts b/typescript/workspace/generated/common/index.ts new file mode 100644 index 00000000..a1e24462 --- /dev/null +++ b/typescript/workspace/generated/common/index.ts @@ -0,0 +1,10 @@ +/* @generated - key "" */ +export * from './_/index'; +export * as adminui from './adminui/index'; +export * as config from './config/index'; +export * as flyway from './flyway/index'; +export * as db from './db'; +export * as http from './http'; +export * as strings from './strings'; +export * as tabular from './tabular'; +export * as ui from './ui'; diff --git a/typescript/workspace/generated/common/package-dist.json b/typescript/workspace/generated/common/package-dist.json new file mode 100644 index 00000000..b691fe11 --- /dev/null +++ b/typescript/workspace/generated/common/package-dist.json @@ -0,0 +1,12 @@ +{ + "name": "@adl-lang/common", + "version": "0.0.0", + "license": "MIT", + "main": "./index.js", + "types": "./index.d.ts", + "dependencies": { + "@adl-lang/runtime": "workspace:*", + "@adl-lang/sys": "workspace:*" + } + } + \ No newline at end of file diff --git a/typescript/workspace/generated/common/package.json b/typescript/workspace/generated/common/package.json new file mode 100644 index 00000000..59a402b9 --- /dev/null +++ b/typescript/workspace/generated/common/package.json @@ -0,0 +1,16 @@ +{ + "name": "@adl-lang/common", + "version": "1.0.0", + "scripts": { + "clean": "rm -rf dist && rm -rf node_modules", + "tsc": "tsc" + }, + "dependencies": { + "@adl-lang/runtime": "^1.0.0", + "@adl-lang/sys": "workspace:*" + }, + "devDependencies": { + "typescript": "^4.9.3", + "tsconfig": "workspace:*" + } +} \ No newline at end of file diff --git a/typescript/workspace/generated/common/resolver.ts b/typescript/workspace/generated/common/resolver.ts new file mode 100644 index 00000000..60920e87 --- /dev/null +++ b/typescript/workspace/generated/common/resolver.ts @@ -0,0 +1,60 @@ +import {_AST_MAP as common} from "./"; +import {_AST_MAP as common_adminui_api} from "./adminui/api"; +import {_AST_MAP as common_adminui_config} from "./adminui/config"; +import {_AST_MAP as common_adminui_db} from "./adminui/db"; +import {_AST_MAP as common_config_aws} from "./config/aws"; +import {_AST_MAP as common_config_azure} from "./config/azure"; +import {_AST_MAP as common_config_db} from "./config/db"; +import {_AST_MAP as common_config_emailer} from "./config/emailer"; +import {_AST_MAP as common_config_frontend} from "./config/frontend"; +import {_AST_MAP as common_config_google} from "./config/google"; +import {_AST_MAP as common_config_jwt} from "./config/jwt"; +import {_AST_MAP as common_config_log} from "./config/log"; +import {_AST_MAP as common_config_okta} from "./config/okta"; +import {_AST_MAP as common_config_sms} from "./config/sms"; +import {_AST_MAP as common_config_storage} from "./config/storage"; +import {_AST_MAP as common_db} from "./db"; +import {_AST_MAP as common_flyway_api} from "./flyway/api"; +import {_AST_MAP as common_flyway_example_patterns} from "./flyway/example_patterns"; +import {_AST_MAP as common_flyway_internals} from "./flyway/internals"; +import {_AST_MAP as common_http} from "./http"; +import {_AST_MAP as common_strings} from "./strings"; +import {_AST_MAP as common_tabular} from "./tabular"; +import {_AST_MAP as common_ui} from "./ui"; +import {ScopedDecl, declResolver} from "@adl-lang/runtime/adl"; +import {ADL_local as adl_lang_sys} from "@adl-lang/sys/resolver"; + +/* @generated from adl */ + +export const ADL_local: { [key: string]: ScopedDecl } = { + ...common, + ...common_adminui_api, + ...common_adminui_config, + ...common_adminui_db, + ...common_config_aws, + ...common_config_azure, + ...common_config_db, + ...common_config_emailer, + ...common_config_frontend, + ...common_config_google, + ...common_config_jwt, + ...common_config_log, + ...common_config_okta, + ...common_config_sms, + ...common_config_storage, + ...common_db, + ...common_flyway_api, + ...common_flyway_example_patterns, + ...common_flyway_internals, + ...common_http, + ...common_strings, + ...common_tabular, + ...common_ui, +}; + +export const ADL: { [key: string]: ScopedDecl } = { + ...ADL_local, + ...adl_lang_sys, +}; + +export const RESOLVER = declResolver(ADL); diff --git a/typescript/workspace/generated/common/strings.ts b/typescript/workspace/generated/common/strings.ts new file mode 100644 index 00000000..a3c775dc --- /dev/null +++ b/typescript/workspace/generated/common/strings.ts @@ -0,0 +1,100 @@ +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common.strings */ + +/** + * Some string type aliases, with attributes to derive UI validation + */ +/** + * A string that isn't empty, and isn't only whitespace. + */ +export type StringNE = string; + +const StringNE_AST : ADL.ScopedDecl = + {"moduleName":"common.strings","decl":{"annotations":[{"value":{"description":"non empty","regex":"^.*\\S+.*$","returnGroup":0},"key":{"moduleName":"common.ui","name":"ValidRegex"}}],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"StringNE","version":{"kind":"nothing"}}}; + +export const snStringNE: ADL.ScopedName = {moduleName:"common.strings", name:"StringNE"}; + +export function texprStringNE(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snStringNE},parameters:[]}}; +} + +/** + * An alphanumeric string, with hyphens for separation. + */ +export type StringANH = string; + +const StringANH_AST : ADL.ScopedDecl = + {"moduleName":"common.strings","decl":{"annotations":[{"value":{"description":"alphanumeric","regex":"^[A-Za-z][A-Za-z0-9-]*$","returnGroup":0},"key":{"moduleName":"common.ui","name":"ValidRegex"}}],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"StringANH","version":{"kind":"nothing"}}}; + +export const snStringANH: ADL.ScopedName = {moduleName:"common.strings", name:"StringANH"}; + +export function texprStringANH(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snStringANH},parameters:[]}}; +} + +/** + * A multi line, free-form text string + */ +export type StringML = string; + +const StringML_AST : ADL.ScopedDecl = + {"moduleName":"common.strings","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"StringML","version":{"kind":"nothing"}}}; + +export const snStringML: ADL.ScopedName = {moduleName:"common.strings", name:"StringML"}; + +export function texprStringML(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snStringML},parameters:[]}}; +} + +/** + * An email address + */ +export type EmailAddress = string; + +const EmailAddress_AST : ADL.ScopedDecl = + {"moduleName":"common.strings","decl":{"annotations":[{"value":{"description":"an email address","regex":"^\\s*((?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|\"(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21\\x23-\\x5b\\x5d-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])*\")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\\x01-\\x08\\x0b\\x0c\\x0e-\\x1f\\x21-\\x5a\\x53-\\x7f]|\\\\[\\x01-\\x09\\x0b\\x0c\\x0e-\\x7f])+)\\]))\\s*$","returnGroup":1},"key":{"moduleName":"common.ui","name":"ValidRegex"}}],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"EmailAddress","version":{"kind":"nothing"}}}; + +export const snEmailAddress: ADL.ScopedName = {moduleName:"common.strings", name:"EmailAddress"}; + +export function texprEmailAddress(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snEmailAddress},parameters:[]}}; +} + +/** + * A markdown text string + */ +export type StringMD = string; + +const StringMD_AST : ADL.ScopedDecl = + {"moduleName":"common.strings","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"StringMD","version":{"kind":"nothing"}}}; + +export const snStringMD: ADL.ScopedName = {moduleName:"common.strings", name:"StringMD"}; + +export function texprStringMD(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snStringMD},parameters:[]}}; +} + +/** + * A password, which cannot be empty. Other constraints + * are application specific. + */ +export type Password = string; + +const Password_AST : ADL.ScopedDecl = + {"moduleName":"common.strings","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"Password","version":{"kind":"nothing"}}}; + +export const snPassword: ADL.ScopedName = {moduleName:"common.strings", name:"Password"}; + +export function texprPassword(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snPassword},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.strings.StringNE" : StringNE_AST, + "common.strings.StringANH" : StringANH_AST, + "common.strings.StringML" : StringML_AST, + "common.strings.EmailAddress" : EmailAddress_AST, + "common.strings.StringMD" : StringMD_AST, + "common.strings.Password" : Password_AST +}; diff --git a/typescript/workspace/generated/common/tabular.ts b/typescript/workspace/generated/common/tabular.ts new file mode 100644 index 00000000..6206496b --- /dev/null +++ b/typescript/workspace/generated/common/tabular.ts @@ -0,0 +1,359 @@ +import * as common from "./_/common"; +import * as common_strings from "./strings"; +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module common.tabular */ + +/** + * Common definitions for querying tabular data + */ +export type FieldName = common_strings.StringNE; + +const FieldName_AST : ADL.ScopedDecl = + {"moduleName":"common.tabular","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.strings","name":"StringNE"}},"parameters":[]}}},"name":"FieldName","version":{"kind":"nothing"}}}; + +export const snFieldName: ADL.ScopedName = {moduleName:"common.tabular", name:"FieldName"}; + +export function texprFieldName(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFieldName},parameters:[]}}; +} + +export interface ExprLike { + expr: Expr; + pattern: string; + caseSensitive: boolean; +} + +export function makeExprLike( + input: { + expr: Expr, + pattern: string, + caseSensitive?: boolean, + } +): ExprLike { + return { + expr: input.expr, + pattern: input.pattern, + caseSensitive: input.caseSensitive === undefined ? true : input.caseSensitive, + }; +} + +const ExprLike_AST : ADL.ScopedDecl = + {"moduleName":"common.tabular","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"expr","default":{"kind":"nothing"},"name":"expr","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"Expr"}},"parameters":[]}},{"annotations":[],"serializedName":"pattern","default":{"kind":"nothing"},"name":"pattern","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"caseSensitive","default":{"kind":"just","value":true},"name":"caseSensitive","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}}]}},"name":"ExprLike","version":{"kind":"nothing"}}}; + +export const snExprLike: ADL.ScopedName = {moduleName:"common.tabular", name:"ExprLike"}; + +export function texprExprLike(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snExprLike},parameters:[]}}; +} + +export interface ExprIn { + expr: Expr; + exprs: Expr[]; +} + +export function makeExprIn( + input: { + expr: Expr, + exprs: Expr[], + } +): ExprIn { + return { + expr: input.expr, + exprs: input.exprs, + }; +} + +const ExprIn_AST : ADL.ScopedDecl = + {"moduleName":"common.tabular","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"expr","default":{"kind":"nothing"},"name":"expr","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"Expr"}},"parameters":[]}},{"annotations":[],"serializedName":"exprs","default":{"kind":"nothing"},"name":"exprs","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"Expr"}},"parameters":[]}]}}]}},"name":"ExprIn","version":{"kind":"nothing"}}}; + +export const snExprIn: ADL.ScopedName = {moduleName:"common.tabular", name:"ExprIn"}; + +export function texprExprIn(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snExprIn},parameters:[]}}; +} + +export interface ExprComparison { + expr1: Expr; + expr2: Expr; +} + +export function makeExprComparison( + input: { + expr1: Expr, + expr2: Expr, + } +): ExprComparison { + return { + expr1: input.expr1, + expr2: input.expr2, + }; +} + +const ExprComparison_AST : ADL.ScopedDecl = + {"moduleName":"common.tabular","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"expr1","default":{"kind":"nothing"},"name":"expr1","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"Expr"}},"parameters":[]}},{"annotations":[],"serializedName":"expr2","default":{"kind":"nothing"},"name":"expr2","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"Expr"}},"parameters":[]}}]}},"name":"ExprComparison","version":{"kind":"nothing"}}}; + +export const snExprComparison: ADL.ScopedName = {moduleName:"common.tabular", name:"ExprComparison"}; + +export function texprExprComparison(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snExprComparison},parameters:[]}}; +} + +export interface FieldPredicate_EqualTo { + kind: 'equalTo'; + value: ExprComparison; +} +export interface FieldPredicate_In { + kind: 'in'; + value: ExprIn; +} +export interface FieldPredicate_Like { + kind: 'like'; + value: ExprLike; +} +export interface FieldPredicate_Isnull { + kind: 'isnull'; + value: Expr; +} +export interface FieldPredicate_Not { + kind: 'not'; + value: FieldPredicate; +} +export interface FieldPredicate_GreaterThan { + kind: 'greaterThan'; + value: ExprComparison; +} +export interface FieldPredicate_LessThan { + kind: 'lessThan'; + value: ExprComparison; +} +export interface FieldPredicate_And { + kind: 'and'; + value: FieldPredicate[]; +} +export interface FieldPredicate_Or { + kind: 'or'; + value: FieldPredicate[]; +} +export interface FieldPredicate_Literal { + kind: 'literal'; + value: boolean; +} + +export type FieldPredicate = FieldPredicate_EqualTo | FieldPredicate_In | FieldPredicate_Like | FieldPredicate_Isnull | FieldPredicate_Not | FieldPredicate_GreaterThan | FieldPredicate_LessThan | FieldPredicate_And | FieldPredicate_Or | FieldPredicate_Literal; + +export interface FieldPredicateOpts { + equalTo: ExprComparison; + in: ExprIn; + like: ExprLike; + isnull: Expr; + not: FieldPredicate; + greaterThan: ExprComparison; + lessThan: ExprComparison; + and: FieldPredicate[]; + or: FieldPredicate[]; + literal: boolean; +} + +export function makeFieldPredicate(kind: K, value: FieldPredicateOpts[K]) { return {kind, value}; } + +const FieldPredicate_AST : ADL.ScopedDecl = + {"moduleName":"common.tabular","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"equalTo","default":{"kind":"nothing"},"name":"equalTo","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"ExprComparison"}},"parameters":[]}},{"annotations":[],"serializedName":"in","default":{"kind":"nothing"},"name":"in","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"ExprIn"}},"parameters":[]}},{"annotations":[],"serializedName":"like","default":{"kind":"nothing"},"name":"like","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"ExprLike"}},"parameters":[]}},{"annotations":[],"serializedName":"isnull","default":{"kind":"nothing"},"name":"isnull","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"Expr"}},"parameters":[]}},{"annotations":[],"serializedName":"not","default":{"kind":"nothing"},"name":"not","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"FieldPredicate"}},"parameters":[]}},{"annotations":[],"serializedName":"greaterThan","default":{"kind":"nothing"},"name":"greaterThan","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"ExprComparison"}},"parameters":[]}},{"annotations":[],"serializedName":"lessThan","default":{"kind":"nothing"},"name":"lessThan","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"ExprComparison"}},"parameters":[]}},{"annotations":[],"serializedName":"and","default":{"kind":"nothing"},"name":"and","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"FieldPredicate"}},"parameters":[]}]}},{"annotations":[],"serializedName":"or","default":{"kind":"nothing"},"name":"or","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"FieldPredicate"}},"parameters":[]}]}},{"annotations":[],"serializedName":"literal","default":{"kind":"nothing"},"name":"literal","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}}]}},"name":"FieldPredicate","version":{"kind":"nothing"}}}; + +export const snFieldPredicate: ADL.ScopedName = {moduleName:"common.tabular", name:"FieldPredicate"}; + +export function texprFieldPredicate(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFieldPredicate},parameters:[]}}; +} + +export interface Expr_String { + kind: 'string'; + value: string; +} +export interface Expr_Int { + kind: 'int'; + value: number; +} +export interface Expr_Bool { + kind: 'bool'; + value: boolean; +} +export interface Expr_Date { + kind: 'date'; + value: common.LocalDate; +} +export interface Expr_Instant { + kind: 'instant'; + value: common.Instant; +} +export interface Expr_Field { + kind: 'field'; + value: FieldName; +} +export interface Expr_CurrentDate { + kind: 'currentDate'; +} +export interface Expr_Concat { + kind: 'concat'; + value: Expr[]; +} + +export type Expr = Expr_String | Expr_Int | Expr_Bool | Expr_Date | Expr_Instant | Expr_Field | Expr_CurrentDate | Expr_Concat; + +export interface ExprOpts { + string: string; + int: number; + bool: boolean; + date: common.LocalDate; + instant: common.Instant; + field: FieldName; + currentDate: null; + concat: Expr[]; +} + +export function makeExpr(kind: K, value: ExprOpts[K]) { return {kind, value}; } + +const Expr_AST : ADL.ScopedDecl = + {"moduleName":"common.tabular","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"string","default":{"kind":"nothing"},"name":"string","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"int","default":{"kind":"nothing"},"name":"int","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}},{"annotations":[],"serializedName":"bool","default":{"kind":"nothing"},"name":"bool","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"date","default":{"kind":"nothing"},"name":"date","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"LocalDate"}},"parameters":[]}},{"annotations":[],"serializedName":"instant","default":{"kind":"nothing"},"name":"instant","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"Instant"}},"parameters":[]}},{"annotations":[],"serializedName":"field","default":{"kind":"nothing"},"name":"field","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"FieldName"}},"parameters":[]}},{"annotations":[],"serializedName":"currentDate","default":{"kind":"nothing"},"name":"currentDate","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"concat","default":{"kind":"nothing"},"name":"concat","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"Expr"}},"parameters":[]}]}}]}},"name":"Expr","version":{"kind":"nothing"}}}; + +export const snExpr: ADL.ScopedName = {moduleName:"common.tabular", name:"Expr"}; + +export function texprExpr(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snExpr},parameters:[]}}; +} + +export type SortDirection = 'ascending' | 'descending'; +export const valuesSortDirection : SortDirection[] = ['ascending', 'descending']; + +const SortDirection_AST : ADL.ScopedDecl = + {"moduleName":"common.tabular","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"ascending","default":{"kind":"nothing"},"name":"ascending","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"descending","default":{"kind":"nothing"},"name":"descending","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}}]}},"name":"SortDirection","version":{"kind":"nothing"}}}; + +export const snSortDirection: ADL.ScopedName = {moduleName:"common.tabular", name:"SortDirection"}; + +export function texprSortDirection(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snSortDirection},parameters:[]}}; +} + +export interface SortField { + field: FieldName; + direction: SortDirection; +} + +export function makeSortField( + input: { + field: FieldName, + direction: SortDirection, + } +): SortField { + return { + field: input.field, + direction: input.direction, + }; +} + +const SortField_AST : ADL.ScopedDecl = + {"moduleName":"common.tabular","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"field","default":{"kind":"nothing"},"name":"field","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"FieldName"}},"parameters":[]}},{"annotations":[],"serializedName":"direction","default":{"kind":"nothing"},"name":"direction","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"SortDirection"}},"parameters":[]}}]}},"name":"SortField","version":{"kind":"nothing"}}}; + +export const snSortField: ADL.ScopedName = {moduleName:"common.tabular", name:"SortField"}; + +export function texprSortField(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snSortField},parameters:[]}}; +} + +export interface TableView { + columns: FieldName[]; + filter: FieldPredicate; + sorting: SortField[]; +} + +export function makeTableView( + input: { + columns: FieldName[], + filter?: FieldPredicate, + sorting?: SortField[], + } +): TableView { + return { + columns: input.columns, + filter: input.filter === undefined ? {kind : "literal", value : true} : input.filter, + sorting: input.sorting === undefined ? [] : input.sorting, + }; +} + +const TableView_AST : ADL.ScopedDecl = + {"moduleName":"common.tabular","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"columns","default":{"kind":"nothing"},"name":"columns","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"FieldName"}},"parameters":[]}]}},{"annotations":[],"serializedName":"filter","default":{"kind":"just","value":{"literal":true}},"name":"filter","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"FieldPredicate"}},"parameters":[]}},{"annotations":[],"serializedName":"sorting","default":{"kind":"just","value":[]},"name":"sorting","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"SortField"}},"parameters":[]}]}}]}},"name":"TableView","version":{"kind":"nothing"}}}; + +export const snTableView: ADL.ScopedName = {moduleName:"common.tabular", name:"TableView"}; + +export function texprTableView(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snTableView},parameters:[]}}; +} + +export interface TableQuery { + filter: FieldPredicate; + sorting: SortField[]; + offset: number; + count: number; +} + +export function makeTableQuery( + input: { + filter?: FieldPredicate, + sorting?: SortField[], + offset?: number, + count?: number, + } +): TableQuery { + return { + filter: input.filter === undefined ? {kind : "literal", value : true} : input.filter, + sorting: input.sorting === undefined ? [] : input.sorting, + offset: input.offset === undefined ? 0 : input.offset, + count: input.count === undefined ? -1 : input.count, + }; +} + +const TableQuery_AST : ADL.ScopedDecl = + {"moduleName":"common.tabular","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"filter","default":{"kind":"just","value":{"literal":true}},"name":"filter","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"FieldPredicate"}},"parameters":[]}},{"annotations":[],"serializedName":"sorting","default":{"kind":"just","value":[]},"name":"sorting","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"SortField"}},"parameters":[]}]}},{"annotations":[],"serializedName":"offset","default":{"kind":"just","value":0},"name":"offset","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}},{"annotations":[],"serializedName":"count","default":{"kind":"just","value":-1},"name":"count","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}}]}},"name":"TableQuery","version":{"kind":"nothing"}}}; + +export const snTableQuery: ADL.ScopedName = {moduleName:"common.tabular", name:"TableQuery"}; + +export function texprTableQuery(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snTableQuery},parameters:[]}}; +} + +export interface SingleField { + value: T; +} + +export function makeSingleField( + input: { + value: T, + } +): SingleField { + return { + value: input.value, + }; +} + +const SingleField_AST : ADL.ScopedDecl = + {"moduleName":"common.tabular","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["T"],"fields":[{"annotations":[],"serializedName":"value","default":{"kind":"nothing"},"name":"value","typeExpr":{"typeRef":{"kind":"typeParam","value":"T"},"parameters":[]}}]}},"name":"SingleField","version":{"kind":"nothing"}}}; + +export const snSingleField: ADL.ScopedName = {moduleName:"common.tabular", name:"SingleField"}; + +export function texprSingleField(texprT : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snSingleField},parameters:[texprT.value]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.tabular.FieldName" : FieldName_AST, + "common.tabular.ExprLike" : ExprLike_AST, + "common.tabular.ExprIn" : ExprIn_AST, + "common.tabular.ExprComparison" : ExprComparison_AST, + "common.tabular.FieldPredicate" : FieldPredicate_AST, + "common.tabular.Expr" : Expr_AST, + "common.tabular.SortDirection" : SortDirection_AST, + "common.tabular.SortField" : SortField_AST, + "common.tabular.TableView" : TableView_AST, + "common.tabular.TableQuery" : TableQuery_AST, + "common.tabular.SingleField" : SingleField_AST +}; diff --git a/typescript/workspace/generated/common/tsconfig.json b/typescript/workspace/generated/common/tsconfig.json new file mode 100644 index 00000000..a3b461dc --- /dev/null +++ b/typescript/workspace/generated/common/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "tsconfig/base.json", + "include": [ + "." + ], + "exclude": [ + "dist", + "build", + "node_modules" + ], + "compilerOptions": { + "outDir": "dist", + "lib": [ + "es2020" + ] + } +} \ No newline at end of file diff --git a/typescript/workspace/generated/common/ui.ts b/typescript/workspace/generated/common/ui.ts new file mode 100644 index 00000000..46fca7b7 --- /dev/null +++ b/typescript/workspace/generated/common/ui.ts @@ -0,0 +1,141 @@ +import * as ADL from "@adl-lang/runtime/adl"; +import * as sys_types from "@adl-lang/sys/types"; + +/* @generated from adl module common.ui */ + +export type FormLabel = string; + +const FormLabel_AST : ADL.ScopedDecl = + {"moduleName":"common.ui","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"FormLabel","version":{"kind":"nothing"}}}; + +export const snFormLabel: ADL.ScopedName = {moduleName:"common.ui", name:"FormLabel"}; + +export function texprFormLabel(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFormLabel},parameters:[]}}; +} + +export type FormGroupKey = string; + +const FormGroupKey_AST : ADL.ScopedDecl = + {"moduleName":"common.ui","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"FormGroupKey","version":{"kind":"nothing"}}}; + +export const snFormGroupKey: ADL.ScopedName = {moduleName:"common.ui", name:"FormGroupKey"}; + +export function texprFormGroupKey(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFormGroupKey},parameters:[]}}; +} + +export interface FormGroups { + defaultKey: FormGroupKey; + labels: sys_types.Pair[]; +} + +export function makeFormGroups( + input: { + defaultKey: FormGroupKey, + labels: sys_types.Pair[], + } +): FormGroups { + return { + defaultKey: input.defaultKey, + labels: input.labels, + }; +} + +const FormGroups_AST : ADL.ScopedDecl = + {"moduleName":"common.ui","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"defaultKey","default":{"kind":"nothing"},"name":"defaultKey","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.ui","name":"FormGroupKey"}},"parameters":[]}},{"annotations":[],"serializedName":"labels","default":{"kind":"nothing"},"name":"labels","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.types","name":"Pair"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.ui","name":"FormGroupKey"}},"parameters":[]},{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}]}}]}},"name":"FormGroups","version":{"kind":"nothing"}}}; + +export const snFormGroups: ADL.ScopedName = {moduleName:"common.ui", name:"FormGroups"}; + +export function texprFormGroups(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snFormGroups},parameters:[]}}; +} + +/** + * An field/type alias annotation to constrain the + * values allowed by a string to the enumerated values + */ +export interface ValidValues { +/** + * The allowed values + */ + values: string[]; +/** + * A (short) user readable string describing the + * expected text. + */ + description: string; +} + +export function makeValidValues( + input: { + values: string[], + description: string, + } +): ValidValues { + return { + values: input.values, + description: input.description, + }; +} + +const ValidValues_AST : ADL.ScopedDecl = + {"moduleName":"common.ui","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"values","default":{"kind":"nothing"},"name":"values","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}},{"annotations":[],"serializedName":"description","default":{"kind":"nothing"},"name":"description","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"ValidValues","version":{"kind":"nothing"}}}; + +export const snValidValues: ADL.ScopedName = {moduleName:"common.ui", name:"ValidValues"}; + +export function texprValidValues(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snValidValues},parameters:[]}}; +} + +/** + * An field/type alias annotation to constrain the + * values allowed by a string to a regular expression + */ +export interface ValidRegex { +/** + * The regexp that must be matched + */ + regex: string; +/** + * A (short) user readable string describing the + * expected text. + */ + description: string; +/** + * The regex group index to return if matches + * 0 is the entire string + */ + returnGroup: number; +} + +export function makeValidRegex( + input: { + regex: string, + description: string, + returnGroup?: number, + } +): ValidRegex { + return { + regex: input.regex, + description: input.description, + returnGroup: input.returnGroup === undefined ? 0 : input.returnGroup, + }; +} + +const ValidRegex_AST : ADL.ScopedDecl = + {"moduleName":"common.ui","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"regex","default":{"kind":"nothing"},"name":"regex","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"description","default":{"kind":"nothing"},"name":"description","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"returnGroup","default":{"kind":"just","value":0},"name":"returnGroup","typeExpr":{"typeRef":{"kind":"primitive","value":"Int8"},"parameters":[]}}]}},"name":"ValidRegex","version":{"kind":"nothing"}}}; + +export const snValidRegex: ADL.ScopedName = {moduleName:"common.ui", name:"ValidRegex"}; + +export function texprValidRegex(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snValidRegex},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "common.ui.FormLabel" : FormLabel_AST, + "common.ui.FormGroupKey" : FormGroupKey_AST, + "common.ui.FormGroups" : FormGroups_AST, + "common.ui.ValidValues" : ValidValues_AST, + "common.ui.ValidRegex" : ValidRegex_AST +}; diff --git a/typescript/workspace/generated/protoclient/.adl-manifest b/typescript/workspace/generated/protoclient/.adl-manifest new file mode 100644 index 00000000..2b37ce66 --- /dev/null +++ b/typescript/workspace/generated/protoclient/.adl-manifest @@ -0,0 +1,8 @@ +# manifest @generated by the adl compiler +index.ts +protoapp/api.ts +protoapp/config.ts +protoapp/db.ts +protoapp/index.ts +protoapp/uiconfig.ts +resolver.ts diff --git a/typescript/workspace/generated/protoclient/index.ts b/typescript/workspace/generated/protoclient/index.ts new file mode 100644 index 00000000..c2601171 --- /dev/null +++ b/typescript/workspace/generated/protoclient/index.ts @@ -0,0 +1,2 @@ +/* @generated - key "" */ +export * as protoapp from './protoapp/index'; diff --git a/typescript/workspace/generated/protoclient/package.json b/typescript/workspace/generated/protoclient/package.json new file mode 100644 index 00000000..08302384 --- /dev/null +++ b/typescript/workspace/generated/protoclient/package.json @@ -0,0 +1,18 @@ +{ + "name": "@adl-lang/protoclient", + "version": "1.0.0", + "scripts": { + "clean": "rm -rf dist && rm -rf node_modules", + "tsc": "tsc" + }, + "dependencies": { + "@adl-lang/sys": "workspace:*", + "@adl-lang/common": "workspace:*", + "base64-js": "^1.5.1", + "@adl-lang/runtime": "^1.0.0" + }, + "devDependencies": { + "typescript": "^4.9.3", + "tsconfig": "workspace:*" + } +} \ No newline at end of file diff --git a/typescript/workspace/generated/protoclient/protoapp/api.ts b/typescript/workspace/generated/protoclient/protoapp/api.ts new file mode 100644 index 00000000..ad35be76 --- /dev/null +++ b/typescript/workspace/generated/protoclient/protoapp/api.ts @@ -0,0 +1,365 @@ +import * as protoclient_protoapp_db from "./db"; +import * as common from "@adl-lang/common/"; +import * as common_config_log from "@adl-lang/common/config/log"; +import * as common_db from "@adl-lang/common/db"; +import * as common_http from "@adl-lang/common/http"; +import * as common_strings from "@adl-lang/common/strings"; +import * as common_tabular from "@adl-lang/common/tabular"; +import * as ADL from "@adl-lang/runtime/adl"; +import * as sys_types from "@adl-lang/sys/types"; + +/* @generated from adl module protoclient.protoapp.api */ + +export interface X<_A> { +} + +export function makeX<_A>( + _input: {} +): X<_A> { + return {}; +} + +const X_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["A"],"fields":[]}},"name":"X","version":{"kind":"nothing"}}}; + +export const snX: ADL.ScopedName = {moduleName:"protoclient.protoapp.api", name:"X"}; + +export function texprX(texprA : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snX},parameters:[texprA.value]}}; +} + +/** + * The app API + */ +export interface ApiRequests { + x: X; + imamap: sys_types.Map; +/** + * Login a user + */ + with_prim: common_http.HttpPost; +/** + * Login a user + */ + login: common_http.HttpPost; +/** + * Post a message to the noticeboard + */ + newMessage: common_http.HttpPost; +/** + * Get recent noticeboard messages + */ + recentMessages: common_http.HttpPost>; +/** + * Gets the logged in user details + */ + whoAmI: common_http.HttpGet; +/** + * Create a new user + */ + createUser: common_http.HttpPost; +/** + * Update an existing user + */ + updateUser: common_http.HttpPost, common.Unit>; +/** + * Delete an existing user + */ + deleteUser: common_http.HttpPost; +/** + * Query existing users sorted and filters according to the + * TableQuery request. + */ + queryUsers: common_http.HttpPost>>; +/** + * Logs an error from the client app without user information, i.e. when the + * user has not logged in + */ + logClientErrorPublic: common_http.HttpPost; +/** + * Logs an error from the client app and includes user information + */ + logClientErrorUser: common_http.HttpPost; +} + +export function makeApiRequests( + input: { + x: X, + imamap: sys_types.Map, + with_prim?: common_http.HttpPost, + login?: common_http.HttpPost, + newMessage?: common_http.HttpPost, + recentMessages?: common_http.HttpPost>, + whoAmI?: common_http.HttpGet, + createUser?: common_http.HttpPost, + updateUser?: common_http.HttpPost, common.Unit>, + deleteUser?: common_http.HttpPost, + queryUsers?: common_http.HttpPost>>, + logClientErrorPublic?: common_http.HttpPost, + logClientErrorUser?: common_http.HttpPost, + } +): ApiRequests { + return { + x: input.x, + imamap: input.imamap, + with_prim: input.with_prim === undefined ? {path : "/login", security : {kind : "public"}, rateLimit : null, reqType : ADL.texprString(), respType : ADL.texprVector(ADL.texprStringMap(ADL.texprInt64()))} : input.with_prim, + login: input.login === undefined ? {path : "/login", security : {kind : "public"}, rateLimit : null, reqType : texprLoginReq(), respType : texprLoginResp()} : input.login, + newMessage: input.newMessage === undefined ? {path : "/messages/new", security : {kind : "token"}, rateLimit : null, reqType : texprNewMessageReq(), respType : common.texprUnit()} : input.newMessage, + recentMessages: input.recentMessages === undefined ? {path : "/messages/recent", security : {kind : "token"}, rateLimit : null, reqType : texprRecentMessagesReq(), respType : common.texprPaginated(texprMessage())} : input.recentMessages, + whoAmI: input.whoAmI === undefined ? {path : "/whoami", security : {kind : "token"}, rateLimit : null, respType : texprUserProfile()} : input.whoAmI, + createUser: input.createUser === undefined ? {path : "/users/create", security : {kind : "tokenWithRole", value : "admin"}, rateLimit : null, reqType : texprUserReq(), respType : protoclient_protoapp_db.texprAppUserId()} : input.createUser, + updateUser: input.updateUser === undefined ? {path : "/users/update", security : {kind : "tokenWithRole", value : "admin"}, rateLimit : null, reqType : common_db.texprWithDbId(texprUserReq()), respType : common.texprUnit()} : input.updateUser, + deleteUser: input.deleteUser === undefined ? {path : "/users/delete", security : {kind : "tokenWithRole", value : "admin"}, rateLimit : null, reqType : protoclient_protoapp_db.texprAppUserId(), respType : common.texprUnit()} : input.deleteUser, + queryUsers: input.queryUsers === undefined ? {path : "/users/query", security : {kind : "tokenWithRole", value : "admin"}, rateLimit : null, reqType : common_tabular.texprTableQuery(), respType : common.texprPaginated(common_db.texprWithDbId(protoclient_protoapp_db.texprAppUser()))} : input.queryUsers, + logClientErrorPublic: input.logClientErrorPublic === undefined ? {path : "/client/log/public", security : {kind : "public"}, rateLimit : {maxRequests : 6, perTimeUnit : "minute"}, reqType : texprClientLogReq(), respType : common.texprUnit()} : input.logClientErrorPublic, + logClientErrorUser: input.logClientErrorUser === undefined ? {path : "/client/log/user", security : {kind : "token"}, rateLimit : null, reqType : texprClientLogReq(), respType : common.texprUnit()} : input.logClientErrorUser, + }; +} + +const ApiRequests_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"x","default":{"kind":"nothing"},"name":"x","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.api","name":"X"}},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}},{"annotations":[],"serializedName":"imamap","default":{"kind":"nothing"},"name":"imamap","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.types","name":"Map"}},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]},{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}},{"annotations":[],"serializedName":"with_prim","default":{"kind":"just","value":{"path":"/login","security":"public"}},"name":"with_prim","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]},{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"primitive","value":"StringMap"},"parameters":[{"typeRef":{"kind":"primitive","value":"Int64"},"parameters":[]}]}]}]}},{"annotations":[],"serializedName":"login","default":{"kind":"just","value":{"path":"/login","security":"public"}},"name":"login","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.api","name":"LoginReq"}},"parameters":[]},{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.api","name":"LoginResp"}},"parameters":[]}]}},{"annotations":[],"serializedName":"newMessage","default":{"kind":"just","value":{"path":"/messages/new","security":"token"}},"name":"newMessage","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.api","name":"NewMessageReq"}},"parameters":[]},{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"Unit"}},"parameters":[]}]}},{"annotations":[],"serializedName":"recentMessages","default":{"kind":"just","value":{"path":"/messages/recent","security":"token"}},"name":"recentMessages","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.api","name":"RecentMessagesReq"}},"parameters":[]},{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"Paginated"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.api","name":"Message"}},"parameters":[]}]}]}},{"annotations":[],"serializedName":"whoAmI","default":{"kind":"just","value":{"path":"/whoami","security":"token"}},"name":"whoAmI","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpGet"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.api","name":"UserProfile"}},"parameters":[]}]}},{"annotations":[],"serializedName":"createUser","default":{"kind":"just","value":{"path":"/users/create","security":{"tokenWithRole":"admin"}}},"name":"createUser","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.api","name":"UserReq"}},"parameters":[]},{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.db","name":"AppUserId"}},"parameters":[]}]}},{"annotations":[],"serializedName":"updateUser","default":{"kind":"just","value":{"path":"/users/update","security":{"tokenWithRole":"admin"}}},"name":"updateUser","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.db","name":"WithDbId"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.api","name":"UserReq"}},"parameters":[]}]},{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"Unit"}},"parameters":[]}]}},{"annotations":[],"serializedName":"deleteUser","default":{"kind":"just","value":{"path":"/users/delete","security":{"tokenWithRole":"admin"}}},"name":"deleteUser","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.db","name":"AppUserId"}},"parameters":[]},{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"Unit"}},"parameters":[]}]}},{"annotations":[],"serializedName":"queryUsers","default":{"kind":"just","value":{"path":"/users/query","security":{"tokenWithRole":"admin"}}},"name":"queryUsers","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.tabular","name":"TableQuery"}},"parameters":[]},{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"Paginated"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"common.db","name":"WithDbId"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.db","name":"AppUser"}},"parameters":[]}]}]}]}},{"annotations":[],"serializedName":"logClientErrorPublic","default":{"kind":"just","value":{"path":"/client/log/public","rateLimit":{"maxRequests":6,"perTimeUnit":"minute"},"security":"public"}},"name":"logClientErrorPublic","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.api","name":"ClientLogReq"}},"parameters":[]},{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"Unit"}},"parameters":[]}]}},{"annotations":[],"serializedName":"logClientErrorUser","default":{"kind":"just","value":{"path":"/client/log/user","security":"token"}},"name":"logClientErrorUser","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.http","name":"HttpPost"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.api","name":"ClientLogReq"}},"parameters":[]},{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"Unit"}},"parameters":[]}]}}]}},"name":"ApiRequests","version":{"kind":"nothing"}}}; + +export const snApiRequests: ADL.ScopedName = {moduleName:"protoclient.protoapp.api", name:"ApiRequests"}; + +export function texprApiRequests(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snApiRequests},parameters:[]}}; +} + +export interface UserProfile { + id: protoclient_protoapp_db.AppUserId; + fullname: string; + email: string; + isAdmin: boolean; +} + +export function makeUserProfile( + input: { + id: protoclient_protoapp_db.AppUserId, + fullname: string, + email: string, + isAdmin: boolean, + } +): UserProfile { + return { + id: input.id, + fullname: input.fullname, + email: input.email, + isAdmin: input.isAdmin, + }; +} + +const UserProfile_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"id","default":{"kind":"nothing"},"name":"id","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.db","name":"AppUserId"}},"parameters":[]}},{"annotations":[],"serializedName":"fullname","default":{"kind":"nothing"},"name":"fullname","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"email","default":{"kind":"nothing"},"name":"email","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"isAdmin","default":{"kind":"nothing"},"name":"isAdmin","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}}]}},"name":"UserProfile","version":{"kind":"nothing"}}}; + +export const snUserProfile: ADL.ScopedName = {moduleName:"protoclient.protoapp.api", name:"UserProfile"}; + +export function texprUserProfile(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snUserProfile},parameters:[]}}; +} + +/** + * Details for a user + */ +export interface UserReq { + fullname: string; + email: string; + password: common_strings.Password; +} + +export function makeUserReq( + input: { + fullname: string, + email: string, + password: common_strings.Password, + } +): UserReq { + return { + fullname: input.fullname, + email: input.email, + password: input.password, + }; +} + +const UserReq_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"fullname","default":{"kind":"nothing"},"name":"fullname","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"email","default":{"kind":"nothing"},"name":"email","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"password","default":{"kind":"nothing"},"name":"password","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.strings","name":"Password"}},"parameters":[]}}]}},"name":"UserReq","version":{"kind":"nothing"}}}; + +export const snUserReq: ADL.ScopedName = {moduleName:"protoclient.protoapp.api", name:"UserReq"}; + +export function texprUserReq(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snUserReq},parameters:[]}}; +} + +export interface LoginReq { + email: common_strings.StringNE; + password: common_strings.Password; +} + +export function makeLoginReq( + input: { + email: common_strings.StringNE, + password: common_strings.Password, + } +): LoginReq { + return { + email: input.email, + password: input.password, + }; +} + +const LoginReq_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"email","default":{"kind":"nothing"},"name":"email","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.strings","name":"StringNE"}},"parameters":[]}},{"annotations":[],"serializedName":"password","default":{"kind":"nothing"},"name":"password","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.strings","name":"Password"}},"parameters":[]}}]}},"name":"LoginReq","version":{"kind":"nothing"}}}; + +export const snLoginReq: ADL.ScopedName = {moduleName:"protoclient.protoapp.api", name:"LoginReq"}; + +export function texprLoginReq(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snLoginReq},parameters:[]}}; +} + +export interface LoginResp_AccessToken { + kind: 'accessToken'; + value: common_strings.StringNE; +} +export interface LoginResp_InvalidCredentials { + kind: 'invalidCredentials'; +} + +export type LoginResp = LoginResp_AccessToken | LoginResp_InvalidCredentials; + +export interface LoginRespOpts { + accessToken: common_strings.StringNE; + invalidCredentials: null; +} + +export function makeLoginResp(kind: K, value: LoginRespOpts[K]) { return {kind, value}; } + +const LoginResp_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.api","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"accessToken","default":{"kind":"nothing"},"name":"accessToken","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.strings","name":"StringNE"}},"parameters":[]}},{"annotations":[],"serializedName":"invalidCredentials","default":{"kind":"nothing"},"name":"invalidCredentials","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}}]}},"name":"LoginResp","version":{"kind":"nothing"}}}; + +export const snLoginResp: ADL.ScopedName = {moduleName:"protoclient.protoapp.api", name:"LoginResp"}; + +export function texprLoginResp(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snLoginResp},parameters:[]}}; +} + +export interface NewMessageReq { + message: common_strings.StringML; +} + +export function makeNewMessageReq( + input: { + message: common_strings.StringML, + } +): NewMessageReq { + return { + message: input.message, + }; +} + +const NewMessageReq_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"message","default":{"kind":"nothing"},"name":"message","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.strings","name":"StringML"}},"parameters":[]}}]}},"name":"NewMessageReq","version":{"kind":"nothing"}}}; + +export const snNewMessageReq: ADL.ScopedName = {moduleName:"protoclient.protoapp.api", name:"NewMessageReq"}; + +export function texprNewMessageReq(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snNewMessageReq},parameters:[]}}; +} + +export interface RecentMessagesReq { + offset: number; + count: number; +} + +export function makeRecentMessagesReq( + input: { + offset?: number, + count?: number, + } +): RecentMessagesReq { + return { + offset: input.offset === undefined ? 0 : input.offset, + count: input.count === undefined ? 20 : input.count, + }; +} + +const RecentMessagesReq_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"offset","default":{"kind":"just","value":0},"name":"offset","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}},{"annotations":[],"serializedName":"count","default":{"kind":"just","value":20},"name":"count","typeExpr":{"typeRef":{"kind":"primitive","value":"Int32"},"parameters":[]}}]}},"name":"RecentMessagesReq","version":{"kind":"nothing"}}}; + +export const snRecentMessagesReq: ADL.ScopedName = {moduleName:"protoclient.protoapp.api", name:"RecentMessagesReq"}; + +export function texprRecentMessagesReq(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snRecentMessagesReq},parameters:[]}}; +} + +export interface Message { + id: protoclient_protoapp_db.MessageId; + postedAt: common.Instant; + userFullName: string; + message: common_strings.StringML; +} + +export function makeMessage( + input: { + id: protoclient_protoapp_db.MessageId, + postedAt: common.Instant, + userFullName: string, + message: common_strings.StringML, + } +): Message { + return { + id: input.id, + postedAt: input.postedAt, + userFullName: input.userFullName, + message: input.message, + }; +} + +const Message_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"id","default":{"kind":"nothing"},"name":"id","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.db","name":"MessageId"}},"parameters":[]}},{"annotations":[],"serializedName":"postedAt","default":{"kind":"nothing"},"name":"postedAt","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"Instant"}},"parameters":[]}},{"annotations":[],"serializedName":"userFullName","default":{"kind":"nothing"},"name":"userFullName","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"message","default":{"kind":"nothing"},"name":"message","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.strings","name":"StringML"}},"parameters":[]}}]}},"name":"Message","version":{"kind":"nothing"}}}; + +export const snMessage: ADL.ScopedName = {moduleName:"protoclient.protoapp.api", name:"Message"}; + +export function texprMessage(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snMessage},parameters:[]}}; +} + +export interface ClientLogReq { + level: common_config_log.LogLevel; + error: string; + stacktrace: (string|null); +} + +export function makeClientLogReq( + input: { + level: common_config_log.LogLevel, + error: string, + stacktrace: (string|null), + } +): ClientLogReq { + return { + level: input.level, + error: input.error, + stacktrace: input.stacktrace, + }; +} + +const ClientLogReq_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.api","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"level","default":{"kind":"nothing"},"name":"level","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.log","name":"LogLevel"}},"parameters":[]}},{"annotations":[],"serializedName":"error","default":{"kind":"nothing"},"name":"error","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"stacktrace","default":{"kind":"nothing"},"name":"stacktrace","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}]}}]}},"name":"ClientLogReq","version":{"kind":"nothing"}}}; + +export const snClientLogReq: ADL.ScopedName = {moduleName:"protoclient.protoapp.api", name:"ClientLogReq"}; + +export function texprClientLogReq(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snClientLogReq},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "protoclient.protoapp.api.X" : X_AST, + "protoclient.protoapp.api.ApiRequests" : ApiRequests_AST, + "protoclient.protoapp.api.UserProfile" : UserProfile_AST, + "protoclient.protoapp.api.UserReq" : UserReq_AST, + "protoclient.protoapp.api.LoginReq" : LoginReq_AST, + "protoclient.protoapp.api.LoginResp" : LoginResp_AST, + "protoclient.protoapp.api.NewMessageReq" : NewMessageReq_AST, + "protoclient.protoapp.api.RecentMessagesReq" : RecentMessagesReq_AST, + "protoclient.protoapp.api.Message" : Message_AST, + "protoclient.protoapp.api.ClientLogReq" : ClientLogReq_AST +}; diff --git a/typescript/workspace/generated/protoclient/protoapp/config.ts b/typescript/workspace/generated/protoclient/protoapp/config.ts new file mode 100644 index 00000000..148a0507 --- /dev/null +++ b/typescript/workspace/generated/protoclient/protoapp/config.ts @@ -0,0 +1,136 @@ +import * as common_config_db from "@adl-lang/common/config/db"; +import * as common_config_frontend from "@adl-lang/common/config/frontend"; +import * as common_config_log from "@adl-lang/common/config/log"; +import * as common_flyway_internals from "@adl-lang/common/flyway/internals"; +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module protoclient.protoapp.config */ + +/** + * Configuration for the server + */ +export interface ServerConfig { +/** + * Port to listen for requests + */ + port: number; +/** + * Environment name, e.g. dev, uat, prod + */ + environment: string; +/** + * Name of the release / code version + */ + releaseName: string; +/** + * The shared secret that will be present on requests + * made by the cron webhook system. + */ + cronSharedSecret: string; +/** + * Secret used to sign JWT tokens + */ + jwtSecret: string; +/** + * Database config + */ + db: common_config_db.PostgreSqlConfig; +/** + * Server-side logging config + */ + logging: common_config_log.LogConfig; +/** + * Client-side logging config + * If not provided all client logs will appear in the server logs + */ + clientLogging: (ClientLogConfig|null); +/** + * Frontend threadpool configuration + */ + threadPool: common_config_frontend.ThreadPoolConfig; + flyway: (LocalFlywayConfig|null); +} + +export function makeServerConfig( + input: { + port: number, + environment: string, + releaseName: string, + cronSharedSecret: string, + jwtSecret: string, + db: common_config_db.PostgreSqlConfig, + logging: common_config_log.LogConfig, + clientLogging?: (ClientLogConfig|null), + threadPool: common_config_frontend.ThreadPoolConfig, + flyway?: (LocalFlywayConfig|null), + } +): ServerConfig { + return { + port: input.port, + environment: input.environment, + releaseName: input.releaseName, + cronSharedSecret: input.cronSharedSecret, + jwtSecret: input.jwtSecret, + db: input.db, + logging: input.logging, + clientLogging: input.clientLogging === undefined ? null : input.clientLogging, + threadPool: input.threadPool, + flyway: input.flyway === undefined ? null : input.flyway, + }; +} + +const ServerConfig_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.config","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"port","default":{"kind":"nothing"},"name":"port","typeExpr":{"typeRef":{"kind":"primitive","value":"Int16"},"parameters":[]}},{"annotations":[],"serializedName":"environment","default":{"kind":"nothing"},"name":"environment","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"releaseName","default":{"kind":"nothing"},"name":"releaseName","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"cronSharedSecret","default":{"kind":"nothing"},"name":"cronSharedSecret","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"jwtSecret","default":{"kind":"nothing"},"name":"jwtSecret","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"db","default":{"kind":"nothing"},"name":"db","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.db","name":"PostgreSqlConfig"}},"parameters":[]}},{"annotations":[],"serializedName":"logging","default":{"kind":"nothing"},"name":"logging","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.log","name":"LogConfig"}},"parameters":[]}},{"annotations":[],"serializedName":"clientLogging","default":{"kind":"just","value":null},"name":"clientLogging","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.config","name":"ClientLogConfig"}},"parameters":[]}]}},{"annotations":[],"serializedName":"threadPool","default":{"kind":"nothing"},"name":"threadPool","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.frontend","name":"ThreadPoolConfig"}},"parameters":[]}},{"annotations":[],"serializedName":"flyway","default":{"kind":"just","value":null},"name":"flyway","typeExpr":{"typeRef":{"kind":"primitive","value":"Nullable"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.config","name":"LocalFlywayConfig"}},"parameters":[]}]}}]}},"name":"ServerConfig","version":{"kind":"nothing"}}}; + +export const snServerConfig: ADL.ScopedName = {moduleName:"protoclient.protoapp.config", name:"ServerConfig"}; + +export function texprServerConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snServerConfig},parameters:[]}}; +} + +export type ClientLogConfig = common_config_log.FluentdConfig; + +const ClientLogConfig_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.config","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.config.log","name":"FluentdConfig"}},"parameters":[]}}},"name":"ClientLogConfig","version":{"kind":"nothing"}}}; + +export const snClientLogConfig: ADL.ScopedName = {moduleName:"protoclient.protoapp.config", name:"ClientLogConfig"}; + +export function texprClientLogConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snClientLogConfig},parameters:[]}}; +} + +export interface LocalFlywayConfig_Fastdev { + kind: 'fastdev'; +} +export interface LocalFlywayConfig_Deployed { + kind: 'deployed'; +} +export interface LocalFlywayConfig_Advanced { + kind: 'advanced'; + value: common_flyway_internals.FlywayCommand; +} + +export type LocalFlywayConfig = LocalFlywayConfig_Fastdev | LocalFlywayConfig_Deployed | LocalFlywayConfig_Advanced; + +export interface LocalFlywayConfigOpts { + fastdev: null; + deployed: null; + advanced: common_flyway_internals.FlywayCommand; +} + +export function makeLocalFlywayConfig(kind: K, value: LocalFlywayConfigOpts[K]) { return {kind, value}; } + +const LocalFlywayConfig_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.config","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"fastdev","default":{"kind":"nothing"},"name":"fastdev","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"deployed","default":{"kind":"nothing"},"name":"deployed","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"advanced","default":{"kind":"nothing"},"name":"advanced","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.flyway.internals","name":"FlywayCommand"}},"parameters":[]}}]}},"name":"LocalFlywayConfig","version":{"kind":"nothing"}}}; + +export const snLocalFlywayConfig: ADL.ScopedName = {moduleName:"protoclient.protoapp.config", name:"LocalFlywayConfig"}; + +export function texprLocalFlywayConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snLocalFlywayConfig},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "protoclient.protoapp.config.ServerConfig" : ServerConfig_AST, + "protoclient.protoapp.config.ClientLogConfig" : ClientLogConfig_AST, + "protoclient.protoapp.config.LocalFlywayConfig" : LocalFlywayConfig_AST +}; diff --git a/typescript/workspace/generated/protoclient/protoapp/db.ts b/typescript/workspace/generated/protoclient/protoapp/db.ts new file mode 100644 index 00000000..23319ffb --- /dev/null +++ b/typescript/workspace/generated/protoclient/protoapp/db.ts @@ -0,0 +1,153 @@ +import * as common from "@adl-lang/common/"; +import * as common_db from "@adl-lang/common/db"; +import * as common_strings from "@adl-lang/common/strings"; +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module protoclient.protoapp.db */ + +export interface Trade { + commodities: Commodity[]; + date: common.Instant; +} + +export function makeTrade( + input: { + commodities: Commodity[], + date: common.Instant, + } +): Trade { + return { + commodities: input.commodities, + date: input.date, + }; +} + +const Trade_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.db","decl":{"annotations":[{"value":{"withIdPrimaryKey":true},"key":{"moduleName":"common.db","name":"DbTable"}}],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"commodities","default":{"kind":"nothing"},"name":"commodities","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.db","name":"Commodity"}},"parameters":[]}]}},{"annotations":[],"serializedName":"date","default":{"kind":"nothing"},"name":"date","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"Instant"}},"parameters":[]}}]}},"name":"Trade","version":{"kind":"nothing"}}}; + +export const snTrade: ADL.ScopedName = {moduleName:"protoclient.protoapp.db", name:"Trade"}; + +export function texprTrade(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snTrade},parameters:[]}}; +} + +export interface Commodity { + code: string; +} + +export function makeCommodity( + input: { + code: string, + } +): Commodity { + return { + code: input.code, + }; +} + +const Commodity_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.db","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"code","default":{"kind":"nothing"},"name":"code","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"Commodity","version":{"kind":"nothing"}}}; + +export const snCommodity: ADL.ScopedName = {moduleName:"protoclient.protoapp.db", name:"Commodity"}; + +export function texprCommodity(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snCommodity},parameters:[]}}; +} + +/** + * Details for a user + */ +export interface AppUser { + fullname: common_strings.StringNE; + email: common_strings.StringNE; + isAdmin: boolean; + hashedPassword: common_strings.StringNE; +} + +export function makeAppUser( + input: { + fullname: common_strings.StringNE, + email: common_strings.StringNE, + isAdmin: boolean, + hashedPassword?: common_strings.StringNE, + } +): AppUser { + return { + fullname: input.fullname, + email: input.email, + isAdmin: input.isAdmin, + hashedPassword: input.hashedPassword === undefined ? "" : input.hashedPassword, + }; +} + +const AppUser_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.db","decl":{"annotations":[{"value":{"indexes":[["email"]],"label":["fullname"],"withIdPrimaryKey":true},"key":{"moduleName":"common.db","name":"DbTable"}}],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"fullname","default":{"kind":"nothing"},"name":"fullname","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.strings","name":"StringNE"}},"parameters":[]}},{"annotations":[],"serializedName":"email","default":{"kind":"nothing"},"name":"email","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.strings","name":"StringNE"}},"parameters":[]}},{"annotations":[],"serializedName":"isAdmin","default":{"kind":"nothing"},"name":"isAdmin","typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}},{"annotations":[],"serializedName":"hashedPassword","default":{"kind":"just","value":""},"name":"hashedPassword","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.strings","name":"StringNE"}},"parameters":[]}}]}},"name":"AppUser","version":{"kind":"nothing"}}}; + +export const snAppUser: ADL.ScopedName = {moduleName:"protoclient.protoapp.db", name:"AppUser"}; + +export function texprAppUser(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snAppUser},parameters:[]}}; +} + +export type AppUserId = common_db.DbKey; + +const AppUserId_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.db","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.db","name":"DbKey"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.db","name":"AppUser"}},"parameters":[]}]}}},"name":"AppUserId","version":{"kind":"nothing"}}}; + +export const snAppUserId: ADL.ScopedName = {moduleName:"protoclient.protoapp.db", name:"AppUserId"}; + +export function texprAppUserId(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snAppUserId},parameters:[]}}; +} + +/** + * messages posted on the noticeboard + */ +export interface Message { + postedAt: common.Instant; + postedBy: common_db.DbKey; + message: common_strings.StringML; +} + +export function makeMessage( + input: { + postedAt: common.Instant, + postedBy: common_db.DbKey, + message: common_strings.StringML, + } +): Message { + return { + postedAt: input.postedAt, + postedBy: input.postedBy, + message: input.message, + }; +} + +const Message_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.db","decl":{"annotations":[{"value":{"indexes":[["posted_at"]],"withIdPrimaryKey":true},"key":{"moduleName":"common.db","name":"DbTable"}}],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"postedAt","default":{"kind":"nothing"},"name":"postedAt","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common","name":"Instant"}},"parameters":[]}},{"annotations":[],"serializedName":"postedBy","default":{"kind":"nothing"},"name":"postedBy","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.db","name":"DbKey"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.db","name":"AppUser"}},"parameters":[]}]}},{"annotations":[],"serializedName":"message","default":{"kind":"nothing"},"name":"message","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.strings","name":"StringML"}},"parameters":[]}}]}},"name":"Message","version":{"kind":"nothing"}}}; + +export const snMessage: ADL.ScopedName = {moduleName:"protoclient.protoapp.db", name:"Message"}; + +export function texprMessage(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snMessage},parameters:[]}}; +} + +export type MessageId = common_db.DbKey; + +const MessageId_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.db","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"common.db","name":"DbKey"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"protoclient.protoapp.db","name":"Message"}},"parameters":[]}]}}},"name":"MessageId","version":{"kind":"nothing"}}}; + +export const snMessageId: ADL.ScopedName = {moduleName:"protoclient.protoapp.db", name:"MessageId"}; + +export function texprMessageId(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snMessageId},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "protoclient.protoapp.db.Trade" : Trade_AST, + "protoclient.protoapp.db.Commodity" : Commodity_AST, + "protoclient.protoapp.db.AppUser" : AppUser_AST, + "protoclient.protoapp.db.AppUserId" : AppUserId_AST, + "protoclient.protoapp.db.Message" : Message_AST, + "protoclient.protoapp.db.MessageId" : MessageId_AST +}; diff --git a/typescript/workspace/generated/protoclient/protoapp/index.ts b/typescript/workspace/generated/protoclient/protoapp/index.ts new file mode 100644 index 00000000..bb4af98e --- /dev/null +++ b/typescript/workspace/generated/protoclient/protoapp/index.ts @@ -0,0 +1,5 @@ +/* @generated - key "protoapp" */ +export * as api from './api'; +export * as config from './config'; +export * as db from './db'; +export * as uiconfig from './uiconfig'; diff --git a/typescript/workspace/generated/protoclient/protoapp/uiconfig.ts b/typescript/workspace/generated/protoclient/protoapp/uiconfig.ts new file mode 100644 index 00000000..2646fadf --- /dev/null +++ b/typescript/workspace/generated/protoclient/protoapp/uiconfig.ts @@ -0,0 +1,48 @@ +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module protoclient.protoapp.uiconfig */ + +/** + * Configuration for the web frontend. + */ +export interface UiConfig { +/** + * Application title + */ + title: string; +/** + * Environment name, e.g. dev, uat, prod + */ + environment: string; +/** + * Name of the release / code version + */ + releaseName: string; +} + +export function makeUiConfig( + input: { + title?: string, + environment: string, + releaseName: string, + } +): UiConfig { + return { + title: input.title === undefined ? "" : input.title, + environment: input.environment, + releaseName: input.releaseName, + }; +} + +const UiConfig_AST : ADL.ScopedDecl = + {"moduleName":"protoclient.protoapp.uiconfig","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"title","default":{"kind":"just","value":""},"name":"title","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"environment","default":{"kind":"nothing"},"name":"environment","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}},{"annotations":[],"serializedName":"releaseName","default":{"kind":"nothing"},"name":"releaseName","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"UiConfig","version":{"kind":"nothing"}}}; + +export const snUiConfig: ADL.ScopedName = {moduleName:"protoclient.protoapp.uiconfig", name:"UiConfig"}; + +export function texprUiConfig(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snUiConfig},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "protoclient.protoapp.uiconfig.UiConfig" : UiConfig_AST +}; diff --git a/typescript/workspace/generated/protoclient/resolver.ts b/typescript/workspace/generated/protoclient/resolver.ts new file mode 100644 index 00000000..f9382a4e --- /dev/null +++ b/typescript/workspace/generated/protoclient/resolver.ts @@ -0,0 +1,24 @@ +import {_AST_MAP as protoclient_protoapp_api} from "./protoapp/api"; +import {_AST_MAP as protoclient_protoapp_config} from "./protoapp/config"; +import {_AST_MAP as protoclient_protoapp_db} from "./protoapp/db"; +import {_AST_MAP as protoclient_protoapp_uiconfig} from "./protoapp/uiconfig"; +import {ADL_local as adl_lang_common} from "@adl-lang/common/resolver"; +import {ScopedDecl, declResolver} from "@adl-lang/runtime/adl"; +import {ADL_local as adl_lang_sys} from "@adl-lang/sys/resolver"; + +/* @generated from adl */ + +export const ADL_local: { [key: string]: ScopedDecl } = { + ...protoclient_protoapp_api, + ...protoclient_protoapp_config, + ...protoclient_protoapp_db, + ...protoclient_protoapp_uiconfig, +}; + +export const ADL: { [key: string]: ScopedDecl } = { + ...ADL_local, + ...adl_lang_common, + ...adl_lang_sys, +}; + +export const RESOLVER = declResolver(ADL); diff --git a/typescript/workspace/generated/protoclient/tsconfig.json b/typescript/workspace/generated/protoclient/tsconfig.json new file mode 100644 index 00000000..a3b461dc --- /dev/null +++ b/typescript/workspace/generated/protoclient/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "tsconfig/base.json", + "include": [ + "." + ], + "exclude": [ + "dist", + "build", + "node_modules" + ], + "compilerOptions": { + "outDir": "dist", + "lib": [ + "es2020" + ] + } +} \ No newline at end of file diff --git a/typescript/workspace/generated/runtime/adl.ts b/typescript/workspace/generated/runtime/adl.ts new file mode 100644 index 00000000..2566f713 --- /dev/null +++ b/typescript/workspace/generated/runtime/adl.ts @@ -0,0 +1,84 @@ +import * as AST from './sys/adlast'; + +export type ScopedName = AST.ScopedName; +export type ScopedDecl = AST.ScopedDecl; +export type ATypeRef<_T> = {value: AST.TypeRef}; +export type ATypeExpr<_T> = {value : AST.TypeExpr}; + +/** + * A function to obtain details on a declared type. + */ +export interface DeclResolver { + (decl : AST.ScopedName): AST.ScopedDecl; +}; + +export function declResolver(...astMaps : ({[key:string] : AST.ScopedDecl})[]) { + const astMap : {[key:string] : AST.ScopedDecl} = {}; + for (let map of astMaps) { + for (let scopedName in map) { + astMap[scopedName] = map[scopedName]; + } + } + + function resolver(scopedName : AST.ScopedName) : AST.ScopedDecl { + const scopedNameStr = scopedName.moduleName + "." + scopedName.name; + const result = astMap[scopedNameStr]; + if (result === undefined) { + throw new Error("Unable to resolve ADL type " + scopedNameStr); + } + return result; + } + + return resolver; +} + +type Unknown = {} | null; +type Json = {} | null; + +/* Type expressions for primitive types */ + +function texprPrimitive(ptype: string): ATypeExpr { + return { + value: { + typeRef: { kind: "primitive", value: ptype }, + parameters: [] + } + }; +}; + +function texprPrimitive1(ptype: string, etype: ATypeExpr): ATypeExpr { + return { + value: { + typeRef: { kind: "primitive", value: ptype }, + parameters: [etype.value] + } + }; +}; + +export function texprVoid() : ATypeExpr {return texprPrimitive("Void");} +export function texprBool() : ATypeExpr {return texprPrimitive("Bool");} +export function texprInt8() : ATypeExpr {return texprPrimitive("Int8");} +export function texprInt16() : ATypeExpr {return texprPrimitive("Int16");} +export function texprInt32() : ATypeExpr {return texprPrimitive("Int32");} +export function texprInt64() : ATypeExpr {return texprPrimitive("Int64");} +export function texprWord8() : ATypeExpr {return texprPrimitive("Word8");} +export function texprWord16() : ATypeExpr {return texprPrimitive("Word16");} +export function texprWord32() : ATypeExpr {return texprPrimitive("Word32");} +export function texprWord64() : ATypeExpr {return texprPrimitive("Word64");} +export function texprFloat() : ATypeExpr {return texprPrimitive("Float");} +export function texprDouble() : ATypeExpr {return texprPrimitive("Double");} +export function texprJson() : ATypeExpr {return texprPrimitive("Json");} +export function texprByteVector() : ATypeExpr {return texprPrimitive("ByteVector");} +export function texprString() : ATypeExpr {return texprPrimitive("String");} + +export function texprVector(etype: ATypeExpr) : ATypeExpr { + return texprPrimitive1("Vector", etype); +} + +export function texprStringMap(etype: ATypeExpr) : ATypeExpr<{[key:string]:T}> { + return texprPrimitive1("StringMap", etype); +} + +export function texprNullable(etype: ATypeExpr) : ATypeExpr { + return texprPrimitive1("Nullable", etype); +} diff --git a/typescript/workspace/generated/runtime/dynamic.ts b/typescript/workspace/generated/runtime/dynamic.ts new file mode 100644 index 00000000..71c65b25 --- /dev/null +++ b/typescript/workspace/generated/runtime/dynamic.ts @@ -0,0 +1,20 @@ +import {typeExprsEqual} from './utils'; +import {JsonBinding} from './json'; +import {Dynamic} from './sys/dynamic'; + +/** + * Convert an ADL value to a dynamically typed value + */ +export function toDynamic(jsonBinding : JsonBinding, value : T) : Dynamic { + return {typeExpr: jsonBinding.typeExpr, value : jsonBinding.toJson(value)}; +} + +/** + * Convert an ADL value to a dynamically typed value + */ +export function fromDynamic(jsonBinding : JsonBinding, dynamic : Dynamic) : (T|null) { + if (typeExprsEqual(jsonBinding.typeExpr, dynamic.typeExpr)) { + return jsonBinding.fromJson(dynamic.value); + } + return null; +} diff --git a/typescript/workspace/generated/runtime/json.ts b/typescript/workspace/generated/runtime/json.ts new file mode 100644 index 00000000..50d23d6d --- /dev/null +++ b/typescript/workspace/generated/runtime/json.ts @@ -0,0 +1,514 @@ +import {DeclResolver,ATypeExpr} from './adl'; +import * as AST from './sys/adlast'; +import {fromByteArray as b64Encode, toByteArray as b64Decode} from 'base64-js'; +import {isVoid, isEnum, scopedNamesEqual} from './utils'; + +/** A type for json serialised values */ + +export type Json = JsonObject | JsonArray | JsonValue; +export type JsonArray = Json[]; +export type JsonValue = string | number | JsonObject | JsonArray | boolean | null; +export interface JsonObject { + [key: string]: Json +}; + +function asJsonObject(jv: Json): JsonObject | undefined { + if (jv instanceof Object && !(jv instanceof Array)) { + return jv as JsonObject; + } + return undefined; +} + +function asJsonArray(jv: Json): JsonArray | undefined{ + if(jv instanceof Array) { + return jv as JsonArray; + } + return undefined; +} + +/** + * A JsonBinding is a de/serialiser for a give ADL type + */ +export interface JsonBinding { + typeExpr : AST.TypeExpr; + + // Convert a value of type T to Json + toJson (t : T): Json; + + // Parse a json blob into a value of type T. Throws + // JsonParseExceptions on failure. + fromJson(json : Json) : T; + + // Variant of fromJson that throws Errors on failure + fromJsonE(json : Json) : T; +}; + +/** + * Construct a JsonBinding for an arbitrary type expression + */ +export function createJsonBinding(dresolver : DeclResolver, texpr : ATypeExpr) : JsonBinding { + const jb0 = buildJsonBinding(dresolver, texpr.value, {}); + function fromJsonE(json :Json): T { + try { + return jb0.fromJson(json); + } catch (e) { + throw mapJsonException(e); + } + } + return {typeExpr : texpr.value, toJson:jb0.toJson, fromJson:jb0.fromJson, fromJsonE}; +}; + +/** + * Interface for json parsing exceptions. + * Any implementation should properly show the parse error tree. + * + * @interface JsonParseException + */ +export interface JsonParseException { + kind: 'JsonParseException'; + getMessage(): string; + pushField(fieldName: string): void; + pushIndex(index: number): void; + toString(): string; +} + +// Map a JsonException to an Error value +export function mapJsonException(exception:unknown): unknown { + if (exception && (exception as {kind:string})['kind'] == "JsonParseException") { + const jserr: JsonParseException = exception as JsonParseException; + return new Error(jserr.getMessage()); + } else { + return exception; + } +} + +/** Convenience function for generating a json parse exception. + * @param {string} message - Exception message. + */ +export function jsonParseException(message: string): JsonParseException { + const context: string[] = []; + let createContextString: () => string = () => { + const rcontext: string[] = context.slice(0); + rcontext.push('$'); + rcontext.reverse(); + return rcontext.join('.'); + }; + return { + kind: 'JsonParseException', + getMessage(): string { + return message + ' at ' + createContextString(); + }, + pushField(fieldName: string): void { + context.push(fieldName); + }, + pushIndex(index: number): void { + context.push('[' + index + ']'); + }, + toString(): string { + return this.getMessage(); + } + }; +} + +/** + * Check if a javascript error is of the json parse exception type. + * @param exception The exception to check. + */ +export function isJsonParseException(exception: unknown): exception is JsonParseException { + return ( exception).kind === 'JsonParseException'; +} + +interface JsonBinding0 { + toJson (t : T): Json; + fromJson(json : Json) : T; +}; + +interface BoundTypeParams { + [key: string]: JsonBinding0; +} + +function buildJsonBinding0(dresolver : DeclResolver, texpr : AST.TypeExpr, boundTypeParams : BoundTypeParams) : JsonBinding0 { + if (texpr.typeRef.kind === "primitive") { + return primitiveJsonBinding(dresolver, texpr.typeRef.value, texpr.parameters, boundTypeParams); + } else if (texpr.typeRef.kind === "reference") { + const ast = dresolver(texpr.typeRef.value); + if (ast.decl.type_.kind === "struct_") { + return structJsonBinding(dresolver, ast.decl.type_.value, texpr.parameters, boundTypeParams); + } else if (ast.decl.type_.kind === "union_") { + const union = ast.decl.type_.value; + if (isEnum(union)) { + return enumJsonBinding(dresolver, union, texpr.parameters, boundTypeParams); + } else { + return unionJsonBinding(dresolver, union, texpr.parameters, boundTypeParams); + } + } else if (ast.decl.type_.kind === "newtype_") { + return newtypeJsonBinding(dresolver, ast.decl.type_.value, texpr.parameters, boundTypeParams); + } else if (ast.decl.type_.kind === "type_") { + return typedefJsonBinding(dresolver, ast.decl.type_.value, texpr.parameters, boundTypeParams); + } + } else if (texpr.typeRef.kind === "typeParam") { + return boundTypeParams[texpr.typeRef.value]; + } + throw new Error("buildJsonBinding : unimplemented ADL type"); +}; + +function buildJsonBinding(dresolver : DeclResolver, texpr : AST.TypeExpr, boundTypeParams : BoundTypeParams) : JsonBinding0 { + const jb0 = buildJsonBinding0(dresolver, texpr, boundTypeParams); + return jb0 as JsonBinding0; +}; + +function primitiveJsonBinding(dresolver : DeclResolver, ptype : string, params : AST.TypeExpr[], boundTypeParams : BoundTypeParams ) : JsonBinding0 { + if (ptype === "String") { return identityJsonBinding("a string", (v) => typeof(v) === 'string'); } + else if (ptype === "Int8") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Void") { return identityJsonBinding("a null", (v) => v === null); } + else if (ptype === "Bool") { return identityJsonBinding("a bool", (v) => typeof(v) === 'boolean'); } + else if (ptype === "Int8") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Int16") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Int32") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Int64") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Word8") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Word16") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Word32") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Word64") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Float") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Double") { return identityJsonBinding("a number", (v) => typeof(v) === 'number'); } + else if (ptype === "Json") { return identityJsonBinding("a json value", (_v) => true); } + else if (ptype === "Bytes") { return bytesJsonBinding(); } + else if (ptype === "Vector") { return vectorJsonBinding(dresolver, params[0], boundTypeParams); } + else if (ptype === "StringMap") { return stringMapJsonBinding(dresolver, params[0], boundTypeParams); } + else if (ptype === "Nullable") { return nullableJsonBinding(dresolver, params[0], boundTypeParams); } + else throw new Error("Unimplemented json binding for primitive " + ptype); +}; + +function identityJsonBinding(expected : string, predicate : (json : Json) => boolean) : JsonBinding0{ + + function toJson(v : T) : Json { + return (v as unknown as Json); + } + + function fromJson(json : Json) : T { + if( !predicate(json)) { + throw jsonParseException("expected " + expected); + } + return json as unknown as T; + } + + return {toJson, fromJson}; +} + +function bytesJsonBinding() : JsonBinding0 { + function toJson(v : Uint8Array) : Json { + return b64Encode(v); + } + + function fromJson(json : Json) : Uint8Array { + if (typeof(json) != 'string') { + throw jsonParseException('expected a string'); + } + return b64Decode(json); + } + + return {toJson, fromJson}; +} + +function vectorJsonBinding(dresolver : DeclResolver, texpr : AST.TypeExpr, boundTypeParams : BoundTypeParams) : JsonBinding0 { + const elementBinding = once(() => buildJsonBinding(dresolver, texpr, boundTypeParams)); + + function toJson(v : T[]) : Json { + return v.map(elementBinding().toJson); + } + + function fromJson(json : Json) : T[] { + const jarr = asJsonArray(json); + if (jarr == undefined) { + throw jsonParseException('expected an array'); + } + let result : T[] = []; + jarr.forEach( (eljson:Json,i:number) => { + try { + result.push(elementBinding().fromJson(eljson)); + } catch(e) { + if (isJsonParseException(e)) { + e.pushIndex(i); + } + throw e; + } + }); + return result; + } + + return {toJson, fromJson}; +} + +type StringMap = {[key:string]: T}; +function stringMapJsonBinding(dresolver : DeclResolver, texpr : AST.TypeExpr, boundTypeParams : BoundTypeParams) : JsonBinding0> { + const elementBinding = once(() => buildJsonBinding(dresolver, texpr, boundTypeParams)); + + function toJson(v : StringMap) : Json { + const result: JsonObject = {}; + for (let k in v) { + result[k] = elementBinding().toJson(v[k]); + } + return result; + } + + function fromJson(json : Json) : StringMap { + const jobj = asJsonObject(json); + if (!jobj) { + throw jsonParseException('expected an object'); + } + let result: Record = {}; + for (let k in jobj) { + try { + result[k] = elementBinding().fromJson(jobj[k]); + } catch(e) { + if (isJsonParseException(e)) { + e.pushField(k); + } + throw e; + } + } + return result; + } + + return {toJson, fromJson}; +} + +function nullableJsonBinding(dresolver : DeclResolver, texpr : AST.TypeExpr, boundTypeParams : BoundTypeParams) : JsonBinding0 { + const elementBinding = once(() => buildJsonBinding(dresolver, texpr, boundTypeParams)); + + function toJson(v : T|null) : Json { + if (v === null) { + return null; + } + return elementBinding().toJson(v); + } + + function fromJson(json : Json) : T|null { + if (json === null) { + return null; + } + return elementBinding().fromJson(json); + } + + return {toJson,fromJson}; +} + +interface StructFieldDetails { + field : AST.Field, + jsonBinding : () => JsonBinding0, + buildDefault : () => { value : unknown } | null +}; + +function structJsonBinding>(dresolver : DeclResolver, struct : AST.Struct, params : AST.TypeExpr[], boundTypeParams : BoundTypeParams ) : JsonBinding0 { + const newBoundTypeParams = createBoundTypeParams(dresolver, struct.typeParams, params, boundTypeParams); + const fieldDetails : StructFieldDetails[] = []; + struct.fields.forEach( (field) => { + let buildDefault = once( () => { + if (field.default.kind === "just") { + const json = field.default.value; + return { 'value' : buildJsonBinding(dresolver, field.typeExpr, newBoundTypeParams).fromJson(json)}; + } else { + return null; + } + }); + + fieldDetails.push( { + field : field, + jsonBinding : once(() => buildJsonBinding(dresolver, field.typeExpr, newBoundTypeParams)), + buildDefault : buildDefault, + }); + }); + + function toJson(v0: unknown) : Json { + const v = v0 as {[key:string]:unknown}; + const json: JsonObject = {}; + fieldDetails.forEach( (fd) => { + json[fd.field.serializedName] = fd.jsonBinding().toJson(v && v[fd.field.name]); + }); + return json; + } + + function fromJson(json: Json): T { + const jobj = asJsonObject(json); + if (!jobj) { + throw jsonParseException("expected an object"); + } + + const v = {} as T; + fieldDetails.forEach( (fd) => { + const name = fd.field.name as keyof T; + + if (jobj[fd.field.serializedName] === undefined) { + const defaultv = fd.buildDefault(); + if (defaultv === null) { + throw jsonParseException("missing struct field " + fd.field.serializedName ); + } else { + const value = defaultv.value as T[keyof T]; + v[name] = value; + } + } else { + try { + const value = fd.jsonBinding().fromJson(jobj[fd.field.serializedName]) as T[keyof T]; + v[name] = value; + } catch(e) { + if (isJsonParseException(e)) { + e.pushField(fd.field.serializedName); + } + throw e; + } + } + }); + return v; + } + + return {toJson, fromJson}; +} + +function enumJsonBinding(_dresolver : DeclResolver, union : AST.Union, _params : AST.TypeExpr[], _boundTypeParams : BoundTypeParams ) : JsonBinding0 { + const toSerialized: {[key:string]:string} = {}; + const fromSerialized: {[key:string]:string} = {}; + union.fields.forEach( field => { + toSerialized[field.name] = field.serializedName; + fromSerialized[field.serializedName] = field.name; + }); + + function toJson(v :unknown) : Json { + return toSerialized[v as string]; + } + + function fromJson(json : Json) : unknown { + if (typeof(json) !== 'string') { + throw jsonParseException("expected a string for enum"); + } + const result = fromSerialized[json as string]; + if (result === undefined) { + throw jsonParseException("invalid string for enum: " + json); + } + return result; + } + + return {toJson, fromJson}; +} + +interface FieldDetails { + field : AST.Field; + isVoid : boolean; + jsonBinding : () => JsonBinding0; +}; + +function unionJsonBinding(dresolver : DeclResolver, union : AST.Union, params : AST.TypeExpr[], boundTypeParams : BoundTypeParams ) : JsonBinding0 { + + const newBoundTypeParams = createBoundTypeParams(dresolver, union.typeParams, params, boundTypeParams); + const detailsByName : {[key: string]: FieldDetails} = {}; + const detailsBySerializedName : {[key: string]: FieldDetails} = {}; + union.fields.forEach( (field) => { + const details = { + field : field, + isVoid : isVoid(field.typeExpr), + jsonBinding : once(() => buildJsonBinding(dresolver, field.typeExpr, newBoundTypeParams)) + }; + detailsByName[field.name] = details; + detailsBySerializedName[field.serializedName] = details; + }); + + function toJson(v0 : unknown) : Json { + const v = v0 as {kind:string, value:unknown}; + const details = detailsByName[v.kind]; + if (details.isVoid) { + return details.field.serializedName; + } else { + const result: JsonObject = {}; + result[details.field.serializedName] = details.jsonBinding().toJson(v.value); + return result; + } + } + + function lookupDetails(serializedName : string) { + let details = detailsBySerializedName[serializedName]; + if (details === undefined) { + throw jsonParseException("invalid union field " + serializedName); + } + return details; + } + + function fromJson(json : Json) : unknown { + if (typeof(json) === "string") { + let details = lookupDetails(json); + if (!details.isVoid) { + throw jsonParseException("union field " + json + "needs an associated value"); + } + return { kind : details.field.name }; + } + const jobj = asJsonObject(json); + if (jobj) { + for (let k in jobj) { + let details = lookupDetails(k); + try { + return { + kind : details.field.name, + value : details.jsonBinding().fromJson(jobj[k]) + } + } catch(e) { + if (isJsonParseException(e)) { + e.pushField(k); + } + throw e; + } + } + throw jsonParseException("union without a property"); + } else { + throw jsonParseException("expected an object or string"); + } + } + + return {toJson, fromJson}; +} + +function newtypeJsonBinding(dresolver : DeclResolver, newtype : AST.NewType, params : AST.TypeExpr[], boundTypeParams : BoundTypeParams ) : JsonBinding0 { + const newBoundTypeParams = createBoundTypeParams(dresolver, newtype.typeParams, params, boundTypeParams); + return buildJsonBinding(dresolver, newtype.typeExpr, newBoundTypeParams); +} + +function typedefJsonBinding(dresolver : DeclResolver, typedef : AST.TypeDef, params : AST.TypeExpr[], boundTypeParams : BoundTypeParams ) : JsonBinding0 { + const newBoundTypeParams = createBoundTypeParams(dresolver, typedef.typeParams, params, boundTypeParams); + return buildJsonBinding(dresolver, typedef.typeExpr, newBoundTypeParams); +} + +function createBoundTypeParams(dresolver : DeclResolver, paramNames : string[], paramTypes : AST.TypeExpr[], boundTypeParams : BoundTypeParams) : BoundTypeParams +{ + let result : BoundTypeParams = {}; + paramNames.forEach( (paramName,i) => { + result[paramName] = buildJsonBinding(dresolver,paramTypes[i], boundTypeParams); + }); + return result; +} + +/** + * Helper function that takes a thunk, and evaluates it only on the first call. Subsequent + * calls return the previous value + */ +function once(run : () => T) : () => T { + let result : T | null = null; + return () => { + if(result === null) { + result = run(); + } + return result; + }; +} + +/** + * Get the value of an annotation of type T + */ +export function getAnnotation(jb: JsonBinding, annotations: AST.Annotations): T | undefined { + if (jb.typeExpr.typeRef.kind != 'reference') { + return undefined; + } + const annScopedName :AST.ScopedName = jb.typeExpr.typeRef.value; + const ann = annotations.find(el => scopedNamesEqual(el.key, annScopedName)); + if (ann === undefined) { + return undefined; + } + return jb.fromJsonE(ann.value); +} diff --git a/typescript/workspace/generated/runtime/package-dist.json b/typescript/workspace/generated/runtime/package-dist.json new file mode 100644 index 00000000..13f2dd89 --- /dev/null +++ b/typescript/workspace/generated/runtime/package-dist.json @@ -0,0 +1,10 @@ +{ + "name": "@adl-lang/runtime", + "version": "0.0.0", + "license": "MIT", + "main": "./index.js", + "types": "./index.d.ts", + "dependencies": { + "base64-js": "^1.5.1" + } +} diff --git a/typescript/workspace/generated/runtime/package.json b/typescript/workspace/generated/runtime/package.json new file mode 100644 index 00000000..40592add --- /dev/null +++ b/typescript/workspace/generated/runtime/package.json @@ -0,0 +1,18 @@ +{ + "name": "@adl-lang/runtime", + "version": "1.0.0", + "type": "commonjs", + "author": "Helix", + "license": "CLOSED", + "private": true, + "scripts": { + "tsc": "tsc" + }, + "dependencies": { + "base64-js": "^1.5.1" + }, + "devDependencies": { + "tsconfig": "workspace:*", + "typescript": "^4.9.3" + } +} diff --git a/typescript/workspace/generated/runtime/sys/adlast.ts b/typescript/workspace/generated/runtime/sys/adlast.ts new file mode 100644 index 00000000..eb391ad8 --- /dev/null +++ b/typescript/workspace/generated/runtime/sys/adlast.ts @@ -0,0 +1,274 @@ +/* @generated from adl module sys.adlast */ + +import * as sys_types from './types'; + +export type ModuleName = string; + +export type Ident = string; + +export type Annotations = sys_types.Map; + +export interface ScopedName { + moduleName: ModuleName; + name: Ident; +} + +export function makeScopedName( + input: { + moduleName: ModuleName, + name: Ident, + } +): ScopedName { + return { + moduleName: input.moduleName, + name: input.name, + }; +} + +export interface TypeRef_Primitive { + kind: 'primitive'; + value: Ident; +} +export interface TypeRef_TypeParam { + kind: 'typeParam'; + value: Ident; +} +export interface TypeRef_Reference { + kind: 'reference'; + value: ScopedName; +} + +export type TypeRef = TypeRef_Primitive | TypeRef_TypeParam | TypeRef_Reference; + +export interface TypeRefOpts { + primitive: Ident; + typeParam: Ident; + reference: ScopedName; +} + +export function makeTypeRef(kind: K, value: TypeRefOpts[K]) { return {kind, value}; } + +export interface TypeExpr { + typeRef: TypeRef; + parameters: TypeExpr[]; +} + +export function makeTypeExpr( + input: { + typeRef: TypeRef, + parameters: TypeExpr[], + } +): TypeExpr { + return { + typeRef: input.typeRef, + parameters: input.parameters, + }; +} + +export interface Field { + name: Ident; + serializedName: Ident; + typeExpr: TypeExpr; + default: sys_types.Maybe<{}|null>; + annotations: Annotations; +} + +export function makeField( + input: { + name: Ident, + serializedName: Ident, + typeExpr: TypeExpr, + default: sys_types.Maybe<{}|null>, + annotations: Annotations, + } +): Field { + return { + name: input.name, + serializedName: input.serializedName, + typeExpr: input.typeExpr, + default: input.default, + annotations: input.annotations, + }; +} + +export interface Struct { + typeParams: Ident[]; + fields: Field[]; +} + +export function makeStruct( + input: { + typeParams: Ident[], + fields: Field[], + } +): Struct { + return { + typeParams: input.typeParams, + fields: input.fields, + }; +} + +export interface Union { + typeParams: Ident[]; + fields: Field[]; +} + +export function makeUnion( + input: { + typeParams: Ident[], + fields: Field[], + } +): Union { + return { + typeParams: input.typeParams, + fields: input.fields, + }; +} + +export interface TypeDef { + typeParams: Ident[]; + typeExpr: TypeExpr; +} + +export function makeTypeDef( + input: { + typeParams: Ident[], + typeExpr: TypeExpr, + } +): TypeDef { + return { + typeParams: input.typeParams, + typeExpr: input.typeExpr, + }; +} + +export interface NewType { + typeParams: Ident[]; + typeExpr: TypeExpr; + default: sys_types.Maybe<{}|null>; +} + +export function makeNewType( + input: { + typeParams: Ident[], + typeExpr: TypeExpr, + default: sys_types.Maybe<{}|null>, + } +): NewType { + return { + typeParams: input.typeParams, + typeExpr: input.typeExpr, + default: input.default, + }; +} + +export interface DeclType_Struct_ { + kind: 'struct_'; + value: Struct; +} +export interface DeclType_Union_ { + kind: 'union_'; + value: Union; +} +export interface DeclType_Type_ { + kind: 'type_'; + value: TypeDef; +} +export interface DeclType_Newtype_ { + kind: 'newtype_'; + value: NewType; +} + +export type DeclType = DeclType_Struct_ | DeclType_Union_ | DeclType_Type_ | DeclType_Newtype_; + +export interface DeclTypeOpts { + struct_: Struct; + union_: Union; + type_: TypeDef; + newtype_: NewType; +} + +export function makeDeclType(kind: K, value: DeclTypeOpts[K]) { return {kind, value}; } + +export interface Decl { + name: Ident; + version: sys_types.Maybe; + type_: DeclType; + annotations: Annotations; +} + +export function makeDecl( + input: { + name: Ident, + version: sys_types.Maybe, + type_: DeclType, + annotations: Annotations, + } +): Decl { + return { + name: input.name, + version: input.version, + type_: input.type_, + annotations: input.annotations, + }; +} + +export interface ScopedDecl { + moduleName: ModuleName; + decl: Decl; +} + +export function makeScopedDecl( + input: { + moduleName: ModuleName, + decl: Decl, + } +): ScopedDecl { + return { + moduleName: input.moduleName, + decl: input.decl, + }; +} + +export type DeclVersions = Decl[]; + +export interface Import_ModuleName { + kind: 'moduleName'; + value: ModuleName; +} +export interface Import_ScopedName { + kind: 'scopedName'; + value: ScopedName; +} + +export type Import = Import_ModuleName | Import_ScopedName; + +export interface ImportOpts { + moduleName: ModuleName; + scopedName: ScopedName; +} + +export function makeImport(kind: K, value: ImportOpts[K]) { return {kind, value}; } + +export interface Module { + name: ModuleName; + imports: Import[]; + decls: {[key: string]: Decl}; + annotations: Annotations; +} + +export function makeModule( + input: { + name: ModuleName, + imports: Import[], + decls: {[key: string]: Decl}, + annotations: Annotations, + } +): Module { + return { + name: input.name, + imports: input.imports, + decls: input.decls, + annotations: input.annotations, + }; +} diff --git a/typescript/workspace/generated/runtime/sys/dynamic.ts b/typescript/workspace/generated/runtime/sys/dynamic.ts new file mode 100644 index 00000000..49a68608 --- /dev/null +++ b/typescript/workspace/generated/runtime/sys/dynamic.ts @@ -0,0 +1,23 @@ +/* @generated from adl module sys.dynamic */ + +import * as sys_adlast from './adlast'; + +/** + * A serialised value along with its type + */ +export interface Dynamic { + typeExpr: sys_adlast.TypeExpr; + value: {}|null; +} + +export function makeDynamic( + input: { + typeExpr: sys_adlast.TypeExpr, + value: {}|null, + } +): Dynamic { + return { + typeExpr: input.typeExpr, + value: input.value, + }; +} diff --git a/typescript/workspace/generated/runtime/sys/types.ts b/typescript/workspace/generated/runtime/sys/types.ts new file mode 100644 index 00000000..aa9735c1 --- /dev/null +++ b/typescript/workspace/generated/runtime/sys/types.ts @@ -0,0 +1,93 @@ +/* @generated from adl module sys.types */ + + +export interface Pair { + v1: T1; + v2: T2; +} + +export function makePair( + input: { + v1: T1, + v2: T2, + } +): Pair { + return { + v1: input.v1, + v2: input.v2, + }; +} + +export interface Either_Left { + kind: 'left'; + value: T1; +} +export interface Either_Right<_T1, T2> { + kind: 'right'; + value: T2; +} + +export type Either = Either_Left | Either_Right; + +export interface EitherOpts { + left: T1; + right: T2; +} + +export function makeEither>(kind: K, value: EitherOpts[K]) { return {kind, value}; } + +export interface Maybe_Nothing<_T> { + kind: 'nothing'; +} +export interface Maybe_Just { + kind: 'just'; + value: T; +} + +export type Maybe = Maybe_Nothing | Maybe_Just; + +export interface MaybeOpts { + nothing: null; + just: T; +} + +export function makeMaybe>(kind: K, value: MaybeOpts[K]) { return {kind, value}; } + +export interface Result_Ok { + kind: 'ok'; + value: T; +} +export interface Result_Error<_T, E> { + kind: 'error'; + value: E; +} + +export type Result = Result_Ok | Result_Error; + +export interface ResultOpts { + ok: T; + error: E; +} + +export function makeResult>(kind: K, value: ResultOpts[K]) { return {kind, value}; } + +export interface MapEntry { + key: K; + value: V; +} + +export function makeMapEntry( + input: { + key: K, + value: V, + } +): MapEntry { + return { + key: input.key, + value: input.value, + }; +} + +export type Map = MapEntry[]; + +export type Set = T[]; diff --git a/typescript/workspace/generated/runtime/tsconfig.json b/typescript/workspace/generated/runtime/tsconfig.json new file mode 100644 index 00000000..3367d02e --- /dev/null +++ b/typescript/workspace/generated/runtime/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "tsconfig/base.json", + "include": ["."], + "exclude": ["dist", "build", "node_modules"], + "compilerOptions": { + "outDir": "dist", + // "target": "es2020", + // "module": "es2020", + "lib": [ + "es2020", + ] + } +} diff --git a/typescript/workspace/generated/runtime/utils.ts b/typescript/workspace/generated/runtime/utils.ts new file mode 100644 index 00000000..3343d34f --- /dev/null +++ b/typescript/workspace/generated/runtime/utils.ts @@ -0,0 +1,77 @@ +import * as AST from './sys/adlast'; + +export function isEnum(union : AST.Union) : boolean { + for (let field of union.fields) { + if (!isVoid(field.typeExpr)) { + return false; + } + } + return true; +} + +export function isVoid(texpr : AST.TypeExpr) : boolean { + if (texpr.typeRef.kind === "primitive") { + return texpr.typeRef.value === "Void"; + } + return false; +} + +export function typeExprsEqual(texpr1 : AST.TypeExpr, texpr2 : AST.TypeExpr) : boolean { + if (!typeRefsEqual(texpr1.typeRef, texpr2.typeRef)) { + return false; + } + if (texpr1.parameters.length != texpr2.parameters.length) { + return false; + } + for (let i = 0; i < texpr1.parameters.length; i++) { + if(!typeExprsEqual(texpr1.parameters[i], texpr2.parameters[i])) { + return false; + } + } + return true; +} + +export function typeRefsEqual(tref1 : AST.TypeRef, tref2 : AST.TypeRef) : boolean { + if (tref1.kind === "primitive" && tref2.kind === "primitive") { + return tref1.value === tref2.value; + } else if (tref1.kind === "typeParam" && tref2.kind === "typeParam") { + return tref1.value === tref2.value; + } else if (tref1.kind === "reference" && tref2.kind === "reference") { + return scopedNamesEqual(tref1.value, tref2.value); + } + return false; +} + +export function scopedNamesEqual(sn1: AST.ScopedName, sn2: AST.ScopedName): boolean { + return sn1.moduleName === sn2.moduleName && sn1.name === sn2.name; +} + +function typeExprToStringImpl(te: AST.TypeExpr, withScopedNames: boolean) : string { + let result = ""; + if (te.typeRef.kind == "primitive") { + result = te.typeRef.value; + } else if (te.typeRef.kind == "typeParam") { + result = te.typeRef.value; + } else if (te.typeRef.kind == "reference") { + result = withScopedNames + ? te.typeRef.value.moduleName + "." + te.typeRef.value.name + : te.typeRef.value.name; + } + if (te.parameters.length > 0) { + result = result + "<" + te.parameters.map(p => typeExprToStringImpl(p, withScopedNames)) + ">"; + } + return result; +} + +/* Convert a type expression to a string, with fully scoped names */ + +export function typeExprToString(te: AST.TypeExpr) : string { + return typeExprToStringImpl(te, true); +} + +/* Convert a type expression to a string, with unscoped names */ + +export function typeExprToStringUnscoped(te: AST.TypeExpr) : string { + return typeExprToStringImpl(te, false); +} + diff --git a/typescript/workspace/generated/sys/.adl-manifest b/typescript/workspace/generated/sys/.adl-manifest new file mode 100644 index 00000000..60fceb87 --- /dev/null +++ b/typescript/workspace/generated/sys/.adl-manifest @@ -0,0 +1,8 @@ +# manifest @generated by the adl compiler +adlast.ts +adlast2.ts +annotations.ts +dynamic.ts +index.ts +resolver.ts +types.ts diff --git a/typescript/workspace/generated/sys/adlast.ts b/typescript/workspace/generated/sys/adlast.ts new file mode 100644 index 00000000..7544389d --- /dev/null +++ b/typescript/workspace/generated/sys/adlast.ts @@ -0,0 +1,448 @@ +import * as sys_types from "./types"; +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module sys.adlast */ + +export type ModuleName = string; + +const ModuleName_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"ModuleName","version":{"kind":"nothing"}}}; + +export const snModuleName: ADL.ScopedName = {moduleName:"sys.adlast", name:"ModuleName"}; + +export function texprModuleName(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snModuleName},parameters:[]}}; +} + +export type Ident = string; + +const Ident_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"Ident","version":{"kind":"nothing"}}}; + +export const snIdent: ADL.ScopedName = {moduleName:"sys.adlast", name:"Ident"}; + +export function texprIdent(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snIdent},parameters:[]}}; +} + +export type Annotations = sys_types.Map; + +const Annotations_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.types","name":"Map"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"ScopedName"}},"parameters":[]},{"typeRef":{"kind":"primitive","value":"Json"},"parameters":[]}]}}},"name":"Annotations","version":{"kind":"nothing"}}}; + +export const snAnnotations: ADL.ScopedName = {moduleName:"sys.adlast", name:"Annotations"}; + +export function texprAnnotations(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snAnnotations},parameters:[]}}; +} + +export interface ScopedName { + moduleName: ModuleName; + name: Ident; +} + +export function makeScopedName( + input: { + moduleName: ModuleName, + name: Ident, + } +): ScopedName { + return { + moduleName: input.moduleName, + name: input.name, + }; +} + +const ScopedName_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"moduleName","default":{"kind":"nothing"},"name":"moduleName","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"ModuleName"}},"parameters":[]}},{"annotations":[],"serializedName":"name","default":{"kind":"nothing"},"name":"name","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Ident"}},"parameters":[]}}]}},"name":"ScopedName","version":{"kind":"nothing"}}}; + +export const snScopedName: ADL.ScopedName = {moduleName:"sys.adlast", name:"ScopedName"}; + +export function texprScopedName(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snScopedName},parameters:[]}}; +} + +export interface TypeRef_Primitive { + kind: 'primitive'; + value: Ident; +} +export interface TypeRef_TypeParam { + kind: 'typeParam'; + value: Ident; +} +export interface TypeRef_Reference { + kind: 'reference'; + value: ScopedName; +} + +export type TypeRef = TypeRef_Primitive | TypeRef_TypeParam | TypeRef_Reference; + +export interface TypeRefOpts { + primitive: Ident; + typeParam: Ident; + reference: ScopedName; +} + +export function makeTypeRef(kind: K, value: TypeRefOpts[K]) { return {kind, value}; } + +const TypeRef_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"primitive","default":{"kind":"nothing"},"name":"primitive","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Ident"}},"parameters":[]}},{"annotations":[],"serializedName":"typeParam","default":{"kind":"nothing"},"name":"typeParam","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Ident"}},"parameters":[]}},{"annotations":[],"serializedName":"reference","default":{"kind":"nothing"},"name":"reference","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"ScopedName"}},"parameters":[]}}]}},"name":"TypeRef","version":{"kind":"nothing"}}}; + +export const snTypeRef: ADL.ScopedName = {moduleName:"sys.adlast", name:"TypeRef"}; + +export function texprTypeRef(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snTypeRef},parameters:[]}}; +} + +export interface TypeExpr { + typeRef: TypeRef; + parameters: TypeExpr[]; +} + +export function makeTypeExpr( + input: { + typeRef: TypeRef, + parameters: TypeExpr[], + } +): TypeExpr { + return { + typeRef: input.typeRef, + parameters: input.parameters, + }; +} + +const TypeExpr_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"typeRef","default":{"kind":"nothing"},"name":"typeRef","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"TypeRef"}},"parameters":[]}},{"annotations":[],"serializedName":"parameters","default":{"kind":"nothing"},"name":"parameters","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"TypeExpr"}},"parameters":[]}]}}]}},"name":"TypeExpr","version":{"kind":"nothing"}}}; + +export const snTypeExpr: ADL.ScopedName = {moduleName:"sys.adlast", name:"TypeExpr"}; + +export function texprTypeExpr(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snTypeExpr},parameters:[]}}; +} + +export interface Field { + name: Ident; + serializedName: Ident; + typeExpr: TypeExpr; + default: sys_types.Maybe<{}|null>; + annotations: Annotations; +} + +export function makeField( + input: { + name: Ident, + serializedName: Ident, + typeExpr: TypeExpr, + default: sys_types.Maybe<{}|null>, + annotations: Annotations, + } +): Field { + return { + name: input.name, + serializedName: input.serializedName, + typeExpr: input.typeExpr, + default: input.default, + annotations: input.annotations, + }; +} + +const Field_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"name","default":{"kind":"nothing"},"name":"name","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Ident"}},"parameters":[]}},{"annotations":[],"serializedName":"serializedName","default":{"kind":"nothing"},"name":"serializedName","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Ident"}},"parameters":[]}},{"annotations":[],"serializedName":"typeExpr","default":{"kind":"nothing"},"name":"typeExpr","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"TypeExpr"}},"parameters":[]}},{"annotations":[],"serializedName":"default","default":{"kind":"nothing"},"name":"default","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.types","name":"Maybe"}},"parameters":[{"typeRef":{"kind":"primitive","value":"Json"},"parameters":[]}]}},{"annotations":[],"serializedName":"annotations","default":{"kind":"nothing"},"name":"annotations","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Annotations"}},"parameters":[]}}]}},"name":"Field","version":{"kind":"nothing"}}}; + +export const snField: ADL.ScopedName = {moduleName:"sys.adlast", name:"Field"}; + +export function texprField(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snField},parameters:[]}}; +} + +export interface Struct { + typeParams: Ident[]; + fields: Field[]; +} + +export function makeStruct( + input: { + typeParams: Ident[], + fields: Field[], + } +): Struct { + return { + typeParams: input.typeParams, + fields: input.fields, + }; +} + +const Struct_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"typeParams","default":{"kind":"nothing"},"name":"typeParams","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Ident"}},"parameters":[]}]}},{"annotations":[],"serializedName":"fields","default":{"kind":"nothing"},"name":"fields","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Field"}},"parameters":[]}]}}]}},"name":"Struct","version":{"kind":"nothing"}}}; + +export const snStruct: ADL.ScopedName = {moduleName:"sys.adlast", name:"Struct"}; + +export function texprStruct(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snStruct},parameters:[]}}; +} + +export interface Union { + typeParams: Ident[]; + fields: Field[]; +} + +export function makeUnion( + input: { + typeParams: Ident[], + fields: Field[], + } +): Union { + return { + typeParams: input.typeParams, + fields: input.fields, + }; +} + +const Union_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"typeParams","default":{"kind":"nothing"},"name":"typeParams","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Ident"}},"parameters":[]}]}},{"annotations":[],"serializedName":"fields","default":{"kind":"nothing"},"name":"fields","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Field"}},"parameters":[]}]}}]}},"name":"Union","version":{"kind":"nothing"}}}; + +export const snUnion: ADL.ScopedName = {moduleName:"sys.adlast", name:"Union"}; + +export function texprUnion(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snUnion},parameters:[]}}; +} + +export interface TypeDef { + typeParams: Ident[]; + typeExpr: TypeExpr; +} + +export function makeTypeDef( + input: { + typeParams: Ident[], + typeExpr: TypeExpr, + } +): TypeDef { + return { + typeParams: input.typeParams, + typeExpr: input.typeExpr, + }; +} + +const TypeDef_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"typeParams","default":{"kind":"nothing"},"name":"typeParams","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Ident"}},"parameters":[]}]}},{"annotations":[],"serializedName":"typeExpr","default":{"kind":"nothing"},"name":"typeExpr","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"TypeExpr"}},"parameters":[]}}]}},"name":"TypeDef","version":{"kind":"nothing"}}}; + +export const snTypeDef: ADL.ScopedName = {moduleName:"sys.adlast", name:"TypeDef"}; + +export function texprTypeDef(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snTypeDef},parameters:[]}}; +} + +export interface NewType { + typeParams: Ident[]; + typeExpr: TypeExpr; + default: sys_types.Maybe<{}|null>; +} + +export function makeNewType( + input: { + typeParams: Ident[], + typeExpr: TypeExpr, + default: sys_types.Maybe<{}|null>, + } +): NewType { + return { + typeParams: input.typeParams, + typeExpr: input.typeExpr, + default: input.default, + }; +} + +const NewType_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"typeParams","default":{"kind":"nothing"},"name":"typeParams","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Ident"}},"parameters":[]}]}},{"annotations":[],"serializedName":"typeExpr","default":{"kind":"nothing"},"name":"typeExpr","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"TypeExpr"}},"parameters":[]}},{"annotations":[],"serializedName":"default","default":{"kind":"nothing"},"name":"default","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.types","name":"Maybe"}},"parameters":[{"typeRef":{"kind":"primitive","value":"Json"},"parameters":[]}]}}]}},"name":"NewType","version":{"kind":"nothing"}}}; + +export const snNewType: ADL.ScopedName = {moduleName:"sys.adlast", name:"NewType"}; + +export function texprNewType(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snNewType},parameters:[]}}; +} + +export interface DeclType_Struct_ { + kind: 'struct_'; + value: Struct; +} +export interface DeclType_Union_ { + kind: 'union_'; + value: Union; +} +export interface DeclType_Type_ { + kind: 'type_'; + value: TypeDef; +} +export interface DeclType_Newtype_ { + kind: 'newtype_'; + value: NewType; +} + +export type DeclType = DeclType_Struct_ | DeclType_Union_ | DeclType_Type_ | DeclType_Newtype_; + +export interface DeclTypeOpts { + struct_: Struct; + union_: Union; + type_: TypeDef; + newtype_: NewType; +} + +export function makeDeclType(kind: K, value: DeclTypeOpts[K]) { return {kind, value}; } + +const DeclType_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"struct_","default":{"kind":"nothing"},"name":"struct_","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Struct"}},"parameters":[]}},{"annotations":[],"serializedName":"union_","default":{"kind":"nothing"},"name":"union_","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Union"}},"parameters":[]}},{"annotations":[],"serializedName":"type_","default":{"kind":"nothing"},"name":"type_","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"TypeDef"}},"parameters":[]}},{"annotations":[],"serializedName":"newtype_","default":{"kind":"nothing"},"name":"newtype_","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"NewType"}},"parameters":[]}}]}},"name":"DeclType","version":{"kind":"nothing"}}}; + +export const snDeclType: ADL.ScopedName = {moduleName:"sys.adlast", name:"DeclType"}; + +export function texprDeclType(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDeclType},parameters:[]}}; +} + +export interface Decl { + name: Ident; + version: sys_types.Maybe; + type_: DeclType; + annotations: Annotations; +} + +export function makeDecl( + input: { + name: Ident, + version: sys_types.Maybe, + type_: DeclType, + annotations: Annotations, + } +): Decl { + return { + name: input.name, + version: input.version, + type_: input.type_, + annotations: input.annotations, + }; +} + +const Decl_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"name","default":{"kind":"nothing"},"name":"name","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Ident"}},"parameters":[]}},{"annotations":[],"serializedName":"version","default":{"kind":"nothing"},"name":"version","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.types","name":"Maybe"}},"parameters":[{"typeRef":{"kind":"primitive","value":"Word32"},"parameters":[]}]}},{"annotations":[],"serializedName":"type_","default":{"kind":"nothing"},"name":"type_","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"DeclType"}},"parameters":[]}},{"annotations":[],"serializedName":"annotations","default":{"kind":"nothing"},"name":"annotations","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Annotations"}},"parameters":[]}}]}},"name":"Decl","version":{"kind":"nothing"}}}; + +export const snDecl: ADL.ScopedName = {moduleName:"sys.adlast", name:"Decl"}; + +export function texprDecl(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDecl},parameters:[]}}; +} + +export interface ScopedDecl { + moduleName: ModuleName; + decl: Decl; +} + +export function makeScopedDecl( + input: { + moduleName: ModuleName, + decl: Decl, + } +): ScopedDecl { + return { + moduleName: input.moduleName, + decl: input.decl, + }; +} + +const ScopedDecl_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"moduleName","default":{"kind":"nothing"},"name":"moduleName","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"ModuleName"}},"parameters":[]}},{"annotations":[],"serializedName":"decl","default":{"kind":"nothing"},"name":"decl","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Decl"}},"parameters":[]}}]}},"name":"ScopedDecl","version":{"kind":"nothing"}}}; + +export const snScopedDecl: ADL.ScopedName = {moduleName:"sys.adlast", name:"ScopedDecl"}; + +export function texprScopedDecl(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snScopedDecl},parameters:[]}}; +} + +export type DeclVersions = Decl[]; + +const DeclVersions_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Decl"}},"parameters":[]}]}}},"name":"DeclVersions","version":{"kind":"nothing"}}}; + +export const snDeclVersions: ADL.ScopedName = {moduleName:"sys.adlast", name:"DeclVersions"}; + +export function texprDeclVersions(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDeclVersions},parameters:[]}}; +} + +export interface Import_ModuleName { + kind: 'moduleName'; + value: ModuleName; +} +export interface Import_ScopedName { + kind: 'scopedName'; + value: ScopedName; +} + +export type Import = Import_ModuleName | Import_ScopedName; + +export interface ImportOpts { + moduleName: ModuleName; + scopedName: ScopedName; +} + +export function makeImport(kind: K, value: ImportOpts[K]) { return {kind, value}; } + +const Import_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"moduleName","default":{"kind":"nothing"},"name":"moduleName","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"ModuleName"}},"parameters":[]}},{"annotations":[],"serializedName":"scopedName","default":{"kind":"nothing"},"name":"scopedName","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"ScopedName"}},"parameters":[]}}]}},"name":"Import","version":{"kind":"nothing"}}}; + +export const snImport: ADL.ScopedName = {moduleName:"sys.adlast", name:"Import"}; + +export function texprImport(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snImport},parameters:[]}}; +} + +export interface Module { + name: ModuleName; + imports: Import[]; + decls: {[key: string]: Decl}; + annotations: Annotations; +} + +export function makeModule( + input: { + name: ModuleName, + imports: Import[], + decls: {[key: string]: Decl}, + annotations: Annotations, + } +): Module { + return { + name: input.name, + imports: input.imports, + decls: input.decls, + annotations: input.annotations, + }; +} + +const Module_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"name","default":{"kind":"nothing"},"name":"name","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"ModuleName"}},"parameters":[]}},{"annotations":[],"serializedName":"imports","default":{"kind":"nothing"},"name":"imports","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Import"}},"parameters":[]}]}},{"annotations":[],"serializedName":"decls","default":{"kind":"nothing"},"name":"decls","typeExpr":{"typeRef":{"kind":"primitive","value":"StringMap"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Decl"}},"parameters":[]}]}},{"annotations":[],"serializedName":"annotations","default":{"kind":"nothing"},"name":"annotations","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"Annotations"}},"parameters":[]}}]}},"name":"Module","version":{"kind":"nothing"}}}; + +export const snModule: ADL.ScopedName = {moduleName:"sys.adlast", name:"Module"}; + +export function texprModule(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snModule},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "sys.adlast.ModuleName" : ModuleName_AST, + "sys.adlast.Ident" : Ident_AST, + "sys.adlast.Annotations" : Annotations_AST, + "sys.adlast.ScopedName" : ScopedName_AST, + "sys.adlast.TypeRef" : TypeRef_AST, + "sys.adlast.TypeExpr" : TypeExpr_AST, + "sys.adlast.Field" : Field_AST, + "sys.adlast.Struct" : Struct_AST, + "sys.adlast.Union" : Union_AST, + "sys.adlast.TypeDef" : TypeDef_AST, + "sys.adlast.NewType" : NewType_AST, + "sys.adlast.DeclType" : DeclType_AST, + "sys.adlast.Decl" : Decl_AST, + "sys.adlast.ScopedDecl" : ScopedDecl_AST, + "sys.adlast.DeclVersions" : DeclVersions_AST, + "sys.adlast.Import" : Import_AST, + "sys.adlast.Module" : Module_AST +}; diff --git a/typescript/workspace/generated/sys/adlast2.ts b/typescript/workspace/generated/sys/adlast2.ts new file mode 100644 index 00000000..51fadba5 --- /dev/null +++ b/typescript/workspace/generated/sys/adlast2.ts @@ -0,0 +1,736 @@ +import * as sys_types from "./types"; +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module sys.adlast2 */ + +export type ModuleName = string; + +const ModuleName_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"ModuleName","version":{"kind":"nothing"}}}; + +export const snModuleName: ADL.ScopedName = {moduleName:"sys.adlast2", name:"ModuleName"}; + +export function texprModuleName(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snModuleName},parameters:[]}}; +} + +export type Ident = string; + +const Ident_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"Ident","version":{"kind":"nothing"}}}; + +export const snIdent: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Ident"}; + +export function texprIdent(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snIdent},parameters:[]}}; +} + +export type Annotations = sys_types.Map; + +const Annotations_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.types","name":"Map"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"ScopedName"}},"parameters":[]},{"typeRef":{"kind":"primitive","value":"Json"},"parameters":[]}]}}},"name":"Annotations","version":{"kind":"nothing"}}}; + +export const snAnnotations: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Annotations"}; + +export function texprAnnotations(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snAnnotations},parameters:[]}}; +} + +export interface ScopedName { + moduleName: ModuleName; + name: Ident; +} + +export function makeScopedName( + input: { + moduleName: ModuleName, + name: Ident, + } +): ScopedName { + return { + moduleName: input.moduleName, + name: input.name, + }; +} + +const ScopedName_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"moduleName","default":{"kind":"nothing"},"name":"moduleName","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"ModuleName"}},"parameters":[]}},{"annotations":[],"serializedName":"name","default":{"kind":"nothing"},"name":"name","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Ident"}},"parameters":[]}}]}},"name":"ScopedName","version":{"kind":"nothing"}}}; + +export const snScopedName: ADL.ScopedName = {moduleName:"sys.adlast2", name:"ScopedName"}; + +export function texprScopedName(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snScopedName},parameters:[]}}; +} + +export interface TypeExpr { + typeRef: R; + parameters: TypeExpr[]; +} + +export function makeTypeExpr( + input: { + typeRef: R, + parameters: TypeExpr[], + } +): TypeExpr { + return { + typeRef: input.typeRef, + parameters: input.parameters, + }; +} + +const TypeExpr_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["R"],"fields":[{"annotations":[],"serializedName":"typeRef","default":{"kind":"nothing"},"name":"typeRef","typeExpr":{"typeRef":{"kind":"typeParam","value":"R"},"parameters":[]}},{"annotations":[],"serializedName":"parameters","default":{"kind":"nothing"},"name":"parameters","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"TypeExpr"}},"parameters":[{"typeRef":{"kind":"typeParam","value":"R"},"parameters":[]}]}]}}]}},"name":"TypeExpr","version":{"kind":"nothing"}}}; + +export const snTypeExpr: ADL.ScopedName = {moduleName:"sys.adlast2", name:"TypeExpr"}; + +export function texprTypeExpr(texprR : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snTypeExpr},parameters:[texprR.value]}}; +} + +export interface Field { + name: Ident; + serializedName: Ident; + typeExpr: TE; + default: sys_types.Maybe<{}|null>; + annotations: Annotations; +} + +export function makeField( + input: { + name: Ident, + serializedName: Ident, + typeExpr: TE, + default: sys_types.Maybe<{}|null>, + annotations: Annotations, + } +): Field { + return { + name: input.name, + serializedName: input.serializedName, + typeExpr: input.typeExpr, + default: input.default, + annotations: input.annotations, + }; +} + +const Field_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["TE"],"fields":[{"annotations":[],"serializedName":"name","default":{"kind":"nothing"},"name":"name","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Ident"}},"parameters":[]}},{"annotations":[],"serializedName":"serializedName","default":{"kind":"nothing"},"name":"serializedName","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Ident"}},"parameters":[]}},{"annotations":[],"serializedName":"typeExpr","default":{"kind":"nothing"},"name":"typeExpr","typeExpr":{"typeRef":{"kind":"typeParam","value":"TE"},"parameters":[]}},{"annotations":[],"serializedName":"default","default":{"kind":"nothing"},"name":"default","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.types","name":"Maybe"}},"parameters":[{"typeRef":{"kind":"primitive","value":"Json"},"parameters":[]}]}},{"annotations":[],"serializedName":"annotations","default":{"kind":"nothing"},"name":"annotations","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Annotations"}},"parameters":[]}}]}},"name":"Field","version":{"kind":"nothing"}}}; + +export const snField: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Field"}; + +export function texprField(texprTE : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snField},parameters:[texprTE.value]}}; +} + +export interface Struct { + typeParams: Ident[]; + fields: Field[]; +} + +export function makeStruct( + input: { + typeParams: Ident[], + fields: Field[], + } +): Struct { + return { + typeParams: input.typeParams, + fields: input.fields, + }; +} + +const Struct_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["TE"],"fields":[{"annotations":[],"serializedName":"typeParams","default":{"kind":"nothing"},"name":"typeParams","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Ident"}},"parameters":[]}]}},{"annotations":[],"serializedName":"fields","default":{"kind":"nothing"},"name":"fields","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Field"}},"parameters":[{"typeRef":{"kind":"typeParam","value":"TE"},"parameters":[]}]}]}}]}},"name":"Struct","version":{"kind":"nothing"}}}; + +export const snStruct: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Struct"}; + +export function texprStruct(texprTE : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snStruct},parameters:[texprTE.value]}}; +} + +export interface Union { + typeParams: Ident[]; + fields: Field[]; +} + +export function makeUnion( + input: { + typeParams: Ident[], + fields: Field[], + } +): Union { + return { + typeParams: input.typeParams, + fields: input.fields, + }; +} + +const Union_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["TE"],"fields":[{"annotations":[],"serializedName":"typeParams","default":{"kind":"nothing"},"name":"typeParams","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Ident"}},"parameters":[]}]}},{"annotations":[],"serializedName":"fields","default":{"kind":"nothing"},"name":"fields","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Field"}},"parameters":[{"typeRef":{"kind":"typeParam","value":"TE"},"parameters":[]}]}]}}]}},"name":"Union","version":{"kind":"nothing"}}}; + +export const snUnion: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Union"}; + +export function texprUnion(texprTE : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snUnion},parameters:[texprTE.value]}}; +} + +export interface TypeDef { + typeParams: Ident[]; + typeExpr: TE; +} + +export function makeTypeDef( + input: { + typeParams: Ident[], + typeExpr: TE, + } +): TypeDef { + return { + typeParams: input.typeParams, + typeExpr: input.typeExpr, + }; +} + +const TypeDef_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["TE"],"fields":[{"annotations":[],"serializedName":"typeParams","default":{"kind":"nothing"},"name":"typeParams","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Ident"}},"parameters":[]}]}},{"annotations":[],"serializedName":"typeExpr","default":{"kind":"nothing"},"name":"typeExpr","typeExpr":{"typeRef":{"kind":"typeParam","value":"TE"},"parameters":[]}}]}},"name":"TypeDef","version":{"kind":"nothing"}}}; + +export const snTypeDef: ADL.ScopedName = {moduleName:"sys.adlast2", name:"TypeDef"}; + +export function texprTypeDef(texprTE : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snTypeDef},parameters:[texprTE.value]}}; +} + +export interface NewType { + typeParams: Ident[]; + typeExpr: TE; + default: sys_types.Maybe<{}|null>; +} + +export function makeNewType( + input: { + typeParams: Ident[], + typeExpr: TE, + default: sys_types.Maybe<{}|null>, + } +): NewType { + return { + typeParams: input.typeParams, + typeExpr: input.typeExpr, + default: input.default, + }; +} + +const NewType_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["TE"],"fields":[{"annotations":[],"serializedName":"typeParams","default":{"kind":"nothing"},"name":"typeParams","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Ident"}},"parameters":[]}]}},{"annotations":[],"serializedName":"typeExpr","default":{"kind":"nothing"},"name":"typeExpr","typeExpr":{"typeRef":{"kind":"typeParam","value":"TE"},"parameters":[]}},{"annotations":[],"serializedName":"default","default":{"kind":"nothing"},"name":"default","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.types","name":"Maybe"}},"parameters":[{"typeRef":{"kind":"primitive","value":"Json"},"parameters":[]}]}}]}},"name":"NewType","version":{"kind":"nothing"}}}; + +export const snNewType: ADL.ScopedName = {moduleName:"sys.adlast2", name:"NewType"}; + +export function texprNewType(texprTE : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snNewType},parameters:[texprTE.value]}}; +} + +export interface DeclType_Struct_ { + kind: 'struct_'; + value: Struct; +} +export interface DeclType_Union_ { + kind: 'union_'; + value: Union; +} +export interface DeclType_Type_ { + kind: 'type_'; + value: TypeDef; +} +export interface DeclType_Newtype_ { + kind: 'newtype_'; + value: NewType; +} + +export type DeclType = DeclType_Struct_ | DeclType_Union_ | DeclType_Type_ | DeclType_Newtype_; + +export interface DeclTypeOpts { + struct_: Struct; + union_: Union; + type_: TypeDef; + newtype_: NewType; +} + +export function makeDeclType>(kind: K, value: DeclTypeOpts[K]) { return {kind, value}; } + +const DeclType_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":["TE"],"fields":[{"annotations":[],"serializedName":"struct_","default":{"kind":"nothing"},"name":"struct_","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Struct"}},"parameters":[{"typeRef":{"kind":"typeParam","value":"TE"},"parameters":[]}]}},{"annotations":[],"serializedName":"union_","default":{"kind":"nothing"},"name":"union_","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Union"}},"parameters":[{"typeRef":{"kind":"typeParam","value":"TE"},"parameters":[]}]}},{"annotations":[],"serializedName":"type_","default":{"kind":"nothing"},"name":"type_","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"TypeDef"}},"parameters":[{"typeRef":{"kind":"typeParam","value":"TE"},"parameters":[]}]}},{"annotations":[],"serializedName":"newtype_","default":{"kind":"nothing"},"name":"newtype_","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"NewType"}},"parameters":[{"typeRef":{"kind":"typeParam","value":"TE"},"parameters":[]}]}}]}},"name":"DeclType","version":{"kind":"nothing"}}}; + +export const snDeclType: ADL.ScopedName = {moduleName:"sys.adlast2", name:"DeclType"}; + +export function texprDeclType(texprTE : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snDeclType},parameters:[texprTE.value]}}; +} + +export interface Decl { + name: Ident; + version: sys_types.Maybe; + type_: DeclType; + annotations: Annotations; +} + +export function makeDecl( + input: { + name: Ident, + version: sys_types.Maybe, + type_: DeclType, + annotations: Annotations, + } +): Decl { + return { + name: input.name, + version: input.version, + type_: input.type_, + annotations: input.annotations, + }; +} + +const Decl_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["TE"],"fields":[{"annotations":[],"serializedName":"name","default":{"kind":"nothing"},"name":"name","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Ident"}},"parameters":[]}},{"annotations":[],"serializedName":"version","default":{"kind":"nothing"},"name":"version","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.types","name":"Maybe"}},"parameters":[{"typeRef":{"kind":"primitive","value":"Word32"},"parameters":[]}]}},{"annotations":[],"serializedName":"type_","default":{"kind":"nothing"},"name":"type_","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"DeclType"}},"parameters":[{"typeRef":{"kind":"typeParam","value":"TE"},"parameters":[]}]}},{"annotations":[],"serializedName":"annotations","default":{"kind":"nothing"},"name":"annotations","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Annotations"}},"parameters":[]}}]}},"name":"Decl","version":{"kind":"nothing"}}}; + +export const snDecl: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Decl"}; + +export function texprDecl(texprTE : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snDecl},parameters:[texprTE.value]}}; +} + +export interface ScopedDecl { + moduleName: ModuleName; + decl: Decl; +} + +export function makeScopedDecl( + input: { + moduleName: ModuleName, + decl: Decl, + } +): ScopedDecl { + return { + moduleName: input.moduleName, + decl: input.decl, + }; +} + +const ScopedDecl_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["TE"],"fields":[{"annotations":[],"serializedName":"moduleName","default":{"kind":"nothing"},"name":"moduleName","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"ModuleName"}},"parameters":[]}},{"annotations":[],"serializedName":"decl","default":{"kind":"nothing"},"name":"decl","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Decl"}},"parameters":[{"typeRef":{"kind":"typeParam","value":"TE"},"parameters":[]}]}}]}},"name":"ScopedDecl","version":{"kind":"nothing"}}}; + +export const snScopedDecl: ADL.ScopedName = {moduleName:"sys.adlast2", name:"ScopedDecl"}; + +export function texprScopedDecl(texprTE : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snScopedDecl},parameters:[texprTE.value]}}; +} + +export type DeclVersions = Decl[]; + +const DeclVersions_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":["TE"],"typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Decl"}},"parameters":[{"typeRef":{"kind":"typeParam","value":"TE"},"parameters":[]}]}]}}},"name":"DeclVersions","version":{"kind":"nothing"}}}; + +export const snDeclVersions: ADL.ScopedName = {moduleName:"sys.adlast2", name:"DeclVersions"}; + +export function texprDeclVersions(texprTE : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snDeclVersions},parameters:[texprTE.value]}}; +} + +export interface Import_ModuleName { + kind: 'moduleName'; + value: ModuleName; +} +export interface Import_ScopedName { + kind: 'scopedName'; + value: ScopedName; +} + +export type Import = Import_ModuleName | Import_ScopedName; + +export interface ImportOpts { + moduleName: ModuleName; + scopedName: ScopedName; +} + +export function makeImport(kind: K, value: ImportOpts[K]) { return {kind, value}; } + +const Import_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"moduleName","default":{"kind":"nothing"},"name":"moduleName","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"ModuleName"}},"parameters":[]}},{"annotations":[],"serializedName":"scopedName","default":{"kind":"nothing"},"name":"scopedName","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"ScopedName"}},"parameters":[]}}]}},"name":"Import","version":{"kind":"nothing"}}}; + +export const snImport: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Import"}; + +export function texprImport(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snImport},parameters:[]}}; +} + +export interface Module { + name: ModuleName; + imports: Import[]; + decls: Decl[]; + annotations: Annotations; +} + +export function makeModule( + input: { + name: ModuleName, + imports: Import[], + decls: Decl[], + annotations: Annotations, + } +): Module { + return { + name: input.name, + imports: input.imports, + decls: input.decls, + annotations: input.annotations, + }; +} + +const Module_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["TE"],"fields":[{"annotations":[],"serializedName":"name","default":{"kind":"nothing"},"name":"name","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"ModuleName"}},"parameters":[]}},{"annotations":[],"serializedName":"imports","default":{"kind":"nothing"},"name":"imports","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Import"}},"parameters":[]}]}},{"annotations":[],"serializedName":"decls","default":{"kind":"nothing"},"name":"decls","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Decl"}},"parameters":[{"typeRef":{"kind":"typeParam","value":"TE"},"parameters":[]}]}]}},{"annotations":[],"serializedName":"annotations","default":{"kind":"nothing"},"name":"annotations","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Annotations"}},"parameters":[]}}]}},"name":"Module","version":{"kind":"nothing"}}}; + +export const snModule: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Module"}; + +export function texprModule(texprTE : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snModule},parameters:[texprTE.value]}}; +} + +/** + * The Span start..end contains all values with start <= x < end. It is empty if start >= end. + */ +export interface Span { + start: number; + end: number; +} + +export function makeSpan( + input: { + start: number, + end: number, + } +): Span { + return { + start: input.start, + end: input.end, + }; +} + +const Span_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"start","default":{"kind":"nothing"},"name":"start","typeExpr":{"typeRef":{"kind":"primitive","value":"Word64"},"parameters":[]}},{"annotations":[],"serializedName":"end","default":{"kind":"nothing"},"name":"end","typeExpr":{"typeRef":{"kind":"primitive","value":"Word64"},"parameters":[]}}]}},"name":"Span","version":{"kind":"nothing"}}}; + +export const snSpan: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Span"}; + +export function texprSpan(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snSpan},parameters:[]}}; +} + +export interface Spanned { + value: T; + span: Span; +} + +export function makeSpanned( + input: { + value: T, + span: Span, + } +): Spanned { + return { + value: input.value, + span: input.span, + }; +} + +const Spanned_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["T"],"fields":[{"annotations":[],"serializedName":"value","default":{"kind":"nothing"},"name":"value","typeExpr":{"typeRef":{"kind":"typeParam","value":"T"},"parameters":[]}},{"annotations":[],"serializedName":"span","default":{"kind":"nothing"},"name":"span","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Span"}},"parameters":[]}}]}},"name":"Spanned","version":{"kind":"nothing"}}}; + +export const snSpanned: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Spanned"}; + +export function texprSpanned(texprT : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snSpanned},parameters:[texprT.value]}}; +} + +export type PrimitiveType = 'Void' | 'Bool' | 'Int8' | 'Int16' | 'Int32' | 'Int64' | 'Word8' | 'Word16' | 'Word32' | 'Word64' | 'Float' | 'Double' | 'Json' | 'ByteVector' | 'String' | 'Vector' | 'StringMap' | 'Nullable' | 'TypeToken'; +export const valuesPrimitiveType : PrimitiveType[] = ['Void', 'Bool', 'Int8', 'Int16', 'Int32', 'Int64', 'Word8', 'Word16', 'Word32', 'Word64', 'Float', 'Double', 'Json', 'ByteVector', 'String', 'Vector', 'StringMap', 'Nullable', 'TypeToken']; + +const PrimitiveType_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"Void","default":{"kind":"nothing"},"name":"Void","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"Bool","default":{"kind":"nothing"},"name":"Bool","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"Int8","default":{"kind":"nothing"},"name":"Int8","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"Int16","default":{"kind":"nothing"},"name":"Int16","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"Int32","default":{"kind":"nothing"},"name":"Int32","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"Int64","default":{"kind":"nothing"},"name":"Int64","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"Word8","default":{"kind":"nothing"},"name":"Word8","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"Word16","default":{"kind":"nothing"},"name":"Word16","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"Word32","default":{"kind":"nothing"},"name":"Word32","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"Word64","default":{"kind":"nothing"},"name":"Word64","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"Float","default":{"kind":"nothing"},"name":"Float","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"Double","default":{"kind":"nothing"},"name":"Double","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"Json","default":{"kind":"nothing"},"name":"Json","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"ByteVector","default":{"kind":"nothing"},"name":"ByteVector","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"String","default":{"kind":"nothing"},"name":"String","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"Vector","default":{"kind":"nothing"},"name":"Vector","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"StringMap","default":{"kind":"nothing"},"name":"StringMap","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"Nullable","default":{"kind":"nothing"},"name":"Nullable","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"TypeToken","default":{"kind":"nothing"},"name":"TypeToken","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}}]}},"name":"PrimitiveType","version":{"kind":"nothing"}}}; + +export const snPrimitiveType: ADL.ScopedName = {moduleName:"sys.adlast2", name:"PrimitiveType"}; + +export function texprPrimitiveType(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snPrimitiveType},parameters:[]}}; +} + +export interface TypeRef_ScopedName { + kind: 'scopedName'; + value: ScopedName; +} +export interface TypeRef_LocalName { + kind: 'localName'; + value: Ident; +} +export interface TypeRef_Primitive { + kind: 'primitive'; + value: PrimitiveType; +} +export interface TypeRef_TypeParam { + kind: 'typeParam'; + value: Ident; +} + +export type TypeRef = TypeRef_ScopedName | TypeRef_LocalName | TypeRef_Primitive | TypeRef_TypeParam; + +export interface TypeRefOpts { + scopedName: ScopedName; + localName: Ident; + primitive: PrimitiveType; + typeParam: Ident; +} + +export function makeTypeRef(kind: K, value: TypeRefOpts[K]) { return {kind, value}; } + +const TypeRef_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"scopedName","default":{"kind":"nothing"},"name":"scopedName","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"ScopedName"}},"parameters":[]}},{"annotations":[],"serializedName":"localName","default":{"kind":"nothing"},"name":"localName","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Ident"}},"parameters":[]}},{"annotations":[],"serializedName":"primitive","default":{"kind":"nothing"},"name":"primitive","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"PrimitiveType"}},"parameters":[]}},{"annotations":[],"serializedName":"typeParam","default":{"kind":"nothing"},"name":"typeParam","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Ident"}},"parameters":[]}}]}},"name":"TypeRef","version":{"kind":"nothing"}}}; + +export const snTypeRef: ADL.ScopedName = {moduleName:"sys.adlast2", name:"TypeRef"}; + +export function texprTypeRef(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snTypeRef},parameters:[]}}; +} + +export type TypeExpr0 = TypeExpr; + +const TypeExpr0_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"TypeExpr"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"ScopedName"}},"parameters":[]}]}}},"name":"TypeExpr0","version":{"kind":"nothing"}}}; + +export const snTypeExpr0: ADL.ScopedName = {moduleName:"sys.adlast2", name:"TypeExpr0"}; + +export function texprTypeExpr0(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snTypeExpr0},parameters:[]}}; +} + +export type Field0 = Field; + +const Field0_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Field"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"TypeExpr0"}},"parameters":[]}]}}},"name":"Field0","version":{"kind":"nothing"}}}; + +export const snField0: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Field0"}; + +export function texprField0(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snField0},parameters:[]}}; +} + +export type Struct0 = Struct; + +const Struct0_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Struct"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"TypeExpr0"}},"parameters":[]}]}}},"name":"Struct0","version":{"kind":"nothing"}}}; + +export const snStruct0: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Struct0"}; + +export function texprStruct0(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snStruct0},parameters:[]}}; +} + +export type Union0 = Union; + +const Union0_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Union"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"TypeExpr0"}},"parameters":[]}]}}},"name":"Union0","version":{"kind":"nothing"}}}; + +export const snUnion0: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Union0"}; + +export function texprUnion0(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snUnion0},parameters:[]}}; +} + +export type DeclType0 = DeclType; + +const DeclType0_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"DeclType"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"TypeExpr0"}},"parameters":[]}]}}},"name":"DeclType0","version":{"kind":"nothing"}}}; + +export const snDeclType0: ADL.ScopedName = {moduleName:"sys.adlast2", name:"DeclType0"}; + +export function texprDeclType0(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDeclType0},parameters:[]}}; +} + +export type Decl0 = Decl; + +const Decl0_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Decl"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"TypeExpr0"}},"parameters":[]}]}}},"name":"Decl0","version":{"kind":"nothing"}}}; + +export const snDecl0: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Decl0"}; + +export function texprDecl0(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDecl0},parameters:[]}}; +} + +export type Module0 = Module; + +const Module0_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Module"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"TypeExpr0"}},"parameters":[]}]}}},"name":"Module0","version":{"kind":"nothing"}}}; + +export const snModule0: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Module0"}; + +export function texprModule0(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snModule0},parameters:[]}}; +} + +export type TypeExpr1 = TypeExpr; + +const TypeExpr1_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"TypeExpr"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"TypeRef"}},"parameters":[]}]}}},"name":"TypeExpr1","version":{"kind":"nothing"}}}; + +export const snTypeExpr1: ADL.ScopedName = {moduleName:"sys.adlast2", name:"TypeExpr1"}; + +export function texprTypeExpr1(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snTypeExpr1},parameters:[]}}; +} + +export type Field1 = Field; + +const Field1_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Field"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"TypeExpr1"}},"parameters":[]}]}}},"name":"Field1","version":{"kind":"nothing"}}}; + +export const snField1: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Field1"}; + +export function texprField1(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snField1},parameters:[]}}; +} + +export type Struct1 = Struct; + +const Struct1_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Struct"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"TypeExpr1"}},"parameters":[]}]}}},"name":"Struct1","version":{"kind":"nothing"}}}; + +export const snStruct1: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Struct1"}; + +export function texprStruct1(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snStruct1},parameters:[]}}; +} + +export type Union1 = Union; + +const Union1_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Union"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"TypeExpr1"}},"parameters":[]}]}}},"name":"Union1","version":{"kind":"nothing"}}}; + +export const snUnion1: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Union1"}; + +export function texprUnion1(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snUnion1},parameters:[]}}; +} + +export type DeclType1 = DeclType; + +const DeclType1_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"DeclType"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"TypeExpr1"}},"parameters":[]}]}}},"name":"DeclType1","version":{"kind":"nothing"}}}; + +export const snDeclType1: ADL.ScopedName = {moduleName:"sys.adlast2", name:"DeclType1"}; + +export function texprDeclType1(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDeclType1},parameters:[]}}; +} + +export type Decl1 = Decl; + +const Decl1_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Decl"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"TypeExpr1"}},"parameters":[]}]}}},"name":"Decl1","version":{"kind":"nothing"}}}; + +export const snDecl1: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Decl1"}; + +export function texprDecl1(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDecl1},parameters:[]}}; +} + +export type Module1 = Module; + +const Module1_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Module"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"TypeExpr1"}},"parameters":[]}]}}},"name":"Module1","version":{"kind":"nothing"}}}; + +export const snModule1: ADL.ScopedName = {moduleName:"sys.adlast2", name:"Module1"}; + +export function texprModule1(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snModule1},parameters:[]}}; +} + +export type AdlAst = {[key: string]: AstModule}; + +const AdlAst_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"StringMap"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"AstModule"}},"parameters":[]}]}}},"name":"AdlAst","version":{"kind":"nothing"}}}; + +export const snAdlAst: ADL.ScopedName = {moduleName:"sys.adlast2", name:"AdlAst"}; + +export function texprAdlAst(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snAdlAst},parameters:[]}}; +} + +export interface AstModule { + name: ModuleName; + imports: Import[]; + decls: {[key: string]: Decl}; + annotations: Annotations; +} + +export function makeAstModule( + input: { + name: ModuleName, + imports: Import[], + decls: {[key: string]: Decl}, + annotations: Annotations, + } +): AstModule { + return { + name: input.name, + imports: input.imports, + decls: input.decls, + annotations: input.annotations, + }; +} + +const AstModule_AST : ADL.ScopedDecl = + {"moduleName":"sys.adlast2","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"name","default":{"kind":"nothing"},"name":"name","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"ModuleName"}},"parameters":[]}},{"annotations":[],"serializedName":"imports","default":{"kind":"nothing"},"name":"imports","typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Import"}},"parameters":[]}]}},{"annotations":[],"serializedName":"decls","default":{"kind":"nothing"},"name":"decls","typeExpr":{"typeRef":{"kind":"primitive","value":"StringMap"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Decl"}},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"TypeExpr1"}},"parameters":[]}]}]}},{"annotations":[],"serializedName":"annotations","default":{"kind":"nothing"},"name":"annotations","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast2","name":"Annotations"}},"parameters":[]}}]}},"name":"AstModule","version":{"kind":"nothing"}}}; + +export const snAstModule: ADL.ScopedName = {moduleName:"sys.adlast2", name:"AstModule"}; + +export function texprAstModule(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snAstModule},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "sys.adlast2.ModuleName" : ModuleName_AST, + "sys.adlast2.Ident" : Ident_AST, + "sys.adlast2.Annotations" : Annotations_AST, + "sys.adlast2.ScopedName" : ScopedName_AST, + "sys.adlast2.TypeExpr" : TypeExpr_AST, + "sys.adlast2.Field" : Field_AST, + "sys.adlast2.Struct" : Struct_AST, + "sys.adlast2.Union" : Union_AST, + "sys.adlast2.TypeDef" : TypeDef_AST, + "sys.adlast2.NewType" : NewType_AST, + "sys.adlast2.DeclType" : DeclType_AST, + "sys.adlast2.Decl" : Decl_AST, + "sys.adlast2.ScopedDecl" : ScopedDecl_AST, + "sys.adlast2.DeclVersions" : DeclVersions_AST, + "sys.adlast2.Import" : Import_AST, + "sys.adlast2.Module" : Module_AST, + "sys.adlast2.Span" : Span_AST, + "sys.adlast2.Spanned" : Spanned_AST, + "sys.adlast2.PrimitiveType" : PrimitiveType_AST, + "sys.adlast2.TypeRef" : TypeRef_AST, + "sys.adlast2.TypeExpr0" : TypeExpr0_AST, + "sys.adlast2.Field0" : Field0_AST, + "sys.adlast2.Struct0" : Struct0_AST, + "sys.adlast2.Union0" : Union0_AST, + "sys.adlast2.DeclType0" : DeclType0_AST, + "sys.adlast2.Decl0" : Decl0_AST, + "sys.adlast2.Module0" : Module0_AST, + "sys.adlast2.TypeExpr1" : TypeExpr1_AST, + "sys.adlast2.Field1" : Field1_AST, + "sys.adlast2.Struct1" : Struct1_AST, + "sys.adlast2.Union1" : Union1_AST, + "sys.adlast2.DeclType1" : DeclType1_AST, + "sys.adlast2.Decl1" : Decl1_AST, + "sys.adlast2.Module1" : Module1_AST, + "sys.adlast2.AdlAst" : AdlAst_AST, + "sys.adlast2.AstModule" : AstModule_AST +}; diff --git a/typescript/workspace/generated/sys/annotations.ts b/typescript/workspace/generated/sys/annotations.ts new file mode 100644 index 00000000..639b7fa4 --- /dev/null +++ b/typescript/workspace/generated/sys/annotations.ts @@ -0,0 +1,66 @@ +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module sys.annotations */ + +export type Doc = string; + +const Doc_AST : ADL.ScopedDecl = + {"moduleName":"sys.annotations","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"Doc","version":{"kind":"nothing"}}}; + +export const snDoc: ADL.ScopedName = {moduleName:"sys.annotations", name:"Doc"}; + +export function texprDoc(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDoc},parameters:[]}}; +} + +export type SerializedName = string; + +const SerializedName_AST : ADL.ScopedDecl = + {"moduleName":"sys.annotations","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}},"name":"SerializedName","version":{"kind":"nothing"}}}; + +export const snSerializedName: ADL.ScopedName = {moduleName:"sys.annotations", name:"SerializedName"}; + +export function texprSerializedName(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snSerializedName},parameters:[]}}; +} + +export interface SerializedWithInternalTag { + tag: string; +} + +export function makeSerializedWithInternalTag( + input: { + tag: string, + } +): SerializedWithInternalTag { + return { + tag: input.tag, + }; +} + +const SerializedWithInternalTag_AST : ADL.ScopedDecl = + {"moduleName":"sys.annotations","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"tag","default":{"kind":"nothing"},"name":"tag","typeExpr":{"typeRef":{"kind":"primitive","value":"String"},"parameters":[]}}]}},"name":"SerializedWithInternalTag","version":{"kind":"nothing"}}}; + +export const snSerializedWithInternalTag: ADL.ScopedName = {moduleName:"sys.annotations", name:"SerializedWithInternalTag"}; + +export function texprSerializedWithInternalTag(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snSerializedWithInternalTag},parameters:[]}}; +} + +export type CustomSerialization = boolean; + +const CustomSerialization_AST : ADL.ScopedDecl = + {"moduleName":"sys.annotations","decl":{"annotations":[],"type_":{"kind":"type_","value":{"typeParams":[],"typeExpr":{"typeRef":{"kind":"primitive","value":"Bool"},"parameters":[]}}},"name":"CustomSerialization","version":{"kind":"nothing"}}}; + +export const snCustomSerialization: ADL.ScopedName = {moduleName:"sys.annotations", name:"CustomSerialization"}; + +export function texprCustomSerialization(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snCustomSerialization},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "sys.annotations.Doc" : Doc_AST, + "sys.annotations.SerializedName" : SerializedName_AST, + "sys.annotations.SerializedWithInternalTag" : SerializedWithInternalTag_AST, + "sys.annotations.CustomSerialization" : CustomSerialization_AST +}; diff --git a/typescript/workspace/generated/sys/dynamic.ts b/typescript/workspace/generated/sys/dynamic.ts new file mode 100644 index 00000000..c94b4985 --- /dev/null +++ b/typescript/workspace/generated/sys/dynamic.ts @@ -0,0 +1,37 @@ +import * as sys_adlast from "./adlast"; +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module sys.dynamic */ + +/** + * A serialised value along with its type + */ +export interface Dynamic { + typeExpr: sys_adlast.TypeExpr; + value: {}|null; +} + +export function makeDynamic( + input: { + typeExpr: sys_adlast.TypeExpr, + value: {}|null, + } +): Dynamic { + return { + typeExpr: input.typeExpr, + value: input.value, + }; +} + +const Dynamic_AST : ADL.ScopedDecl = + {"moduleName":"sys.dynamic","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":[],"fields":[{"annotations":[],"serializedName":"typeExpr","default":{"kind":"nothing"},"name":"typeExpr","typeExpr":{"typeRef":{"kind":"reference","value":{"moduleName":"sys.adlast","name":"TypeExpr"}},"parameters":[]}},{"annotations":[],"serializedName":"value","default":{"kind":"nothing"},"name":"value","typeExpr":{"typeRef":{"kind":"primitive","value":"Json"},"parameters":[]}}]}},"name":"Dynamic","version":{"kind":"nothing"}}}; + +export const snDynamic: ADL.ScopedName = {moduleName:"sys.dynamic", name:"Dynamic"}; + +export function texprDynamic(): ADL.ATypeExpr { + return {value:{typeRef:{kind:"reference",value:snDynamic},parameters:[]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "sys.dynamic.Dynamic" : Dynamic_AST +}; diff --git a/typescript/workspace/generated/sys/index.ts b/typescript/workspace/generated/sys/index.ts new file mode 100644 index 00000000..abbd484a --- /dev/null +++ b/typescript/workspace/generated/sys/index.ts @@ -0,0 +1,6 @@ +/* @generated - key "" */ +export * as adlast from './adlast'; +export * as adlast2 from './adlast2'; +export * as annotations from './annotations'; +export * as dynamic from './dynamic'; +export * as types from './types'; diff --git a/typescript/workspace/generated/sys/package.json b/typescript/workspace/generated/sys/package.json new file mode 100644 index 00000000..d878560c --- /dev/null +++ b/typescript/workspace/generated/sys/package.json @@ -0,0 +1,16 @@ +{ + "name": "@adl-lang/sys", + "version": "1.0.0", + "scripts": { + "clean": "rm -rf dist && rm -rf node_modules", + "tsc": "tsc" + }, + "dependencies": { + "@adl-lang/runtime": "^1.0.0", + "base64-js": "^1.5.1" + }, + "devDependencies": { + "typescript": "^4.9.3", + "tsconfig": "workspace:*" + } +} \ No newline at end of file diff --git a/typescript/workspace/generated/sys/resolver.ts b/typescript/workspace/generated/sys/resolver.ts new file mode 100644 index 00000000..e52e8536 --- /dev/null +++ b/typescript/workspace/generated/sys/resolver.ts @@ -0,0 +1,22 @@ +import {_AST_MAP as sys_adlast} from "./adlast"; +import {_AST_MAP as sys_adlast2} from "./adlast2"; +import {_AST_MAP as sys_annotations} from "./annotations"; +import {_AST_MAP as sys_dynamic} from "./dynamic"; +import {_AST_MAP as sys_types} from "./types"; +import {ScopedDecl, declResolver} from "@adl-lang/runtime/adl"; + +/* @generated from adl */ + +export const ADL_local: { [key: string]: ScopedDecl } = { + ...sys_adlast, + ...sys_adlast2, + ...sys_annotations, + ...sys_dynamic, + ...sys_types, +}; + +export const ADL: { [key: string]: ScopedDecl } = { + ...ADL_local, +}; + +export const RESOLVER = declResolver(ADL); diff --git a/typescript/workspace/generated/sys/tsconfig.json b/typescript/workspace/generated/sys/tsconfig.json new file mode 100644 index 00000000..a3b461dc --- /dev/null +++ b/typescript/workspace/generated/sys/tsconfig.json @@ -0,0 +1,17 @@ +{ + "extends": "tsconfig/base.json", + "include": [ + "." + ], + "exclude": [ + "dist", + "build", + "node_modules" + ], + "compilerOptions": { + "outDir": "dist", + "lib": [ + "es2020" + ] + } +} \ No newline at end of file diff --git a/typescript/workspace/generated/sys/types.ts b/typescript/workspace/generated/sys/types.ts new file mode 100644 index 00000000..2c528156 --- /dev/null +++ b/typescript/workspace/generated/sys/types.ts @@ -0,0 +1,167 @@ +import * as ADL from "@adl-lang/runtime/adl"; + +/* @generated from adl module sys.types */ + +export interface Pair { + v1: T1; + v2: T2; +} + +export function makePair( + input: { + v1: T1, + v2: T2, + } +): Pair { + return { + v1: input.v1, + v2: input.v2, + }; +} + +const Pair_AST : ADL.ScopedDecl = + {"moduleName":"sys.types","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["T1","T2"],"fields":[{"annotations":[],"serializedName":"v1","default":{"kind":"nothing"},"name":"v1","typeExpr":{"typeRef":{"kind":"typeParam","value":"T1"},"parameters":[]}},{"annotations":[],"serializedName":"v2","default":{"kind":"nothing"},"name":"v2","typeExpr":{"typeRef":{"kind":"typeParam","value":"T2"},"parameters":[]}}]}},"name":"Pair","version":{"kind":"nothing"}}}; + +export const snPair: ADL.ScopedName = {moduleName:"sys.types", name:"Pair"}; + +export function texprPair(texprT1 : ADL.ATypeExpr, texprT2 : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snPair},parameters:[texprT1.value,texprT2.value]}}; +} + +export interface Either_Left { + kind: 'left'; + value: T1; +} +export interface Either_Right<_T1, T2> { + kind: 'right'; + value: T2; +} + +export type Either = Either_Left | Either_Right; + +export interface EitherOpts { + left: T1; + right: T2; +} + +export function makeEither>(kind: K, value: EitherOpts[K]) { return {kind, value}; } + +const Either_AST : ADL.ScopedDecl = + {"moduleName":"sys.types","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":["T1","T2"],"fields":[{"annotations":[],"serializedName":"left","default":{"kind":"nothing"},"name":"left","typeExpr":{"typeRef":{"kind":"typeParam","value":"T1"},"parameters":[]}},{"annotations":[],"serializedName":"right","default":{"kind":"nothing"},"name":"right","typeExpr":{"typeRef":{"kind":"typeParam","value":"T2"},"parameters":[]}}]}},"name":"Either","version":{"kind":"nothing"}}}; + +export const snEither: ADL.ScopedName = {moduleName:"sys.types", name:"Either"}; + +export function texprEither(texprT1 : ADL.ATypeExpr, texprT2 : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snEither},parameters:[texprT1.value,texprT2.value]}}; +} + +export interface Maybe_Nothing<_T> { + kind: 'nothing'; +} +export interface Maybe_Just { + kind: 'just'; + value: T; +} + +export type Maybe = Maybe_Nothing | Maybe_Just; + +export interface MaybeOpts { + nothing: null; + just: T; +} + +export function makeMaybe>(kind: K, value: MaybeOpts[K]) { return {kind, value}; } + +const Maybe_AST : ADL.ScopedDecl = + {"moduleName":"sys.types","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":["T"],"fields":[{"annotations":[],"serializedName":"nothing","default":{"kind":"nothing"},"name":"nothing","typeExpr":{"typeRef":{"kind":"primitive","value":"Void"},"parameters":[]}},{"annotations":[],"serializedName":"just","default":{"kind":"nothing"},"name":"just","typeExpr":{"typeRef":{"kind":"typeParam","value":"T"},"parameters":[]}}]}},"name":"Maybe","version":{"kind":"nothing"}}}; + +export const snMaybe: ADL.ScopedName = {moduleName:"sys.types", name:"Maybe"}; + +export function texprMaybe(texprT : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snMaybe},parameters:[texprT.value]}}; +} + +export interface Result_Ok { + kind: 'ok'; + value: T; +} +export interface Result_Error<_T, E> { + kind: 'error'; + value: E; +} + +export type Result = Result_Ok | Result_Error; + +export interface ResultOpts { + ok: T; + error: E; +} + +export function makeResult>(kind: K, value: ResultOpts[K]) { return {kind, value}; } + +const Result_AST : ADL.ScopedDecl = + {"moduleName":"sys.types","decl":{"annotations":[],"type_":{"kind":"union_","value":{"typeParams":["T","E"],"fields":[{"annotations":[],"serializedName":"ok","default":{"kind":"nothing"},"name":"ok","typeExpr":{"typeRef":{"kind":"typeParam","value":"T"},"parameters":[]}},{"annotations":[],"serializedName":"error","default":{"kind":"nothing"},"name":"error","typeExpr":{"typeRef":{"kind":"typeParam","value":"E"},"parameters":[]}}]}},"name":"Result","version":{"kind":"nothing"}}}; + +export const snResult: ADL.ScopedName = {moduleName:"sys.types", name:"Result"}; + +export function texprResult(texprT : ADL.ATypeExpr, texprE : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snResult},parameters:[texprT.value,texprE.value]}}; +} + +export interface MapEntry { + key: K; + value: V; +} + +export function makeMapEntry( + input: { + key: K, + value: V, + } +): MapEntry { + return { + key: input.key, + value: input.value, + }; +} + +const MapEntry_AST : ADL.ScopedDecl = + {"moduleName":"sys.types","decl":{"annotations":[],"type_":{"kind":"struct_","value":{"typeParams":["K","V"],"fields":[{"annotations":[],"serializedName":"k","default":{"kind":"nothing"},"name":"key","typeExpr":{"typeRef":{"kind":"typeParam","value":"K"},"parameters":[]}},{"annotations":[],"serializedName":"v","default":{"kind":"nothing"},"name":"value","typeExpr":{"typeRef":{"kind":"typeParam","value":"V"},"parameters":[]}}]}},"name":"MapEntry","version":{"kind":"nothing"}}}; + +export const snMapEntry: ADL.ScopedName = {moduleName:"sys.types", name:"MapEntry"}; + +export function texprMapEntry(texprK : ADL.ATypeExpr, texprV : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snMapEntry},parameters:[texprK.value,texprV.value]}}; +} + +export type Map = MapEntry[]; + +const Map_AST : ADL.ScopedDecl = + {"moduleName":"sys.types","decl":{"annotations":[],"type_":{"kind":"newtype_","value":{"typeParams":["K","V"],"default":{"kind":"nothing"},"typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"reference","value":{"moduleName":"sys.types","name":"MapEntry"}},"parameters":[{"typeRef":{"kind":"typeParam","value":"K"},"parameters":[]},{"typeRef":{"kind":"typeParam","value":"V"},"parameters":[]}]}]}}},"name":"Map","version":{"kind":"nothing"}}}; + +export const snMap: ADL.ScopedName = {moduleName:"sys.types", name:"Map"}; + +export function texprMap(texprK : ADL.ATypeExpr, texprV : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snMap},parameters:[texprK.value,texprV.value]}}; +} + +export type Set = T[]; + +const Set_AST : ADL.ScopedDecl = + {"moduleName":"sys.types","decl":{"annotations":[],"type_":{"kind":"newtype_","value":{"typeParams":["T"],"default":{"kind":"nothing"},"typeExpr":{"typeRef":{"kind":"primitive","value":"Vector"},"parameters":[{"typeRef":{"kind":"typeParam","value":"T"},"parameters":[]}]}}},"name":"Set","version":{"kind":"nothing"}}}; + +export const snSet: ADL.ScopedName = {moduleName:"sys.types", name:"Set"}; + +export function texprSet(texprT : ADL.ATypeExpr): ADL.ATypeExpr> { + return {value:{typeRef:{kind:"reference",value:snSet},parameters:[texprT.value]}}; +} + +export const _AST_MAP: { [key: string]: ADL.ScopedDecl } = { + "sys.types.Pair" : Pair_AST, + "sys.types.Either" : Either_AST, + "sys.types.Maybe" : Maybe_AST, + "sys.types.Result" : Result_AST, + "sys.types.MapEntry" : MapEntry_AST, + "sys.types.Map" : Map_AST, + "sys.types.Set" : Set_AST +}; diff --git a/typescript/workspace/package.json b/typescript/workspace/package.json new file mode 100644 index 00000000..3967b55b --- /dev/null +++ b/typescript/workspace/package.json @@ -0,0 +1,16 @@ +{ + "name": "workspace", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@types/node": "^18.16.1", + "typescript": "^4.9.3" + } +} diff --git a/typescript/workspace/packages/tsconfig/README.md b/typescript/workspace/packages/tsconfig/README.md new file mode 100644 index 00000000..0da79cf2 --- /dev/null +++ b/typescript/workspace/packages/tsconfig/README.md @@ -0,0 +1,3 @@ +# `tsconfig` + +These are base shared `tsconfig.json`s from which all other `tsconfig.json`'s inherit from. diff --git a/typescript/workspace/packages/tsconfig/base.json b/typescript/workspace/packages/tsconfig/base.json new file mode 100644 index 00000000..d78afa7d --- /dev/null +++ b/typescript/workspace/packages/tsconfig/base.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Default", + "compilerOptions": { + "composite": false, + "declaration": true, + "declarationMap": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "inlineSources": false, + "isolatedModules": true, + "moduleResolution": "node", + "noUnusedLocals": false, + "noUnusedParameters": false, + "preserveWatchOutput": true, + "skipLibCheck": true, + "strict": true, + "module": "ESNext", + "target": "es6" + }, + "exclude": ["node_modules"] +} diff --git a/typescript/workspace/packages/tsconfig/nextjs.json b/typescript/workspace/packages/tsconfig/nextjs.json new file mode 100644 index 00000000..3b7dfa90 --- /dev/null +++ b/typescript/workspace/packages/tsconfig/nextjs.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Next.js", + "extends": "./base.json", + "compilerOptions": { + "target": "es5", + "lib": ["dom", "dom.iterable", "esnext"], + "allowJs": true, + "skipLibCheck": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "noEmit": true, + "incremental": true, + "esModuleInterop": true, + "module": "esnext", + "resolveJsonModule": true, + "isolatedModules": true, + "jsx": "preserve" + }, + "include": ["src", "next-env.d.ts"], + "exclude": ["node_modules"] +} diff --git a/typescript/workspace/packages/tsconfig/package.json b/typescript/workspace/packages/tsconfig/package.json new file mode 100644 index 00000000..f4810fc3 --- /dev/null +++ b/typescript/workspace/packages/tsconfig/package.json @@ -0,0 +1,10 @@ +{ + "name": "tsconfig", + "version": "0.0.0", + "private": true, + "files": [ + "base.json", + "nextjs.json", + "react-library.json" + ] +} diff --git a/typescript/workspace/packages/tsconfig/react-library.json b/typescript/workspace/packages/tsconfig/react-library.json new file mode 100644 index 00000000..af8711c5 --- /dev/null +++ b/typescript/workspace/packages/tsconfig/react-library.json @@ -0,0 +1,11 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "React Library", + "extends": "./base.json", + "compilerOptions": { + "jsx": "react-jsx", + "lib": ["ES2015"], + "module": "ESNext", + "target": "es6" + } +} diff --git a/typescript/workspace/pnpm-lock.yaml b/typescript/workspace/pnpm-lock.yaml new file mode 100644 index 00000000..0730cbef --- /dev/null +++ b/typescript/workspace/pnpm-lock.yaml @@ -0,0 +1,97 @@ +lockfileVersion: '6.0' + +importers: + + .: + devDependencies: + '@types/node': + specifier: ^18.16.1 + version: 18.16.1 + typescript: + specifier: ^4.9.3 + version: 4.9.3 + + generated/common: + dependencies: + '@adl-lang/runtime': + specifier: workspace:* + version: link:../runtime + '@adl-lang/sys': + specifier: workspace:* + version: link:../sys + devDependencies: + tsconfig: + specifier: workspace:* + version: link:../../packages/tsconfig + typescript: + specifier: ^4.9.3 + version: 4.9.3 + + generated/protoclient: + dependencies: + '@adl-lang/common': + specifier: workspace:* + version: link:../common + '@adl-lang/runtime': + specifier: workspace:* + version: link:../runtime + '@adl-lang/sys': + specifier: workspace:* + version: link:../sys + base64-js: + specifier: ^1.5.1 + version: 1.5.1 + devDependencies: + tsconfig: + specifier: workspace:* + version: link:../../packages/tsconfig + typescript: + specifier: ^4.9.3 + version: 4.9.3 + + generated/runtime: + dependencies: + base64-js: + specifier: ^1.5.1 + version: 1.5.1 + devDependencies: + tsconfig: + specifier: workspace:* + version: link:../../packages/tsconfig + typescript: + specifier: ^4.9.3 + version: 4.9.3 + + generated/sys: + dependencies: + '@adl-lang/runtime': + specifier: workspace:* + version: link:../runtime + base64-js: + specifier: ^1.5.1 + version: 1.5.1 + devDependencies: + tsconfig: + specifier: workspace:* + version: link:../../packages/tsconfig + typescript: + specifier: ^4.9.3 + version: 4.9.3 + + packages/tsconfig: {} + +packages: + + /@types/node@18.16.1: + resolution: {integrity: sha512-DZxSZWXxFfOlx7k7Rv4LAyiMroaxa3Ly/7OOzZO8cBNho0YzAi4qlbrx8W27JGqG57IgR/6J7r+nOJWw6kcvZA==} + dev: true + + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: false + + /typescript@4.9.3: + resolution: {integrity: sha512-CIfGzTelbKNEnLpLdGFgdyKhG23CKdKgQPOBc+OUNrkJ2vr+KSzsSV5kq5iWhEQbok+quxgGzrAtGWCyU7tHnA==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: true diff --git a/typescript/workspace/pnpm-workspace.yaml b/typescript/workspace/pnpm-workspace.yaml new file mode 100644 index 00000000..9bd049f0 --- /dev/null +++ b/typescript/workspace/pnpm-workspace.yaml @@ -0,0 +1,7 @@ +packages: + # launchable things: applications, story-book (maybe tests) + - "solutions/*" + # hand coded non-launchable things: components, libraries etc. + - "packages/*" + # generated code + - "generated/*" From e3658bf98ffb9a3c6bbe4516a7bad51a7eb9498c Mon Sep 17 00:00:00 2001 From: Gary Miller Date: Tue, 2 May 2023 19:31:45 +1000 Subject: [PATCH 2/2] resolver and index differ based on transative and same package test --- adl/adl.work.json | 41 ++++++------- adl/adl.work1.json | 46 ++++++++------- adl/adl.work2.json | 29 ++++++--- adl/adl.work3.json | 47 ++++++++------- adl/adlc/adlc/packaging.adl | 1 + rust/compiler/src/adlgen/adlc/packaging.rs | 5 +- rust/compiler/src/adlstdlib/mod.rs | 13 ++-- rust/compiler/src/cli/ast.rs | 2 +- rust/compiler/src/cli/mod.rs | 8 +-- rust/compiler/src/cli/rust/mod.rs | 5 +- rust/compiler/src/cli/tsgen/defaultval.rs | 2 +- rust/compiler/src/cli/tsgen/generate.rs | 5 +- rust/compiler/src/cli/tsgen/mod.rs | 59 +++++++++++-------- rust/compiler/src/cli/tsgen/tests.rs | 28 +++++++-- rust/compiler/src/cli/tsgen/utils.rs | 16 +++-- rust/compiler/src/cli/workspace.rs | 5 +- rust/compiler/src/processing/loader.rs | 40 ++++++++----- rust/compiler/src/processing/resolver.rs | 41 ++++++++----- .../workspace/generated/common/package.json | 4 +- .../generated/protoclient/package.json | 14 ++--- .../workspace/generated/sys/package.json | 8 +-- typescript/workspace/pnpm-lock.yaml | 6 +- 22 files changed, 258 insertions(+), 167 deletions(-) diff --git a/adl/adl.work.json b/adl/adl.work.json index 1ed06448..d2ab018f 100644 --- a/adl/adl.work.json +++ b/adl/adl.work.json @@ -3,46 +3,47 @@ "runtimes": [ { "ts_runtime": { - "output_dir": "../generated/typescript/tests", - "strip_first": false + "output_dir": "../generated/typescript/tests/runtime" } } ], - "embedded_sys_loader" : { "just": { - "path": "", - "ts_opts": { - "npm_pkg_name": "@adl-lang/sys", - "npm_version": "1.0.0", - "extra_dependencies": { - "base64-js": "^1.5.1" - }, - "extra_dev_dependencies": { - "tsconfig": "workspace:*", - "typescript": "^4.9.3" - } - } - }}, "use": [ { - "path": "./adlc", + "ref": { + "dir": { + "path": "./adlc" + } + }, "ts_opts": { "npm_pkg_name": "@adl-lang/adlc" } }, { - "path": "./tests/test31/lib", + "ref": { + "dir": { + "path": "./tests/test31/lib" + } + }, "ts_opts": { "npm_pkg_name": "@adl-lang/common" } }, { - "path": "./stdlib", + "ref": { + "dir": { + "path": "./stdlib" + } + }, "ts_opts": { "npm_pkg_name": "@adl-lang/sys" } }, { - "path": "./tests/test31/proj", + "ref": { + "dir": { + "path": "./tests/test31/proj" + } + }, "ts_opts": { "npm_pkg_name": "@adl-lang/protoclient", "runtime_opts": { diff --git a/adl/adl.work1.json b/adl/adl.work1.json index dcd940c3..6c164fb4 100644 --- a/adl/adl.work1.json +++ b/adl/adl.work1.json @@ -1,6 +1,5 @@ { "adlc": "0.0.0", - "use_embedded_sys_loader": true, "runtimes": [ { "ts_runtime": { @@ -9,23 +8,13 @@ } } ], - "embedded_sys_loader" : { "just": { - "path": "", - "ts_opts": { - "npm_pkg_name": "@adl-lang/sys", - "npm_version": "1.0.0", - "extra_dependencies": { - "base64-js": "^1.5.1" - }, - "extra_dev_dependencies": { - "tsconfig": "workspace:*", - "typescript": "^4.9.3" - } - } - }}, "use": [ { - "path": "./adlc", + "ref": { + "dir": { + "path": "./adlc" + } + }, "ts_opts": { "npm_pkg_name": "@adl-lang/adlc", "extra_dev_dependencies": { @@ -45,7 +34,11 @@ } }, { - "path": "./tests/test31/lib", + "ref": { + "dir": { + "path": "./tests/test31/lib" + } + }, "ts_opts": { "npm_pkg_name": "@adl-lang/common", "extra_dev_dependencies": { @@ -58,15 +51,28 @@ "outputs": { "gen": { "output_dir": "../generated1/common", - "manifest": "../generated1/common/.adl-manifest", - "strip_first": false + "manifest": "../generated1/common/.adl-manifest" } }, "include_resolver": false } }, { - "path": "./tests/test31/proj", + "ref": { + "dir": { + "path": "./stdlib" + } + }, + "ts_opts": { + "npm_pkg_name": "@adl-lang/sys" + } + }, + { + "ref": { + "dir": { + "path": "./tests/test31/proj" + } + }, "ts_opts": { "npm_pkg_name": "@adl-lang/protoclient", "extra_dependencies": { diff --git a/adl/adl.work2.json b/adl/adl.work2.json index 103345cb..33cb9b12 100644 --- a/adl/adl.work2.json +++ b/adl/adl.work2.json @@ -1,6 +1,5 @@ { "adlc": "0.0.0", - "use_embedded_sys_loader": true, "runtimes": [ { "ts_runtime": { @@ -9,10 +8,13 @@ } } ], - "embedded_sys_loader": "nothing", "use": [ { - "path": "./adlc", + "ref": { + "dir": { + "path": "./adlc" + } + }, "ts_opts": { "npm_pkg_name": "@adl-lang/adlc", "extra_dev_dependencies": { @@ -32,7 +34,11 @@ } }, { - "path": "./tests/test31/lib", + "ref": { + "dir": { + "path": "./tests/test31/lib" + } + }, "ts_opts": { "npm_pkg_name": "@adl-lang/common", "extra_dev_dependencies": { @@ -45,15 +51,18 @@ "outputs": { "gen": { "output_dir": "../generated2/common", - "manifest": "../generated2/common/.adl-manifest", - "strip_first": false + "manifest": "../generated2/common/.adl-manifest" } }, "include_resolver": false } }, { - "path": "./stdlib", + "ref": { + "dir": { + "path": "./stdlib" + } + }, "ts_opts": { "npm_pkg_name": "@adl-lang/sys", "extra_dev_dependencies": { @@ -73,7 +82,11 @@ } }, { - "path": "./tests/test31/proj", + "ref": { + "dir": { + "path": "./tests/test31/proj" + } + }, "ts_opts": { "npm_pkg_name": "@adl-lang/protoclient", "extra_dependencies": { diff --git a/adl/adl.work3.json b/adl/adl.work3.json index f4ed7d59..bf19edb1 100644 --- a/adl/adl.work3.json +++ b/adl/adl.work3.json @@ -1,38 +1,44 @@ { "adlc": "0.0.0", - "use_embedded_sys_loader": true, "runtimes": [ ], - "embedded_sys_loader" : { "just": { - "path": "", - "ts_opts": { - "npm_pkg_name": "@adl-lang/sys", - "npm_version": "1.0.0", - "extra_dependencies": { - "base64-js": "^1.5.1" - }, - "extra_dev_dependencies": { - "tsconfig": "workspace:*", - "typescript": "^4.9.3" - } - } - }}, - "use": [ { - "path": "./adlc", + "ref": { + "embedded": { + "alias": "adlc" + } + }, "ts_opts": { "npm_pkg_name": "@adl-lang/adlc" } }, { - "path": "./tests/test31/lib", + "ref": { + "embedded": { + "alias": "sys" + } + }, + "ts_opts": { + "npm_pkg_name": "@adl-lang/sys" + } + }, + { + "ref": { + "dir": { + "path": "./tests/test31/lib" + } + }, "ts_opts": { "npm_pkg_name": "@adl-lang/common" } }, { - "path": "./tests/test31/proj", + "ref": { + "dir": { + "path": "./tests/test31/proj" + } + }, "ts_opts": { "npm_pkg_name": "@adl-lang/protoclient", "generate_transitive": true, @@ -49,8 +55,7 @@ "outputs": { "gen": { "output_dir": "../generated3/test31", - "manifest": "../generated3/test31/.adl-manifest", - "strip_first": false + "manifest": "../generated3/test31/.adl-manifest" } }, "include_resolver": true diff --git a/adl/adlc/adlc/packaging.adl b/adl/adlc/adlc/packaging.adl index 8e830c28..7d7f0a85 100644 --- a/adl/adlc/adlc/packaging.adl +++ b/adl/adlc/adlc/packaging.adl @@ -64,6 +64,7 @@ struct TsWriteRuntime { /// The struct in AdlWorkspace::use required by the WorkspaceLoader struct LoaderRef { LoaderRefType ref; + AdlPackage pkg; InjectAnnotations loader_inject_annotate = []; InjectAnnotations resolver_inject_annotate = []; }; diff --git a/rust/compiler/src/adlgen/adlc/packaging.rs b/rust/compiler/src/adlgen/adlc/packaging.rs index d5233c46..80efbfe1 100644 --- a/rust/compiler/src/adlgen/adlc/packaging.rs +++ b/rust/compiler/src/adlgen/adlc/packaging.rs @@ -206,6 +206,8 @@ pub struct LoaderRef { #[serde(rename="ref")] pub r#ref: LoaderRefType, + pub pkg: AdlPackage, + #[serde(default="LoaderRef::def_loader_inject_annotate")] pub loader_inject_annotate: InjectAnnotations, @@ -214,9 +216,10 @@ pub struct LoaderRef { } impl LoaderRef { - pub fn new(r#ref: LoaderRefType) -> LoaderRef { + pub fn new(r#ref: LoaderRefType, pkg: AdlPackage) -> LoaderRef { LoaderRef { r#ref: r#ref, + pkg: pkg, loader_inject_annotate: LoaderRef::def_loader_inject_annotate(), resolver_inject_annotate: LoaderRef::def_resolver_inject_annotate(), } diff --git a/rust/compiler/src/adlstdlib/mod.rs b/rust/compiler/src/adlstdlib/mod.rs index d0bbfbb2..d4dfc198 100644 --- a/rust/compiler/src/adlstdlib/mod.rs +++ b/rust/compiler/src/adlstdlib/mod.rs @@ -3,9 +3,10 @@ use std::{borrow::Cow, path::PathBuf}; use anyhow::anyhow; use rust_embed::{EmbeddedFile, RustEmbed}; +use serde::Deserialize; use crate::{ - adlgen::{adlc::packaging::EmbeddedPkg, sys::adlast2::ModuleName}, + adlgen::{adlc::packaging::{EmbeddedPkg, AdlPackage}, sys::adlast2::ModuleName}, cli::StdlibOpt, }; @@ -29,7 +30,7 @@ pub fn get_file_names(em: EmbeddedPkg) -> Vec { // path.to_str().unwrap().to_string() // } -pub fn get_adl_pkg(em: EmbeddedPkg) -> Option> { +pub fn get_adl_pkg(em: &EmbeddedPkg) -> Option> { let d = match em { EmbeddedPkg::Sys => StdlibAsset::get("adl.pkg.json"), EmbeddedPkg::Adlc => AdlcAsset::get("adl.pkg.json"), @@ -37,19 +38,23 @@ pub fn get_adl_pkg(em: EmbeddedPkg) -> Option> { d.map(|d| d.data) } -pub fn get_stdlib(em: EmbeddedPkg, mn: &ModuleName, ext: &str) -> Option> { +pub fn get_stdlib(em: &EmbeddedPkg, mn: &ModuleName, ext: &str) -> Option<(AdlPackage, Cow<'static, [u8]>)> { let mut fname = mn.replace(".", "/"); fname.push_str(".adl"); if ext != "" { fname.push_str("-"); fname.push_str(ext); } + let pkg_content = get_adl_pkg(em); + let content = std::str::from_utf8(pkg_content.as_ref().unwrap()).unwrap(); + let de = &mut serde_json::Deserializer::from_str(&content); + let pkg = AdlPackage::deserialize(de).unwrap(); let get = match em { EmbeddedPkg::Sys => StdlibAsset::get, EmbeddedPkg::Adlc => AdlcAsset::get, }; if let Some(f) = get(fname.as_str()) { - return Some(f.data); + return Some((pkg, f.data)); }; None } diff --git a/rust/compiler/src/cli/ast.rs b/rust/compiler/src/cli/ast.rs index 07ff2b8e..51501557 100644 --- a/rust/compiler/src/cli/ast.rs +++ b/rust/compiler/src/cli/ast.rs @@ -23,7 +23,7 @@ pub fn ast(opts: &AstOpts) -> anyhow::Result<()> { let mut adlast = AdlAst::new(); resolver.get_module_names().iter().for_each(|mn| { - let m = resolver.get_module(&mn).unwrap(); + let (m, _) = resolver.get_module(&mn).unwrap(); let decls: HashMap<_, _> = m.decls.iter().map(|d| (d.name.clone(), d.clone())).collect(); let m_ast = AstModule { name: m.name.clone(), diff --git a/rust/compiler/src/cli/mod.rs b/rust/compiler/src/cli/mod.rs index 3b4ae9a9..25278e2a 100644 --- a/rust/compiler/src/cli/mod.rs +++ b/rust/compiler/src/cli/mod.rs @@ -122,7 +122,7 @@ pub fn run_cli() -> i32 { capitalize_type_names: opts.capitalize_type_names, }; let empty = vec![]; - tsgen::tsgen(false, false, loader, &ts_opts, None, AdlPackageRefType::Dir(DirectoryRef{ path: ".".to_string() }), empty) + tsgen::tsgen(false, false, loader, None, &ts_opts, None, AdlPackageRefType::Dir(DirectoryRef{ path: ".".to_string() }), empty) } Command::WriteStdlib(opts) => crate::adlstdlib::dump_stdlib(&opts), }; @@ -309,9 +309,9 @@ pub struct TsOpts { #[arg(value_name = "ADLMODULE")] pub modules: Vec, - /// When creating the path for output ts files delete the first part of the module name - #[arg(long, default_value_t = true)] - pub strip_first: bool, + // /// When creating the path for output ts files delete the first part of the module name + // #[arg(long, default_value_t = true)] + // pub strip_first: bool, /// If set capitalizes branch (field) name in the exported interfaces (used to generate backward code). /// diff --git a/rust/compiler/src/cli/rust/mod.rs b/rust/compiler/src/cli/rust/mod.rs index 768d966b..f45e93df 100644 --- a/rust/compiler/src/cli/rust/mod.rs +++ b/rust/compiler/src/cli/rust/mod.rs @@ -3,6 +3,7 @@ use std::path::PathBuf; use anyhow::anyhow; +use crate::adlgen::adlc::packaging::AdlPackage; use crate::adlgen::sys::adlast2::{self as adlast}; use crate::processing::loader::loader_from_search_paths; use crate::processing::resolver::{Module1, Resolver}; @@ -23,7 +24,7 @@ pub fn rust(opts: &RustOpts) -> anyhow::Result<()> { Err(e) => return Err(anyhow!("Failed to load module {}: {:?}", m, e)), } } - let modules: Vec = resolver + let modules: Vec<(Module1, Option<&AdlPackage>)> = resolver .get_module_names() .into_iter() .map(|mn| resolver.get_module(&mn).unwrap()) @@ -34,7 +35,7 @@ pub fn rust(opts: &RustOpts) -> anyhow::Result<()> { opts.output.manifest.clone(), )?; - for m in modules { + for (m,_) in modules { let path = path_from_module_name(opts, m.name.to_owned()); let code = gen_module(&m).unwrap(); writer.write(path.as_path(), code)?; diff --git a/rust/compiler/src/cli/tsgen/defaultval.rs b/rust/compiler/src/cli/tsgen/defaultval.rs index 7e5e7710..3fb8b890 100644 --- a/rust/compiler/src/cli/tsgen/defaultval.rs +++ b/rust/compiler/src/cli/tsgen/defaultval.rs @@ -208,7 +208,7 @@ impl TsDefaultValue<'_> { match &type_expr.type_ref { TypeRef::ScopedName(sn) => { let resolver = self.ctx.resolver; - if let Some(m_remote) = resolver.get_module(&sn.module_name) { + if let Some((m_remote, _)) = resolver.get_module(&sn.module_name) { if let Some(decl) = resolver.get_decl(sn) { let dvg = TsDefaultValue { ctx: &ResolverModule { diff --git a/rust/compiler/src/cli/tsgen/generate.rs b/rust/compiler/src/cli/tsgen/generate.rs index 823d05df..632bafd0 100644 --- a/rust/compiler/src/cli/tsgen/generate.rs +++ b/rust/compiler/src/cli/tsgen/generate.rs @@ -370,7 +370,7 @@ impl TsGenVisitor<'_> { scoped_name: &ScopedName, params: &Vec>, ) -> Result<(bool, String), String> { - let npm_pkg2 = if let Some(m2) = self.resolver.get_module(&scoped_name.module_name) { + let npm_pkg2 = if let Some((m2,_)) = self.resolver.get_module(&scoped_name.module_name) { get_npm_pkg(&m2) } else { None @@ -381,8 +381,7 @@ impl TsGenVisitor<'_> { npm_pkg_import(npm_pkg2.unwrap(), scoped_name.module_name.clone()) } else { let same_pkg = npm_pkg2 == self.npm_pkg.clone(); - - rel_import(same_pkg, &self.module.name, &scoped_name.module_name) + rel_import(!self.opts.generate_transitive, same_pkg, &self.module.name, &scoped_name.module_name) }; let i_name = scoped_name .module_name diff --git a/rust/compiler/src/cli/tsgen/mod.rs b/rust/compiler/src/cli/tsgen/mod.rs index b0ede614..8cf6bb4b 100644 --- a/rust/compiler/src/cli/tsgen/mod.rs +++ b/rust/compiler/src/cli/tsgen/mod.rs @@ -15,8 +15,8 @@ use genco::fmt::{self, Indentation}; use genco::prelude::*; use crate::adlgen::adlc::packaging::{ - AdlPackageRefType, AdlWorkspace, ModuleSrc, NpmPackage, Payload1, TsRuntimeOpt, - TsStyle, TsWriteRuntime, TypescriptGenOptions, + AdlPackageRefType, AdlWorkspace, ModuleSrc, NpmPackage, Payload1, TsRuntimeOpt, TsStyle, + TsWriteRuntime, TypescriptGenOptions, AdlPackage, }; use crate::adlgen::sys::adlast2::Module1; use crate::adlgen::sys::adlast2::{self as adlast}; @@ -114,6 +114,7 @@ pub fn tsgen( strip_first: bool, packageable: bool, loader: Box, + pkg: Option, opts: &TypescriptGenOptions, wrk_root: Option, r#ref: AdlPackageRefType, @@ -145,7 +146,7 @@ pub fn tsgen( let _parent = outputdir.file_name().unwrap().to_str().unwrap().to_string(); - let modules: Vec = resolver + let modules: Vec<(Module1,Option<&AdlPackage>)> = resolver .get_module_names() .into_iter() .map(|mn| resolver.get_module(&mn).unwrap()) @@ -153,12 +154,14 @@ pub fn tsgen( let index_map = &mut HashMap::new(); - for m in &modules { + for (m,pkg2) in &modules { let does_contain = module_names.contains(&m.name); if opts.generate_transitive || does_contain { let path = path_from_module_name(strip_first, m.name.to_owned()); - utils::collect_indexes(path.clone(), index_map); + if pkg2.eq(&pkg.as_ref()) { + utils::collect_indexes(path.clone(), index_map); + } let path = path.as_path(); // if None == path.components().next() { @@ -281,7 +284,7 @@ pub fn gen_npm_package(payload: &Payload1, wrk1: &AdlWorkspace) -> any } TsRuntimeOpt::Generate(_) => {} }; - for (k,v) in &opts.scripts { + for (k, v) in &opts.scripts { npm_package.scripts.entry(k.clone()).or_insert(v.clone()); } @@ -357,7 +360,7 @@ pub fn gen_npm_package(payload: &Payload1, wrk1: &AdlWorkspace) -> any if let Some(ts_config) = &opts.tsconfig { let content = serde_json::to_string_pretty(ts_config)?; writer.write(Path::new("tsconfig.json"), content)?; - log::info!("generated {:?}", outputdir.clone().join("tsconfig.json")); + log::info!("generated {:?}", outputdir.clone().join("tsconfig.json")); } Ok(()) @@ -438,27 +441,29 @@ fn gen_resolver( generate_transitive: bool, runtime_opts: &TsRuntimeOpt, resolver: &Resolver, - modules: &Vec, + modules: &Vec<(Module1, Option<&AdlPackage>)>, adl_pkg_resolvers: HashSet, ) -> anyhow::Result<()> { let mut local_keys = vec![]; let m_imports: Vec = modules .iter() - .map(|m| { - let npm_pkg2 = if let Some(m2) = resolver.get_module(&m.name) { + .map(|(m, _)| { + let npm_pkg2 = if let Some((m2,_)) = resolver.get_module(&m.name) { get_npm_pkg(&m2) } else { None }; - if let Some(npm_pkg2) = &npm_pkg2 { - if adl_pkg_resolvers.contains(npm_pkg2) { - let alias = npm_pkg2 - .replace("@", "") - .replace("-", "_") - .replace("/", "_"); - return js::import(format!("{}/resolver", npm_pkg2), "ADL_local") - .with_alias(alias); + if !generate_transitive { + if let Some(npm_pkg2) = &npm_pkg2 { + if adl_pkg_resolvers.contains(npm_pkg2) { + let alias = npm_pkg2 + .replace("@", "") + .replace("-", "_") + .replace("/", "_"); + return js::import(format!("{}/resolver", npm_pkg2), "ADL_local") + .with_alias(alias); + } } } if !generate_transitive && npm_pkg2 != None { @@ -469,7 +474,7 @@ fn gen_resolver( return js::import(npm_pkg_import(npm_pkg2, m.name.clone()), "_AST_MAP") .with_alias(alias); } else { - let name = rel_import_in_resolver(m); + let name = rel_import_in_resolver(!generate_transitive, m); let alias = m.name.replace(".", "_"); local_keys.push(alias.clone()); return js::import(format!("./{}", name), "_AST_MAP").with_alias(alias); @@ -481,7 +486,7 @@ fn gen_resolver( return js::import(format!("./{}", m.name.replace(".", "/")), "_AST_MAP") .with_alias(alias); } else { - let name = rel_import_in_resolver(m); + let name = rel_import_in_resolver(!generate_transitive, m); let alias = m.name.replace(".", "_"); local_keys.push(alias.clone()); return js::import(format!("./{}", name), "_AST_MAP").with_alias(alias); @@ -506,7 +511,11 @@ fn gen_resolver( }; let gened = "/* @generated from adl */"; - let mut dep_keys: Vec<&String> = adl_pkg_resolvers.iter().collect(); + let mut dep_keys: Vec<&String> = if !generate_transitive { + adl_pkg_resolvers.iter().collect() + } else { + vec![] + }; dep_keys.sort(); local_keys.sort(); quote_in! { *t => @@ -521,7 +530,7 @@ fn gen_resolver( };$['\r'] export const ADL: { [key: string]: ScopedDecl } = {$['\r'] - ...ADL_local, + ...ADL_local,$['\r'] $(for m in dep_keys => ...$(m.replace("@", "").replace("-", "_").replace("/", "_")),$['\r']) };$['\r'] @@ -531,9 +540,11 @@ fn gen_resolver( Ok(()) } -fn rel_import_in_resolver(m: &adlast::Module>) -> String { +fn rel_import_in_resolver(strip_first: bool, m: &adlast::Module>) -> String { let mut it = m.name.split(".").into_iter().peekable(); - it.next(); + if strip_first { + it.next(); + } let mut name = String::new(); while let Some(n) = it.next() { name.push_str(n); diff --git a/rust/compiler/src/cli/tsgen/tests.rs b/rust/compiler/src/cli/tsgen/tests.rs index 6f0564bf..e5c4cff9 100644 --- a/rust/compiler/src/cli/tsgen/tests.rs +++ b/rust/compiler/src/cli/tsgen/tests.rs @@ -6,17 +6,22 @@ use serde::Deserialize; use crate::{ adlgen::adlc::{ - packaging::{GenOutput, ModuleSrc, ReferenceableScopeOption, TsGenRuntime, DirectoryRef}, + packaging::{DirectoryRef, GenOutput, ModuleSrc, ReferenceableScopeOption, TsGenRuntime}, testing_table::TestFilesMetaData, }, - processing::loader::loader_from_search_paths, cli::formatter, + cli::formatter, + processing::loader::loader_from_search_paths, }; use super::*; #[test] fn generate_ts_from_test_files() { - let _ = env_logger::builder().is_test(true).format(formatter).filter_level(log::LevelFilter::Info).try_init(); + let _ = env_logger::builder() + .is_test(true) + .format(formatter) + .filter_level(log::LevelFilter::Info) + .try_init(); let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); d.push("../../adl/tests/testing_table.json"); @@ -78,6 +83,8 @@ fn generate_ts_from_test_files() { let ts_opts = TypescriptGenOptions { npm_pkg_name: "testing".to_string(), npm_version: "0.0.0".to_string(), + scripts: TypescriptGenOptions::def_scripts(), + tsconfig: TypescriptGenOptions::def_tsconfig(), extra_dependencies: TypescriptGenOptions::def_extra_dependencies(), extra_dev_dependencies: TypescriptGenOptions::def_extra_dev_dependencies(), outputs: Some(crate::adlgen::adlc::packaging::OutputOpts::Gen(GenOutput { @@ -139,7 +146,18 @@ fn generate_ts_from_test_files() { // TODO consider failed. // t.fail let dep_adl_pkgs = vec![]; - match tsgen(false, false, loader_from_search_paths(&search_path), &ts_opts, None, AdlPackageRefType::Dir(DirectoryRef{ path: ".".to_string() }), dep_adl_pkgs) { + match tsgen( + false, + false, + loader_from_search_paths(&search_path), + None, + &ts_opts, + None, + AdlPackageRefType::Dir(DirectoryRef { + path: ".".to_string(), + }), + dep_adl_pkgs, + ) { Ok(_) => { println!( "{} {} - ts gen output; {}", @@ -201,4 +219,4 @@ fn generate_ts_from_test_files() { // Ok(tests) => { dbg!(tests); }, // Err(err) => assert!(false, "error deserializing testing_table {}", err), // } -} \ No newline at end of file +} diff --git a/rust/compiler/src/cli/tsgen/utils.rs b/rust/compiler/src/cli/tsgen/utils.rs index 73355b69..899094a3 100644 --- a/rust/compiler/src/cli/tsgen/utils.rs +++ b/rust/compiler/src/cli/tsgen/utils.rs @@ -100,7 +100,7 @@ pub fn npm_pkg_import(npm_pkg2: String, module_name: String) -> String { path } -pub fn rel_import(same_adl_pkg: bool, src: &String, dst: &String) -> String { +pub fn rel_import(strip_first:bool, same_adl_pkg: bool, src: &String, dst: &String) -> String { let src_v: Vec<&str> = src.split(['.']).collect(); let src_v = &src_v[..src_v.len() - 1]; let dst_v0: Vec<&str> = dst.split(['.']).collect(); @@ -111,7 +111,11 @@ pub fn rel_import(same_adl_pkg: bool, src: &String, dst: &String) -> String { let mut import = String::new(); if !same_adl_pkg { if src_v.len() == 0 { - import.push_str("../"); + if strip_first { + import.push_str("../"); + } else { + import.push_str("./"); + } } else { while let Some(_) = &src_i.next() { import.push_str("../"); @@ -130,7 +134,11 @@ pub fn rel_import(same_adl_pkg: bool, src: &String, dst: &String) -> String { return import; } if src_v.len() == 0 && dst_v.len() != 0 { - import.push_str(".."); + if strip_first { + import.push_str(".."); + } else { + import.push_str("."); + } dst_i.next(); while let Some(del) = &dst_i.next() { import.push_str("/"); @@ -349,7 +357,7 @@ mod tests { for t in tests { assert_eq!( - rel_import(t.1, &t.2.to_string(), &t.3.to_string()), + rel_import(true, t.1, &t.2.to_string(), &t.3.to_string()), t.4, "{}", t.0 diff --git a/rust/compiler/src/cli/workspace.rs b/rust/compiler/src/cli/workspace.rs index cc66e909..482ed00c 100644 --- a/rust/compiler/src/cli/workspace.rs +++ b/rust/compiler/src/cli/workspace.rs @@ -42,7 +42,7 @@ pub(crate) fn workspace(opts: &super::GenOpts) -> Result<(), anyhow::Error> { } return false; }).collect(); - tsgen::tsgen(true, true, loader, &opts, Some(wrk_root), pkg.p_ref.r#ref.clone(), deps)?; + tsgen::tsgen(!opts.generate_transitive, true, loader, Some(pkg.pkg.clone()), &opts, Some(wrk_root), pkg.p_ref.r#ref.clone(), deps)?; tsgen::gen_npm_package(pkg, &wrk1.1)?; } } @@ -89,6 +89,7 @@ fn payload1_to_loader_ref(payload1: &Payload1) -> Result { - if let Some(c) = get_adl_pkg(e.alias.clone()) { + if let Some(c) = get_adl_pkg(&e.alias) { let x = std::str::from_utf8(c.as_ref()).map_err(|err| { anyhow!( "Error converting adl.pkg.json from embedded pkg {:?}. err: {}", diff --git a/rust/compiler/src/processing/loader.rs b/rust/compiler/src/processing/loader.rs index 492ec4f4..129f253b 100644 --- a/rust/compiler/src/processing/loader.rs +++ b/rust/compiler/src/processing/loader.rs @@ -7,7 +7,7 @@ use std::io::ErrorKind; use std::path::PathBuf; use crate::adlgen::adlc::packaging::{ - EmbeddedPkg, InjectAnnotation, InjectAnnotations, LoaderRefType, LoaderWorkspace, + EmbeddedPkg, InjectAnnotation, InjectAnnotations, LoaderRefType, LoaderWorkspace, AdlPackage, }; use crate::adlgen::sys::adlast2::{self as adlast, Module0}; use crate::parser::{convert_error, raw_module}; @@ -35,7 +35,7 @@ pub trait AdlLoader { fn load( &mut self, module_name: &adlast::ModuleName, - ) -> Result)>, anyhow::Error>; + ) -> Result, Option)>, anyhow::Error>; fn debug(&self); } @@ -59,7 +59,7 @@ impl AdlLoader for WorkspaceLoader { fn load( &mut self, module_name: &adlast::ModuleName, - ) -> Result)>, anyhow::Error> { + ) -> Result, Option)>, anyhow::Error> { // if let Some(embedded_sys_loader_ref) = &self.workspace.embedded_sys_loader.0 { // if let Some(mut module) = self.embedded.load(module_name)? { // if module_name != "sys.annotations" { @@ -115,7 +115,7 @@ impl AdlLoader for WorkspaceLoader { let module0 = loader.load(module_name); match module0 { Ok(module2) => { - if let Some((mut module1, _)) = module2.clone() { + if let Some((mut module1, _, _)) = module2.clone() { for an in &pkg.loader_inject_annotate { match an { InjectAnnotation::Module(man) => { @@ -138,7 +138,7 @@ impl AdlLoader for WorkspaceLoader { } } } - return Ok(Some((module1, Some(pkg.resolver_inject_annotate.clone())))); + return Ok(Some((module1, Some(pkg.pkg.clone()), Some(pkg.resolver_inject_annotate.clone())))); } else { // return Ok(None); // return Err(anyhow!("Module not found '{}'", module_name)); @@ -173,7 +173,7 @@ impl AdlLoader for MultiLoader { fn load( &mut self, module_name: &adlast::ModuleName, - ) -> Result)>, anyhow::Error> { + ) -> Result, Option)>, anyhow::Error> { for loader in &mut self.loaders { if let Some(module) = loader.load(module_name)? { return Ok(Some(module)); @@ -195,24 +195,32 @@ impl AdlLoader for EmbeddedStdlibLoader { fn load( &mut self, module_name: &adlast::ModuleName, - ) -> Result)>, anyhow::Error> { - match crate::adlstdlib::get_stdlib(self.pkg.clone(), module_name, "") { - Some(data) => match std::str::from_utf8(data.as_ref()) { - Ok(content) => return parse(&content).map(|m| Some((m, None))), + ) -> Result, Option)>, anyhow::Error> { + if let Some((pkg, data)) = crate::adlstdlib::get_stdlib(&self.pkg, module_name, "") { + match std::str::from_utf8(data.as_ref()) { + Ok(content) => return parse(&content).map(|m| Some((m, Some(pkg), None))), Err(err) => return Err(anyhow::Error::from(err)), - }, - None => return Ok(None), + } + } else { + Ok(None) } } } pub struct DirTreeLoader { root: PathBuf, + // pkg:Option, } impl DirTreeLoader { - pub fn new(root: PathBuf) -> Self { - DirTreeLoader { root } + pub fn new( + root: PathBuf, + // pkg:Option, + ) -> Self { + DirTreeLoader { + root, + // pkg, + } } } @@ -224,7 +232,7 @@ impl AdlLoader for DirTreeLoader { fn load( &mut self, module_name: &adlast::ModuleName, - ) -> Result)>, anyhow::Error> { + ) -> Result, Option)>, anyhow::Error> { let mut path = self.root.clone(); for mp in module_name.split(".") { path.push(mp); @@ -239,7 +247,7 @@ impl AdlLoader for DirTreeLoader { Ok(content) => content, }; log::info!("loaded {} from {}", module_name, path.display()); - parse(&content).map(|m| Some((m, None))) + parse(&content).map(|m| Some((m, None, None))) } } diff --git a/rust/compiler/src/processing/resolver.rs b/rust/compiler/src/processing/resolver.rs index 9efc84f7..9a452e24 100644 --- a/rust/compiler/src/processing/resolver.rs +++ b/rust/compiler/src/processing/resolver.rs @@ -2,6 +2,7 @@ use anyhow::anyhow; use std::collections::HashMap; use std::collections::HashSet; +use crate::adlgen::adlc::packaging::AdlPackage; use crate::adlgen::adlc::packaging::InjectAnnotation; use crate::adlgen::adlc::packaging::InjectAnnotations; use crate::adlgen::sys::adlast2::{self as adlast, ScopedName}; @@ -27,6 +28,7 @@ pub struct Resolver { #[derive(Debug)] pub struct ResolvedModule { module1: Module1, + pkg: Option, inject_annotions: Option, decls: HashMap, } @@ -52,7 +54,7 @@ impl Resolver { self.modules.get(module_name) } - pub fn get_module(&self, module_name: &ModuleName) -> Option { + pub fn get_module(&self, module_name: &ModuleName) -> Option<(Module1, Option<&AdlPackage>)> { let rm0 = self.modules.get(module_name); if let Some(rm1) = rm0 { let inject_annotions = &rm1.inject_annotions; @@ -63,15 +65,15 @@ impl Resolver { for an in inj { match an { InjectAnnotation::Module(man) => { - ann.insert(man.0.0.clone(), man.0.1.clone()); - }, + ann.insert(man.0 .0.clone(), man.0 .1.clone()); + } } } module1.annotations = Map(ann); - return Some(module1); + return Some((module1, rm1.pkg.as_ref())); } } - return Some(rm1.module1.to_owned()); + return Some((rm1.module1.to_owned(), rm1.pkg.as_ref())); } else { return None; } @@ -98,18 +100,26 @@ impl Resolver { let inp1 = self.loader.load(inp).unwrap().unwrap().0; eprintln!("IN PROGRESS {} IMPORTS {:?}", inp, inp1); } - return Err(anyhow!("Circular reference loop including module_name: '{}' in_progress: {:?}", module_name, in_progress)); + return Err(anyhow!( + "Circular reference loop including module_name: '{}' in_progress: {:?}", + module_name, + in_progress + )); } in_progress.insert(module_name.clone()); - let mut module0 = self - .loader - .load(module_name)? - .ok_or_else(|| { - self.loader.debug(); - anyhow!("Module {} not found", module_name) - })?; + let mut module0 = match self.loader.load(module_name) { + Ok(x) => match x { + Some(y) => y, + None => return Err(anyhow!("Module {} not found", module_name)), + }, + Err(er) => return Err(anyhow!("Module {} not found with error {:?}", module_name, er.to_string())), + }; + // .ok_or_else(|| { + // // self.loader.debug(); + // anyhow!("Module {} not found", module_name) + // })?; self.add_default_imports(&mut module0.0); let module_refs = find_module_refs(&module0.0); @@ -137,7 +147,8 @@ impl Resolver { let rmodule = ResolvedModule { module1, - inject_annotions: module0.1, + pkg: module0.1.map(|p| p.clone()), + inject_annotions: module0.2, decls, }; self.modules.insert(module_name.clone(), rmodule); @@ -167,7 +178,7 @@ impl Resolver { result.insert(sn.name.clone(), sn.clone()); } adlast::Import::ModuleName(mn) => { - if let Some(m) = self.get_module(&mn) { + if let Some((m, _)) = self.get_module(&mn) { for decl_name in m.decls.iter().map(|d| &d.name) { result.insert( decl_name.clone(), diff --git a/typescript/workspace/generated/common/package.json b/typescript/workspace/generated/common/package.json index 59a402b9..ee8a0020 100644 --- a/typescript/workspace/generated/common/package.json +++ b/typescript/workspace/generated/common/package.json @@ -10,7 +10,7 @@ "@adl-lang/sys": "workspace:*" }, "devDependencies": { - "typescript": "^4.9.3", - "tsconfig": "workspace:*" + "tsconfig": "workspace:*", + "typescript": "^4.9.3" } } \ No newline at end of file diff --git a/typescript/workspace/generated/protoclient/package.json b/typescript/workspace/generated/protoclient/package.json index 08302384..235de664 100644 --- a/typescript/workspace/generated/protoclient/package.json +++ b/typescript/workspace/generated/protoclient/package.json @@ -2,17 +2,17 @@ "name": "@adl-lang/protoclient", "version": "1.0.0", "scripts": { - "clean": "rm -rf dist && rm -rf node_modules", - "tsc": "tsc" + "tsc": "tsc", + "clean": "rm -rf dist && rm -rf node_modules" }, "dependencies": { - "@adl-lang/sys": "workspace:*", - "@adl-lang/common": "workspace:*", "base64-js": "^1.5.1", - "@adl-lang/runtime": "^1.0.0" + "@adl-lang/sys": "workspace:*", + "@adl-lang/runtime": "^1.0.0", + "@adl-lang/common": "workspace:*" }, "devDependencies": { - "typescript": "^4.9.3", - "tsconfig": "workspace:*" + "tsconfig": "workspace:*", + "typescript": "^4.9.3" } } \ No newline at end of file diff --git a/typescript/workspace/generated/sys/package.json b/typescript/workspace/generated/sys/package.json index d878560c..7ad7e145 100644 --- a/typescript/workspace/generated/sys/package.json +++ b/typescript/workspace/generated/sys/package.json @@ -6,11 +6,11 @@ "tsc": "tsc" }, "dependencies": { - "@adl-lang/runtime": "^1.0.0", - "base64-js": "^1.5.1" + "base64-js": "^1.5.1", + "@adl-lang/runtime": "^1.0.0" }, "devDependencies": { - "typescript": "^4.9.3", - "tsconfig": "workspace:*" + "tsconfig": "workspace:*", + "typescript": "^4.9.3" } } \ No newline at end of file diff --git a/typescript/workspace/pnpm-lock.yaml b/typescript/workspace/pnpm-lock.yaml index 0730cbef..a5c7a629 100644 --- a/typescript/workspace/pnpm-lock.yaml +++ b/typescript/workspace/pnpm-lock.yaml @@ -14,7 +14,7 @@ importers: generated/common: dependencies: '@adl-lang/runtime': - specifier: workspace:* + specifier: ^1.0.0 version: link:../runtime '@adl-lang/sys': specifier: workspace:* @@ -33,7 +33,7 @@ importers: specifier: workspace:* version: link:../common '@adl-lang/runtime': - specifier: workspace:* + specifier: ^1.0.0 version: link:../runtime '@adl-lang/sys': specifier: workspace:* @@ -65,7 +65,7 @@ importers: generated/sys: dependencies: '@adl-lang/runtime': - specifier: workspace:* + specifier: ^1.0.0 version: link:../runtime base64-js: specifier: ^1.5.1