Skip to content

Commit

Permalink
Server API REST and Deno publish
Browse files Browse the repository at this point in the history
  • Loading branch information
alexandermontillarivera committed Mar 10, 2023
1 parent e0cd92a commit 92e5238
Show file tree
Hide file tree
Showing 9 changed files with 208 additions and 12 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules
dist
dist
api/.env
1 change: 1 addition & 0 deletions .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ tsconfig.esm.json
tsconfig.json
api
src
mod.ts
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ import markupToJSON from 'markuptojson'
// COMMON JS
const markupToJSON require('markuptojson')

// DENO
import markupToJSON from 'https://deno.land/x/markuptojson_deno/mod.ts'

// -- HTML TO JSON -- //
const HTML = "<h1 class='title' id='mainTitle'>Hello World <span>Master</span></h1>"
const JSON = markupToJSON.htmlToJSON(HTML)
Expand Down Expand Up @@ -54,7 +57,12 @@ You can also import the functions separately.
// ESMODULES
import { htmlToJSON, jsonToHTML } from 'markuptojson'


// COMMONJS
const { htmlToJSON, jsonToHTML } = require('markuptojson')

// DENO
import { htmlToJSON, jsonToHTML } from 'https://deno.land/x/markuptojson_deno/mod.ts'

```
Thanks to **typescript** you will be able to have autocompletion in visual studio code and other popular IDEs, so you can easily extract the api responses and some performance information. Just like **typescript** helps with module methods for easy use.
2 changes: 1 addition & 1 deletion api/.env
Original file line number Diff line number Diff line change
@@ -1 +1 @@
set PORT = "400"
PORT = 4000
4 changes: 3 additions & 1 deletion api/deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
"no-local",
"no-inferrable-types",
"no-prototype-builtins",
"no-cond-assign"
"no-cond-assign",
"strict-boolean-expressions",
"@typescript-eslint/strict-boolean-expressions"
]
}
},
Expand Down
6 changes: 5 additions & 1 deletion api/imports.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
{
"imports": {
"https://esm.sh/": "https://esm.sh/",
"https://cdn.skypack.dev/": "https://cdn.skypack.dev/"
"https://cdn.skypack.dev/": "https://cdn.skypack.dev/",
"opine/": "https://deno.land/x/[email protected]/",
"colors/": "https://deno.land/x/[email protected]/",
"cors/": "https://deno.land/x/[email protected]/",
"markuptojson/": "https://esm.sh/[email protected]/"
}
}
169 changes: 162 additions & 7 deletions api/src/app.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,167 @@
import { Application, Router } from 'https://deno.land/x/[email protected]/mod.ts'
import { opine, json, urlencoded } from 'opine/mod.ts'
import { fg } from 'colors/mod.ts'
import { opineCors } from 'cors/mod.ts'
import config from './config.ts'
import { htmlToJSON, jsonToHTML, type JsonDBO } from 'markuptojson/'

const router = new Router()
const app = new Application()
const app = opine()

router.post('/', (ctx) => {
// const s = ctx.request.body()?.value('asdsad')
app.use(json({ limit: '100mb' }))
app.use(urlencoded({ extends: false, limit: '100mb' }))
app.use(opineCors({
allowedHeaders: '*',
origin: '*',
methods: 'PUT, POST, GET, DELETE, OPTIONS, PATCH',
credentials: true
}))

// routes

app.get('/', (_req, res) => {
res.setStatus(200).json([
{
route: '/api/json',
description: 'Create valid Json DBO for interactivity with the [markupjson(NodeJS, Deno, CDNs, Browser)] package and this API',
format: 'HTML',
type: 'string',
method: 'POST',
exampleInput: "<h1 class='main-title' id='title'>Hello World <span>By markuptojson</span></h1>",
output: [
{
tagName: 'h1',
tagAttrs: {
class: 'main-title',
id: 'title'
},
children: [
{
tagName: 'span',
tagAttrs: {},
children: [],
content: 'By markuptojson'
}
],
content: 'Hello World'
}
],
limit: '100mb',
bodyRequestNameParam: 'htmlContent',
responseParamName: 'data',
statusCodes: [
{
500: 'Internal error server',
400: 'Bad request, not valid html content',
200: 'Success'
}
]
},
{
route: '/api/html',
description: 'Convert JsonDBO create by API or markuptojson module to html',
format: 'ARRAY',
type: {
tagAttrs: 'string',
content: 'string',
children: 'array of this type',
tagName: 'string'
},
method: 'POST',
exampleInput: [
{
tagName: 'h1',
tagAttrs: {
class: 'main-title',
id: 'title'
},
children: [
{
tagName: 'span',
tagAttrs: {},
children: [],
content: 'By markuptojson'
}
],
content: 'Hello World'
}
],
output: "<h1 class='main-title' id='title'>Hello World <span>By markuptojson</span></h1>",
limit: '100mb',
bodyRequestNameParam: 'jsonContent',
responseParamName: 'data',
statusCodes: [
{
500: 'Internal error server',
400: 'Bad request, not valid JsonDBO array content',
200: 'Success'
}
]
}
])
})

app.post('/api/json', (req, res) => {
const html: string = String(req.body.htmlContent)
const regex = /<[a-z][\s\S]*>/i
try {
if (!regex.test(html)) {
return res.setStatus(400).json({
message: 'Require a valid body param [htmlContent] => html content'
})
}

const jsonResult = htmlToJSON(html)

res.setStatus(200).json({
data: jsonResult
})
} catch (_error) {
res.setStatus(500).json({
message: 'Internal error server...'
})
}
})

app.post('/api/html', (req, res) => {
const json = req.body.jsonContent as JsonDBO[]

try {
if (!Array.isArray(json)) {
return res.setStatus(400).json({
message: 'Require Array of param [jsonContent]'
})
}

const validData: JsonDBO[] = json.filter((item: any) => {
return (
typeof item === 'object' &&
(Boolean(item.tagAttrs)) &&
typeof item.tagAttrs === 'object' &&
(Boolean(item.content)) &&
typeof item.content === 'string' &&
Array.isArray(item.children) &&
(Boolean(item.tagName)) &&
typeof item.tagName === 'string'
)
})

if (validData.length !== json.length) {
return res.setStatus(400).json({
message: 'Incorrect format, generate valid [jsonContent] in [POST] /api/json'
})
}

const html = jsonToHTML(json)

res.setStatus(200).json({
data: html
})
} catch (_error) {
res.setStatus(500).json({
message: 'Internal error server...'
})
}
})

app.use(router.routes())
await app.listen({ port: config.PORT })
app.listen(config.PORT, () => {
fg.green(`[APP]: listening in http://localhost:${String(config.PORT)}`)
})
6 changes: 5 additions & 1 deletion api/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
/* eslint-disable @typescript-eslint/strict-boolean-expressions */
import { config as access } from 'https://deno.land/[email protected]/dotenv/mod.ts'

const env = await access()

const config: {
PORT: number
} = {
PORT: 4000
PORT: Number(env.PORT || Deno.env.get('PORT') || 4000)
}

export default config
21 changes: 21 additions & 0 deletions mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// @ts-expect-error deno
import markuptojson, { htmlToJSON, jsonToHTML } from './src/index.ts'

export interface JsonDBO {
tagAttrs: Record<string, string>
content: string
children: JsonDBO[] | never[]
tagName: string
}

export {
htmlToJSON,
jsonToHTML
}

export interface MarkupToJSON {
jsonToHTML: (arrayJson: JsonDBO[]) => string
htmlToJSON: (htmlString: string) => JsonDBO[]
}

export default markuptojson

0 comments on commit 92e5238

Please sign in to comment.