Files
doneit-web/src/app/app.module.ts
T
peter.maquiran 3eecedb23f fix publication
2025-09-17 18:37:35 +01:00

425 lines
14 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { NgModule, CUSTOM_ELEMENTS_SCHEMA, ErrorHandler } from '@angular/core';
import { BrowserModule, HammerModule } from '@angular/platform-browser';
import { RouteReuseStrategy } from '@angular/router';
import { IonicModule, IonicRouteStrategy } from '@ionic/angular';
import { StatusBar } from '@ionic-native/status-bar/ngx';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { HTTP_INTERCEPTORS, HttpClientModule } from '@angular/common/http';
import { InAppBrowser } from '@ionic-native/in-app-browser/ngx';
import { WebView } from '@ionic-native/ionic-webview/ngx';
import { FilePath } from '@ionic-native/file-path/ngx';
import { Camera } from '@ionic-native/camera/ngx';
import { IonicStorageModule } from '@ionic/storage';
import { CommonModule } from '@angular/common';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { CalendarModule, DateAdapter } from 'angular-calendar';
import { adapterFactory } from 'angular-calendar/date-adapters/date-fns';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import {MatDatepickerModule} from '@angular/material/datepicker';
import {MAT_DATE_LOCALE} from '@angular/material/core';
import { Network } from '@ionic-native/network/ngx';
import { MultipleDocumentsPicker } from '@awesome-cordova-plugins/multiple-document-picker/ngx';
import { DocumentViewer } from '@awesome-cordova-plugins/document-viewer/ngx';
import { FFMpeg } from '@awesome-cordova-plugins/ffmpeg/ngx';
import { FFmpeg } from '@ffmpeg/ffmpeg';
import {
NgxMatDatetimePickerModule,
NgxMatNativeDateModule,
NgxMatTimepickerModule
} from '@angular-material-components/datetime-picker';
import { MatDialogModule } from '@angular/material/dialog';
import { MatSelectModule } from '@angular/material/select';
import { NgxMatMomentModule } from '@angular-material-components/moment-adapter';
import { MatButtonModule } from '@angular/material/button';
import { HttpClient } from '@angular/common/http';
import { FontAwesomeModule, FaIconLibrary } from '@fortawesome/angular-fontawesome';
import { fas } from '@fortawesome/free-solid-svg-icons'
import { far } from '@fortawesome/free-regular-svg-icons'
import { fab } from '@fortawesome/free-brands-svg-icons'
import { ScreenOrientation } from '@ionic-native/screen-orientation/ngx';
import { SQLite } from '@ionic-native/sqlite/ngx';
import { CookieService } from 'ngx-cookie-service';
import { ImagePicker } from '@ionic-native/image-picker/ngx';
import { MediaCapture } from '@awesome-cordova-plugins/media-capture/ngx';
import { Media } from '@ionic-native/media/ngx';
import { File } from '@awesome-cordova-plugins/file/ngx';
import { StreamingMedia } from '@ionic-native/streaming-media/ngx';
import { PhotoViewer } from '@ionic-native/photo-viewer/ngx';
import {NgxImageCompressService} from 'ngx-image-compress';
import { CustomImageCachePageRoutingModule } from './services/file/custom-image-cache/custom-image-cache-routing.module';
import { IonicImageLoaderModule } from 'ionic-image-loader-v5';
import { NgxExtendedPdfViewerModule } from 'ngx-extended-pdf-viewer';
import { FileOpener } from '@awesome-cordova-plugins/file-opener/ngx';
import { MatInputModule } from '@angular/material/input';
import { MatNativeDateModule } from '@angular/material/core';
import * as SentrySibling from '@sentry/angular';
import { AngularFireModule } from '@angular/fire';
import { AngularFireMessagingModule } from '@angular/fire/messaging';
import { firebaseConfig } from '../firebase-config';
import { EditorModule } from '@tinymce/tinymce-angular';;
import { CreateProcessPageModule } from './modals/create-process/create-process.module';
import { CreateProcessPage } from './modals/create-process/create-process.page';
import { LoggingInterceptorService } from './services/logging-interceptor.service';
import { PopupQuestionPipe } from './modals/popup-question.pipe';
import '@teamhive/capacitor-video-recorder';
import { tokenInterceptor } from './infra/monitoring/interceptors/token.interceptors';
import { InputFilterDirective } from './services/directives/input-filter.directive';
import { DeplomaOptionsPageModule } from './shared/popover/deploma-options/deploma-options.module';
import { DiplomaOptionsPage } from './shared/popover/deploma-options/deploma-options.page';
import { ImageCropperModule } from 'ngx-image-cropper';
import { metricsInterceptor } from './infra/monitoring/interceptors/metter.interceptor';
import {MatMenuModule} from '@angular/material/menu';
import {MatIconModule} from '@angular/material/icon';
import { ChatModule } from './module/chat/chat.module';
import { registerLocaleData } from '@angular/common';
import localePt from '@angular/common/locales/pt';
import { UserModule } from './module/user/user.module';
import { Logger } from './services/logger/main/service';
registerLocaleData(localePt, 'pt');
import * as Sentry from '@sentry/capacitor';
import { Integration } from '@sentry/types';
import { BrowserTracing } from '@sentry/tracing';
import { LogsDatabase } from './infra/database/dexie/instance/logs/service';
import { AppErrorHandler } from './infra/crash-analytics/app-error-handler';
// Sentry.init(
// {
// dsn: 'https://5b345a3ae70b4e4da463da65881b4aaa@o4504340905525248.ingest.sentry.io/4504345615794176',
// // To set your release and dist versions
// release: 'gabinetedigital@1.0.0',
// dist: '1',
// // Set tracesSampleRate to 1.0 to capture 100% of transactions for performance monitoring.
// // We recommend adjusting this value in production.
// tracesSampleRate: 1.0,
// debug: true, // logs to console
// beforeSend(event) {
// console.log('event.exception.values[0].value', event.exception.values[0].value);
// if (event.level === 'error') {
// LogsDatabase.sentryError.add(event as any).then(() => {
// console.log('event', event)
// })
// // openTelemetryLogging.send({
// // level: 'info',
// // message: event.exception.values[0].value,
// // payload: {
// // object: {
// // sentry: true,
// // error: event
// // }
// // },
// // })
// }
// // Return event to send it to Sentry
// return event;
// },
// }
// );
(function () {
const httpLogs = [];
// --- Patch fetch ---
const originalFetch = window.fetch;
window.fetch = async (input, config = {}) => {
const url = typeof input === "string" ? input : (input as any).url;
const method = config?.method || "GET";
// Capture tracer header
let tracerHeader = null;
if (config?.headers) {
if (config.headers instanceof Headers) {
tracerHeader = config.headers.get("x-tracer");
} else if (typeof config.headers === "object") {
tracerHeader = config.headers["x-tracer"] || config.headers["X-Tracer"];
}
}
// Capture request body (payload)
let requestPayload = null;
if (config?.body) {
try {
if (typeof config.body === "string") {
requestPayload = config.body;
} else if (config.body !== null && typeof config.body === "object") {
// Keep plain objects/arrays as-is
requestPayload = config.body;
} else {
// For other cases (like FormData, Blob, etc.), attempt safe stringify
requestPayload = JSON.stringify(config.body);
}
} catch {
requestPayload = "[Unserializable body]";
}
}
const start = Date.now();
try {
const response = await originalFetch(input, config);
// Clone response so we dont consume it
const clone = response.clone();
let responsePayload = null;
try {
const contentType = clone.headers.get("content-type") || "";
if (contentType.includes("application/json")) {
responsePayload = await clone.json();
} else if (contentType.includes("text")) {
responsePayload = await clone.text();
} else {
responsePayload = "[Non-textual body]";
}
} catch {
responsePayload = "[Unserializable response]";
}
const log = {
type: "fetch",
url,
method,
status: response.status,
xTracer: tracerHeader,
requestPayload,
responsePayload,
duration: Date.now() - start,
timestamp: new Date().toISOString(),
};
if(response.status >= 400 || response.status === 0) {
Logger.error('XHR', log)
}
httpLogs.push(log);
return response;
} catch (error) {
const log = {
type: "fetch",
url,
method,
status: "NETWORK_ERROR",
xTracer: tracerHeader,
requestPayload,
responsePayload: null,
duration: Date.now() - start,
timestamp: new Date().toISOString(),
};
if(!url.includes('petermaquiran.xyz') && url != "") {
Logger.error('XHR', log);
}
httpLogs.push(log);
throw error;
}
};
// --- Patch XMLHttpRequest ---
const OriginalXHR = window.XMLHttpRequest;
function CustomXHR() {
const xhr: any = new OriginalXHR();
const start = Date.now();
xhr._xTracer = null;
xhr._requestPayload = null;
const originalSetRequestHeader = xhr.setRequestHeader;
xhr.setRequestHeader = function (key, value) {
if (key.toLowerCase() === "x-tracer") {
xhr._xTracer = value;
}
return originalSetRequestHeader.call(xhr, key, value);
};
const originalSend = xhr.send;
xhr.send = function (body) {
if (body) {
try {
xhr._requestPayload = typeof body === "string" ? body : JSON.stringify(body);
} catch {
xhr._requestPayload = "[Unserializable body]";
}
}
return originalSend.call(xhr, body);
};
xhr.addEventListener("loadend", function () {
let responsePayload = null;
try {
const contentType = xhr.getResponseHeader("content-type") || "";
if (contentType.includes("application/json")) {
responsePayload = JSON.parse(xhr.responseText);
} else if (contentType.includes("text")) {
responsePayload = xhr.responseText;
} else {
responsePayload = "[Non-textual body]";
}
} catch {
responsePayload = "[Unserializable response]";
}
const log = {
type: "xhr",
url: xhr.responseURL,
method: xhr._method || "GET",
status: xhr.status,
xTracer: xhr._xTracer,
requestPayload: xhr._requestPayload,
responsePayload,
duration: Date.now() - start,
timestamp: new Date().toISOString(),
};
if(xhr.status >= 400 && !log.url.includes('petermaquiran.xyz') || xhr.status === 0 && !log.url.includes('petermaquiran.xyz')) {
Logger.error('XHR', log)
}
httpLogs.push(log);
});
const originalOpen = xhr.open;
xhr.open = function (method, url, ...rest) {
xhr._method = method;
return originalOpen.call(xhr, method, url, ...rest);
};
return xhr;
}
(window as any).XMLHttpRequest = CustomXHR;
// Expose logs
(window as any).getHttpLogs = () => httpLogs;
})();
@NgModule({
declarations: [AppComponent, PopupQuestionPipe, InputFilterDirective],
imports: [BrowserModule,
CommonModule,
FormsModule,
CalendarModule.forRoot({
provide: DateAdapter,
useFactory: adapterFactory
}),
//AngularFireModule.initializeApp(environment.firebase),
//AngularFireMessagingModule,
IonicImageLoaderModule,
IonicModule.forRoot({animated: false}),
IonicStorageModule.forRoot({
name: '__mydb',
driverOrder: ['indexeddb', 'sqlite', 'websql']
}),
AppRoutingModule,
FontAwesomeModule,
HttpClientModule,
// NgbModule,
NoopAnimationsModule,
MatDatepickerModule,
//
NgxMatDatetimePickerModule,
NgxMatTimepickerModule,
NgxMatNativeDateModule,
NgxMatMomentModule,
MatButtonModule,
ReactiveFormsModule,
MatSelectModule,
MatDialogModule,
//
HammerModule,
CustomImageCachePageRoutingModule,
//
MatInputModule,
MatNativeDateModule,
NgxMatDatetimePickerModule,
NgxMatTimepickerModule,
NgxMatNativeDateModule,
NgxMatMomentModule,
MatSelectModule,
MatButtonModule,
AngularFireModule.initializeApp(firebaseConfig),
AngularFireMessagingModule,
EditorModule,
// options
DeplomaOptionsPageModule,
CreateProcessPageModule,
ImageCropperModule,
MatMenuModule,
MatIconModule,
// module
ChatModule,
UserModule
],
entryComponents: [
DiplomaOptionsPage,
CreateProcessPage
],
providers: [
{ provide: MAT_DATE_LOCALE, useValue: 'pt' },
//{ provide: ErrorHandler, useClass: AppErrorHandler },
// {
// provide: ErrorHandler,
// // Attach the Sentry ErrorHandler
// useValue: SentrySibling.createErrorHandler(),
// },
StatusBar,
//SplashScreen,
HttpClient,
HttpClientModule,
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
InAppBrowser,
Camera,
File,
WebView,
FilePath,
/* FCM,
FirebaseX, */
ScreenOrientation,
Network,
SQLite,
CookieService,
ImagePicker,
MediaCapture,
Media,
StreamingMedia,
PhotoViewer,
NgxImageCompressService,
MultipleDocumentsPicker,
NgxExtendedPdfViewerModule,
FileOpener,
DocumentViewer,
FFMpeg,
FFmpeg,
{ provide: HTTP_INTERCEPTORS, useClass: LoggingInterceptorService, multi: true },
tokenInterceptor,
metricsInterceptor,
],
bootstrap: [AppComponent],
schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule {
constructor(library: FaIconLibrary) {
library.addIconPacks(fas, fab, far);
}
}