Initial import

This commit is contained in:
Garrett Mills 2022-04-09 12:17:36 -05:00
commit 4833707736
34 changed files with 3574 additions and 0 deletions

193
.gitignore vendored Normal file
View File

@ -0,0 +1,193 @@
# ---> JetBrains
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
# ---> Node
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
/lib
/exbuild

8
.idea/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

View File

@ -0,0 +1,40 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JSCodeStyleSettings version="0">
<option name="USE_SEMICOLON_AFTER_STATEMENT" value="false" />
<option name="FORCE_SEMICOLON_STYLE" value="true" />
<option name="USE_DOUBLE_QUOTES" value="false" />
<option name="FORCE_QUOTE_STYlE" value="true" />
<option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" />
<option name="OBJECT_LITERAL_WRAP" value="2" />
</JSCodeStyleSettings>
<TypeScriptCodeStyleSettings version="0">
<option name="USE_SEMICOLON_AFTER_STATEMENT" value="false" />
<option name="FORCE_SEMICOLON_STYLE" value="true" />
<option name="USE_DOUBLE_QUOTES" value="false" />
<option name="FORCE_QUOTE_STYlE" value="true" />
<option name="ENFORCE_TRAILING_COMMA" value="WhenMultiline" />
<option name="OBJECT_LITERAL_WRAP" value="2" />
</TypeScriptCodeStyleSettings>
<codeStyleSettings language="JavaScript">
<option name="INDENT_CASE_FROM_SWITCH" value="false" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
<option name="ALIGN_MULTILINE_FOR" value="false" />
<option name="METHOD_CALL_CHAIN_WRAP" value="2" />
<option name="IF_BRACE_FORCE" value="3" />
<option name="DOWHILE_BRACE_FORCE" value="3" />
<option name="WHILE_BRACE_FORCE" value="3" />
<option name="FOR_BRACE_FORCE" value="3" />
</codeStyleSettings>
<codeStyleSettings language="TypeScript">
<option name="INDENT_CASE_FROM_SWITCH" value="false" />
<option name="ALIGN_MULTILINE_PARAMETERS" value="false" />
<option name="ALIGN_MULTILINE_FOR" value="false" />
<option name="METHOD_CALL_CHAIN_WRAP" value="2" />
<option name="IF_BRACE_FORCE" value="3" />
<option name="DOWHILE_BRACE_FORCE" value="3" />
<option name="WHILE_BRACE_FORCE" value="3" />
<option name="FOR_BRACE_FORCE" value="3" />
</codeStyleSettings>
</code_scheme>
</component>

View File

@ -0,0 +1,5 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

10
.idea/extollo.iml Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="di" />
<orderEntry type="module" module-name="lib" />
</component>
</module>

10
.idea/modules.xml Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/../di/.idea/di.iml" filepath="$PROJECT_DIR$/../di/.idea/di.iml" />
<module fileurl="file://$PROJECT_DIR$/.idea/extollo.iml" filepath="$PROJECT_DIR$/.idea/extollo.iml" />
<module fileurl="file://$PROJECT_DIR$/../extollo_lib/.idea/lib.iml" filepath="$PROJECT_DIR$/../extollo_lib/.idea/lib.iml" />
</modules>
</component>
</project>

7
.idea/vcs.xml Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/../extollo_lib" vcs="Git" />
</component>
</project>

0
CONTRIBUTING.md Normal file
View File

19
LICENSE Normal file
View File

@ -0,0 +1,19 @@
Copyright © 2021 Garrett Mills
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the “Software”),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

31
README.md Normal file
View File

