Skip to content

Commit

Permalink
Adds an --init script to start a boilerplate project.
Browse files Browse the repository at this point in the history
  • Loading branch information
mightymax committed Nov 30, 2023
1 parent 9b70c67 commit 5195169
Show file tree
Hide file tree
Showing 13 changed files with 129 additions and 16 deletions.
4 changes: 2 additions & 2 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"yaml.schemas": {
"static/ld-workbench.schema.json": [
"configurations/*.yml",
"static/example/*.yml"
"pipelines/configurations/**/*.yml",
"static/example/*.yml",
],
}
}
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,25 @@ LDWorkbench is a Linked Data Transformation tool designed to use only SPARQL as

This project is currently in a Proof of Concept phase, feel free to watch our progress, but please do not use this project in a production setup.

## Install & Usage
The quickest way to get started with LDWorkbench is follow these instruction:

```bash
mkdir ldworkbench
cd ldworkbench
npm i git+https://github.com/netwerk-digitaal-erfgoed/ld-workbench.git
npx ldworkbench --init
```

Your workbench is now ready for use. An example workbench is provided, run it with this command:

```bash
npx ldworkbench
```

### Configuring a workbench project


## Development
For local development, these script should get you going:
```bash
Expand Down
4 changes: 0 additions & 4 deletions data/.gitignore

This file was deleted.

Binary file added ldworkbench-0.0.1.tgz
Binary file not shown.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
{
"name": "ld-workbench",
"name": "ldworkbench",
"type": "module",
"bin": {
"ld-workbench": "dist/main.js"
"ldworkbench": "dist/main.js"
},
"version": "0.0.1",
"description": "LDWorkbench is a Linked Data Transformation tool designed to use only SPARQL as transformation language.",
Expand All @@ -12,8 +12,8 @@
"prepare": "husky install",
"build": "npx tsc",
"dev": "npx tsc --watch --preserveWatchOutput",
"ld-workbench": "node dist/main",
"ld-workbench:example": "node dist/main --configDir static",
"ldworkbench": "node dist/main",
"ldworkbench:example": "node dist/main --configDir static",
"util:lint": "ESLINT_STRICT=true ESLINT_EXPENSIVE=true eslint --ext .tsx --ext .ts ./src",
"util:json-schema-to-typescript": "npx json2ts -i ./static/ld-workbench.schema.json -o src/lib/LDWorkbenchConfiguration.d.ts"
},
Expand Down
17 changes: 17 additions & 0 deletions src/cliArgs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import chalk from 'chalk';
import { program } from 'commander';
import { error } from './utils/error.js';
import version from './utils/version.js';
import init from './utils/init.js';

program
.name('ld-workbench')
Expand All @@ -10,14 +11,30 @@ program
.option('--configDir </path/to/yaml/>', 'Path to a folder containing your configuration files.')
.option('-p, --pipeline <name-of-pipeline>', 'Name of the pipeline you want to run')
.option('-s, --stage <name-of-stage>', 'Name of the stage of the pipeline you want to run')
.option('--init', 'Initializes a new LDWorkbench project')
.version(version());
program.parse();
export const cliArgs: {
config?: string;
configDir?: string;
pipeline?: string;
stage?: string
init?: boolean
} = program.opts();

if (cliArgs.init !== undefined) {
if(Object.values(cliArgs).length !== 1) {
error('The --init flag can not be used in conjuction with other CLI arguments.')
}
try {
init()
console.log(chalk.green('A boilerplate LDWorkbech has been created. You can now run a project using `npx ldworkbench`.'))
} catch(e) {
error(e as Error)
}
process.exit(0)
}

if (cliArgs.config !== undefined && cliArgs.configDir !== undefined) {
error(
'Do not use both the --config and the --configDir options.',
Expand Down
2 changes: 1 addition & 1 deletion src/lib/Pipeline.class.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class Pipeline {
private readonly $configuration: LDWorkbenchConfiguration
) {
// create data folder:
this.dataDir = path.join("data", kebabcase(this.$configuration.name));
this.dataDir = path.join("pipelines", "data", kebabcase(this.$configuration.name));
fs.mkdirSync(this.dataDir, { recursive: true });
const destinationFile = this.configuration.destination ?? `file://${path.join(this.dataDir, 'statements.nt')}`
if (!isFilePathString(destinationFile)) {
Expand Down
1 change: 1 addition & 0 deletions src/main.ts → src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#!/usr/bin/env node
import inquirer from 'inquirer'
import chalk from 'chalk'
import { error } from './utils/error.js'
Expand Down
73 changes: 73 additions & 0 deletions src/utils/init.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import fs from 'fs';
import { fileURLToPath } from 'url';
import * as path from 'path';
import glob from 'glob'

export default function init(): void {
const $dirname = path.dirname(fileURLToPath(import.meta.url));
if(fs.existsSync('pipelines')) {
throw new Error('The --init script found an existing directory "pipelines". Make sure this directory does not exists before running this script.')
}
fs.mkdirSync('pipelines')
fs.mkdirSync(path.join('pipelines', 'data'))
fs.mkdirSync(path.join('pipelines', 'configurations'))
fs.mkdirSync(path.join('pipelines', 'configurations', 'example'))
const filepaths = glob.sync(path.join($dirname, '..', '..', 'static', 'example', '*'))
for(const filepath of filepaths) {
fs.copyFileSync(filepath, path.join('pipelines', 'configurations', 'example', path.basename(filepath)))
}
const yamlFile = path.join('pipelines', 'configurations', 'example', 'config.yml')
const yaml = fs.readFileSync(yamlFile, 'utf-8')
.replaceAll(/\/static\//g, '/pipelines/configurations/')
fs.writeFileSync(yamlFile, yaml)

const yamlSchemasSettings = {
"yaml.schemas": {
"node_modules/ldworkbench/static/ld-workbench.schema.json": [
"pipelines/configurations/**/*.yml",
"static/example/*.yml",
],
}
}

const extensions = [
"dbaeumer.vscode-eslint",
"stardog-union.vscode-langserver-sparql",
"stardog-union.stardog-rdf-grammars",
"MarkLindeman.turtle-vocab-autocomplete"
]

// setting up VSC/Git settings, if this fails, that's fine:
try {
if (!fs.existsSync('.gitignore')) {
fs.writeFileSync('.gitignore', 'node_modules\n')
}
if (!fs.existsSync('.vscode')) fs.mkdirSync('.vscode')
const settingsFile = path.join('.vscode', 'settings.json')
const extensionsFile = path.join('.vscode', 'extensions.json')
if (!fs.existsSync(settingsFile)) {
fs.writeFileSync(settingsFile, JSON.stringify(yamlSchemasSettings, undefined, 2))
} else {
const settings = JSON.parse(fs.readFileSync(settingsFile, 'utf-8'))
if (!Object.hasOwn(settings, 'yaml.schemas')) {
settings['yaml.schemas'] = yamlSchemasSettings['yaml.schemas']
} else {
settings['yaml.schemas']["node_modules/ldworkbench/static/ld-workbench.schema.json"] = yamlSchemasSettings['yaml.schemas']["node_modules/ldworkbench/static/ld-workbench.schema.json"]
}
fs.writeFileSync(settingsFile, JSON.stringify(yamlSchemasSettings, undefined, 2))
}

if (!fs.existsSync(extensionsFile)) {
fs.writeFileSync(extensionsFile, JSON.stringify({recommendations: extensions}, undefined, 2))
} else {
const settings = JSON.parse(fs.readFileSync(settingsFile, 'utf-8'))
if (!Object.hasOwn(settings, 'recommendations')) {
settings.recommendations = extensions
} else {
settings.recommendations = (settings.recommendations as string[]).concat(extensions)
}
fs.writeFileSync(settingsFile, JSON.stringify(settingsFile, undefined, 2))
}
} catch(e) {}

}
2 changes: 1 addition & 1 deletion src/utils/loadPipelines.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ export default function loadPipelines (configDirOrFile: string): Map<string, LDW
const pipelines = new Map<string, LDWorkbenchConfiguration>()

if (!fs.existsSync(configDirOrFile))
throw new Error(`Configuration directory/file ${chalk.italic(configDirOrFile)} could not be found.`)
throw new Error(`Configuration directory/file ${chalk.italic(configDirOrFile)} could not be found.\nIf this is your first run of LDWorkbench, you might want to use \`npx ldworkbench --init\` to setup an example workbench project.`)

const files: string[] = []
if (fs.lstatSync(configDirOrFile).isDirectory()) {
Expand Down
6 changes: 5 additions & 1 deletion src/utils/validate.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import Ajv, { type ValidateFunction, type ErrorObject } from 'ajv';
import parseYamlFile from './parseYamlFile.js';
import { fileURLToPath } from 'url';
import * as path from 'path';

/**
* Validate an object against a JSON Schema provided as a YAML file.
Expand All @@ -9,7 +11,9 @@ import parseYamlFile from './parseYamlFile.js';
*/
export default function validate(filePathOrObject: object | string): ErrorObject[] | null {
// Parse the YAML schema file
const schema = parseYamlFile('./static/ld-workbench.schema.json');
const dirname = path.dirname(fileURLToPath(import.meta.url));
const filename = path.resolve(path.join(dirname, '..', '..', 'static', 'ld-workbench.schema.json'))
const schema = parseYamlFile(filename);
const configuration = typeof filePathOrObject === 'string'
? parseYamlFile(filePathOrObject)
: filePathOrObject
Expand Down
7 changes: 5 additions & 2 deletions src/utils/version.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
import fs from 'fs';

import { fileURLToPath } from 'url';
import * as path from 'path';
export default function version(): string {
const { version } = JSON.parse(fs.readFileSync('./package.json', 'utf-8'));
const dirname = path.dirname(fileURLToPath(import.meta.url));
const filename = path.resolve(path.join(dirname, '..', '..', 'package.json'))
const { version } = JSON.parse(fs.readFileSync(filename, 'utf-8'));
return version;
}
2 changes: 1 addition & 1 deletion static/example/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ description: >
# This is optional, by default it will be stored in the data directory of the pipeline using filename 'statements.nt'
destination: file://data/example-pipeline.nt
destination: file://pipelines/data/example-pipeline.nt

# The individual stages for your pipeline
stages:
Expand Down

0 comments on commit 5195169

Please sign in to comment.