23 |
24 |
31 |
--------------------------------------------------------------------------------
/packages/http-client/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: [
3 | 'eslint:recommended',
4 | 'plugin:@typescript-eslint/recommended',
5 | 'plugin:@typescript-eslint/eslint-recommended',
6 | 'plugin:prettier/recommended',
7 | ],
8 | parser: '@typescript-eslint/parser',
9 | plugins: ['@typescript-eslint', 'prettier'],
10 | root: true,
11 | ignorePatterns: ['dist/'],
12 | rules: {
13 | '@typescript-eslint/no-inferrable-types': 0,
14 | '@typescript-eslint/no-unused-vars': [
15 | 'error',
16 | {
17 | varsIgnorePattern: '^_',
18 | argsIgnorePattern: '^_',
19 | caughtErrorsIgnorePattern: '^_',
20 | },
21 | ],
22 | },
23 | }
24 |
--------------------------------------------------------------------------------
/packages/http-server/.eslintrc.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | extends: [
3 | 'eslint:recommended',
4 | 'plugin:@typescript-eslint/recommended',
5 | 'plugin:@typescript-eslint/eslint-recommended',
6 | 'plugin:prettier/recommended',
7 | ],
8 | parser: '@typescript-eslint/parser',
9 | plugins: ['@typescript-eslint', 'prettier'],
10 | root: true,
11 | ignorePatterns: ['dist/'],
12 | rules: {
13 | '@typescript-eslint/no-inferrable-types': 0,
14 | '@typescript-eslint/no-unused-vars': [
15 | 'error',
16 | {
17 | varsIgnorePattern: '^_',
18 | argsIgnorePattern: '^_',
19 | caughtErrorsIgnorePattern: '^_',
20 | },
21 | ],
22 | },
23 | }
24 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/documentation.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: DocumentationRequest
3 | about: Use this template for requesting new documentation
4 | title: "[DOCS]: [DESCRIPTION]"
5 | ---
6 |
7 | # Documentation Request
8 |
9 | Packages related to documentation request:
10 |
11 | - [ ] sdk
12 | - [ ] etl
13 | - [ ] widget
14 | - [ ] http-client
15 | - [ ] http-server
16 | - [ ] spa (explorer)
17 | - [ ] OWL/SHACL definitions
18 |
19 | ### Description
20 |
21 | Describe the documentation you would like to see added or improved.
22 |
23 | ### Additional information
24 |
25 | Provide any additional information that might be helpful in understanding the documentation issue.
26 | Library Feature Request
27 | csharp
28 | Copy code
29 | ### Description
30 |
--------------------------------------------------------------------------------
/packages/http-server/src/types.ts:
--------------------------------------------------------------------------------
1 | import * as D from '@docmaps/sdk'
2 | import * as TE from 'fp-ts/TaskEither'
3 |
4 | // TODO: use io-ts? this is only decodable by consumers...
5 | export type ApiInfo = {
6 | api_url: string
7 | api_version: string
8 | ephemeral_document_expiry: {
9 | max_seconds: number
10 | max_retrievals: number
11 | }
12 | peers: {
13 | api_url: string
14 | }[]
15 | }
16 |
17 | export type ThingSpec = {
18 | identifier: string
19 | kind: 'iri' | 'doi'
20 | }
21 |
22 | // TODO is this the same as the Client?
23 | export interface BackendAdapter {
24 | docmapWithIri(iri: string): TE.TaskEitherDocmaps are a powerful, community-driven framework that will meet key requirements for representations of editorial processes in a healthy publishing ecosystem.
66 |This page is your gateway to technical documentation for the packages and tools maintained by the Docmaps Project core maintainers. Explore the navigation links above to get started.
67 | 68 | 69 | 70 | -------------------------------------------------------------------------------- /packages/etl/README.md: -------------------------------------------------------------------------------- 1 | # Extract-Transform-Load CLI for Docmaps 2 | 3 | This typescript library is designed to provide core, highly-general docmaps 4 | functionality for ease-of-use in Typescript. It provides out-of-the-box 5 | validation of JSON-LD documents interpreted as docmaps directly. It is intended 6 | to additionally support validation of Docmap sub-elements, such as individual 7 | Actions or Actors that might be published separately from a whole Docmap. It 8 | will also be integrated into concrete tools such as a docmap-from-meca ETL pipeline 9 | and general visualization tools. 10 | 11 | # Usage 12 | 13 | Via a global install: 14 | 15 | ```bash 16 | npm i -g @docmaps/etl 17 | npx docmaps-etl item --source crossref-api 10.5194/angeo-40-247-2022 # sub with your DOI of interest 18 | ``` 19 | 20 | In this repository: 21 | 22 | ```bash 23 | pnpm install # or npm install 24 | pnpm docmaps-etl item --source crossref-api 10.5194/angeo-40-247-2022 # or npm docmaps-etl 25 | ``` 26 | 27 | ## Implementation 28 | 29 | This tool and library are written using the [`@docmaps/sdk` package](/packages/sdk) 30 | in this repository, as well as the [`crossref-openapi-client-ts`](https://github.com/Docmaps-Project/crossref-openapi-client-ts) 31 | also maintained by Knowledge Futures, Inc. As seen in `src/crossref.ts`[src/crossref.ts], 32 | Codecs from the SDK are processed using functional paradigms provided conveniently by 33 | `fp-ts`. 34 | 35 | ## Documentation 36 | 37 | Documentation is comments-only for now. See [relevant issue](https://github.com/Docmaps-Project/docmaps/issues/20). 38 | 39 | ## Contributing 40 | 41 | For Code of Conduct, see the repository-wide [CODE_OF_CONDUCT.md](/CODE_OF_CONDUCT.md). 42 | 43 | For info about local development of this repository, see [CONTRIBUTING.md](CONTRIBUTING.md). 44 | 45 | ## Current next steps 46 | 47 | Review the issues on this repository for up-to-date info of desired improvements. 48 | There are also expressive TODOs in the codebase. 49 | Here are some examples: 50 | 51 | - [ ] Enable direct configuration of the publisher information for generated Docmaps 52 | - [ ] Handle paginated requests for efficient parallel processing. 53 | - [ ] Make the ETL interface generic enough to handle at least one other data source than Crossref. 54 | -------------------------------------------------------------------------------- /packages/etl/test/unit/command.test.ts: -------------------------------------------------------------------------------- 1 | import test from 'ava' 2 | import { isLeft } from 'fp-ts/lib/Either' 3 | import { ItemCmd } from '../../src/command' 4 | import { whenThenResolve } from './utils' 5 | import * as cm from './__fixtures__/crossref' 6 | 7 | // This test is redundant with a test in the crossref case. Possibly there 8 | // is no need for a test suite at this level as integration can handle it; 9 | // however this asserts that the Cmd still passes through. 10 | test('ItemCmd: crossref: happy-path scenario: a manuscript with one preprint and no reviews', async (t) => { 11 | const mocks = cm.CrossrefClientMocks() 12 | whenThenResolve( 13 | mocks.worksT.getWorks, 14 | { doi: cm.MANUSCRIPT_DOI }, 15 | cm.mockCrossrefManuscriptWithPreprintResponse, 16 | ) 17 | whenThenResolve(mocks.worksT.getWorks, { doi: cm.PREPRINT_DOI }, cm.mockCrossrefPreprintResponse) 18 | 19 | const publisher = { 20 | id: 'my_pub_id', 21 | name: 'my_name', 22 | } 23 | 24 | const res = await ItemCmd([cm.MANUSCRIPT_DOI], { 25 | source: { 26 | preset: 'crossref-api', 27 | client: mocks.crs, 28 | }, 29 | publisher: publisher, 30 | }) 31 | 32 | if (isLeft(res)) { 33 | t.fail(`Got error instead of docmaps: ${res.left}`) 34 | return 35 | } 36 | 37 | t.is(res.right.length, 1) 38 | const dm = res.right[0] 39 | 40 | // necessary because Typescript doesn't narrow down type of dm just because 41 | // test failure guarantees we can't get here 42 | if (!dm) { 43 | t.fail('impossibly, we couldnt find the first docmap in a list of one') 44 | return //necessary 45 | } 46 | 47 | t.deepEqual(dm.type, 'docmap') 48 | t.deepEqual(dm.publisher, { 49 | id: 'my_pub_id', 50 | name: 'my_name', 51 | }) 52 | t.is(dm.steps ? Object.keys(dm.steps).length : 0, 2) 53 | t.is(dm.steps?.['_:b0']?.inputs?.length, 0) 54 | t.is(dm.steps?.['_:b0']?.actions[0]?.inputs.length, 0) 55 | t.deepEqual(dm.steps?.['_:b0']?.actions[0]?.outputs[0]?.doi, cm.PREPRINT_DOI) 56 | t.deepEqual(dm.steps?.['_:b1']?.actions[0]?.inputs[0]?.doi, cm.PREPRINT_DOI) 57 | t.deepEqual(dm.steps?.['_:b1']?.actions[0]?.outputs[0]?.doi, cm.MANUSCRIPT_DOI) 58 | //TODO: can write stronger assertions as we learn what this should look like 59 | }) 60 | -------------------------------------------------------------------------------- /packages/spa/rollup.config.js: -------------------------------------------------------------------------------- 1 | import { spawn } from 'child_process'; 2 | import svelte from 'rollup-plugin-svelte'; 3 | import commonjs from '@rollup/plugin-commonjs'; 4 | import terser from '@rollup/plugin-terser'; 5 | import resolve from '@rollup/plugin-node-resolve'; 6 | import livereload from 'rollup-plugin-livereload'; 7 | import nodePolyfills from 'rollup-plugin-polyfill-node'; 8 | import css from 'rollup-plugin-css-only'; 9 | 10 | const production = !process.env.ROLLUP_WATCH; 11 | 12 | function serve() { 13 | let server; 14 | 15 | function toExit() { 16 | if (server) server.kill(0); 17 | } 18 | 19 | return { 20 | writeBundle() { 21 | if (server) return; 22 | server = spawn('npm', ['run', 'start', '--', '--dev'], { 23 | stdio: ['ignore', 'inherit', 'inherit'], 24 | shell: true 25 | }); 26 | 27 | process.on('SIGTERM', toExit); 28 | process.on('exit', toExit); 29 | } 30 | }; 31 | } 32 | 33 | export default { 34 | input: 'src/main.js', 35 | output: { 36 | sourcemap: true, 37 | format: 'iife', 38 | name: 'app', 39 | file: 'public/build/bundle.js' 40 | }, 41 | plugins: [ 42 | svelte({ 43 | compilerOptions: { 44 | // enable run-time checks when not in production 45 | dev: !production 46 | } 47 | }), 48 | // we'll extract any component CSS out into 49 | // a separate file - better for performance 50 | css({ output: 'bundle.css' }), 51 | 52 | nodePolyfills(), 53 | 54 | // If you have external dependencies installed from 55 | // npm, you'll most likely need these plugins. In 56 | // some cases you'll need additional configuration - 57 | // consult the documentation for details: 58 | // https://github.com/rollup/plugins/tree/master/packages/commonjs 59 | resolve({ 60 | browser: true, 61 | dedupe: ['svelte'], 62 | exportConditions: ['svelte'] 63 | }), 64 | commonjs(), 65 | 66 | // In dev mode, call `npm run start` once 67 | // the bundle has been generated 68 | !production && serve(), 69 | 70 | // Watch the `public` directory and refresh the 71 | // browser on changes when not in production 72 | !production && livereload('public'), 73 | 74 | // If we're building for production (npm run build 75 | // instead of npm run dev), minify 76 | production && terser() 77 | ], 78 | watch: { 79 | clearScreen: false 80 | } 81 | }; 82 | -------------------------------------------------------------------------------- /packages/example/src/index.ts: -------------------------------------------------------------------------------- 1 | import * as D from '@docmaps/sdk' 2 | import * as E from 'fp-ts/lib/Either' 3 | import * as A from 'fp-ts/lib/Array' 4 | import {pipe} from 'fp-ts/lib/function' 5 | import * as t from 'io-ts' 6 | import util from "util"; 7 | import { readFileSync } from 'fs'; 8 | 9 | // program starts 10 | console.log("\n\n---Docmaps exploration in TS---\n\n") 11 | 12 | // get a file as string (this could be an API response on a browser) 13 | const file = readFileSync('./docmap.jsonld', 'utf-8'); 14 | 15 | //-- equivalent to: 16 | // const program = D.Docmap.decode(JSON.parse(file)) followed by more computation 17 | 18 | const program = pipe( 19 | // any value as input 20 | file, 21 | // function that takes that value as only argument 22 | JSON.parse, 23 | // function that takes the return of previous as only argument 24 | // this one returns an E.Either
](screenshots/preprint_posted.png)
84 |
85 | [
](screenshots/preprint_published.png)
86 |
87 | [
](screenshots/preprint_published_reviewed.png)
88 |
89 | [
](screenshots/preprint_refereed.png)
--------------------------------------------------------------------------------
/packages/http-server/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@docmaps/http-server",
3 | "version": "0.1.0",
4 | "description": "Node.js runtime for serving docmaps using other composed docmaps-related npm modules",
5 | "type": "module",
6 | "main": "dist/httpserver/main.js",
7 | "scripts": {
8 | "test": "ava",
9 | "clean": "rm -rf dist/",
10 | "test:integration": "ava test/integration/",
11 | "test:cleanup": "docker compose -f test/integration/assets/docker-compose.yml down",
12 | "test:unit": "ava test/unit/",
13 | "compose:repave": "rm -rf tmp/oxigraph_data/*",
14 | "compose:up": "docker compose -f $INIT_CWD/docker-compose.local.yml up --build",
15 | "lint": "npx eslint .",
16 | "lint:fix": "npx eslint --fix .",
17 | "start": "tsx dist/httpserver/main.js",
18 | "build:deps": "pnpm run --filter=@docmaps/http-server^... build",
19 | "build": "tsc --declaration"
20 | },
21 | "keywords": [],
22 | "author": "eve github.com/ships",
23 | "license": "ISC",
24 | "files": [
25 | "dist/",
26 | "README.md",
27 | "package.json",
28 | "tsconfig.json"
29 | ],
30 | "dependencies": {
31 | "@commander-js/extra-typings": "^11.0.0",
32 | "@docmaps/http-client": "workspace:^0.1.0",
33 | "@rdfjs/data-model": "^2.0.1",
34 | "@rdfjs/namespace": "^2.0.0",
35 | "@tpluscode/sparql-builder": "^1.1.0",
36 | "@ts-rest/core": "^3.30.2",
37 | "@ts-rest/express": "^3.30.2",
38 | "@zazuko/rdf-vocabularies": "^2023.1.19",
39 | "commander": "^11.0.0",
40 | "cors": "^2.8.5",
41 | "@docmaps/sdk": "workspace:^0.0.0",
42 | "express": "^4.18.2",
43 | "fetch-sparql-endpoint": "^4.0.0",
44 | "fp-ts": "^2.14.0",
45 | "isomorphic-fetch": "^3.0.0",
46 | "n3": "^1.17.1",
47 | "oxigraph": "^0.3.19",
48 | "pino": "^8.16.1",
49 | "pino-http": "^8.5.1",
50 | "streaming-iterables": "^8.0.0",
51 | "tsx": "^4.0.0"
52 | },
53 | "devDependencies": {
54 | "@docmaps/build-configs": "workspace:^",
55 | "@rdfjs/types": "^1.1.0",
56 | "@types/cors": "^2.8.14",
57 | "@types/express": "^4.17.17",
58 | "@types/isomorphic-fetch": "^0.0.39",
59 | "@types/n3": "^1.16.0",
60 | "@types/node": "^20.0.0",
61 | "@types/rdfjs__data-model": "^2.0.4",
62 | "@types/rdfjs__namespace": "^2.0.5",
63 | "@typescript-eslint/eslint-plugin": "^6.0.0",
64 | "@typescript-eslint/parser": "^6.0.0",
65 | "ava": "^5.2.0",
66 | "eslint": "^8.39.0",
67 | "eslint-config-prettier": "^9.0.0",
68 | "eslint-plugin-prettier": "^5.0.0",
69 | "prettier": "^3.0.0",
70 | "ts-mockito": "^2.6.1",
71 | "typescript": "^5.2.2",
72 | "zod": "^3.22.2"
73 | },
74 | "ava": {
75 | "extensions": {
76 | "ts": "module"
77 | },
78 | "nodeArguments": [
79 | "--loader=tsx/esm"
80 | ],
81 | "files": [
82 | "**/*.test.ts"
83 | ]
84 | },
85 | "engines": {
86 | "node": ">=18.14.0"
87 | }
88 | }
89 |
--------------------------------------------------------------------------------
/packages/etl/test/unit/crossref/functions.test.ts:
--------------------------------------------------------------------------------
1 | import test, { ExecutionContext } from 'ava'
2 | import * as cm from '../__fixtures__/crossref'
3 | import * as E from 'fp-ts/lib/Either'
4 | import { inspect } from 'util'
5 | import * as F from '../../../src/plugins/crossref/functions'
6 | import type { ActionT } from '@docmaps/sdk'
7 |
8 | function rightOrInspectError