@ -0,0 +1,31 @@
<center>
<br>
<img alt="The Extollo logo" src="https://static.garrettmills.dev/sites/extollo/docs/assets/logo/svg/Extollo-Icon-and-Text-LIGHT-Final.svg" height="150">
<br><br>
<b>extollo</b> - (v. <em>latin</em>) - to lift up, to elevate
<br><br>
Extollo is a <a href="https://www.gnu.org/philosophy/floss-and-foss.en.html" target="_blank">free & libre</a> application framework in TypeScript.
</center>
<hr>
Built on principles of modularity, strict-typing, inversion-of-control, and developer ergonomics, Extollo enables developers to build maintainable, scalable, and expressive applications.
Node.js provides an excellent platform for quickly getting an application up and running, but this loose minimalism can lead to larger, more unweildy code-bases as your application grows. Extollo fixes this by providing an opinionated, robust framework and first-party modules that provide, among other things:
- Type-based dependency injection
- Strongly-typed ORM with an expressive query-builder and models
- Customizable session & caching interfaces
- Modular, pre-compiled, nest-able routes
- First-party, extensible command line tools
- Unit-based application structure
## Getting Started
Writing an application with Extollo is very straightforward if you are familiar with Node.js/TypeScript, or similar frameworks like Laravel.
Check out the [Getting Started](https://extollo.garrettmills.dev/pages/Documentation/Getting-Started.html) page on the documentation site for more information.
## License & Philosophy
The Extollo project is, and will always be, free & libre software. The framework itself is open-source available [here](https://code.garrettmills.dev/Extollo), and is licensed under the terms of the MIT license. See the LICENSE file for more information.
## Contributing
Have an improvement or fix to Extollo? Contributors are always welcome. See the CONTRIBUTING.md file for next steps.

140
ex Executable file
View File

@ -0,0 +1,140 @@
#!/bin/bash -e
ENV_NODE="$(which node)"
ENV_PNPM="$(which pnpm)"
LOGO=" _
/ /\ ______ _ _ _
/ / \ | ____| | | | | |
/ / /\ \ | |__ __ _| |_ ___ | | | ___
/ / /\ \ \ | __| \ \/ / __/ _ \| | |/ _ \\
/ / / \ \_\ | |____ > <| || (_) | | | (_) |
\/_/ \/_/ |______/_/\_\\\__\___/|_|_|\___/
"
# Author: Tasos Latsas
# spinner.sh
#
# Display an awesome 'spinner' while running your long shell commands
#
# Do *NOT* call _spinner function directly.
# Use {start,stop}_spinner wrapper functions
# usage:
# 1. source this script in your's
# 2. start the spinner:
# start_spinner [display-message-here]
# 3. run your command
# 4. stop the spinner:
# stop_spinner [your command's exit status]
#
# Also see: test.sh
function _spinner() {
# $1 start/stop
#
# on start: $2 display message
# on stop : $2 process exit status
# $3 spinner function pid (supplied from stop_spinner)
local on_success="DONE"
local on_fail="FAIL"
local white="\e[1;37m"
local green="\e[1;32m"
local red="\e[1;31m"
local nc="\e[0m"
case $1 in
start)
# calculate the column where spinner and status msg will be displayed
let column=$(tput cols)-${#2}-8
# display message and position the cursor in $column column
echo -ne ${2}
printf "%${column}s"
# start spinner
i=1
sp='\|/-'
delay=${SPINNER_DELAY:-0.15}
while :
do
printf "\b${sp:i++%${#sp}:1}"
sleep $delay
done
;;
stop)
if [[ -z ${3} ]]; then
echo "spinner is not running.."
exit 1
fi
kill $3 > /dev/null 2>&1
# inform the user uppon success or failure
echo -en "\b["
if [[ $2 -eq 0 ]]; then
echo -en "${green}${on_success}${nc}"
else
echo -en "${red}${on_fail}${nc}"
fi
echo -e "]"
;;
*)
echo "invalid argument, try {start/stop}"
exit 1
;;
esac
}
function start_spinner {
# $1 : msg to display
_spinner "start" "${1}" &
# set global spinner pid
_sp_pid=$!
disown
}
function stop_spinner {
# $1 : command exit status
_spinner "stop" $1 $_sp_pid
unset _sp_pid
}
function echoRun() {
echo ""
echo "+ $@"
echo ""
"$@"
echo ""
}
if [ ! -d "./node_modules" ]; then
echo "$LOGO"
echo "+----------------------------------------+"
echo "| Docs: https://extollo.garrettmills.dev |"
echo "+----------------------------------------+"
echo ""
echo "Welcome to Extollo! Let's set things up for the first time..."
if [ ! -x "$ENV_PNPM" ]; then
echo "Please install PNPM to use Extollo."
fi
echoRun "$ENV_PNPM" i
if [ ! -f "./.env" ]; then
echoRun cp example.env .env
fi
echo ""
echo ""
printf "\033[32m✓\033[39m Looks like you're all set up! Run this command again to access the Extollo CLI.\n"
else
start_spinner "Building your app..."
"$ENV_PNPM" run build > /dev/null
stop_spinner 0
"$ENV_NODE" --experimental-repl-await ./lib/cli.js $@
fi

