Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds an --init script to start a boilerplate project. #11

Merged
merged 1 commit into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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