Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
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
1 change: 1 addition & 0 deletions browser/.eslintrc.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ module.exports = {
'react/tsconfig.json',
'data-browser/tsconfig.json',
'e2e/tsconfig.json',
'create-template/tsconfig.json',
],
},
plugins: ['react', '@typescript-eslint', 'prettier', 'react-hooks', 'jsx-a11y'],
Expand Down
21 changes: 19 additions & 2 deletions browser/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,26 @@

This changelog covers all five packages, as they are (for now) updated as a whole

## UNRELEASED
## Unreleased

- #970 Add "show commit" button in History view
### Atomic Browser

- [#952](https://github.com/atomicdata-dev/atomic-server/issues/952) Add templates containing pre made ontologies and resources.
- [#970](https://github.com/atomicdata-dev/atomic-server/issues/970) Add "show commit" button in History
- [#968](https://github.com/atomicdata-dev/atomic-server/issues/968) Allow users to pick files by entering a subject into the file picker search bar.
- [#969](https://github.com/atomicdata-dev/atomic-server/issues/969) Fix markdown editor sometimes doesn't update the value after saving.
- [#975](https://github.com/atomicdata-dev/atomic-server/issues/975) Add create button to resource selector without classtype.
- Fix markdown editor closing the edit page when a button is clicked.
- Add an edit button to the default resource view.

### @tomic/lib

- BREAKING CHANGE: removed the `importJsonAdString` function.
- Added `store.importJsonAD()` method.

### @tomic/create-template

- Added `@tomic/create-template` package to create new templates.

## v0.39.0

Expand Down
1 change: 1 addition & 0 deletions browser/create-template/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/bin
36 changes: 36 additions & 0 deletions browser/create-template/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"version": "0.39.0",
"author": "Polle Pas",
"dependencies": {
"@tomic/lib": "workspace:*",
"chalk": "^5.3.0",
"prettier": "3.0.3"
},
"devDependencies": {
"@types/node": "^20.11.5",
"typescript": "^5.4.5"
},
"description": "",
"license": "MIT",
"name": "@tomic/create-template",
"publishConfig": {
"access": "public"
},
"scripts": {
"build": "tsc",
"lint": "eslint ./src --ext .js,.ts",
"lint-fix": "eslint ./src --ext .js,.ts --fix",
"prepublishOnly": "pnpm run build && pnpm run lint-fix",
"watch": "tsc --build --watch",
"start": "pnpm exec tsc --build --watch",
"tsc": "pnpm exec tsc --build",
"typecheck": "pnpm exec tsc --noEmit"
},
"bin": {
"create-template": "./bin/src/index.js"
},
"type": "module",
"peerDependencies": {
"@tomic/lib": "workspace:*"
}
}
9 changes: 9 additions & 0 deletions browser/create-template/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# @tomic/template

```cli
npm create @tomic/template my-project -- --template <TEMPLATE> --server-url <SERVER_URL>
pnpm create @tomic/template my-project --template <TEMPLATE> --server-url <SERVER_URL>
bun create @tomic/template my-project --template <TEMPLATE> --server-url <SERVER_URL>
```

_Check out [the docs here](https://docs.atomicdata.dev/create-template/atomic-template)._
20 changes: 20 additions & 0 deletions browser/create-template/src/buildEndUsageString.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import chalk from 'chalk';
import {
getPackagemanager,
getRunCommand,
startCommand,
} from './packageManager.js';

export function buildEndUsageString(template: string, folder: string): string {
const packageManager = getPackagemanager();

const commands = [
chalk.blue('\nTo continue run the following commands:'),
`cd ${folder}`,
`${packageManager} install`,
getRunCommand(packageManager, 'update-ontologies'),
startCommand(template, packageManager),
];

return commands.join('\n');
}
14 changes: 14 additions & 0 deletions browser/create-template/src/copyTemplate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import fs from 'node:fs';
import path from 'node:path';
import { log } from './utils.js';

export function copyTemplate(template: string, outputDir: string): void {
// Copy the specified dir from the templates folder to the output dir
fs.cpSync(
path.join(import.meta.dirname, `../../templates/${template}`),
outputDir,
{ recursive: true },
);

log(`Created template in ${outputDir}`);
}
24 changes: 24 additions & 0 deletions browser/create-template/src/createOutputFolder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import fs from 'node:fs';
import { ask } from './utils.js';

export async function createOutputFolder(outputDir: string): Promise<void> {
if (fs.existsSync(outputDir)) {
const shouldContinue = await ask(
`Folder already exists, Everything in the existing folder will be deleted. Continue? (y/n) `,
);

if (shouldContinue.toLowerCase() !== 'y') {
console.error('Aborted');
process.exit(0);
}

fs.rmSync(outputDir, { recursive: true });
}

try {
fs.mkdirSync(outputDir);
} catch (error) {
console.error(`Failed to create directory: ${outputDir}`);
process.exit(1);
}
}
64 changes: 64 additions & 0 deletions browser/create-template/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/usr/bin/env node
/* eslint-disable no-console */
import path from 'node:path';
import { parseArgs } from 'node:util';
import { copyTemplate } from './copyTemplate.js';
import { createOutputFolder } from './createOutputFolder.js';
import { buildEndUsageString } from './buildEndUsageString.js';
import { postProcess } from './postprocess.js';
import { isTemplate } from './templates.js';
import { log } from './utils.js';
import chalk from 'chalk';

const args = parseArgs({
options: {
template: {
type: 'string',
},
'server-url': {
type: 'string',
},
},
allowPositionals: true,
});

if (!args.values.template) {
console.error(
'Missing template argument, provide a template by adding --template <template> to the command',
);
process.exit(1);
}

if (!args.values['server-url']) {
console.error(
'Missing an AtomicServer server-url argument, provide a server-url by adding --server-url <server-url> to the command',
);
process.exit(1);
}

if (!isTemplate(args.values.template)) {
console.error(`Invalid template: ${args.values.template}`);
process.exit(1);
}

let outputDir = process.cwd();

if (args.positionals.length > 0) {
outputDir = path.join(outputDir, args.positionals[0]);
}

await createOutputFolder(outputDir);

copyTemplate(args.values.template, outputDir);

await postProcess({
folderPath: outputDir,
template: args.values.template,
serverUrl: args.values['server-url'],
});

log('');
log(chalk.green('Done!'));

const endUsage = buildEndUsageString(args.values.template, args.positionals[0]);
console.log(endUsage);
32 changes: 32 additions & 0 deletions browser/create-template/src/packageManager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
export function getPackagemanager(): string {
const userAgent = process.env.npm_config_user_agent;
const defaultPackageManager = 'npm';

if (!userAgent) {
return defaultPackageManager;
}

if (userAgent.includes('yarn')) {
return 'yarn';
} else if (userAgent.includes('pnpm')) {
return 'pnpm';
}

return defaultPackageManager;
}

export function getRunCommand(packageManager: string = 'npm', command: string) {
if (packageManager === 'npm' && command !== 'start') {
return `npm run ${command}`;
}

return `${packageManager} ${command}`;
}

export function startCommand(template: string, packageManager: string) {
if (template === 'sveltekit-site') {
return getRunCommand(packageManager, 'dev');
}

return getRunCommand(packageManager, 'start');
}
70 changes: 70 additions & 0 deletions browser/create-template/src/postprocess.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
import path from 'node:path';
import fs from 'node:fs';
import { Store, type Resource } from '@tomic/lib';
import { type TemplateKey, templates } from './templates.js';
import chalk from 'chalk';
import { log } from './utils.js';
import { getPackagemanager } from './packageManager.js';

export interface PostProcessContext {
folderPath: string;
template: TemplateKey;
serverUrl: string;
}

export async function postProcess(context: PostProcessContext) {
const { folderPath, template, serverUrl } = context;

const store = new Store({ serverUrl });
const baseTemplate = templates[template];
const ontologySubject = new URL(
baseTemplate.ontologyID,
serverUrl,
).toString();

const ontology = await store.getResource(ontologySubject);

if (ontology.error) {
console.error(
`The ${baseTemplate.name} does not exist on your drive. To get the template go to the Create Resource page and select the ${baseTemplate.name} template`,
);
process.exit(1);
}

await modifyConfig(folderPath, ontology);
await modifyReadme(folderPath);
await createEnvFile(folderPath, baseTemplate.generateEnv({ serverUrl }));
}

async function modifyConfig(folderPath: string, ontology: Resource) {
log(`Generating ${chalk.gray('atomic.config.json')}...`);
const configPath = path.join(folderPath, 'atomic.config.json');
const content = await fs.promises.readFile(configPath, { encoding: 'utf-8' });

const newContent = content.replaceAll('<ONTOLOGY>', ontology.subject);

await fs.promises.writeFile(configPath, newContent);
}

async function modifyReadme(folderPath: string) {
log(`Generating ${chalk.gray('README.md')}...`);
const readmePath = path.join(folderPath, 'README.md');
const content = await fs.promises.readFile(readmePath, { encoding: 'utf-8' });

const packageManager = getPackagemanager();
const newContent = content
.replaceAll('<PACKAGE_MANAGER>', packageManager)
.replaceAll(
'<PACKAGE_MANAGER_RUN>',
packageManager === 'npm' ? 'npm run' : packageManager,
);

await fs.promises.writeFile(readmePath, newContent);
}

async function createEnvFile(folderPath: string, envContent: string) {
log(`Generating ${chalk.gray('.env')} file...`);

const envPath = path.join(folderPath, '.env');
await fs.promises.writeFile(envPath, envContent);
}
29 changes: 29 additions & 0 deletions browser/create-template/src/templates.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export type TemplateKey = keyof typeof templates;

export type BaseTemplate = {
name: string;
ontologyID: string;
generateEnv: (context: { serverUrl: string }) => string;
};

const baseTemplates = {
website: {
name: 'website',
ontologyID: '01j6zqa7qgamwh5960dzy99j70',
generateEnv: ({ serverUrl }) => {
const siteSubject = new URL(
'01j5zrevq917dp0wm4p2vnd7nr',
serverUrl,
).toString();

return `PUBLIC_ATOMIC_SERVER_URL=${serverUrl}\nPUBLIC_WEBSITE_RESOURCE=${siteSubject}`;
},
},
} satisfies Record<string, BaseTemplate>;

export const templates = {
'sveltekit-site': baseTemplates.website,
} satisfies Record<string, BaseTemplate>;

export const isTemplate = (value: string): value is TemplateKey =>
value in templates;
19 changes: 19 additions & 0 deletions browser/create-template/src/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import readline from 'node:readline';

export function ask(question: string): Promise<string> {
return new Promise(resolve => {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
rl.question(question, answer => {
rl.close();
resolve(answer);
});
});
}

export function log(message: unknown, ...optionalParams: unknown[]): void {
// eslint-disable-next-line no-console
console.log(message, ...(optionalParams ?? []));
}
21 changes: 21 additions & 0 deletions browser/create-template/templates/sveltekit-site/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
node_modules

# Output
.output
.vercel
/.svelte-kit
/build

# OS
.DS_Store
Thumbs.db

# Env
.env
.env.*
!.env.example
!.env.test

# Vite
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
1 change: 1 addition & 0 deletions browser/create-template/templates/sveltekit-site/.npmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
engine-strict=true
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Package Managers
package-lock.json
pnpm-lock.yaml
yarn.lock
Loading