4
example.env Normal file
View File

@ -0,0 +1,4 @@
DEBUG_MODE=true
EXTOLLO_LOGGING_LEVEL=6
DATABASE_PASSWORD=extollo
DATABASE_HOST=db01.platform.local

51
package.json Normal file
View File

@ -0,0 +1,51 @@
{
"name": "@extollo/extollo",
"version": "0.1.0",
"description": "The framework lifts up your code.",
"main": "lib/index.js",
"types": "lib/index.d.ts",
"directories": {
"lib": "lib"
},
"dependencies": {
"@extollo/lib": "^0.9.0",
"copyfiles": "^2.4.1",
"rimraf": "^3.0.2",
"ts-expose-internals": "^4.5.4",
"ts-patch": "^2.0.1",
"ts-to-zod": "^1.8.0",
"typescript": "^4.3.2",
"zod": "^3.11.6"
},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "excc -c package.json -t tsconfig.json",
"app": "pnpm run build && node lib/index.js",
"cli": "pnpm run build && node lib/cli.js"
},
"files": [
"lib/**/*"
],
"prepare": "npm run build",
"postversion": "git push && git push --tags",
"repository": {
"type": "git",
"url": "https://code.garrettmills.dev/extollo/extollo"
},
"author": "garrettmills <shout@garrettmills.dev>",
"license": "MIT",
"extollo": {
"cc": {
"zodify": [
"src/app/types"
],
"non-source": [
".env",
"src/app/resources"
]
}
},
"devDependencies": {
"@extollo/cc": "^0.6.0"
}
}

2686
pnpm-lock.yaml Normal file

File diff suppressed because it is too large Load Diff

46
src/Units.extollo.ts Normal file
View File

@ -0,0 +1,46 @@
import {
Config,
Controllers,
HTTPServer,
Files,
Middlewares,
Routing,
Unit,
Database,
Models,
CommandLine,
Internationalization,
Authentication,
Discovery,
ValidationUnit,
Migrations,
Queueables,
Redis,
Bus,
} from '@extollo/lib'
import {AppUnit} from './app/AppUnit'
Error.stackTraceLimit = 500
export const Units = [
Config,
Redis,
Queueables,
Bus,
ValidationUnit,
Files,
CommandLine,
Controllers,
Middlewares,
Database,
Models,
Migrations,
Internationalization,
Authentication,
AppUnit,
Routing,
Discovery,
HTTPServer,
] as (typeof Unit)[]

9
src/app/AppUnit.ts Normal file
View File

@ -0,0 +1,9 @@
import {ORMUser, Singleton, Unit} from '@extollo/lib'
import {User} from './models/User.model'
@Singleton()
export class AppUnit extends Unit {
async up(): Promise<void> {
this.container().registerStaticOverride(ORMUser, User)
}
}

View File

@ -0,0 +1,5 @@
import { env } from '@extollo/lib'
export default {
name: env('APP_NAME', 'Extollo'),
}

View File

@ -0,0 +1,21 @@
import {AuthenticationConfig, CoreIDLoginProvider, OAuth2LoginProviderConfig, ORMUserRepository, env} from '@extollo/lib'
const authConfig: AuthenticationConfig = {
storage: ORMUserRepository,
providers: {
coreid: {
driver: CoreIDLoginProvider,
config: {
default: true,
displayName: 'Starship CoreID',
clientId: env('COREID_CLIENT_ID'),
clientSecret: env('COREID_CLIENT_SECRET'),
loginUrl: env('COREID_BASE', '') + '/auth/service/oauth2/authorize?client_id=%c&redirect_uri=%r',
tokenUrl: env('COREID_BASE', '') + '/auth/service/oauth2/redeem',
userUrl: env('COREID_BASE', '') + '/api/v1/auth/users/me',
} as OAuth2LoginProviderConfig,
}
},
}
export default authConfig

