pwi-plata-type 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,58 @@
1
+ import { tools } from "./plata-create-tools.js";
2
+ import * as path from 'node:path'
3
+
4
+ export async function h() {
5
+ return tools.args.forEachArg(async (command, args) => {
6
+ const promises: any[] = []
7
+
8
+ switch (command) {
9
+ case 'lib':
10
+ const nameLib = args.shift()
11
+ promises.push(tools.files.deployFileToProject(
12
+ 'configs',
13
+ 'config',
14
+ `${nameLib.toLowerCase()}.ts`,
15
+ { Name: `${nameLib}`, name: `${nameLib.toLowerCase()}` }
16
+ ).finally(() => console.log(`Config ${nameLib.toLowerCase()} criada`)))
17
+
18
+ promises.push(tools.files.deployFileToProject(
19
+ 'libs',
20
+ 'lib',
21
+ `${nameLib.toLowerCase()}.ts`,
22
+ { Name: `${nameLib}`, name: `${nameLib.toLowerCase()}` }
23
+ ).finally(() => console.log(`Lib ${nameLib.toLowerCase()} criada`)))
24
+ break;
25
+ case 'config':
26
+ const nameConfig = args.shift()
27
+ promises.push(tools.files.deployFileToProject(
28
+ 'configs',
29
+ 'config',
30
+ `${nameConfig.toLowerCase()}.ts`,
31
+ { Name: `${nameConfig}`, name: `${nameConfig.toLowerCase()}` }
32
+ ).finally(() => console.log(`Config ${nameConfig.toLowerCase()} criada`)))
33
+ break;
34
+ case 'cluster':
35
+ console.log('CLUSTER AINDA NÃO CRIANDO AINDA')
36
+ break;
37
+ case 'route':
38
+ const routeArg = `${args.shift()}`.split('/')
39
+
40
+ const routeFileName = routeArg[routeArg.length - 1] === '' ? 'index' : routeArg.pop()
41
+ const routeFilePath = path.join('routes', ...routeArg.filter(v => v !== ''))
42
+
43
+ promises.push(tools.files.deployFileToProject(
44
+ routeFilePath,
45
+ 'route',
46
+ `${routeFileName}.ts`,
47
+ {}
48
+ ).finally(() => console.log(
49
+ `Rota ${routeFilePath}/${routeFileName === 'index' ? '' : routeFileName} criada`
50
+ )))
51
+
52
+ break;
53
+ }
54
+
55
+ await Promise.all(promises)
56
+ return args
57
+ })
58
+ }
@@ -0,0 +1,41 @@
1
+ import { tools } from "./plata-create-tools.js";
2
+
3
+ export async function h() {
4
+ return tools.args.forEachArg(async (command, args) => {
5
+ const promises: any[] = []
6
+
7
+ switch (command) {
8
+ case 'lib':
9
+ const nameLib = args.shift()
10
+ promises.push(tools.files.deployFileToProject(
11
+ 'configs',
12
+ 'config',
13
+ `${nameLib.toLowerCase()}.ts`,
14
+ { Name: `${nameLib}`, name: `${nameLib.toLowerCase()}` }
15
+ ).finally(() => console.log(`Config ${nameLib.toLowerCase()} criada`)))
16
+
17
+ promises.push(tools.files.deployFileToProject(
18
+ 'libs',
19
+ 'lib',
20
+ `${nameLib.toLowerCase()}.ts`,
21
+ { Name: `${nameLib}`, name: `${nameLib.toLowerCase()}` }
22
+ ).finally(() => console.log(`Lib ${nameLib.toLowerCase()} criada`)))
23
+ break;
24
+ case 'config':
25
+ const nameConfig = args.shift()
26
+ promises.push(tools.files.deployFileToProject(
27
+ 'configs',
28
+ 'config',
29
+ `${nameConfig.toLowerCase()}.ts`,
30
+ { Name: `${nameConfig}`, name: `${nameConfig.toLowerCase()}` }
31
+ ).finally(() => console.log(`Config ${nameConfig.toLowerCase()} criada`)))
32
+ break;
33
+ case 'cluster':
34
+ console.log('CLUSTER AINDA NÃO CRIANDO AINDA')
35
+ break;
36
+ }
37
+
38
+ await Promise.all(promises)
39
+ return args
40
+ })
41
+ }
@@ -0,0 +1,98 @@
1
+ import * as fs from 'node:fs'
2
+ import * as path from 'node:path'
3
+
4
+ import { PlataDirs, PlataFiles } from '../../libs/tools.js'
5
+
6
+ export module tools {
7
+ export module files {
8
+ export async function mkdirIfNotExists(dir: string) {
9
+ try {
10
+ const p = path.resolve(dir)
11
+
12
+ if (!fs.existsSync(p)) {
13
+ fs.mkdirSync(p, { recursive: true })
14
+ }
15
+ } catch (err) {
16
+ console.error(err)
17
+ process.exit(1)
18
+ }
19
+ }
20
+
21
+ export async function copyFileIfNotExists(source: string, destination: string) {
22
+ try {
23
+ const s = path.resolve(source)
24
+ const d = path.resolve(destination)
25
+
26
+ if (!fs.existsSync(d)) {
27
+ fs.copyFileSync(s, d)
28
+ }
29
+ } catch (err) {
30
+ console.error(err)
31
+ process.exit(1)
32
+ }
33
+ }
34
+
35
+ export async function copyFileToProject(projectFolder: string, templateFile: string, fileName: string): Promise<string> {
36
+ const s = path.resolve(PlataDirs.getPlataTempleteDir('create-cli', `${templateFile}.ts`))
37
+ let d = path.resolve(PlataDirs.getProjectDir(), projectFolder)
38
+
39
+ await mkdirIfNotExists(d)
40
+ d = path.join(d, fileName)
41
+ await copyFileIfNotExists(s, d)
42
+
43
+ return d
44
+ }
45
+
46
+ export async function deployFileToProject(projectFolder: string, templateFile: string, fileName: string, args: any) {
47
+ const fileInProject = await copyFileToProject(projectFolder, templateFile, fileName)
48
+
49
+ const content: any = await PlataFiles.readFileSync(fileInProject, (line) => {
50
+ if (line === '//@ts-nocheck') {
51
+ return ''
52
+ }
53
+
54
+ if (line === '') {
55
+ return ''
56
+ }
57
+
58
+ // Procura por texto para subistituir esse texto que esta no formato ç__PARAMETRO__ç
59
+ let lastIndex = 0
60
+ while(lastIndex !== -1) {
61
+ lastIndex = line.indexOf('ç__', lastIndex)
62
+
63
+ if (lastIndex !== -1) {
64
+ const pIndex = line.indexOf('__ç', lastIndex)
65
+ const param = line.slice(lastIndex + 3, pIndex)
66
+
67
+ line = line.replace(new RegExp(`ç__${param}__ç`, 'g'), args[param])
68
+ }
69
+ }
70
+
71
+ return line
72
+ })
73
+
74
+ if (content.err !== undefined) {
75
+ console.log(content.err)
76
+ process.exit(1)
77
+ } else {
78
+ fs.writeFileSync(fileInProject, content)
79
+ }
80
+ }
81
+ }
82
+
83
+ export module args {
84
+ export type argsCallBack = (command: string, args: string[]) => Promise<string[]>
85
+
86
+ export async function forEachArg(callback: argsCallBack) {
87
+ let args = process.argv.slice(process.argv.indexOf('--') + 1)
88
+
89
+ while(args.length !== 0) {
90
+ const command = args.shift()
91
+
92
+ if (command !== undefined) {
93
+ args = await callback(command, args)
94
+ }
95
+ }
96
+ }
97
+ }
98
+ }
@@ -0,0 +1,34 @@
1
+ import { PlataDirs } from "../libs/tools.js";
2
+
3
+ interface Handler {
4
+ h: () => Promise<void>
5
+ }
6
+
7
+ const main = async () => {
8
+ const projectPackage = await PlataDirs.ProjectJson
9
+
10
+ if (projectPackage.plata_no_setup !== undefined) {
11
+ console.log('Existe o parametro plata_no_setup no package.json ou seja a plata não esta configurada')
12
+ process.exit(0)
13
+
14
+ }
15
+
16
+ let handler: Handler
17
+
18
+ switch(projectPackage.plata_type ?? 'api') {
19
+ case 'api':
20
+ handler = (await import('./extras/plata-create-api.js')) as unknown as Handler
21
+ break;
22
+ case 'lib':
23
+ handler = (await import('./extras/plata-create-lib.js')) as unknown as Handler
24
+ break;
25
+ default:
26
+ console.log(`tipo ${projectPackage.plata_type} não suportado pela plata`)
27
+ process.exit(0)
28
+ break;
29
+ }
30
+
31
+ await handler.h()
32
+ }
33
+
34
+ main()
package/bin/plata.ts ADDED
@@ -0,0 +1,76 @@
1
+ import { PlataClusterManager, PlataClusterMsg } from "../libs/cluster.js"
2
+ import { loadEnvProjectFile } from "../libs/env.js"
3
+ import { loadExpressRoutes } from "../libs/routes.js"
4
+ import express, { Express } from "express"
5
+
6
+ const main = async () => {
7
+ const clusterLib = new PlataClusterManager();
8
+
9
+ if (clusterLib.isPrimary()) {
10
+ {
11
+ console.log('Carregando .env')
12
+ const err = await loadEnvProjectFile()
13
+
14
+ if (err !== null) {
15
+ console.log(err)
16
+ process.exit(1)
17
+ }
18
+ }
19
+
20
+ console.log(process.env.ENV)
21
+
22
+ clusterLib.run({
23
+ name: '_plata_express',
24
+ onStart: async () => null,
25
+ env: process.env.ENV
26
+ })
27
+
28
+ clusterLib.loadClusters()
29
+ } else {
30
+ await loadEnvProjectFile()
31
+
32
+ process.on('message', async (msg: PlataClusterMsg) => {
33
+ process.emit(msg.id as any, msg as any)
34
+ })
35
+
36
+ if (process.env._plata_name === '_plata_express') {
37
+ process.on('exit', () => process.send({
38
+ id: 0,
39
+ name: '_plata',
40
+ data: {
41
+ action: 'KILL'
42
+ }
43
+ }))
44
+
45
+ const port = process.env.PORT ?? 3050
46
+ const app: Express = express()
47
+
48
+ app.use(process.env._PLATA_API_ROOT ?? '/api',await loadExpressRoutes())
49
+
50
+ app.use((err, req, res, next) => {
51
+ return res.status(500).json({
52
+ errorId: 'B00000',
53
+ error: 'Erro interno da aplicação',
54
+ msg: err.message
55
+ })
56
+ })
57
+
58
+ app.all('*', (req, res) => {
59
+ return res.status(404).json({
60
+ errorId: 'B00001',
61
+ error: 'Rota não encontrada',
62
+ msg: req.path
63
+ })
64
+ })
65
+
66
+ app.listen(port, () => {
67
+ console.log(`Iniciando Worker Express na porta ${port}`)
68
+ setTimeout(() => process.removeAllListeners('exit'), 500)
69
+ })
70
+ } else {
71
+ await clusterLib.loadWorker()
72
+ }
73
+ }
74
+ }
75
+
76
+ main()
package/index.ts ADDED
@@ -0,0 +1,11 @@
1
+ import * as PlataCluster from './libs/cluster.js'
2
+ import * as PlataEnv from './libs/env.js'
3
+ import * as PlataRoutes from './libs/routes.js'
4
+ import * as PlataTools from './libs/tools.js'
5
+
6
+ export {
7
+ PlataCluster,
8
+ PlataEnv,
9
+ PlataRoutes,
10
+ PlataTools,
11
+ }
@@ -0,0 +1,184 @@
1
+ import { PlataRequire, PlataDirs, PlataFiles } from './tools.js'
2
+ import { cpus } from 'node:os'
3
+ import * as typeCluster from 'node:cluster'
4
+
5
+ export interface PlataClusterWorkerConfig {
6
+ name: string,
7
+ env: string,
8
+ onStart: () => Promise<void>
9
+ workers?: number,
10
+ workersEnv?: any,
11
+ onExit?: (worker: typeCluster.Worker, code: number, signal: string) => void,
12
+ }
13
+
14
+ export interface PlataCluster {
15
+ pids: number[],
16
+ config: PlataClusterWorkerConfig
17
+ }
18
+
19
+ export interface PlataClusterMsg {
20
+ name: string,
21
+ id: string,
22
+ data: any
23
+ }
24
+
25
+ export interface PlataClusterProcess {
26
+ clusters: PlataCluster[]
27
+ }
28
+
29
+ export interface _PlataClusterProcess extends NodeJS.Process {
30
+ _plata?: PlataClusterProcess
31
+ }
32
+
33
+ export function getClusterNodeProcess(): PlataClusterProcess {
34
+ const p = process as _PlataClusterProcess
35
+
36
+ if (p._plata === undefined) {
37
+ p._plata = {
38
+ clusters: []
39
+ }
40
+ }
41
+
42
+ if (p._plata.clusters === undefined) {
43
+ p._plata.clusters = []
44
+ }
45
+
46
+ return p._plata
47
+ }
48
+
49
+ export class PlataClusterManager {
50
+ private readonly Cluster = typeCluster.default as unknown as typeCluster.Cluster
51
+ private readonly Process = getClusterNodeProcess()
52
+
53
+ constructor() {
54
+ // Registra o evento que lida com
55
+ if (this.Cluster.isPrimary) {
56
+ if (this.Cluster.eventNames().indexOf('exit') === -1) {
57
+ this.Cluster.on('exit', (worker, code, signal) => {
58
+ if (worker.process.pid === undefined) return
59
+
60
+ const clusterIndex = this.Process.clusters.findIndex(cluster =>
61
+ cluster.pids.indexOf(worker.process.pid ?? 0) !== -1
62
+ )
63
+
64
+ if(clusterIndex !== -1) {
65
+ const cluster = this.Process.clusters[clusterIndex]
66
+
67
+ console.log(`O Worker ${worker.process.pid} do cluster ${cluster.config.name} morreu com o codigo ${code} ${signal ?? ''}`)
68
+ console.log(`Iniciando um novo worker no cluster ${cluster.config.name}`)
69
+
70
+ this.Cluster.emit(`_plata.cluster.worker.exit-${cluster.config.name}`, worker, code, signal)
71
+
72
+ const w = this.Cluster.fork({
73
+ ...cluster.config.workersEnv,
74
+ ENV: cluster.config.env,
75
+ _plata_name: cluster.config.name
76
+ })
77
+
78
+ const pidIndex = cluster.pids.indexOf(worker.process.pid)
79
+
80
+ cluster.pids[pidIndex] = w.process.pid ?? 0
81
+ }
82
+ })
83
+ }
84
+
85
+ if (this.Cluster.eventNames().indexOf('message') === -1) {
86
+ this.Cluster.on('message', this._clusterMsgServer)
87
+ }
88
+ }
89
+ }
90
+
91
+ public async run(config: PlataClusterWorkerConfig) {
92
+ if (config.workers === undefined) {
93
+ if (config.env === 'prod') {
94
+ config.workers = cpus().length
95
+ } else {
96
+ config.workers = 1
97
+ }
98
+ }
99
+
100
+ console.log(`Iniciando ${config.workers} workers para o cluster ${config.name}`)
101
+
102
+ const cluster: PlataCluster = {
103
+ pids: [],
104
+ config
105
+ }
106
+
107
+ for (let i = 0; i < config.workers; i++) {
108
+ const w = this.Cluster.fork({
109
+ ...config.workersEnv,
110
+ ENV: cluster.config.env,
111
+ _plata_name: cluster.config.name
112
+ })
113
+
114
+ cluster.pids.push(w.process.pid ?? 0)
115
+ }
116
+
117
+ if (config.onExit !== undefined)
118
+ this.Cluster.on(`_plata.cluster.worker.exit-${cluster.config.name}`, config.onExit)
119
+ ;
120
+
121
+ this.Process.clusters.push(cluster)
122
+ }
123
+
124
+ public isPrimary(): boolean {
125
+ return this.Cluster.isPrimary
126
+ }
127
+
128
+ public async loadClusters() {
129
+ const required: any = await PlataRequire.requireFolderAsync<any>(PlataDirs.getProjectDirClusters()).then(
130
+ result => result,
131
+ err => {
132
+ return { err }
133
+ }
134
+ )
135
+
136
+ if (required.err !== undefined) {
137
+ console.log(required.err)
138
+ process.exit(1)
139
+ }
140
+
141
+ const TypedRequired: PlataRequire.Required<PlataClusterWorkerConfig>[] = required
142
+ const promisesClusters: any[] = []
143
+
144
+ for (let i = 0; i < TypedRequired.length; i++) {
145
+ const required = TypedRequired[i];
146
+
147
+ promisesClusters.push(this.run(required.exports))
148
+ }
149
+
150
+
151
+ return Promise.all(promisesClusters)
152
+ }
153
+
154
+ public async loadWorker() {
155
+ const file: string | null = await PlataFiles.findFile(
156
+ [
157
+ PlataDirs.getProjectDirClusters()
158
+ ],
159
+ `${process.env["_plata_name"]}.ts`
160
+ ).catch(err => {
161
+ console.error(err)
162
+ return null
163
+ })
164
+
165
+ if (file !== null) {
166
+ const config: PlataClusterWorkerConfig = (await import(file) as any).default
167
+
168
+ await config.onStart()
169
+ }
170
+ }
171
+
172
+ private async _clusterMsgServer(worker: typeCluster.Worker, msg: PlataClusterMsg) {
173
+ if (msg.name !== '_plata') {
174
+ // TODO :::
175
+ } else {
176
+ switch(msg.data.action) {
177
+ case 'KILL':
178
+ console.log('Solicitado kill do app')
179
+ process.exit(0)
180
+ ;
181
+ }
182
+ }
183
+ }
184
+ }
package/libs/env.ts ADDED
@@ -0,0 +1,28 @@
1
+ import { PlataDirs, PlataFiles } from "./tools.js"
2
+
3
+ export interface EnvConfig {
4
+ readonly env: 'prod' | 'debug' | 'homolog' | string
5
+ }
6
+
7
+ export async function loadEnvProjectFile() {
8
+ const config = process.env['ENV'] === undefined ?
9
+ (await import(PlataDirs.getProjectConfigFileDir('env.js')) as any).default as EnvConfig
10
+ : { env: process.env['ENV'] }
11
+
12
+ return PlataFiles.readFileAsync(
13
+ PlataDirs.getProjectEnvFileDir(`${config.env}.env`),
14
+ async (line) => {
15
+ if (line[0] === '#') return
16
+
17
+ if (line !== '') {
18
+ const env = line.split('=')
19
+
20
+ if (env.length >= 2) {
21
+ const [ key, ...value ] = env
22
+
23
+ process.env[key.toUpperCase()] = value.join('')
24
+ }
25
+ }
26
+ }
27
+ )
28
+ }
package/libs/routes.ts ADDED
@@ -0,0 +1,34 @@
1
+ import { PlataDirs, PlataRequire } from "./tools.js";
2
+ import express, { Express, Router } from "express";
3
+
4
+ export type PlataRouter = () => Router
5
+
6
+ export async function loadExpressRoutes(): Promise<Router> {
7
+ const promise = PlataRequire.requireFolderAsync<PlataRouter>(PlataDirs.getProjectRoutesDir())
8
+
9
+ const router = Router()
10
+ router.use(express.json())
11
+
12
+ const routes = await promise.catch(err => { return { error: err } })
13
+
14
+ if ((routes as any).error === undefined) {
15
+ const r = routes as PlataRequire.Required<PlataRouter>[]
16
+
17
+ for (let i = 0; i < r.length; i++) {
18
+ const element = r[i];
19
+
20
+ const httpRoute = element.filePath
21
+ .replace(PlataDirs.getProjectRoutesDir(), '')
22
+ .replace(/.(ts|js)$/, '')
23
+ .replace(/index/, '')
24
+ .replace(/\\/, '/')
25
+ ;
26
+
27
+ router.use(httpRoute, element.exports())
28
+ }
29
+ } else {
30
+ console.log(routes)
31
+ }
32
+
33
+ return router
34
+ }
package/libs/tools.ts ADDED
@@ -0,0 +1,161 @@
1
+ import * as path from 'node:path'
2
+ import * as fs from 'node:fs'
3
+ import * as readline from 'node:readline'
4
+ import * as tGlob from 'glob'
5
+
6
+ const glob = (tGlob as any).default as typeof tGlob
7
+
8
+ export module PlataDirs {
9
+ export function getProjectDir(): string {
10
+ return path.resolve('.')
11
+ }
12
+
13
+ export function getProjectDirClusters(): string {
14
+ return path.resolve('.', 'clusters')
15
+ }
16
+
17
+ export function getProjectDirConfig(): string {
18
+ return path.resolve('.', 'configs')
19
+ }
20
+
21
+ export function getProjectConfigFileDir(file: string): string {
22
+ return path.resolve('.', 'configs', file)
23
+ }
24
+
25
+ export function getProjectDirEnvs(): string {
26
+ return path.resolve('.', 'envs')
27
+ }
28
+
29
+ export function getProjectEnvFileDir(file: string): string {
30
+ return path.resolve('.', 'envs', file)
31
+ }
32
+
33
+ export function getProjectRoutesDir(): string {
34
+ return path.resolve('.', 'routes')
35
+ }
36
+
37
+ export const ProjectJson: any = JSON.parse(
38
+ fs.readFileSync(
39
+ path.join(PlataDirs.getProjectDir(), 'package.json')
40
+ ).toString()
41
+ )
42
+
43
+ export function getPlataDir(): string {
44
+ return path.resolve('.', 'node_modules', ProjectJson.plata_name)
45
+ }
46
+
47
+ export function getPlataTempletesDir(): string {
48
+ return path.join(getPlataDir(), 'templates')
49
+ }
50
+
51
+ export function getPlataTempleteDir(group:string, template: string) {
52
+ return path.join(getPlataTempletesDir(), group, template)
53
+ }
54
+
55
+ }
56
+
57
+ export module PlataFiles {
58
+ export type readLineCallback = (line: string) => Promise<void>
59
+
60
+ export type readLineCallbackSync = (line: string) => string
61
+
62
+ export function readFileAsync(file: string, callback: readLineCallback): Promise<Error | null> {
63
+ return new Promise(resolve => {
64
+ try {
65
+ const promises: any = []
66
+
67
+ const stream = readline.createInterface({
68
+ input: fs.createReadStream(file),
69
+ crlfDelay: Infinity
70
+ })
71
+
72
+ stream.on('close', () => {
73
+ Promise.all(promises).then(
74
+ () => resolve(null),
75
+ (err) => resolve(err),
76
+ )
77
+ })
78
+
79
+ stream.on('line', (line) => {
80
+ promises.push(callback(line))
81
+ })
82
+ } catch (e) {
83
+ resolve(e)
84
+ }
85
+ })
86
+ }
87
+
88
+ export function readFileSync(file: string, callback: readLineCallbackSync): Promise<string | { err: any }> {
89
+ return new Promise(resolve => {
90
+ try {
91
+ const content = []
92
+ const stream = readline.createInterface({
93
+ input: fs.createReadStream(file),
94
+ crlfDelay: Infinity
95
+ })
96
+
97
+ stream.on('close', () => {
98
+ resolve(content.join('\n'))
99
+ })
100
+
101
+ stream.on('line', (line) => {
102
+ content.push(callback(line))
103
+ })
104
+
105
+ } catch(e) {
106
+ resolve({ err: e })
107
+ }
108
+ })
109
+ }
110
+
111
+ export async function findFile(folders: string[], file: string): Promise<string | null> {
112
+ for (let i = 0; i < folders.length; i++) {
113
+ const folder = folders[i];
114
+
115
+ const f = glob.sync(`${folder}/**/${file}`)[0]
116
+
117
+ if (f !== undefined) {
118
+ return f
119
+ }
120
+ }
121
+
122
+ return null
123
+ }
124
+ }
125
+
126
+ export module PlataRequire {
127
+ export interface Required<Type> {
128
+ filePath: string,
129
+ name: string,
130
+ exports: Type
131
+ }
132
+
133
+ export async function requireAsync<Type>(file: string): Promise<Required<Type>> {
134
+ const p = path.resolve(file)
135
+
136
+ return {
137
+ filePath: p,
138
+ name: path.basename(p).replace('.ts', '').replace('.js', ''),
139
+ exports: (await import(p) as any).default as Type
140
+ }
141
+ }
142
+
143
+ export async function requireFolderAsync<Type>(folder: string): Promise<Required<Type>[]> {
144
+ const promises: Promise<Required<Type>>[] = []
145
+ const p = path.resolve(folder)
146
+
147
+ glob.sync(`${p}/**/*.ts`).forEach(value => {
148
+ value = value.replace('.ts', '.js')
149
+
150
+ promises.push(requireAsync<Type>(value))
151
+ })
152
+
153
+ return Promise.all(promises)
154
+ }
155
+ }
156
+
157
+ export module PlataExtra {
158
+ export function Sleep(ms: number) {
159
+ return new Promise(resolve => setTimeout(resolve, ms))
160
+ }
161
+ }
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "pwi-plata-type",
3
+ "version": "0.1.0",
4
+ "type": "module",
5
+ "main": "index.ts",
6
+ "bin": {
7
+ "plata": "bin/plata.ts",
8
+ "plata-cli-create": "bin/plata-create.ts"
9
+ },
10
+ "scripts": {
11
+ "postinstall": "node postinstall.js"
12
+ },
13
+ "keywords": [],
14
+ "author": "",
15
+ "license": "UNLICENSED",
16
+ "dependencies": {
17
+ "@types/express": "^4.17.13",
18
+ "@types/glob": "^7.2.0",
19
+ "@types/jest": "^28.1.1",
20
+ "glob": "^8.0.3",
21
+ "jest": "^28.1.1",
22
+ "ts-jest": "^28.0.4",
23
+ "ts-node": "^10.8.1"
24
+ },
25
+ "description": "",
26
+ "devDependencies": {
27
+ "express": "^4.18.1"
28
+ }
29
+ }
@@ -0,0 +1,108 @@
1
+ import * as fs from 'node:fs'
2
+ import * as path from 'node:path'
3
+
4
+ export function tools(dirs) {
5
+ const tools = new Object(null)
6
+
7
+ tools.mkdirIfNotExists = async (dir) => {
8
+ try {
9
+ const p = path.resolve(dir)
10
+
11
+ if (!fs.existsSync(p)) {
12
+ fs.mkdirSync(p, { resolve: true })
13
+ }
14
+ } catch (err) {
15
+ console.error(err)
16
+ process.exit(1)
17
+ }
18
+ }
19
+
20
+ tools.copyFile = async (source, destination) => {
21
+ try {
22
+ const s = path.resolve(source)
23
+ const d = path.resolve(destination)
24
+
25
+ fs.copyFileSync(s, d)
26
+ } catch (err) {
27
+ console.error(err)
28
+ process.exit(1)
29
+ }
30
+ }
31
+
32
+ tools.copyFileIfNotExists = async (source, destination) => {
33
+ try {
34
+ const s = path.resolve(source)
35
+ const d = path.resolve(destination)
36
+
37
+ if (!fs.existsSync(d)) {
38
+ tools.copyFile(s, d)
39
+ }
40
+ } catch (err) {
41
+ console.error(err)
42
+ process.exit(1)
43
+ }
44
+ }
45
+
46
+ tools.forEachFileInFolder = async (folder, callback) => {
47
+ try {
48
+ const f = path.resolve(folder)
49
+ const files = fs.readdirSync(f)
50
+
51
+ const promises = []
52
+
53
+ files.forEach(file => {
54
+ const filePath = path.join(f, file)
55
+
56
+ promises.push(
57
+ (async () => callback(file, filePath))()
58
+ )
59
+ })
60
+
61
+ await Promise.all(promises)
62
+ } catch (err) {
63
+ console.error(err)
64
+ process.exit(1)
65
+ }
66
+ }
67
+
68
+ tools.createFolderProject = (async (folder) =>
69
+ tools.mkdirIfNotExists(path.join(dirs.projectDir, folder))
70
+ )
71
+
72
+ tools.copyFolderToProject = async (folder) => {
73
+ const templateFolder = path.join(dirs.templateDir, folder)
74
+ const destination = path.join(dirs.projectDir, folder)
75
+
76
+ await tools.mkdirIfNotExists(destination)
77
+
78
+ await tools.forEachFileInFolder(templateFolder, async (file, filePath) =>
79
+ tools.copyFileIfNotExists(
80
+ filePath,
81
+ path.join(destination, file)
82
+ )
83
+ )
84
+ }
85
+
86
+ tools.syncFolderProject = async (folder) => {
87
+ const templateFolder = path.join(dirs.templateDir, folder)
88
+ const destination = path.join(dirs.projectDir, folder)
89
+
90
+ await tools.mkdirIfNotExists(destination)
91
+
92
+ await tools.forEachFileInFolder(templateFolder, async (file, filePath) =>
93
+ tools.copyFile(
94
+ filePath,
95
+ path.join(destination, file)
96
+ )
97
+ )
98
+ }
99
+
100
+ tools.syncFileToProject = async (file) => {
101
+ const templateFile = path.join(dirs.templateDir, file)
102
+ const destination = path.join(dirs.projectDir, file)
103
+
104
+ await tools.copyFile(templateFile, destination)
105
+ }
106
+
107
+ return tools
108
+ }
package/postinstall.js ADDED
@@ -0,0 +1,38 @@
1
+ import * as fs from 'node:fs'
2
+ import * as path from 'node:path'
3
+
4
+ const main = async () => {
5
+ const plataDir = path.resolve('.')
6
+ const templatesDir = path.resolve(plataDir, 'templates', 'postinstall')
7
+ const projectDir = path.resolve(plataDir, '..', '..')
8
+ let projectPackageJson = JSON.parse(fs.readFileSync(path.join(projectDir, 'package.json')).toString())
9
+ const plataPackageJson = JSON.parse(fs.readFileSync(path.join(plataDir, 'package.json')))
10
+
11
+ if (projectPackageJson.plata_no_setup !== undefined) {
12
+ process.exit(0)
13
+ }
14
+
15
+ projectPackageJson.plata_type = projectPackageJson.plata_type ?? 'api'
16
+ projectPackageJson.plata_name = plataPackageJson.name
17
+ projectPackageJson.license = "UNLICENSED"
18
+
19
+ const templateDir = path.join(templatesDir, projectPackageJson.plata_type)
20
+
21
+ const { install } = await import(path.join(templateDir, '_install.mjs'))
22
+
23
+ projectPackageJson = await install({
24
+ dirs: {
25
+ plataDir,
26
+ templateDir,
27
+ projectDir,
28
+ },
29
+ projectPackageJson
30
+ })
31
+
32
+ fs.writeFileSync(
33
+ path.join(projectDir, 'package.json'),
34
+ JSON.stringify(projectPackageJson, null, 4)
35
+ )
36
+ }
37
+
38
+ main()
@@ -0,0 +1,9 @@
1
+ const config: ç__Name__çConfig = {
2
+
3
+ }
4
+
5
+ interface ç__Name__çConfig {
6
+
7
+ }
8
+
9
+ export default config
@@ -0,0 +1,19 @@
1
+ //@ts-nocheck
2
+ import * as ç__Name__çConfigImport from '../configs/ç__name__ç.js'
3
+ const ç__Name__çConfig = ç__Name__çConfigImport.default as unknown as typeof ç__Name__çConfigImport
4
+
5
+ export class ç__Name__ç {
6
+ constructor(config: typeof ç__Name__çConfig) {
7
+
8
+ }
9
+ }
10
+
11
+ export function getç__Name__ç(): ç__Name__ç {
12
+ const p = process as any
13
+
14
+ if (p._plata._libç__Name__ç === undefined) {
15
+ p._plata._libç__Name__ç = new ç__Name__ç(ç__Name__çConfig)
16
+ }
17
+
18
+ return p._plata._libç__Name__ç
19
+ }
@@ -0,0 +1,11 @@
1
+ import { Router } from 'express'
2
+
3
+ export default (): Router => {
4
+ const router = Router()
5
+
6
+ router.get('/', (req, res) => {
7
+ return res.status(200).json({})
8
+ })
9
+
10
+ return router
11
+ }
@@ -0,0 +1,34 @@
1
+ {
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": [
7
+ {
8
+ "name": "DEV",
9
+ "request": "launch",
10
+ "runtimeArgs": [
11
+ "run-script",
12
+ "dev"
13
+ ],
14
+ "runtimeExecutable": "npm",
15
+ "skipFiles": [
16
+ "<node_internals>/**"
17
+ ],
18
+ "type": "node"
19
+ },
20
+ {
21
+ "name": "DEBUG",
22
+ "request": "launch",
23
+ "runtimeArgs": [
24
+ "run-script",
25
+ "start"
26
+ ],
27
+ "runtimeExecutable": "npm",
28
+ "skipFiles": [
29
+ "<node_internals>/**"
30
+ ],
31
+ "type": "node"
32
+ }
33
+ ]
34
+ }
@@ -0,0 +1,13 @@
1
+ FROM node:16-alpine
2
+
3
+ WORKDIR /usr/src/app
4
+
5
+ COPY package*.json ./
6
+
7
+ EXPOSE 3050
8
+
9
+ RUN npm ci --only=production
10
+
11
+ COPY . ./
12
+
13
+ CMD [ "npm", "start" ]
@@ -0,0 +1,28 @@
1
+ export async function install({ dirs, projectPackageJson }) {
2
+ const { tools } = await import('../../../postinstall-tools.mjs')
3
+ const promises = []
4
+
5
+ const t = tools(dirs)
6
+
7
+ promises.push(t.createFolderProject('clusters'))
8
+ promises.push(t.createFolderProject('routes'))
9
+ promises.push(t.createFolderProject('libs'))
10
+
11
+ promises.push(t.copyFolderToProject('configs'))
12
+ promises.push(t.copyFolderToProject('envs'))
13
+ promises.push(t.syncFolderProject('.vscode'))
14
+
15
+ promises.push(t.syncFileToProject('Dockerfile'))
16
+ promises.push(t.syncFileToProject('tsconfig.json'))
17
+
18
+ projectPackageJson.type = "module"
19
+ projectPackageJson.scripts = new Object(null)
20
+ projectPackageJson.scripts.start = "ts-node --transpile-only --esm ./node_modules/.bin/plata"
21
+ projectPackageJson.scripts.create = "ts-node --transpile-only --esm ./node_modules/.bin/plata-cli-create --"
22
+ projectPackageJson.scripts.dev = "npx nodemon -e '.js,.mjs,.json,.ts' --exec 'npm start'"
23
+ projectPackageJson.main = undefined
24
+
25
+ await Promise.all(promises)
26
+
27
+ return projectPackageJson
28
+ }
@@ -0,0 +1,9 @@
1
+ const config: EnvConfig = {
2
+ env: 'debug'
3
+ }
4
+
5
+ interface EnvConfig {
6
+ readonly env: 'prod' | 'debug' | 'homolog' | string
7
+ }
8
+
9
+ export default config
@@ -0,0 +1,8 @@
1
+ # Ambiente:
2
+ ENV=debug
3
+
4
+
5
+
6
+ # Configurações da plata:
7
+ PORT=3050
8
+ _PLATA_API_ROOT=/api
@@ -0,0 +1,9 @@
1
+ # Ambiente:
2
+ ENV=homolog
3
+
4
+
5
+
6
+
7
+ # Configurações da plata:
8
+ PORT=3050
9
+ _PLATA_API_ROOT=/api
@@ -0,0 +1,9 @@
1
+ # Ambiente:
2
+ ENV=prod
3
+
4
+
5
+
6
+
7
+ # Configurações da plata:
8
+ PORT=3050
9
+ _PLATA_API_ROOT=/api
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strictNullChecks": true,
4
+ "module": "es2022",
5
+ "target": "es2022",
6
+ "noImplicitAny": true,
7
+ "declaration": true,
8
+ "sourceMap": true,
9
+ "esModuleInterop": true
10
+ },
11
+ "include": [
12
+ "./node_modules/plata-type/**/*"
13
+ ]
14
+
15
+ }
16
+
@@ -0,0 +1,28 @@
1
+ export async function install({ dirs, projectPackageJson }) {
2
+ const { tools } = await import('../../../postinstall-tools.mjs')
3
+ const promises = []
4
+
5
+ const t = tools(dirs)
6
+
7
+ promises.push(t.createFolderProject('clusters'))
8
+ promises.push(t.createFolderProject('routes'))
9
+ promises.push(t.createFolderProject('libs'))
10
+
11
+ promises.push(t.createFolderProject('configs'))
12
+ promises.push(t.createFolderProject('bin'))
13
+
14
+ promises.push(t.syncFileToProject('postinstall.js'))
15
+ promises.push(t.syncFileToProject('postinstall-tools.mjs'))
16
+ promises.push(t.syncFileToProject('tsconfig.json'))
17
+
18
+ projectPackageJson.type = "module"
19
+ projectPackageJson.scripts = new Object(null)
20
+ projectPackageJson.scripts.dev = "ts-node"
21
+ projectPackageJson.scripts.postinstall = "node postinstall.js"
22
+ projectPackageJson.scripts.create = "ts-node --transpile-only --esm ./node_modules/.bin/plata-cli-create --"
23
+ projectPackageJson.main = undefined
24
+
25
+ await Promise.all(promises)
26
+
27
+ return projectPackageJson
28
+ }
@@ -0,0 +1,112 @@
1
+ import * as fs from 'node:fs'
2
+ import * as path from 'node:path'
3
+
4
+ export function tools(dirs) {
5
+ const tools = new Object(null)
6
+
7
+ tools.mkdirIfNotExists = async (dir) => {
8
+ try {
9
+ const p = path.resolve(dir)
10
+
11
+ if (!fs.existsSync(p)) {
12
+ fs.mkdirSync(p, { resolve: true })
13
+ }
14
+ } catch (err) {
15
+ console.error(err)
16
+ process.exit(1)
17
+ }
18
+ }
19
+
20
+ tools.copyFile = async (source, destination) => {
21
+ try {
22
+ const s = path.resolve(source)
23
+ const d = path.resolve(destination)
24
+
25
+ fs.copyFileSync(s, d)
26
+ } catch (err) {
27
+ console.error(err)
28
+ process.exit(1)
29
+ }
30
+ }
31
+
32
+ tools.copyFileIfNotExists = async (source, destination) => {
33
+ try {
34
+ const s = path.resolve(source)
35
+ const d = path.resolve(destination)
36
+
37
+ if (!fs.existsSync(d) && fs.existsSync(s)) {
38
+ tools.copyFile(s, d)
39
+ }
40
+ } catch (err) {
41
+ console.error(err)
42
+ process.exit(1)
43
+ }
44
+ }
45
+
46
+ tools.forEachFileInFolder = async (folder, callback) => {
47
+ try {
48
+ const f = path.resolve(folder)
49
+ if (!fs.existsSync(f)) {
50
+ return
51
+ }
52
+
53
+ const files = fs.readdirSync(f)
54
+
55
+ const promises = []
56
+
57
+ files.forEach(file => {
58
+ const filePath = path.join(f, file)
59
+
60
+ promises.push(
61
+ (async () => callback(file, filePath))()
62
+ )
63
+ })
64
+
65
+ await Promise.all(promises)
66
+ } catch (err) {
67
+ console.error(err)
68
+ process.exit(1)
69
+ }
70
+ }
71
+
72
+ tools.createFolderProject = (async (folder) =>
73
+ tools.mkdirIfNotExists(path.join(dirs.projectDir, folder))
74
+ )
75
+
76
+ tools.copyFolderToProject = async (folder) => {
77
+ const templateFolder = path.join(dirs.templateDir, folder)
78
+ const destination = path.join(dirs.projectDir, folder)
79
+
80
+ await tools.mkdirIfNotExists(destination)
81
+
82
+ await tools.forEachFileInFolder(templateFolder, async (file, filePath) =>
83
+ tools.copyFileIfNotExists(
84
+ filePath,
85
+ path.join(destination, file)
86
+ )
87
+ )
88
+ }
89
+
90
+ tools.syncFolderProject = async (folder) => {
91
+ const templateFolder = path.join(dirs.templateDir, folder)
92
+ const destination = path.join(dirs.projectDir, folder)
93
+
94
+ await tools.mkdirIfNotExists(destination)
95
+
96
+ await tools.forEachFileInFolder(templateFolder, async (file, filePath) =>
97
+ tools.copyFile(
98
+ filePath,
99
+ path.join(destination, file)
100
+ )
101
+ )
102
+ }
103
+
104
+ tools.syncFileToProject = async (file) => {
105
+ const templateFile = path.join(dirs.templateDir, file)
106
+ const destination = path.join(dirs.projectDir, file)
107
+
108
+ await tools.copyFile(templateFile, destination)
109
+ }
110
+
111
+ return tools
112
+ }
@@ -0,0 +1,29 @@
1
+ import * as fs from 'node:fs'
2
+ import * as path from 'node:path'
3
+ import { tools } from './postinstall-tools.mjs'
4
+
5
+ const main = async() => {
6
+ const plataDir = path.resolve('.')
7
+ const projectDir = path.resolve(plataDir, '..', '..')
8
+ const projectPackageJson = JSON.parse(fs.readFileSync(path.join(projectDir, 'package.json')).toString())
9
+
10
+ if (projectPackageJson.plata_no_setup !== undefined) {
11
+ process.exit(0)
12
+ }
13
+
14
+ const t = tools({
15
+ plataDir,
16
+ projectDir,
17
+ templateDir: plataDir
18
+ })
19
+
20
+ const promises = []
21
+
22
+ promises.push(t.copyFolderToProject('configs'))
23
+ promises.push(t.syncFolderProject('clusters'))
24
+ promises.push(t.syncFolderProject('libs'))
25
+
26
+ await Promise.all(promises)
27
+ }
28
+
29
+ main()
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strictNullChecks": true,
4
+ "module": "es2022",
5
+ "target": "es2022",
6
+ "noImplicitAny": true,
7
+ "declaration": true,
8
+ "sourceMap": true,
9
+ "esModuleInterop": true
10
+ },
11
+ "include": [
12
+ "./node_modules/plata-type/**/*"
13
+ ]
14
+
15
+ }
16
+
package/tsconfig.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "strictNullChecks": true,
4
+ "module": "es2022",
5
+ "target": "es2022",
6
+ "noImplicitAny": true,
7
+ "declaration": true,
8
+ "sourceMap": true,
9
+ "esModuleInterop": true
10
+ },
11
+ "include": [
12
+ "./node_modules/plata-type/**/*"
13
+ ]
14
+
15
+ }
16
+