feat: 支持一键发布服务端
This commit is contained in:
@@ -1,6 +1,16 @@
|
||||
import type { ApiResponse, PaginatedData } from '@mp-pilates/shared'
|
||||
|
||||
const BASE_URL = 'http://localhost:3000/api'
|
||||
const BASE_URL = (() => {
|
||||
try {
|
||||
const { miniProgram } = uni.getAccountInfoSync()
|
||||
if (miniProgram.envVersion !== 'develop') {
|
||||
return 'https://focus.richarjiang.com/api'
|
||||
}
|
||||
} catch {
|
||||
// 非小程序环境,使用开发地址
|
||||
}
|
||||
return 'http://localhost:3000/api'
|
||||
})()
|
||||
|
||||
interface RequestOptions {
|
||||
readonly url: string
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
# Database
|
||||
DATABASE_URL=postgresql://user:pass@localhost:5432/mp_pilates
|
||||
|
||||
# JWT
|
||||
JWT_SECRET=change-me-to-a-secure-random-string
|
||||
|
||||
# WeChat Mini Program
|
||||
WX_APPID=your-appid
|
||||
WX_SECRET=your-secret
|
||||
|
||||
# WeChat Pay
|
||||
WX_MCH_ID=your-mch-id
|
||||
WX_MCH_KEY=your-mch-key
|
||||
WX_MCH_SERIAL_NO=your-serial-no
|
||||
WX_MCH_CERT_PATH=./certs/apiclient_cert.pem
|
||||
WX_MCH_KEY_PATH=./certs/apiclient_key.pem
|
||||
|
||||
# Server
|
||||
PORT=3000
|
||||
@@ -3,6 +3,7 @@
|
||||
"collection": "@nestjs/schematics",
|
||||
"sourceRoot": "src",
|
||||
"compilerOptions": {
|
||||
"deleteOutDir": true
|
||||
"deleteOutDir": true,
|
||||
"tsConfigPath": "tsconfig.build.json"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,10 +27,13 @@
|
||||
"@prisma/client": "^5.19.0",
|
||||
"class-transformer": "^0.5.1",
|
||||
"class-validator": "^0.14.1",
|
||||
"nest-winston": "^1.10.2",
|
||||
"passport": "^0.7.0",
|
||||
"passport-jwt": "^4.0.1",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"rxjs": "^7.8.1"
|
||||
"rxjs": "^7.8.1",
|
||||
"winston": "^3.19.0",
|
||||
"winston-daily-rotate-file": "^5.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@nestjs/cli": "^10.4.0",
|
||||
@@ -48,13 +51,21 @@
|
||||
"typescript": "^5.4.0"
|
||||
},
|
||||
"jest": {
|
||||
"moduleFileExtensions": ["js", "json", "ts"],
|
||||
"moduleFileExtensions": [
|
||||
"js",
|
||||
"json",
|
||||
"ts"
|
||||
],
|
||||
"rootDir": "src",
|
||||
"testRegex": ".*\\.spec\\.ts$",
|
||||
"transform": {
|
||||
"^.+\\.(t|j)s$": "ts-jest"
|
||||
},
|
||||
"collectCoverageFrom": ["**/*.(t|j)s", "!**/*.module.ts", "!main.ts"],
|
||||
"collectCoverageFrom": [
|
||||
"**/*.(t|j)s",
|
||||
"!**/*.module.ts",
|
||||
"!main.ts"
|
||||
],
|
||||
"coverageDirectory": "../coverage",
|
||||
"testEnvironment": "node",
|
||||
"moduleNameMapper": {
|
||||
|
||||
@@ -3,7 +3,7 @@ generator client {
|
||||
}
|
||||
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
provider = "mysql"
|
||||
url = env("DATABASE_URL")
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ export class AuthController {
|
||||
@Body() bindPhoneDto: BindPhoneDto,
|
||||
): Promise<User> {
|
||||
return this.authService.bindPhone(
|
||||
req.user.userId,
|
||||
req.user.sub,
|
||||
bindPhoneDto.encryptedData,
|
||||
bindPhoneDto.iv,
|
||||
)
|
||||
|
||||
@@ -6,7 +6,7 @@ import { UserRole } from '@mp-pilates/shared'
|
||||
import { JwtPayload } from './auth.service'
|
||||
|
||||
export interface AuthenticatedUser {
|
||||
userId: string
|
||||
sub: string
|
||||
role: UserRole
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ export class JwtStrategy extends PassportStrategy(Strategy) {
|
||||
})
|
||||
}
|
||||
|
||||
validate(payload: JwtPayload): AuthenticatedUser {
|
||||
validate(payload: JwtPayload): { sub: string; role: UserRole } {
|
||||
return {
|
||||
userId: payload.sub,
|
||||
sub: payload.sub,
|
||||
role: payload.role,
|
||||
}
|
||||
}
|
||||
|
||||
68
packages/server/src/common/filters/api-exception.filter.ts
Normal file
68
packages/server/src/common/filters/api-exception.filter.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import {
|
||||
ExceptionFilter,
|
||||
Catch,
|
||||
ArgumentsHost,
|
||||
HttpException,
|
||||
HttpStatus,
|
||||
Logger,
|
||||
} from '@nestjs/common'
|
||||
import type { Request, Response } from 'express'
|
||||
import type { ApiResponse } from '@mp-pilates/shared'
|
||||
|
||||
@Catch()
|
||||
export class ApiExceptionFilter implements ExceptionFilter {
|
||||
private readonly logger = new Logger(ApiExceptionFilter.name)
|
||||
|
||||
catch(exception: unknown, host: ArgumentsHost): void {
|
||||
const ctx = host.switchToHttp()
|
||||
const request = ctx.getRequest<Request>()
|
||||
const response = ctx.getResponse<Response>()
|
||||
|
||||
const status =
|
||||
exception instanceof HttpException
|
||||
? exception.getStatus()
|
||||
: HttpStatus.INTERNAL_SERVER_ERROR
|
||||
|
||||
const message =
|
||||
exception instanceof HttpException
|
||||
? this.extractMessage(exception)
|
||||
: '服务器内部错误'
|
||||
|
||||
// Log all server errors (5xx) with full stack; log 4xx at warn level
|
||||
if (status >= 500) {
|
||||
this.logger.error(
|
||||
`${request.method} ${request.originalUrl} → ${String(status)} ${message}`,
|
||||
exception instanceof Error ? exception.stack : undefined,
|
||||
)
|
||||
} else if (status >= 400) {
|
||||
this.logger.warn(
|
||||
`${request.method} ${request.originalUrl} → ${String(status)} ${message}`,
|
||||
)
|
||||
}
|
||||
|
||||
const body: ApiResponse<null> = {
|
||||
success: false,
|
||||
data: null,
|
||||
message,
|
||||
}
|
||||
|
||||
response.status(status).json(body)
|
||||
}
|
||||
|
||||
private extractMessage(exception: HttpException): string {
|
||||
const response = exception.getResponse()
|
||||
if (typeof response === 'string') {
|
||||
return response
|
||||
}
|
||||
if (typeof response === 'object' && response !== null) {
|
||||
const res = response as Record<string, unknown>
|
||||
if (typeof res.message === 'string') {
|
||||
return res.message
|
||||
}
|
||||
if (Array.isArray(res.message)) {
|
||||
return res.message.join('; ')
|
||||
}
|
||||
}
|
||||
return exception.message
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
import {
|
||||
Injectable,
|
||||
NestInterceptor,
|
||||
ExecutionContext,
|
||||
CallHandler,
|
||||
} from '@nestjs/common'
|
||||
import { Observable, map } from 'rxjs'
|
||||
import type { ApiResponse } from '@mp-pilates/shared'
|
||||
|
||||
@Injectable()
|
||||
export class ApiResponseInterceptor<T>
|
||||
implements NestInterceptor<T, ApiResponse<T>>
|
||||
{
|
||||
intercept(
|
||||
_context: ExecutionContext,
|
||||
next: CallHandler<T>,
|
||||
): Observable<ApiResponse<T>> {
|
||||
return next.handle().pipe(
|
||||
map((data) => ({
|
||||
success: true,
|
||||
data: data ?? null,
|
||||
message: null,
|
||||
})),
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import {
|
||||
Injectable,
|
||||
NestInterceptor,
|
||||
ExecutionContext,
|
||||
CallHandler,
|
||||
Logger,
|
||||
} from '@nestjs/common'
|
||||
import { Observable, tap } from 'rxjs'
|
||||
import type { Request, Response } from 'express'
|
||||
|
||||
/** Fields stripped from logged request bodies to avoid leaking secrets. */
|
||||
const SENSITIVE_FIELDS: ReadonlySet<string> = new Set([
|
||||
'password',
|
||||
'token',
|
||||
'secret',
|
||||
'code',
|
||||
'sessionKey',
|
||||
'encryptedData',
|
||||
'iv',
|
||||
])
|
||||
|
||||
function sanitizeBody(
|
||||
body: Record<string, unknown> | undefined,
|
||||
): Record<string, unknown> | undefined {
|
||||
if (!body || typeof body !== 'object') return undefined
|
||||
return Object.fromEntries(
|
||||
Object.entries(body).map(([key, value]) =>
|
||||
SENSITIVE_FIELDS.has(key) ? [key, '***'] : [key, value],
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class LoggingInterceptor implements NestInterceptor {
|
||||
private readonly logger = new Logger('HTTP')
|
||||
|
||||
intercept(context: ExecutionContext, next: CallHandler): Observable<unknown> {
|
||||
const req = context.switchToHttp().getRequest<Request>()
|
||||
const { method, originalUrl } = req
|
||||
const start = Date.now()
|
||||
|
||||
return next.handle().pipe(
|
||||
tap({
|
||||
next: () => {
|
||||
const res = context.switchToHttp().getResponse<Response>()
|
||||
const duration = Date.now() - start
|
||||
const bodyLog = this.formatBody(method, req.body as Record<string, unknown>)
|
||||
this.logger.log(
|
||||
`${method} ${originalUrl} → ${String(res.statusCode)} (${String(duration)}ms)${bodyLog}`,
|
||||
)
|
||||
},
|
||||
error: (err: unknown) => {
|
||||
const duration = Date.now() - start
|
||||
const status =
|
||||
err instanceof Object && 'getStatus' in err
|
||||
? String((err as { getStatus: () => number }).getStatus())
|
||||
: '500'
|
||||
const bodyLog = this.formatBody(method, req.body as Record<string, unknown>)
|
||||
this.logger.error(
|
||||
`${method} ${originalUrl} → ${status} (${String(duration)}ms)${bodyLog}`,
|
||||
)
|
||||
},
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
private formatBody(
|
||||
method: string,
|
||||
body: Record<string, unknown> | undefined,
|
||||
): string {
|
||||
if (!['POST', 'PUT', 'PATCH'].includes(method)) return ''
|
||||
const sanitized = sanitizeBody(body)
|
||||
if (!sanitized || Object.keys(sanitized).length === 0) return ''
|
||||
return ` body=${JSON.stringify(sanitized)}`
|
||||
}
|
||||
}
|
||||
70
packages/server/src/common/logger/logger.config.ts
Normal file
70
packages/server/src/common/logger/logger.config.ts
Normal file
@@ -0,0 +1,70 @@
|
||||
import * as winston from 'winston'
|
||||
import 'winston-daily-rotate-file'
|
||||
import type { WinstonModuleOptions } from 'nest-winston'
|
||||
|
||||
const { combine, timestamp, printf, colorize, errors } = winston.format
|
||||
|
||||
/** Shared log line format: `[timestamp] [LEVEL] [context] message` */
|
||||
const logPrint = printf(({ timestamp, level, context, message, stack }) => {
|
||||
const ctx = context ? `[${context}] ` : ''
|
||||
const msg = stack ?? message
|
||||
return `${timestamp as string} [${level}] ${ctx}${msg as string}`
|
||||
})
|
||||
|
||||
function buildTransports(): winston.transport[] {
|
||||
const transports: winston.transport[] = []
|
||||
|
||||
const isProduction = process.env.NODE_ENV === 'production'
|
||||
|
||||
// Console — always enabled; colorized in dev, plain in prod
|
||||
transports.push(
|
||||
new winston.transports.Console({
|
||||
format: combine(
|
||||
...(isProduction ? [] : [colorize({ all: true })]),
|
||||
timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }),
|
||||
errors({ stack: true }),
|
||||
logPrint,
|
||||
),
|
||||
}),
|
||||
)
|
||||
|
||||
// File transports — always enabled so logs persist even in dev
|
||||
// App log: all levels, 14-day retention, 20 MB max per file
|
||||
transports.push(
|
||||
new winston.transports.DailyRotateFile({
|
||||
dirname: 'logs',
|
||||
filename: 'app-%DATE%.log',
|
||||
datePattern: 'YYYY-MM-DD',
|
||||
maxSize: '20m',
|
||||
maxFiles: '14d',
|
||||
format: combine(
|
||||
timestamp({ format: 'YYYY-MM-DDTHH:mm:ss.SSSZ' }),
|
||||
errors({ stack: true }),
|
||||
logPrint,
|
||||
),
|
||||
}),
|
||||
)
|
||||
|
||||
// Error log: error-level only, 30-day retention
|
||||
transports.push(
|
||||
new winston.transports.DailyRotateFile({
|
||||
dirname: 'logs',
|
||||
filename: 'error-%DATE%.log',
|
||||
datePattern: 'YYYY-MM-DD',
|
||||
level: 'error',
|
||||
maxSize: '20m',
|
||||
maxFiles: '30d',
|
||||
format: combine(
|
||||
timestamp({ format: 'YYYY-MM-DDTHH:mm:ss.SSSZ' }),
|
||||
errors({ stack: true }),
|
||||
logPrint,
|
||||
),
|
||||
}),
|
||||
)
|
||||
|
||||
return transports
|
||||
}
|
||||
|
||||
export const loggerConfig: WinstonModuleOptions = {
|
||||
transports: buildTransports(),
|
||||
}
|
||||
@@ -1,10 +1,17 @@
|
||||
import { NestFactory } from '@nestjs/core'
|
||||
import { ValidationPipe } from '@nestjs/common'
|
||||
import { Logger, ValidationPipe } from '@nestjs/common'
|
||||
import { ConfigService } from '@nestjs/config'
|
||||
import { WinstonModule } from 'nest-winston'
|
||||
import { AppModule } from './app.module'
|
||||
import { loggerConfig } from './common/logger/logger.config'
|
||||
import { ApiResponseInterceptor } from './common/interceptors/api-response.interceptor'
|
||||
import { LoggingInterceptor } from './common/interceptors/logging.interceptor'
|
||||
import { ApiExceptionFilter } from './common/filters/api-exception.filter'
|
||||
|
||||
async function bootstrap() {
|
||||
const app = await NestFactory.create(AppModule)
|
||||
const logger = WinstonModule.createLogger(loggerConfig)
|
||||
|
||||
const app = await NestFactory.create(AppModule, { logger })
|
||||
const configService = app.get(ConfigService)
|
||||
|
||||
app.setGlobalPrefix('api')
|
||||
@@ -15,10 +22,15 @@ async function bootstrap() {
|
||||
transform: true,
|
||||
}),
|
||||
)
|
||||
app.useGlobalInterceptors(
|
||||
new LoggingInterceptor(),
|
||||
new ApiResponseInterceptor(),
|
||||
)
|
||||
app.useGlobalFilters(new ApiExceptionFilter())
|
||||
app.enableCors()
|
||||
|
||||
const port = configService.get<number>('PORT', 3000)
|
||||
await app.listen(port)
|
||||
console.log(`Server running on http://localhost:${port}`)
|
||||
new Logger('Bootstrap').log(`Server running on http://localhost:${port}`)
|
||||
}
|
||||
bootstrap()
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "dist"
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"paths": {},
|
||||
"incremental": false
|
||||
},
|
||||
"exclude": ["node_modules", "dist", "test", "**/*.spec.ts"]
|
||||
}
|
||||
|
||||
1
packages/server/tsconfig.build.tsbuildinfo
Normal file
1
packages/server/tsconfig.build.tsbuildinfo
Normal file
File diff suppressed because one or more lines are too long
20
packages/shared/src/constants.js
Normal file
20
packages/shared/src/constants.js
Normal file
@@ -0,0 +1,20 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.WEEKDAY_LABELS = exports.DATE_SELECTOR_DAYS = exports.TIME_PERIODS = exports.SLOT_GENERATION_DAYS = exports.DEFAULT_SLOT_CAPACITY = exports.DEFAULT_CANCEL_HOURS_LIMIT = void 0;
|
||||
/** 默认免费取消截止小时数 */
|
||||
exports.DEFAULT_CANCEL_HOURS_LIMIT = 2;
|
||||
/** 默认时段容量(私教 = 1) */
|
||||
exports.DEFAULT_SLOT_CAPACITY = 1;
|
||||
/** 自动生成时段的天数范围 */
|
||||
exports.SLOT_GENERATION_DAYS = 14;
|
||||
/** 时段筛选区间 */
|
||||
exports.TIME_PERIODS = {
|
||||
MORNING: { label: '上午', start: '06:00', end: '12:00' },
|
||||
AFTERNOON: { label: '下午', start: '12:00', end: '18:00' },
|
||||
EVENING: { label: '晚上', start: '18:00', end: '22:00' },
|
||||
};
|
||||
/** 日期选择器展示天数 */
|
||||
exports.DATE_SELECTOR_DAYS = 7;
|
||||
/** 星期映射 */
|
||||
exports.WEEKDAY_LABELS = ['', '周一', '周二', '周三', '周四', '周五', '周六', '周日'];
|
||||
//# sourceMappingURL=constants.js.map
|
||||
1
packages/shared/src/constants.js.map
Normal file
1
packages/shared/src/constants.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"constants.js","sourceRoot":"","sources":["constants.ts"],"names":[],"mappings":";;;AAAA,kBAAkB;AACL,QAAA,0BAA0B,GAAG,CAAC,CAAA;AAE3C,qBAAqB;AACR,QAAA,qBAAqB,GAAG,CAAC,CAAA;AAEtC,kBAAkB;AACL,QAAA,oBAAoB,GAAG,EAAE,CAAA;AAEtC,aAAa;AACA,QAAA,YAAY,GAAG;IAC1B,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE;IACtD,SAAS,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE;IACxD,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE;CAC9C,CAAA;AAEV,gBAAgB;AACH,QAAA,kBAAkB,GAAG,CAAC,CAAA;AAEnC,WAAW;AACE,QAAA,cAAc,GAAG,CAAC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAU,CAAA"}
|
||||
51
packages/shared/src/enums.js
Normal file
51
packages/shared/src/enums.js
Normal file
@@ -0,0 +1,51 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.OrderStatus = exports.BookingStatus = exports.TimeSlotSource = exports.TimeSlotStatus = exports.MembershipStatus = exports.CardTypeCategory = exports.UserRole = void 0;
|
||||
// ===== User =====
|
||||
var UserRole;
|
||||
(function (UserRole) {
|
||||
UserRole["MEMBER"] = "MEMBER";
|
||||
UserRole["ADMIN"] = "ADMIN";
|
||||
})(UserRole || (exports.UserRole = UserRole = {}));
|
||||
// ===== CardType =====
|
||||
var CardTypeCategory;
|
||||
(function (CardTypeCategory) {
|
||||
CardTypeCategory["TIMES"] = "TIMES";
|
||||
CardTypeCategory["DURATION"] = "DURATION";
|
||||
CardTypeCategory["TRIAL"] = "TRIAL";
|
||||
})(CardTypeCategory || (exports.CardTypeCategory = CardTypeCategory = {}));
|
||||
// ===== Membership =====
|
||||
var MembershipStatus;
|
||||
(function (MembershipStatus) {
|
||||
MembershipStatus["ACTIVE"] = "ACTIVE";
|
||||
MembershipStatus["EXPIRED"] = "EXPIRED";
|
||||
MembershipStatus["USED_UP"] = "USED_UP";
|
||||
})(MembershipStatus || (exports.MembershipStatus = MembershipStatus = {}));
|
||||
// ===== TimeSlot =====
|
||||
var TimeSlotStatus;
|
||||
(function (TimeSlotStatus) {
|
||||
TimeSlotStatus["OPEN"] = "OPEN";
|
||||
TimeSlotStatus["FULL"] = "FULL";
|
||||
TimeSlotStatus["CLOSED"] = "CLOSED";
|
||||
})(TimeSlotStatus || (exports.TimeSlotStatus = TimeSlotStatus = {}));
|
||||
var TimeSlotSource;
|
||||
(function (TimeSlotSource) {
|
||||
TimeSlotSource["TEMPLATE"] = "TEMPLATE";
|
||||
TimeSlotSource["MANUAL"] = "MANUAL";
|
||||
})(TimeSlotSource || (exports.TimeSlotSource = TimeSlotSource = {}));
|
||||
// ===== Booking =====
|
||||
var BookingStatus;
|
||||
(function (BookingStatus) {
|
||||
BookingStatus["CONFIRMED"] = "CONFIRMED";
|
||||
BookingStatus["CANCELLED"] = "CANCELLED";
|
||||
BookingStatus["COMPLETED"] = "COMPLETED";
|
||||
BookingStatus["NO_SHOW"] = "NO_SHOW";
|
||||
})(BookingStatus || (exports.BookingStatus = BookingStatus = {}));
|
||||
// ===== Order =====
|
||||
var OrderStatus;
|
||||
(function (OrderStatus) {
|
||||
OrderStatus["PENDING"] = "PENDING";
|
||||
OrderStatus["PAID"] = "PAID";
|
||||
OrderStatus["REFUNDED"] = "REFUNDED";
|
||||
})(OrderStatus || (exports.OrderStatus = OrderStatus = {}));
|
||||
//# sourceMappingURL=enums.js.map
|
||||
1
packages/shared/src/enums.js.map
Normal file
1
packages/shared/src/enums.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"enums.js","sourceRoot":"","sources":["enums.ts"],"names":[],"mappings":";;;AAAA,mBAAmB;AACnB,IAAY,QAGX;AAHD,WAAY,QAAQ;IAClB,6BAAiB,CAAA;IACjB,2BAAe,CAAA;AACjB,CAAC,EAHW,QAAQ,wBAAR,QAAQ,QAGnB;AAED,uBAAuB;AACvB,IAAY,gBAIX;AAJD,WAAY,gBAAgB;IAC1B,mCAAe,CAAA;IACf,yCAAqB,CAAA;IACrB,mCAAe,CAAA;AACjB,CAAC,EAJW,gBAAgB,gCAAhB,gBAAgB,QAI3B;AAED,yBAAyB;AACzB,IAAY,gBAIX;AAJD,WAAY,gBAAgB;IAC1B,qCAAiB,CAAA;IACjB,uCAAmB,CAAA;IACnB,uCAAmB,CAAA;AACrB,CAAC,EAJW,gBAAgB,gCAAhB,gBAAgB,QAI3B;AAED,uBAAuB;AACvB,IAAY,cAIX;AAJD,WAAY,cAAc;IACxB,+BAAa,CAAA;IACb,+BAAa,CAAA;IACb,mCAAiB,CAAA;AACnB,CAAC,EAJW,cAAc,8BAAd,cAAc,QAIzB;AAED,IAAY,cAGX;AAHD,WAAY,cAAc;IACxB,uCAAqB,CAAA;IACrB,mCAAiB,CAAA;AACnB,CAAC,EAHW,cAAc,8BAAd,cAAc,QAGzB;AAED,sBAAsB;AACtB,IAAY,aAKX;AALD,WAAY,aAAa;IACvB,wCAAuB,CAAA;IACvB,wCAAuB,CAAA;IACvB,wCAAuB,CAAA;IACvB,oCAAmB,CAAA;AACrB,CAAC,EALW,aAAa,6BAAb,aAAa,QAKxB;AAED,oBAAoB;AACpB,IAAY,WAIX;AAJD,WAAY,WAAW;IACrB,kCAAmB,CAAA;IACnB,4BAAa,CAAA;IACb,oCAAqB,CAAA;AACvB,CAAC,EAJW,WAAW,2BAAX,WAAW,QAItB"}
|
||||
21
packages/shared/src/index.js
Normal file
21
packages/shared/src/index.js
Normal file
@@ -0,0 +1,21 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.WEEKDAY_LABELS = exports.DATE_SELECTOR_DAYS = exports.TIME_PERIODS = exports.SLOT_GENERATION_DAYS = exports.DEFAULT_SLOT_CAPACITY = exports.DEFAULT_CANCEL_HOURS_LIMIT = exports.OrderStatus = exports.BookingStatus = exports.TimeSlotSource = exports.TimeSlotStatus = exports.MembershipStatus = exports.CardTypeCategory = exports.UserRole = void 0;
|
||||
// Enums
|
||||
var enums_1 = require("./enums");
|
||||
Object.defineProperty(exports, "UserRole", { enumerable: true, get: function () { return enums_1.UserRole; } });
|
||||
Object.defineProperty(exports, "CardTypeCategory", { enumerable: true, get: function () { return enums_1.CardTypeCategory; } });
|
||||
Object.defineProperty(exports, "MembershipStatus", { enumerable: true, get: function () { return enums_1.MembershipStatus; } });
|
||||
Object.defineProperty(exports, "TimeSlotStatus", { enumerable: true, get: function () { return enums_1.TimeSlotStatus; } });
|
||||
Object.defineProperty(exports, "TimeSlotSource", { enumerable: true, get: function () { return enums_1.TimeSlotSource; } });
|
||||
Object.defineProperty(exports, "BookingStatus", { enumerable: true, get: function () { return enums_1.BookingStatus; } });
|
||||
Object.defineProperty(exports, "OrderStatus", { enumerable: true, get: function () { return enums_1.OrderStatus; } });
|
||||
// Constants
|
||||
var constants_1 = require("./constants");
|
||||
Object.defineProperty(exports, "DEFAULT_CANCEL_HOURS_LIMIT", { enumerable: true, get: function () { return constants_1.DEFAULT_CANCEL_HOURS_LIMIT; } });
|
||||
Object.defineProperty(exports, "DEFAULT_SLOT_CAPACITY", { enumerable: true, get: function () { return constants_1.DEFAULT_SLOT_CAPACITY; } });
|
||||
Object.defineProperty(exports, "SLOT_GENERATION_DAYS", { enumerable: true, get: function () { return constants_1.SLOT_GENERATION_DAYS; } });
|
||||
Object.defineProperty(exports, "TIME_PERIODS", { enumerable: true, get: function () { return constants_1.TIME_PERIODS; } });
|
||||
Object.defineProperty(exports, "DATE_SELECTOR_DAYS", { enumerable: true, get: function () { return constants_1.DATE_SELECTOR_DAYS; } });
|
||||
Object.defineProperty(exports, "WEEKDAY_LABELS", { enumerable: true, get: function () { return constants_1.WEEKDAY_LABELS; } });
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
packages/shared/src/index.js.map
Normal file
1
packages/shared/src/index.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";;;AAAA,QAAQ;AACR,iCAQgB;AAPd,iGAAA,QAAQ,OAAA;AACR,yGAAA,gBAAgB,OAAA;AAChB,yGAAA,gBAAgB,OAAA;AAChB,uGAAA,cAAc,OAAA;AACd,uGAAA,cAAc,OAAA;AACd,sGAAA,aAAa,OAAA;AACb,oGAAA,WAAW,OAAA;AAGb,YAAY;AACZ,yCAOoB;AANlB,uHAAA,0BAA0B,OAAA;AAC1B,kHAAA,qBAAqB,OAAA;AACrB,iHAAA,oBAAoB,OAAA;AACpB,yGAAA,YAAY,OAAA;AACZ,+GAAA,kBAAkB,OAAA;AAClB,2GAAA,cAAc,OAAA"}
|
||||
3
packages/shared/src/types/api.js
Normal file
3
packages/shared/src/types/api.js
Normal file
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=api.js.map
|
||||
1
packages/shared/src/types/api.js.map
Normal file
1
packages/shared/src/types/api.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"api.js","sourceRoot":"","sources":["api.ts"],"names":[],"mappings":""}
|
||||
3
packages/shared/src/types/booking.js
Normal file
3
packages/shared/src/types/booking.js
Normal file
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=booking.js.map
|
||||
1
packages/shared/src/types/booking.js.map
Normal file
1
packages/shared/src/types/booking.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"booking.js","sourceRoot":"","sources":["booking.ts"],"names":[],"mappings":""}
|
||||
3
packages/shared/src/types/card-type.js
Normal file
3
packages/shared/src/types/card-type.js
Normal file
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=card-type.js.map
|
||||
1
packages/shared/src/types/card-type.js.map
Normal file
1
packages/shared/src/types/card-type.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"card-type.js","sourceRoot":"","sources":["card-type.ts"],"names":[],"mappings":""}
|
||||
3
packages/shared/src/types/index.js
Normal file
3
packages/shared/src/types/index.js
Normal file
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
packages/shared/src/types/index.js.map
Normal file
1
packages/shared/src/types/index.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":""}
|
||||
3
packages/shared/src/types/membership.js
Normal file
3
packages/shared/src/types/membership.js
Normal file
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=membership.js.map
|
||||
1
packages/shared/src/types/membership.js.map
Normal file
1
packages/shared/src/types/membership.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"membership.js","sourceRoot":"","sources":["membership.ts"],"names":[],"mappings":""}
|
||||
3
packages/shared/src/types/order.js
Normal file
3
packages/shared/src/types/order.js
Normal file
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=order.js.map
|
||||
1
packages/shared/src/types/order.js.map
Normal file
1
packages/shared/src/types/order.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"order.js","sourceRoot":"","sources":["order.ts"],"names":[],"mappings":""}
|
||||
3
packages/shared/src/types/studio.js
Normal file
3
packages/shared/src/types/studio.js
Normal file
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=studio.js.map
|
||||
1
packages/shared/src/types/studio.js.map
Normal file
1
packages/shared/src/types/studio.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"studio.js","sourceRoot":"","sources":["studio.ts"],"names":[],"mappings":""}
|
||||
3
packages/shared/src/types/time-slot.js
Normal file
3
packages/shared/src/types/time-slot.js
Normal file
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=time-slot.js.map
|
||||
1
packages/shared/src/types/time-slot.js.map
Normal file
1
packages/shared/src/types/time-slot.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"time-slot.js","sourceRoot":"","sources":["time-slot.ts"],"names":[],"mappings":""}
|
||||
3
packages/shared/src/types/user.js
Normal file
3
packages/shared/src/types/user.js
Normal file
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=user.js.map
|
||||
1
packages/shared/src/types/user.js.map
Normal file
1
packages/shared/src/types/user.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"user.js","sourceRoot":"","sources":["user.ts"],"names":[],"mappings":""}
|
||||
3
packages/shared/src/types/week-template.js
Normal file
3
packages/shared/src/types/week-template.js
Normal file
@@ -0,0 +1,3 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
//# sourceMappingURL=week-template.js.map
|
||||
1
packages/shared/src/types/week-template.js.map
Normal file
1
packages/shared/src/types/week-template.js.map
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"week-template.js","sourceRoot":"","sources":["week-template.ts"],"names":[],"mappings":""}
|
||||
@@ -3,6 +3,8 @@
|
||||
"compilerOptions": {
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"module": "CommonJS",
|
||||
"moduleResolution": "node",
|
||||
"declaration": true,
|
||||
"declarationMap": true
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user