View File

@ -0,0 +1,14 @@
import { env } from "@extollo/lib";
export default {
connections: {
default: {
user: env('DATABASE_USERNAME', 'extollo'),
password: env('DATABASE_PASSWORD'),
host: env('DATABASE_HOST', 'localhost'),
port: env('DATABASE_PORT', 5432),
database: env('DATABASE_NAME', 'extollo'),
dialect: env('DATABASE_DIALECT', 'postgres'),
},
},
}

View File

@ -0,0 +1,5 @@
import { env } from "@extollo/lib"
export default {
app_name: env('APP_NAME', 'Extollo'),
}

View File

@ -0,0 +1,6 @@
import {env} from '@extollo/lib'
export default {
welcome_to_extollo: 'Welcome to Extollo!',
viewed_page_num_times: 'You have viewed this page :num: times.',
}

View File

@ -0,0 +1,24 @@
import {OAuth2Client, OAuth2Scope, env, /*uuid4*/} from '@extollo/lib'
export default {
secret: env('OAUTH2_SECRET'),
scopes: {
'user-info': {
id: 'user-info',
name: 'user-info',
description: 'access basic information about your account',
},
} as {[key: string]: OAuth2Scope},
clients: {
// 'test-1': {
// id: 'test-1',
// display: 'Test 1',
// secret: env('TEST_CLIENT_SECRET', uuid4()),
// allowedFlows: ['code'],
// allowedScopeIds: ['user-info'],
// allowedRedirectUris: [
// 'http://localhost:1234/callback',
// ],
// },
} as {[key: string]: OAuth2Client},
}

View File

@ -0,0 +1,66 @@
import {
env,
basePath,
ORMSession,
LocalFilesystem,
LocalFilesystemConfig,
RedisCache,
CacheQueue,
BusConnectorConfig, QueueConfig, SyncQueue
} from "@extollo/lib"
import {LogRequest} from "../http/middlewares/LogRequest.middleware";
export default {
debug: env('DEBUG_MODE', false),
session: {
/* The implementation of @extollo/lib.Session that serves as the session backend. */
driver: ORMSession,
},
bus: {
connectors: [
{type: 'redis'},
] as BusConnectorConfig[],
},
queue: {
driver: CacheQueue,
} as QueueConfig,
cache: {
driver: RedisCache,
},
/*
* Here, you can define various filesystem drivers that can be used in
* your application to store/retrieve files.
*
* The key in the object is the 'name' of the filesystem as it will be
* fetched in code. For example, if you have a `fubar: { ... }` item,
* then you can retrieve that filesystem using the Files service like
* so:
*
* files.getFilesystem('fubar') // => Filesystem { ... }
*/
filesystems: {
default: {
/* If true, this will serve as the default filesystem for modules in your application. */
isDefault: true,
/* The implementation of @extollo/lib.Filesystem that serves as the backend. */
driver: LocalFilesystem,
/* The config required by the filesystem driver. */
config: {
baseDir: basePath('..', 'uploads').toLocal,
} as LocalFilesystemConfig,
}
},
middleware: {
global: {
pre: [LogRequest],
},
},
}

View File

@ -0,0 +1,26 @@
import {Controller, view, Session, Inject, Injectable, Locale, Validator} from '@extollo/lib'
import {UserLogin} from "../../../types/UserLogin";
@Injectable()
export class Home extends Controller {
@Inject()
protected readonly session!: Session;
@Inject()
protected readonly locale!: Locale;
public welcome() {
this.session.set('app_visits', this.session.get('app_visits', 0) + 1)
const valid = new Promise<UserLogin>(() => {})
return view('@extollo:welcome', {
app_visits: this.session.get('app_visits'),
locale: this.locale.helper(),
})
}
public test() {
return new Validator<UserLogin>()
}
}

