├── ASPTypeScriptSample
├── src
│ ├── views
│ │ ├── home
│ │ │ └── index.html
│ │ ├── shared
│ │ │ ├── validation-error.html
│ │ │ └── layout.html
│ │ └── student
│ │ │ ├── filter.html
│ │ │ ├── details.html
│ │ │ ├── index.html
│ │ │ ├── create.html
│ │ │ └── edit.html
│ ├── helpers
│ │ ├── helpers.d.ts
│ │ ├── session.d.ts
│ │ ├── handlebars-helpers.ts
│ │ ├── vb-functions.asp
│ │ ├── view.ts
│ │ └── server-error.ts
│ ├── db
│ │ └── create.sql
│ ├── domain
│ │ ├── student.ts
│ │ └── validator.ts
│ ├── controllers
│ │ ├── home-controller.ts
│ │ ├── results.ts
│ │ ├── base-controller.ts
│ │ └── student-controller.ts
│ ├── repositories
│ │ ├── base-repository.ts
│ │ └── student-repository.ts
│ ├── errors
│ │ └── http-error.ts
│ ├── index.ts
│ └── routers
│ │ └── router.ts
├── assets
│ ├── css
│ │ └── site.css
│ └── js
│ │ └── student
│ │ └── edit.js
├── Global.asa
├── 500.asp
├── tsconfig.json
├── packages.config
├── Web.config
├── Web.Debug.config
├── Web.Release.config
├── Default.asp
├── lib
│ ├── polyfills.js
│ └── json2.js
├── types
│ ├── adodb
│ │ ├── index.d.ts
│ │ └── constants.d.ts
│ └── asp
│ │ └── index.d.ts
└── ASPTypeScriptSample.csproj
├── ASPTypeScriptSample.sln
├── .gitattributes
├── .gitignore
└── README.md
/ASPTypeScriptSample/src/views/home/index.html:
--------------------------------------------------------------------------------
1 |
{{ message }}
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/helpers/helpers.d.ts:
--------------------------------------------------------------------------------
1 | declare function ToVBDate(jsDate: Date): any;
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/helpers/session.d.ts:
--------------------------------------------------------------------------------
1 | declare function setSession(key: string, val: any): void;
--------------------------------------------------------------------------------
/ASPTypeScriptSample/assets/css/site.css:
--------------------------------------------------------------------------------
1 | html {
2 | font-size: 14px;
3 | }
4 |
5 | .form-control {
6 | max-width: 280px;
7 | }
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/db/create.sql:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bysanches/ASPTypeScriptSample/HEAD/ASPTypeScriptSample/src/db/create.sql
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/domain/student.ts:
--------------------------------------------------------------------------------
1 | interface Student {
2 | id: string;
3 | name: string;
4 | document: string;
5 | birthdate: Date;
6 | }
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/helpers/handlebars-helpers.ts:
--------------------------------------------------------------------------------
1 | Handlebars.registerHelper('formatDate', d => {
2 | if (d != null && moment(d).isValid()) {
3 | return moment(d).format('DD/MM/YYYY');
4 | }
5 | return d;
6 | });
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/helpers/vb-functions.asp:
--------------------------------------------------------------------------------
1 | <%
2 | Function SetSession(ByVal key, ByVal val)
3 | Session(key) = val
4 | End Function
5 |
6 | Function ToVBDate(ByVal jsDate)
7 | ToVBDate = DateAdd("s", jsDate.getTime() / 1000, #1970-1-1#)
8 | End Function
9 | %>
--------------------------------------------------------------------------------
/ASPTypeScriptSample/Global.asa:
--------------------------------------------------------------------------------
1 |
7 |
8 |
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/views/shared/validation-error.html:
--------------------------------------------------------------------------------
1 | Erro de validação
2 |
3 | {{#each this}}
4 | - {{0}}: {{1}}
5 | {{/each}}
6 |
7 |
8 | Por favor, volte e verifique os valores informados.
9 |
10 | Voltar
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/views/student/filter.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/ASPTypeScriptSample/500.asp:
--------------------------------------------------------------------------------
1 | <%@ language="VBScript" codepage="65001" %>
2 |
3 |
4 |
5 |
6 | ERROR
7 |
8 |
9 |
10 | <%= getErrorMessage() %>
11 |
12 |
13 |
--------------------------------------------------------------------------------
/ASPTypeScriptSample/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "noImplicitAny": false,
4 | "noEmitOnError": true,
5 | "removeComments": true,
6 | "sourceMap": true,
7 | "target": "es3",
8 | "lib": [ "es5", "scripthost" ],
9 | "module": "none"
10 | },
11 | "exclude": [
12 | "node_modules",
13 | "wwwroot"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/controllers/home-controller.ts:
--------------------------------------------------------------------------------
1 | namespace ASPTypeScriptSample.Controllers {
2 | export class HomeController extends BaseController {
3 | index() {
4 | let model = { message: 'Classic ASP + TypeScript Sample Web App' };
5 | return this.view('/src/views/home/index.html', model);
6 | }
7 |
8 | about() {
9 | throw new Error('not implemented');
10 | }
11 | }
12 | }
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/controllers/results.ts:
--------------------------------------------------------------------------------
1 | namespace ASPTypeScriptSample.Controllers {
2 | export class HtmlResult {
3 | constructor(public content: string) { }
4 |
5 | toString() {
6 | return this.content;
7 | }
8 | }
9 |
10 | export class HttpErrorResult {
11 | constructor(public error: HttpError) { }
12 |
13 | toString() {
14 | return `${this.error.name}: ${this.error.message}`;
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/ASPTypeScriptSample/packages.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/views/student/details.html:
--------------------------------------------------------------------------------
1 | Student {{ name }}
2 |
3 |
4 |
5 | | Name |
6 | {{ name }} |
7 |
8 |
9 |
10 | | Document |
11 | {{ document }} |
12 |
13 |
14 |
15 | | Birth Date |
16 | {{ formatDate birthdate }} |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/ASPTypeScriptSample/Web.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
--------------------------------------------------------------------------------
/ASPTypeScriptSample/assets/js/student/edit.js:
--------------------------------------------------------------------------------
1 | jQuery(function ($) {
2 | $('#studentForm').validate({
3 | errorClass: 'has-danger',
4 | validClass: 'has-success',
5 | highlight: function (element, errorClass, validClass) {
6 | $(element).closest('.form-group').removeClass(validClass).addClass(errorClass);
7 | },
8 | unhighlight: function (element, errorClass, validClass) {
9 | $(element).closest('.form-group').addClass(validClass).removeClass(errorClass);
10 | },
11 | errorPlacement: function (error, element) {
12 | error.addClass('form-control-feedback');
13 | element.closest('.form-group').append(error);
14 | }
15 | });
16 | });
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/repositories/base-repository.ts:
--------------------------------------------------------------------------------
1 | namespace ASPTypeScriptSample.Repositories {
2 | const connectionString = Application('connectionString') as string;
3 |
4 | export interface Closable {
5 | Close();
6 | State: number;
7 | }
8 |
9 | export function using(closable: T, expr: (closable: T) => any) {
10 | try {
11 | return expr.call(this, closable);
12 | } finally {
13 | if (closable.State === adStateOpen) closable.Close();
14 | }
15 | }
16 |
17 | export class BaseRepository {
18 | protected openConnection(): ADODB.Connection {
19 | let conn = new ActiveXObject('ADODB.Connection') as ADODB.Connection;
20 | conn.Open(connectionString);
21 | return conn;
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/views/student/index.html:
--------------------------------------------------------------------------------
1 | Students
2 |
3 | {{>filter term}}
4 |
5 |
6 |
7 |
8 | | Name |
9 | Document |
10 | Birth Date |
11 |
12 |
13 |
14 |
15 | {{#each items}}
16 |
17 | |
18 | {{ name }}
19 | |
20 | {{ document }} |
21 | {{ formatDate birthdate }} |
22 |
23 | {{/each}}
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/errors/http-error.ts:
--------------------------------------------------------------------------------
1 | class HttpError implements Error {
2 | name: string;
3 |
4 | constructor(public code: number, public message: string) {
5 | this.name = 'HttpError';
6 | this.message = this.code + ' ' + this.message;
7 | }
8 |
9 | toString() {
10 | return `${this.name}: ${this.message}`;
11 | }
12 | }
13 |
14 | class NotFoundError extends HttpError {
15 | constructor() {
16 | super(404, 'Not Found');
17 | this.name = 'NotFoundError';
18 | }
19 | }
20 |
21 | class MethodNotAllowedError extends HttpError {
22 | constructor() {
23 | super(405, 'Method Not Allowed');
24 | this.name = 'MethodNotAllowedError';
25 | }
26 | }
27 |
28 | class BadRequestError extends HttpError {
29 | constructor() {
30 | super(400, 'Bad Request');
31 | this.name = 'BadRequestError';
32 | }
33 | }
--------------------------------------------------------------------------------
/ASPTypeScriptSample.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 14
4 | VisualStudioVersion = 14.0.25420.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ASPTypeScriptSample", "ASPTypeScriptSample\ASPTypeScriptSample.csproj", "{EEF92A02-1E4B-404F-AD47-A991A1AD171D}"
7 | EndProject
8 | Global
9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 | Debug|Any CPU = Debug|Any CPU
11 | Release|Any CPU = Release|Any CPU
12 | EndGlobalSection
13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
14 | {EEF92A02-1E4B-404F-AD47-A991A1AD171D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
15 | {EEF92A02-1E4B-404F-AD47-A991A1AD171D}.Debug|Any CPU.Build.0 = Debug|Any CPU
16 | {EEF92A02-1E4B-404F-AD47-A991A1AD171D}.Release|Any CPU.ActiveCfg = Release|Any CPU
17 | {EEF92A02-1E4B-404F-AD47-A991A1AD171D}.Release|Any CPU.Build.0 = Release|Any CPU
18 | EndGlobalSection
19 | GlobalSection(SolutionProperties) = preSolution
20 | HideSolutionNode = FALSE
21 | EndGlobalSection
22 | EndGlobal
23 |
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/views/shared/layout.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | {{ title }}
5 |
6 |
7 |
8 |
9 |
10 |
19 |
20 |
21 |
22 | {{{ body }}}
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | {{{ scripts }}}
31 |
32 |
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/views/student/create.html:
--------------------------------------------------------------------------------
1 | New student
2 |
3 |
--------------------------------------------------------------------------------
/ASPTypeScriptSample/Web.Debug.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
29 |
30 |
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/index.ts:
--------------------------------------------------------------------------------
1 | function executeHtmlResult(result: ASPTypeScriptSample.Controllers.HtmlResult): string {
2 | let view = ASPTypeScriptSample.View;
3 |
4 | Handlebars.registerHelper('active', controller =>
5 | view.activeNavItem(controller));
6 |
7 | Handlebars.registerHelper('navItem', (label: string, controller: string, action: string) =>
8 | new Handlebars.SafeString(view.navItem(label, controller, action)));
9 |
10 | let template = view.getTemplate('/src/views/shared/layout.html');
11 |
12 | return template({
13 | title: view.getTitle(),
14 | body: result.content,
15 | scripts: view.renderScripts()
16 | });
17 | }
18 |
19 | function main() {
20 | let router = new ASPTypeScriptSample.Routers.QueryStringRouter();
21 | let actionDelegate = router.route();
22 | let result = actionDelegate();
23 |
24 | switch (result.constructor) {
25 | case ASPTypeScriptSample.Controllers.HtmlResult:
26 | Response.Write(executeHtmlResult(result));
27 | break;
28 | case ASPTypeScriptSample.Controllers.HttpErrorResult:
29 | Response.Status = result.error.code;
30 | Response.Write(executeHtmlResult(
31 | new ASPTypeScriptSample.Controllers.HtmlResult(result.toString())));
32 | break;
33 | default:
34 | Response.Write(result);
35 | }
36 | }
--------------------------------------------------------------------------------
/ASPTypeScriptSample/Web.Release.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
17 |
18 |
19 |
30 |
31 |
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/views/student/edit.html:
--------------------------------------------------------------------------------
1 | Edit student {{ name }}
2 |
3 |
--------------------------------------------------------------------------------
/ASPTypeScriptSample/Default.asp:
--------------------------------------------------------------------------------
1 | <%@ language="VBScript" codepage="65001" %>
2 | <% Response.ContentType = "text/html; charset=utf-8" %>
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 | <% main %>
25 |
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/helpers/view.ts:
--------------------------------------------------------------------------------
1 | namespace ASPTypeScriptSample.View {
2 | var scripts = [];
3 |
4 | export function registerScript(src: string) {
5 | scripts.push(src);
6 | }
7 |
8 | export function renderScripts() {
9 | return scripts.map(src => ``).join();
10 | }
11 |
12 | export function getTemplate(path: string) {
13 | var stream = new ActiveXObject('ADODB.Stream') as ADODB.Stream;
14 | stream.Type = adTypeText;
15 | stream.CharSet = 'utf-8';
16 | stream.Open();
17 | stream.LoadFromFile(Server.MapPath(path));
18 | var result = stream.ReadText();
19 | stream.Close();
20 |
21 | return Handlebars.compile(result);
22 | }
23 |
24 | export function activeNavItem(controller: string, action: string = 'index') {
25 | let c = Request.QueryString('c')() || 'home';
26 | let a = Request.QueryString('a')() || 'index';
27 |
28 | if (controller === c && action === a)
29 | return 'active';
30 | }
31 |
32 | export function navItem(label: string, controller: string = 'home', action: string = 'index') {
33 | let active = activeNavItem(controller, action);
34 |
35 | return `
36 | ${label}
37 | `;
38 | }
39 |
40 | let title: string;
41 |
42 | export function setTitle(t: string) {
43 | title = t;
44 | }
45 |
46 | export function getTitle() {
47 | return (title && title + ' - ' || '') + 'Classic ASP + TypeScript';
48 | }
49 | }
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/routers/router.ts:
--------------------------------------------------------------------------------
1 | namespace ASPTypeScriptSample.Routers {
2 | function isNullOrWhitespace(str: string) {
3 | return str == null || /^\s*$/.test(str);
4 | }
5 |
6 | function dashedToPascalCase(dashed: string): string {
7 | if (dashed != null) {
8 | return dashed.replace(/^([a-z])|-([a-z])/g,
9 | match => match.toUpperCase()).replace('-', '');
10 | }
11 | }
12 |
13 | export interface Router {
14 | route(): () => any;
15 | }
16 |
17 | export class QueryStringRouter implements Router {
18 | private controllerName: string;
19 | private actionName: string;
20 |
21 | constructor(defaultCtrl?: string, defaultAction?: string) {
22 | this.controllerName = Request.QueryString('c')();
23 | this.actionName = Request.QueryString('a')();
24 |
25 | if (isNullOrWhitespace(this.controllerName)) this.controllerName = defaultCtrl || 'home';
26 | if (isNullOrWhitespace(this.actionName)) this.actionName = defaultAction || 'index';
27 | }
28 |
29 | private getControllerClassName(controller: string): string {
30 | return dashedToPascalCase(controller) + 'Controller';
31 | }
32 |
33 | private invalidRoute() {
34 | throw new Error('Path not found:' +
35 | ` c = ${this.controllerName},` +
36 | ` a = ${this.actionName}`);
37 | }
38 |
39 | route() {
40 | let controllers = ASPTypeScriptSample.Controllers;
41 | let ctrlClassName = this.getControllerClassName(this.controllerName);
42 |
43 | let ctrlClass = controllers[ctrlClassName];
44 | let actionMethod = ctrlClass && ctrlClass.prototype[this.actionName];
45 |
46 | if (ctrlClass != null && actionMethod != null) {
47 | return () => actionMethod.call(new ctrlClass());
48 | } else {
49 | this.invalidRoute();
50 | }
51 | }
52 | }
53 | }
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/helpers/server-error.ts:
--------------------------------------------------------------------------------
1 | function getErrorMessage() {
2 | let e = Server.GetLastError();
3 | let result = `ERROR ${new Date().toString()}\n`;
4 |
5 | if (e.ASPCode())
6 | result += `ASPCode: ${e.ASPCode()}\n`;
7 |
8 | if (e.ASPDescription())
9 | result += `ASPDescription: ${e.ASPDescription()}\n`;
10 |
11 | if (e.Number())
12 | result += `Number: ${e.Number().toString(16)}\n`;
13 |
14 | if (e.Source())
15 | result += `Source: ${e.Source()}\n`;
16 |
17 | if (e.Category())
18 | result += `Category: ${e.Category()}\n`;
19 |
20 | if (e.Description())
21 | result += `Description: ${e.Description()}\n`;
22 |
23 | if (e.File())
24 | result += `File: ${e.File()}\n`;
25 |
26 | if (e.Line())
27 | result += `Line: ${e.Line()}\n`;
28 |
29 | if (e.Column())
30 | result += `Column: ${e.Column()}\n`;
31 |
32 | result += '\nAPPLICATION\n' + getSummary(Application.Contents);
33 | result += '\nSESSION\n' + getSummary(Session.Contents);
34 | result += '\nQUERYSTRING\n' + getSummary(Request.QueryString);
35 | result += '\nFORM\n' + getSummary(Request.Form);
36 | result += '\nCOOKIES\n' + getSummary(Request.Cookies);
37 | result += '\nSERVER VARIABLES\n' + getServerVariablesSummary();
38 |
39 | return result;
40 | }
41 |
42 | function getSummary(dic: ASP.IVariantDictionary | ASP.IRequestDictionary) {
43 | let result = '';
44 | for (let i = 1; i <= dic.Count(); i++) {
45 | let key = dic.Key(i);
46 | let val = dic.Item(key);
47 |
48 | result += `${key}: ${val}\n`;
49 | }
50 | return result;
51 | }
52 |
53 | function getServerVariablesSummary() {
54 | let result = `URL: ${Request.ServerVariables('URL')()}\n`;
55 |
56 | let referer = Request.ServerVariables('HTTP_REFERER')();
57 | if (referer)
58 | result += `HTTP_REFERER: ${referer}\n`;
59 |
60 | let userAgent = Request.ServerVariables('HTTP_USER_AGENT')();
61 | if (userAgent)
62 | result += `HTTP_USER_AGENT: ${userAgent}`;
63 |
64 | return result;
65 | }
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/controllers/base-controller.ts:
--------------------------------------------------------------------------------
1 | namespace ASPTypeScriptSample.Controllers {
2 | export class BaseController {
3 | /**
4 | * Validates the current request to accept POST method only.
5 | */
6 | protected postOnly() {
7 | let method = Request.ServerVariables('REQUEST_METHOD')();
8 | if (method !== 'POST') {
9 | return this.methodNotAllowed();
10 | }
11 | }
12 |
13 | protected methodNotAllowed() {
14 | //Response.Clear();
15 | //Response.Status = '405 Method Not Allowed';
16 | //Response.End();
17 | return new HttpErrorResult(new MethodNotAllowedError());
18 | }
19 |
20 | protected badRequest() {
21 | //Response.Clear();
22 | //Response.Status = '400 Bad Request';
23 | //Response.End();
24 | return new HttpErrorResult(new BadRequestError());
25 | }
26 |
27 | protected notFound() {
28 | //Response.Clear();
29 | //Response.Status = '404 Not Found';
30 | //Response.End();
31 | return new HttpErrorResult(new NotFoundError());
32 | }
33 |
34 | protected redirectTo(ctrl: string, action: string = 'index', params?: object) {
35 | let url = `?c=${ctrl}&a=${action}`;
36 | let qs = '';
37 | if (params != null) {
38 | for (let key in params) {
39 | if (params.hasOwnProperty(key)) {
40 | if (qs.length > 0) qs += '&';
41 | qs += key + '=' + Server.URLEncode(params[key]);
42 | }
43 | }
44 | }
45 | url += qs.length > 0 ? '&' + qs : '';
46 | Response.Redirect(url);
47 | }
48 |
49 | protected getTemplate(path: string) {
50 | return View.getTemplate(path);
51 | }
52 |
53 | protected view(path: string, data: any) {
54 | let template = this.getTemplate(path);
55 | return new HtmlResult(template(data));
56 | }
57 | }
58 | }
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/domain/validator.ts:
--------------------------------------------------------------------------------
1 | class Validator {
2 | private notifications;
3 |
4 | constructor() {
5 | this.notifications = [];
6 | }
7 |
8 | private addNotification(prop: string, message: string) {
9 | this.notifications.push([prop, message]);
10 | }
11 |
12 | valid() {
13 | return this.notifications.length === 0;
14 | }
15 |
16 | getNotifications() {
17 | return this.notifications.slice(0);
18 | }
19 |
20 | required(prop: string, val: string): Validator {
21 | if (!val || val == null) {
22 | this.addNotification(prop, 'valor requerido');
23 | }
24 | return this;
25 | }
26 |
27 | number(prop: string, val: string): Validator {
28 | if (val && val != null) {
29 | if (!/^(?:-?\d+|-?\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test(val)) {
30 | this.addNotification(prop, 'valor inválido');
31 | }
32 | }
33 | return this;
34 | }
35 |
36 | digits(prop: string, val: string): Validator {
37 | if (val && val != null) {
38 | if (/\D/.test(val)) {
39 | this.addNotification(prop, 'o campo deve conter apenas dígitos');
40 | }
41 | }
42 | return this;
43 | }
44 |
45 | maxLength(prop: string, val: string, length: number): Validator {
46 | if (val && val != null) {
47 | if (val.length > length) {
48 | this.addNotification(prop, `o campo deve ter ${length} caracteres ou menos`);
49 | }
50 | }
51 | return this;
52 | }
53 |
54 | fixedLength(prop: string, val: string, length: number): Validator {
55 | if (val && val != null) {
56 | if (val.length !== length) {
57 | this.addNotification(prop, `o campo deve ter exatamente ${length} caracteres`);
58 | }
59 | }
60 | return this;
61 | }
62 |
63 | date(prop: string, val: string): Validator {
64 | if (val && val != null) {
65 | if (!moment.isDate(val) && !moment(val, 'DD/MM/YYYY').isValid()) {
66 | this.addNotification(prop, 'data inválida');
67 | }
68 | }
69 | return this;
70 | }
71 | }
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | ###############################################################################
2 | # Set default behavior to automatically normalize line endings.
3 | ###############################################################################
4 | * text=auto
5 |
6 | ###############################################################################
7 | # Set default behavior for command prompt diff.
8 | #
9 | # This is need for earlier builds of msysgit that does not have it on by
10 | # default for csharp files.
11 | # Note: This is only used by command line
12 | ###############################################################################
13 | #*.cs diff=csharp
14 |
15 | ###############################################################################
16 | # Set the merge driver for project and solution files
17 | #
18 | # Merging from the command prompt will add diff markers to the files if there
19 | # are conflicts (Merging from VS is not affected by the settings below, in VS
20 | # the diff markers are never inserted). Diff markers may cause the following
21 | # file extensions to fail to load in VS. An alternative would be to treat
22 | # these files as binary and thus will always conflict and require user
23 | # intervention with every merge. To do so, just uncomment the entries below
24 | ###############################################################################
25 | #*.sln merge=binary
26 | #*.csproj merge=binary
27 | #*.vbproj merge=binary
28 | #*.vcxproj merge=binary
29 | #*.vcproj merge=binary
30 | #*.dbproj merge=binary
31 | #*.fsproj merge=binary
32 | #*.lsproj merge=binary
33 | #*.wixproj merge=binary
34 | #*.modelproj merge=binary
35 | #*.sqlproj merge=binary
36 | #*.wwaproj merge=binary
37 |
38 | ###############################################################################
39 | # behavior for image files
40 | #
41 | # image files are treated as binary by default.
42 | ###############################################################################
43 | #*.jpg binary
44 | #*.png binary
45 | #*.gif binary
46 |
47 | ###############################################################################
48 | # diff behavior for common document formats
49 | #
50 | # Convert binary document formats to text before diffing them. This feature
51 | # is only available from the command line. Turn it on by uncommenting the
52 | # entries below.
53 | ###############################################################################
54 | #*.doc diff=astextplain
55 | #*.DOC diff=astextplain
56 | #*.docx diff=astextplain
57 | #*.DOCX diff=astextplain
58 | #*.dot diff=astextplain
59 | #*.DOT diff=astextplain
60 | #*.pdf diff=astextplain
61 | #*.PDF diff=astextplain
62 | #*.rtf diff=astextplain
63 | #*.RTF diff=astextplain
64 |
--------------------------------------------------------------------------------
/ASPTypeScriptSample/src/controllers/student-controller.ts:
--------------------------------------------------------------------------------
1 | namespace ASPTypeScriptSample.Controllers {
2 | const viewRoot = '/src/views/student/';
3 |
4 | export class StudentController extends BaseController {
5 | index() {
6 | let term = Request.QueryString('term')();
7 | let repo = Repositories.createStudentRepository();
8 | let students = term ? repo.query(term) : repo.all();
9 |
10 | this.registerFilterPartial();
11 | View.setTitle('Students');
12 | return this.view(viewRoot + 'index.html', { term, items: students });
13 | }
14 |
15 | private registerFilterPartial() {
16 | Handlebars.registerPartial('filter', this.getTemplate(viewRoot + 'filter.html'))
17 | }
18 |
19 | details() {
20 | let id = Request.QueryString('id')();
21 | if (!id || id.length !== 36) return this.badRequest();
22 |
23 | let repo = Repositories.createStudentRepository();
24 | let student = repo.getById(id);
25 |
26 | if (student == null) return this.notFound();
27 |
28 | View.setTitle('Student Detail');
29 | return this.view(viewRoot + 'details.html', student);
30 | }
31 |
32 | create() {
33 | View.registerScript('/assets/js/student/edit.js');
34 | View.setTitle('New Student');
35 | return this.view(viewRoot + 'create.html', {});
36 | }
37 |
38 | edit() {
39 | let id = Request.QueryString('id')();
40 | if (!id || id.length !== 36) return this.badRequest();
41 |
42 | let repo = Repositories.createStudentRepository();
43 | let student = repo.getById(id);
44 |
45 | if (student == null) return this.notFound();
46 |
47 | View.registerScript('/assets/js/student/edit.js');
48 | View.setTitle('Edit Student');
49 | return this.view(viewRoot + 'edit.html', student);
50 | }
51 |
52 | save() {
53 | this.postOnly();
54 |
55 | let v = this.validateSave();
56 |
57 | if (!v.valid()) {
58 | return this.view('/src/views/shared/validation-error.html', v.getNotifications());
59 | }
60 |
61 | let cmd = this.getSaveCommand();
62 |
63 | let repo = Repositories.createStudentRepository();
64 | let id: string;
65 |
66 | if (cmd.id) {
67 | repo.update(cmd.id, cmd.name, cmd.document, cmd.birthdate);
68 | id = cmd.id;
69 | } else {
70 | id = repo.create(cmd.name, cmd.document, cmd.birthdate);
71 | }
72 |
73 | this.redirectTo('student', 'details', { id });
74 | }
75 |
76 | private validateSave() {
77 | let s = {
78 | id: Request.Form('id')(),
79 | name: Request.Form('name')(),
80 | document: Request.Form('document')(),
81 | birthdate: Request.Form('birthdate')(),
82 | };
83 |
84 | let v = new Validator()
85 | .fixedLength('id', s.id, 36)
86 | .required('name', s.name)
87 | .maxLength('name', s.name, 50)
88 | .required('document', s.document)
89 | .fixedLength('document', s.document, 11)
90 | .required('birthdate', s.birthdate)
91 | .date('birthdate', s.birthdate);
92 |
93 | return v;
94 | }
95 |
96 | private getSaveCommand(): SaveCommand {
97 | return {
98 | id: Request.Form('id')(),
99 | name: Request.Form('name')(),
100 | document: Request.Form('document')(),
101 | birthdate: moment(Request.Form('birthdate')(), 'DD/MM/YYYY').toDate()
102 | };
103 | }
104 |
105 | reset() {
106 | Session.Contents.Remove('students')
107 | this.redirectTo('student');
108 | }
109 |
110 | debug() {
111 | let data = JSON.parse(Session('students'));
112 | return `${JSON.stringify(data, null, 2)}`;
113 | }
114 | }
115 |
116 | interface SaveCommand {
117 | id?: string;
118 | name: string;
119 | document: string;
120 | birthdate: Date;
121 | }
122 | }
--------------------------------------------------------------------------------
/ASPTypeScriptSample/lib/polyfills.js:
--------------------------------------------------------------------------------
1 | if (!Array.prototype.filter) {
2 | Array.prototype.filter = function (fun/*, thisArg*/) {
3 | 'use strict';
4 |
5 | if (this === void 0 || this === null) {
6 | throw new TypeError();
7 | }
8 |
9 | var t = Object(this);
10 | var len = t.length >>> 0;
11 | if (typeof fun !== 'function') {
12 | throw new TypeError();
13 | }
14 |
15 | var res = [];
16 | var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
17 | for (var i = 0; i < len; i++) {
18 | if (i in t) {
19 | var val = t[i];
20 |
21 | // NOTE: Technically this should Object.defineProperty at
22 | // the next index, as push can be affected by
23 | // properties on Object.prototype and Array.prototype.
24 | // But that method's new, and collisions should be
25 | // rare, so use the more-compatible alternative.
26 | if (fun.call(thisArg, val, i, t)) {
27 | res.push(val);
28 | }
29 | }
30 | }
31 |
32 | return res;
33 | };
34 | }
35 |
36 | // Production steps of ECMA-262, Edition 5, 15.4.4.19
37 | // Reference: http://es5.github.io/#x15.4.4.19
38 | if (!Array.prototype.map) {
39 |
40 | Array.prototype.map = function (callback, thisArg) {
41 |
42 | var T, A, k;
43 |
44 | if (this == null) {
45 | throw new TypeError(' this is null or not defined');
46 | }
47 |
48 | // 1. Let O be the result of calling ToObject passing the |this|
49 | // value as the argument.
50 | var O = Object(this);
51 |
52 | // 2. Let lenValue be the result of calling the Get internal
53 | // method of O with the argument "length".
54 | // 3. Let len be ToUint32(lenValue).
55 | var len = O.length >>> 0;
56 |
57 | // 4. If IsCallable(callback) is false, throw a TypeError exception.
58 | // See: http://es5.github.com/#x9.11
59 | if (typeof callback !== 'function') {
60 | throw new TypeError(callback + ' is not a function');
61 | }
62 |
63 | // 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
64 | if (arguments.length > 1) {
65 | T = thisArg;
66 | }
67 |
68 | // 6. Let A be a new array created as if by the expression new Array(len)
69 | // where Array is the standard built-in constructor with that name and
70 | // len is the value of len.
71 | A = new Array(len);
72 |
73 | // 7. Let k be 0
74 | k = 0;
75 |
76 | // 8. Repeat, while k < len
77 | while (k < len) {
78 |
79 | var kValue, mappedValue;
80 |
81 | // a. Let Pk be ToString(k).
82 | // This is implicit for LHS operands of the in operator
83 | // b. Let kPresent be the result of calling the HasProperty internal
84 | // method of O with argument Pk.
85 | // This step can be combined with c
86 | // c. If kPresent is true, then
87 | if (k in O) {
88 |
89 | // i. Let kValue be the result of calling the Get internal
90 | // method of O with argument Pk.
91 | kValue = O[k];
92 |
93 | // ii. Let mappedValue be the result of calling the Call internal
94 | // method of callback with T as the this value and argument
95 | // list containing kValue, k, and O.
96 | mappedValue = callback.call(T, kValue, k, O);
97 |
98 | // iii. Call the DefineOwnProperty internal method of A with arguments
99 | // Pk, Property Descriptor
100 | // { Value: mappedValue,
101 | // Writable: true,
102 | // Enumerable: true,
103 | // Configurable: true },
104 | // and false.
105 |
106 | // In browsers that support Object.defineProperty, use the following:
107 | // Object.defineProperty(A, k, {
108 | // value: mappedValue,
109 | // writable: true,
110 | // enumerable: true,
111 | // configurable: true
112 | // });
113 |
114 | // For best browser support, use the following:
115 | A[k] = mappedValue;
116 | }
117 | // d. Increase k by 1.
118 | k++;
119 | }
120 |
121 | // 9. return A
122 | return A;
123 | };
124 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | [Xx]64/
19 | [Xx]86/
20 | [Bb]uild/
21 | bld/
22 | [Bb]in/
23 | [Oo]bj/
24 |
25 | # Visual Studio 2015 cache/options directory
26 | .vs/
27 | # Uncomment if you have tasks that create the project's static files in wwwroot
28 | #wwwroot/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | # DNX
44 | project.lock.json
45 | artifacts/
46 |
47 | *_i.c
48 | *_p.c
49 | *_i.h
50 | *.ilk
51 | *.meta
52 | *.obj
53 | *.pch
54 | *.pdb
55 | *.pgc
56 | *.pgd
57 | *.rsp
58 | *.sbr
59 | *.tlb
60 | *.tli
61 | *.tlh
62 | *.tmp
63 | *.tmp_proj
64 | *.log
65 | *.vspscc
66 | *.vssscc
67 | .builds
68 | *.pidb
69 | *.svclog
70 | *.scc
71 |
72 | # Chutzpah Test files
73 | _Chutzpah*
74 |
75 | # Visual C++ cache files
76 | ipch/
77 | *.aps
78 | *.ncb
79 | *.opendb
80 | *.opensdf
81 | *.sdf
82 | *.cachefile
83 | *.VC.db
84 |
85 | # Visual Studio profiler
86 | *.psess
87 | *.vsp
88 | *.vspx
89 | *.sap
90 |
91 | # TFS 2012 Local Workspace
92 | $tf/
93 |
94 | # Guidance Automation Toolkit
95 | *.gpState
96 |
97 | # ReSharper is a .NET coding add-in
98 | _ReSharper*/
99 | *.[Rr]e[Ss]harper
100 | *.DotSettings.user
101 |
102 | # JustCode is a .NET coding add-in
103 | .JustCode
104 |
105 | # TeamCity is a build add-in
106 | _TeamCity*
107 |
108 | # DotCover is a Code Coverage Tool
109 | *.dotCover
110 |
111 | # NCrunch
112 | _NCrunch_*
113 | .*crunch*.local.xml
114 | nCrunchTemp_*
115 |
116 | # MightyMoose
117 | *.mm.*
118 | AutoTest.Net/
119 |
120 | # Web workbench (sass)
121 | .sass-cache/
122 |
123 | # Installshield output folder
124 | [Ee]xpress/
125 |
126 | # DocProject is a documentation generator add-in
127 | DocProject/buildhelp/
128 | DocProject/Help/*.HxT
129 | DocProject/Help/*.HxC
130 | DocProject/Help/*.hhc
131 | DocProject/Help/*.hhk
132 | DocProject/Help/*.hhp
133 | DocProject/Help/Html2
134 | DocProject/Help/html
135 |
136 | # Click-Once directory
137 | publish/
138 |
139 | # Publish Web Output
140 | *.[Pp]ublish.xml
141 | *.azurePubxml
142 |
143 | # TODO: Un-comment the next line if you do not want to checkin
144 | # your web deploy settings because they may include unencrypted
145 | # passwords
146 | #*.pubxml
147 | *.publishproj
148 |
149 | # NuGet Packages
150 | *.nupkg
151 | # The packages folder can be ignored because of Package Restore
152 | **/packages/*
153 | # except build/, which is used as an MSBuild target.
154 | !**/packages/build/
155 | # Uncomment if necessary however generally it will be regenerated when needed
156 | #!**/packages/repositories.config
157 | # NuGet v3's project.json files produces more ignoreable files
158 | *.nuget.props
159 | *.nuget.targets
160 |
161 | # Microsoft Azure Build Output
162 | csx/
163 | *.build.csdef
164 |
165 | # Microsoft Azure Emulator
166 | ecf/
167 | rcf/
168 |
169 | # Windows Store app package directory
170 | AppPackages/
171 | BundleArtifacts/
172 |
173 | # Visual Studio cache files
174 | # files ending in .cache can be ignored
175 | *.[Cc]ache
176 | # but keep track of directories ending in .cache
177 | !*.[Cc]ache/
178 |
179 | # Others
180 | ClientBin/
181 | [Ss]tyle[Cc]op.*
182 | ~$*
183 | *~
184 | *.dbmdl
185 | *.dbproj.schemaview
186 | *.pfx
187 | *.publishsettings
188 | node_modules/
189 | orleans.codegen.cs
190 |
191 | # RIA/Silverlight projects
192 | Generated_Code/
193 |
194 | # Backup & report files from converting an old project file
195 | # to a newer Visual Studio version. Backup files are not needed,
196 | # because we have git ;-)
197 | _UpgradeReport_Files/
198 | Backup*/
199 | UpgradeLog*.XML
200 | UpgradeLog*.htm
201 |
202 | # SQL Server files
203 | *.mdf
204 | *.ldf
205 |
206 | # Business Intelligence projects
207 | *.rdl.data
208 | *.bim.layout
209 | *.bim_*.settings
210 |
211 | # Microsoft Fakes
212 | FakesAssemblies/
213 |
214 | # GhostDoc plugin setting file
215 | *.GhostDoc.xml
216 |
217 | # Node.js Tools for Visual Studio
218 | .ntvs_analysis.dat
219 |
220 | # Visual Studio 6 build log
221 | *.plg
222 |
223 | # Visual Studio 6 workspace options file
224 | *.opt
225 |
226 | # Visual Studio LightSwitch build output
227 | **/*.HTMLClient/GeneratedArtifacts
228 | **/*.DesktopClient/GeneratedArtifacts
229 | **/*.DesktopClient/ModelManifest.xml
230 | **/*.Server/GeneratedArtifacts
231 | **/*.Server/ModelManifest.xml
232 | _Pvt_Extensions
233 |
234 | # LightSwitch generated files
235 | GeneratedArtifacts/
236 | ModelManifest.xml
237 |
238 | # Paket dependency manager
239 | .paket/paket.exe
240 |
241 | # FAKE - F# Make
242 | .fake/
243 |
244 | # NuGet packages
245 | Content
246 | Scripts
247 | fonts
248 |
249 | # TypeScript files
250 | ASPTypeScriptSample/src/**/*.js
251 | ASPTypeScriptSample/src/**/*.map
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Classic ASP + TypeScript sample application
2 | ===========================================
3 |
4 | Inspired by [this post].
5 |
6 | This is a sample application developed with classic asp and typescript.
7 |
8 | But why
9 | -------
10 |
11 | 
12 |
13 | Sometimes we're simply stuck with old applications running in classic asp.
14 |
15 | TypeScript adds usefull tools for development like IntelliSense, refactoring, a real class system, a type system, compile time errors, autocompletion, jsdocs, and more.
16 |
17 | It can be used in existing applications, sharing code and session state.
18 |
19 | Also, it was fun to do :)
20 |
21 | Run the project
22 | ---------------
23 |
24 | To fetch the js and css packages from nuget, run the command `Update-Package -Reinstall` from the package manager console.
25 |
26 | The package handlebars.TypeScript.DefinitelyTyped installs two .d.ts files, it is necessary to delete the one for version 1.0.0.
27 |
28 | It runs on IIS Express, it can be executed directly from visual studio (without debug).
29 |
30 | Script execution order
31 | ----------------------
32 |
33 | Scripts run in classic asp in the following order:
34 |
35 | 1. any `