initial-commit
This commit is contained in:
38
.gitignore
vendored
Normal file
38
.gitignore
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
.env
|
||||||
|
node_modules
|
||||||
|
.DS_Store
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
coverage
|
||||||
|
*.local
|
||||||
|
out
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Cypress
|
||||||
|
/cypress/videos/
|
||||||
|
/cypress/screenshots/
|
||||||
|
|
||||||
|
# Vitest
|
||||||
|
__screenshots__/
|
||||||
114
bin/create.js
Executable file
114
bin/create.js
Executable file
@@ -0,0 +1,114 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
|
||||||
|
import {
|
||||||
|
readFileSync,
|
||||||
|
writeFileSync,
|
||||||
|
mkdirSync,
|
||||||
|
readdirSync,
|
||||||
|
copyFileSync,
|
||||||
|
existsSync,
|
||||||
|
} from 'fs'
|
||||||
|
import { join, dirname } from 'path'
|
||||||
|
import { fileURLToPath } from 'url'
|
||||||
|
|
||||||
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
||||||
|
const TEMPLATE_DIR = join(__dirname, '..', 'template')
|
||||||
|
|
||||||
|
const toKebabCase = (str) => {
|
||||||
|
return str
|
||||||
|
.replace(/([a-z])([A-Z])/g, '$1-$2')
|
||||||
|
.replace(/[\s_]+/g, '-')
|
||||||
|
.toLowerCase()
|
||||||
|
}
|
||||||
|
|
||||||
|
const toPascalCase = (str) => {
|
||||||
|
return str
|
||||||
|
.replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''))
|
||||||
|
.replace(/^./, (s) => s.toUpperCase())
|
||||||
|
}
|
||||||
|
|
||||||
|
const toTitleCase = (str) => {
|
||||||
|
return str
|
||||||
|
.replace(/[-_\s]+(.)?/g, (_, c) => (c ? ' ' + c.toUpperCase() : ''))
|
||||||
|
.replace(/^./, (s) => s.toUpperCase())
|
||||||
|
.replace(/\b\w/g, (c) => c.toUpperCase())
|
||||||
|
}
|
||||||
|
|
||||||
|
const replaceValues = (content, values) => {
|
||||||
|
return content.replace(/\$\{(.*?)\}/g, (_, key) => {
|
||||||
|
return values[key] ?? `\${${key}}`
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const copyDir = (src, dest, values) => {
|
||||||
|
mkdirSync(dest, { recursive: true })
|
||||||
|
const entries = readdirSync(src, { withFileTypes: true })
|
||||||
|
|
||||||
|
for (const entry of entries) {
|
||||||
|
const srcPath = join(src, entry.name)
|
||||||
|
const destName = replaceValues(entry.name, values)
|
||||||
|
const destPath = join(dest, destName)
|
||||||
|
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
copyDir(srcPath, destPath, values)
|
||||||
|
} else {
|
||||||
|
copyFileSync(srcPath, destPath)
|
||||||
|
const content = readFileSync(destPath, 'utf8')
|
||||||
|
writeFileSync(destPath, replaceValues(content, values))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const prompt = async (question) => {
|
||||||
|
const readline = await import('readline')
|
||||||
|
const rl = readline.createInterface({
|
||||||
|
input: process.stdin,
|
||||||
|
output: process.stdout,
|
||||||
|
})
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
rl.question(question, (answer) => {
|
||||||
|
rl.close()
|
||||||
|
resolve(answer)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const main = async () => {
|
||||||
|
const name = await prompt('Plugin name: ')
|
||||||
|
const description = await prompt('Plugin description: ')
|
||||||
|
|
||||||
|
const trimmedName = name?.trim()
|
||||||
|
|
||||||
|
if (!trimmedName) {
|
||||||
|
console.error('Plugin name is required')
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
const kebab = toKebabCase(trimmedName)
|
||||||
|
const pascal = toPascalCase(trimmedName)
|
||||||
|
const title = toTitleCase(trimmedName)
|
||||||
|
|
||||||
|
const values = {
|
||||||
|
NAME_KEBAB_CASE: kebab,
|
||||||
|
NAME_PASCAL_CASE: pascal,
|
||||||
|
NAME_TITLE_CASE: title,
|
||||||
|
DESCRIPTION: description.trim(),
|
||||||
|
}
|
||||||
|
|
||||||
|
const destDir = join(process.cwd(), `takerofnotes-plugin-${kebab}`)
|
||||||
|
|
||||||
|
if (existsSync(destDir)) {
|
||||||
|
console.error(`Directory already exists: ${destDir}`)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
copyDir(TEMPLATE_DIR, destDir, values)
|
||||||
|
|
||||||
|
console.log(`\nPlugin created: takerofnotes-plugin-${kebab}`)
|
||||||
|
console.log(`\nNext steps:`)
|
||||||
|
console.log(` cd takerofnotes-plugin-${kebab}`)
|
||||||
|
console.log(` npm install`)
|
||||||
|
console.log(` cat README.md`)
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
16
package-lock.json
generated
Normal file
16
package-lock.json
generated
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"name": "create-takerofnotes-plugin",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "create-takerofnotes-plugin",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"license": "MIT",
|
||||||
|
"bin": {
|
||||||
|
"create-takerofnotes-plugin": "bin/create.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
package.json
Normal file
22
package.json
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"name": "create-takerofnotes-plugin",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description": "Scaffold a new Taker of Notes storage plugin",
|
||||||
|
"type": "module",
|
||||||
|
"bin": {
|
||||||
|
"create-takerofnotes-plugin": "./bin/create.js"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"bin"
|
||||||
|
],
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"No tests yet\""
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"takerofnotes",
|
||||||
|
"plugin",
|
||||||
|
"scaffold"
|
||||||
|
],
|
||||||
|
"author": "nicwands",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
||||||
38
template/.gitignore
vendored
Normal file
38
template/.gitignore
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# Logs
|
||||||
|
logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
pnpm-debug.log*
|
||||||
|
lerna-debug.log*
|
||||||
|
|
||||||
|
.env
|
||||||
|
node_modules
|
||||||
|
.DS_Store
|
||||||
|
dist
|
||||||
|
dist-ssr
|
||||||
|
coverage
|
||||||
|
*.local
|
||||||
|
.npmrc
|
||||||
|
|
||||||
|
# Editor directories and files
|
||||||
|
.vscode/*
|
||||||
|
!.vscode/extensions.json
|
||||||
|
.idea
|
||||||
|
*.suo
|
||||||
|
*.ntvs*
|
||||||
|
*.njsproj
|
||||||
|
*.sln
|
||||||
|
*.sw?
|
||||||
|
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
.eslintcache
|
||||||
|
|
||||||
|
# Cypress
|
||||||
|
/cypress/videos/
|
||||||
|
/cypress/screenshots/
|
||||||
|
|
||||||
|
# Vitest
|
||||||
|
__screenshots__/
|
||||||
1
template/.nvmrc
Normal file
1
template/.nvmrc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
22
|
||||||
20
template/README.md
Normal file
20
template/README.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
# Taker of Notes Plugin: ${NAME_TITLE_CASE}
|
||||||
|
|
||||||
|
${DESCRIPTION}
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
1. Install dependencies: `npm install`
|
||||||
|
2. Run tests: `npm test`
|
||||||
|
3. Build: `npm run build`
|
||||||
|
|
||||||
|
## Project Structure
|
||||||
|
|
||||||
|
- `src/` - Source code
|
||||||
|
- `test/` - Tests
|
||||||
|
- `dist/` - Built output
|
||||||
|
- `rollup.config.js` - Build configuration
|
||||||
|
|
||||||
|
## Development
|
||||||
|
|
||||||
|
Implement your storage adapter in `src/${NAME_PASCAL_CASE}.js`.
|
||||||
27
template/package.json
Normal file
27
template/package.json
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"name": "@takerofnotes/plugin-${NAME_KEBAB_CASE}",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"repository": {
|
||||||
|
"type": "git"
|
||||||
|
},
|
||||||
|
"type": "module",
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"exports": "./dist/index.js",
|
||||||
|
"scripts": {
|
||||||
|
"build": "rollup -c",
|
||||||
|
"test": "vitest",
|
||||||
|
"prepublishOnly": "npm run build"
|
||||||
|
},
|
||||||
|
"author": "nicwands",
|
||||||
|
"license": "MIT",
|
||||||
|
"description": "${DESCRIPTION}",
|
||||||
|
"dependencies": {
|
||||||
|
"@takerofnotes/plugin-sdk": "^0.2.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@rollup/plugin-commonjs": "^29.0.0",
|
||||||
|
"@rollup/plugin-node-resolve": "^16.0.3",
|
||||||
|
"rollup": "^4.59.0",
|
||||||
|
"vitest": "^4.0.18"
|
||||||
|
}
|
||||||
|
}
|
||||||
13
template/rollup.config.js
Normal file
13
template/rollup.config.js
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// rollup.config.js
|
||||||
|
import resolve from '@rollup/plugin-node-resolve'
|
||||||
|
import commonjs from '@rollup/plugin-commonjs'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
input: 'src/index.js',
|
||||||
|
output: {
|
||||||
|
file: 'dist/index.js',
|
||||||
|
format: 'esm',
|
||||||
|
sourcemap: true,
|
||||||
|
},
|
||||||
|
plugins: [resolve(), commonjs()],
|
||||||
|
}
|
||||||
23
template/src/${NAME_PASCAL_CASE}Adapter.js
Normal file
23
template/src/${NAME_PASCAL_CASE}Adapter.js
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import { BaseNotesAdapter } from '@takerofnotes/plugin-sdk'
|
||||||
|
|
||||||
|
export default class ${NAME_PASCAL_CASE}Adapter extends BaseNotesAdapter {
|
||||||
|
constructor(config) {
|
||||||
|
super()
|
||||||
|
|
||||||
|
for (const field in config) {
|
||||||
|
this[field] = config[field]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async init() {}
|
||||||
|
|
||||||
|
async getAll() {}
|
||||||
|
|
||||||
|
async create(note) {}
|
||||||
|
|
||||||
|
async update(note) {}
|
||||||
|
|
||||||
|
async delete(id) {}
|
||||||
|
|
||||||
|
async testConnection() {}
|
||||||
|
}
|
||||||
14
template/src/index.js
Normal file
14
template/src/index.js
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { definePlugin } from '@takerofnotes/plugin-sdk'
|
||||||
|
import ${NAME_PASCAL_CASE}Adapter from './${NAME_PASCAL_CASE}Adapter'
|
||||||
|
|
||||||
|
export default definePlugin({
|
||||||
|
id: '${NAME_KEBAB_CASE}',
|
||||||
|
name: '${NAME_TITLE_CASE}',
|
||||||
|
description: '${DESCRIPTION}',
|
||||||
|
version: '0.1.0',
|
||||||
|
apiVersion: '0.3.1',
|
||||||
|
configSchema: [],
|
||||||
|
createAdapter(config) {
|
||||||
|
return new ${NAME_PASCAL_CASE}Adapter(config)
|
||||||
|
},
|
||||||
|
})
|
||||||
8
template/test/plugin.test.js
Normal file
8
template/test/plugin.test.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { describePluginTests } from '@takerofnotes/plugin-sdk'
|
||||||
|
import plugin from '../src/index.js'
|
||||||
|
|
||||||
|
const adapter = plugin.createAdapter({
|
||||||
|
// Adapter config here
|
||||||
|
})
|
||||||
|
|
||||||
|
describePluginTests({ plugin, adapter }, describe, it, expect)
|
||||||
8
template/vitest.config.js
Normal file
8
template/vitest.config.js
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
import { defineConfig } from 'vitest/config'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
test: {
|
||||||
|
globals: true,
|
||||||
|
testTimeout: 30000,
|
||||||
|
},
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user