View File

@ -0,0 +1,11 @@
import {Inject, Injectable, Logging, Middleware} from '@extollo/lib'
@Injectable()
export class LogRequest extends Middleware {
@Inject()
protected readonly logging!: Logging
public async apply() {
this.logging.info(`Incoming request: ${this.request.method} @ ${this.request.path}`)
}
}

View File

@ -0,0 +1,13 @@
import {Route, SessionAuthMiddleware, AuthRequiredMiddleware} from '@extollo/lib'
import {Home} from '../controllers/main/Home.controller'
Route.group('/', () => {
Route.get('/')
.calls<Home>(Home, home => home.welcome)
})
Route.group('', () => {
Route.get('/dash')
.pre(AuthRequiredMiddleware)
.calls<Home>(Home, home => home.welcome)
}).pre(SessionAuthMiddleware)

View File

@ -0,0 +1,15 @@
import {Inject, Injectable, Logging, BaseJob} from '@extollo/lib'
@Injectable()
export default class LogMessage extends BaseJob {
@Inject()
protected readonly logging!: Logging
async execute(): Promise<void> {
this.logging.info('Executing LogMessage...')
await new Promise<void>(res => {
setTimeout(() => res(), 3000)
})
this.logging.success('The LogMessage job has executed!')
}
}

View File

@ -0,0 +1,5 @@
import {ORMUser} from '@extollo/lib'
export class User extends ORMUser {
}

View File

@ -0,0 +1,6 @@
html
head
title !{locale('app_name')}
body
h1 !{locale('welcome_to_extollo')}
h2 !{locale('viewed_page_num_times', { interp: { num: app_visits } })}

View File

@ -0,0 +1,14 @@
export interface UserLogin {
/**
* @minLength 1
* @maxLength 100
*/
username: string,
/**
* @minLength 1
* @maxLength 100
*/
password: string,
}

43
src/bootstrap.ts Normal file
View File

@ -0,0 +1,43 @@
import {Application, CommandLineApplication} from '@extollo/lib'
import {Units} from './Units.extollo'
/*
* Helper functions to bootstrap the Application instance for different uses.
*/
/**
* Get the base application with no final-target unit.
*/
export function base(): Application {
const app = Application.getApplication()
app.scaffold(__dirname, Units.slice(0, -1))
return app
}
/**
* Get the application with the final unit replaced with the CommandLineApplication
* for use on the CLI.
*/
export function cli(): Application {
const app = Application.getApplication()
app.forceStartupMessage = false
const units = [...Units]
units.reverse()
CommandLineApplication.setReplacement(units[0])
units[0] = CommandLineApplication
units.reverse()
app.scaffold(__dirname, units)
return app
}
/**
* Get the application as it should be run normally.
*/
export function app(): Application {
const app = Application.getApplication()
app.scaffold(__dirname, Units)
return app
}

15
src/cli.ts Normal file
View File

@ -0,0 +1,15 @@
#!/usr/bin/env -S node --experimental-repl-await
import {globalRegistry} from '@extollo/lib'
import {cli} from './bootstrap'
globalRegistry.run(async () => {
/*
* The Application
* -----------------------------------------------------
* The application instance is a global inversion of control container that
* ties your entire application together. The app container manages services
* and lifecycle.
*/
const app = cli()
await app.run()
})

13
src/index.ts Normal file
View File

@ -0,0 +1,13 @@
import {globalRegistry} from '@extollo/lib'
import {app} from './bootstrap'
globalRegistry.run(async () => {
/*
* The Application
* -----------------------------------------------------
* The application instance is a global inversion of control container that
* ties your entire application together. The app container manages services
* and lifecycle.
*/
await app().run()
})

13
tsconfig.json Normal file
View File

@ -0,0 +1,13 @@
{
"compilerOptions": {
"target": "es6",
"module": "commonjs",
"declaration": true,
"outDir": "./lib",
"strict": true,
"experimentalDecorators": true,
"emitDecoratorMetadata": true
},
"include": ["src"],
"exclude": ["node_modules"]
}